pax_global_header00006660000000000000000000000064151165513030014512gustar00rootroot0000000000000052 comment=360045cbc742b79b29ec4c583dbe5560eb066ac0 dune-grid-2.11.0/000077500000000000000000000000001511655130300134515ustar00rootroot00000000000000dune-grid-2.11.0/.gitignore000066400000000000000000000004671511655130300154500ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception *~ /build*/ # ignore files generated during python setup.py sdist MANIFEST _skbuild/ dist *.egg-info/ # ignore macOS filesystem .DS_Store dune-grid-2.11.0/.gitlab-ci.yml000066400000000000000000000025731511655130300161140ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception --- include: - project: 'core/ci-config' ref: master file: 'config/common/releases/2.11.yml' - project: 'core/ci-config' ref: master file: 'jobs/common/releases/2.11.yml' before_script: - . /duneci/bin/duneci-init-job - duneci-install-module https://gitlab.dune-project.org/core/dune-common.git - duneci-install-module https://gitlab.dune-project.org/core/dune-geometry.git - duneci-install-module https://gitlab.dune-project.org/staging/dune-uggrid.git # Check for spelling mistakes in text code-spelling-check: stage: .pre # Avoid the global 'before_script' before_script: "" image: registry.dune-project.org/docker/ci/debian:11 tags: [duneci] script: # * Codespell-versions after Debian 11 seem to work without ignoring 'ba'. # * Currently the Python code contains methods that are named "tesselate" # (instead of the correct "tessellate"). These are deprecated and will # be removed eventually. Until then, we have to ignore "tesselate". - codespell --ignore-words-list ba,deques,nin,iiterator,nd,ot,tesselate reuse: stage: .pre image: name: docker.io/fsfe/reuse:latest entrypoint: [""] tags: [duneci] before_script: "" script: - reuse lint dune-grid-2.11.0/CHANGELOG.md000066400000000000000000000442601511655130300152700ustar00rootroot00000000000000 # Release 2.11 - The grid concepts are now able to check grids that have entity types disabled. For such entity codimension, the type `typename T::template Codim<0>::Entity` is required to satisfy the `EntityGeneral` concept only if the type exists (i.e. substitution failure is allowed). - The `GmshReader` facility now supports reading Version 4 Gmsh files. This includes both the ASCII and the binary variants of this format. The user interface is unchanged by this, but this may change eventually. The code is essentially the one from Simon Praetorius' `dune-gmsh4` module, but not all features of that module are supported yet. Likewise, not every feature of `GmshReader` works for Version 4 files. In particular, getting element or boundary segment data is not supported yet, and neither is constructing explicit `BoundarySegment` objects. However, basic grid file reading works, and more features will/may be added eventually. - Make `YaspGrid` compatible with MSVC's implementation of the C++ Standard Library. # Release 2.10 ## Changelog - Gmsh reader learned to read and export gmsh physical entity names. - Removed the deprecated method `geomTypes()` from all the grid (indexset) implementations since they have not been used nor supported by the grid interface for ages. Use `types()` instead. Note that `types()` returns an object of type `IndexSet::Types`, which might not be `std::vector`. Also, the object is returned by value instead of by reference. - Provide `communicate()` method in `OneDGrid` and `IdentityGrid` - Change the `IndexSet::Types` type of `OndDGrid` and `YaspGrid` to `std::array`. - Grid concepts are here! A `Grid` can now be inspected and also its components checked for valid interfaces at compilation time using c++20 concepts. Note that, this feature is still in development and might be subject to changes. - A new parameter `bisectioncompatibility` for DGF block GridParameter was added. - `MultipleCodimMultipleGeomTypeMapper` is assignable. - The method `UGGridGeometry::integrationElement` has been simplified, and is faster now. - The method `UGGridGeometry::affine` has been reimplemented, and is much faster now. - For simplices, `UGGridGeometry` now caches the values of `jacobianTransposed`, `jacobianInverseTransposed`, etc. This may speed up the code when these methods are called many times per element. ## Python - Improve pickling support (GridViews and some GridFunction objects can now be pickled). - Add a prototype reader for Paraview directly based on the Python bindings. This is added to the tutorial and only demonstrates how a reader could be implemented. GridViews and GridFunctions can be pickled and then read into Paraview without going through vtu. As an example manipulation the subsampling level can be adjusted directly in Paraview so that higher order functions can be visualized. ## Deprecations and removals - Deprecated `CommDataHandleIF::fixedsize()` has been removed. Use `fixedSize()` with capital S instead. - Remove deprecated `CollectiveCommunication`, use `Communication` instead. - Deprecated `update()` member function of mappers have been removed. Use the member function `update(gridView)` with a grid view argument when updating the mapper after the grid or grid view changes. The interface change reflects that grid view has value semantics. - The deprecated convenience classes `LeafSingleCodimSingleGeomTypeMapper`, `LevelSingleCodimSingleGeomTypeMapper`, `LeafMultipleCodimMultipleGeomTypeMapper`, `LevelMultipleCodimMultipleGeomTypeMapper` have been removed since they don't comply with the new mapper interface. Just use `SingleCodimSingleGeomTypeMapper` and `MultipleCodimMultipleGeomTypeMapper`. - Remove Yasp's deprecated `YLoadBalance` interface. Use `Yasp::Partitioning` instead. - Remove deprecated `GmshReader`'s default constructor. Either use other constructors or use static methods without constructing an object. - Remove deprecated CMake module `UseUG.cmake`. # Release 2.9 - UGGrid is now thread safe on the grid view. - The `Geometry` interface was extended by methods `jacobian(local)` and `jacobianInverse(local)` and corresponding typedefs `Jacobian` and `JacobianInverse`. All grid implementations need to provide the new interface. For transition, the methods and typedefs are default-implemented in the `Dune::Geometry` interface class which is used for all grid geometries. - The `Geometry::integrationElement` now needs to return the type `Volume` instead of `ctype`. Note that this may be different from `ctype` if the grid supports typed dimensions. In such a case, `ctype` is a length, and not appropriate for a volume quantity. - The `FindAlberta.cmake` module only searches for world dimension libraries up to dim 3. This can be increased by setting the CMake variable `ALBERTA_MAX_WORLD_DIM` - A method `GridView::isConforming()` was added indicating whether a given grid view is representing a conforming grid. For some grid implementations this could vary from the compile time static `GridView::conforming` depending on run time parameters. - The Python bindings now support tensorproduct coordinates of `YaspGrid` ## Deprecations and removals - Support for PSurface has been removed. - Support for AmiraMesh has been removed. - Following the deprecation of `CollectiveCommunication` in dune-common, grids define the type `Communication`. The type `CollectiveCommunication` is deprecated and will be removed after Dune 2.9. - The CMake function `add_dune_ug_flags` is deprecated. It should not be used since all flags are already set automatically. Also the package flags for the UG grid are not registered any more. - The `dune-uggrid` module does not set the preprocessor flag `HAVE_UG` anymore. Use `HAVE_DUNE_UGGRID` instead. - The `YLoadBalance` interface is deprecated, as well the implementations. Users should switch to `Yasp::Partitioning`. # Release 2.8 - Specialization of `StructuredGridFactory` for `AlbertaGrid` is added to address the special numbering requirements of that grid. - Return type of `GridFactory::createGrid()` changed to `std::unique_ptr`. While still the replacement type `ToUniquePtr` from dune-common works, it is marked deprecated and the std implementation should be used directly now. - `UGGrid` removes support for `_2` and `_3` macros. - `SingleCodimSingleGeomTypeMapper` and `MultipleCodimMultipleGeomTypeMapper` now have an `update(gridView)` method to update the stored `GridView` and recalculate the indices after mesh adaptation. - The `update()` member function of mappers is deprecated. Use the new member function `update(gridView)` with a grid view argument when updating the mapper after the grid or grid view changes. The interface change reflects that grid view has value semantics. - The "convenience" classes `LeafSingleCodimSingleGeomTypeMapper`, `LevelSingleCodimSingleGeomTypeMapper`, `LeafMultipleCodimMultipleGeomTypeMapper`, `LevelMultipleCodimMultipleGeomTypeMapper` have been deprecated since they don't comply with the new mapper interface. Just use `SingleCodimSingleGeomTypeMapper` and `MultipleCodimMultipleGeomTypeMapper`. - `IdSet` now exports grid `dimension` and `Codim::Entity`. - `UGGrid` index sets can now compute the indices of vertices of edges. - `UGGrid`: Fixed a bug in the numbering of prism edges. - Various bugs have been fixed in the `UGGrid` subdomain communication implementation. - `YaspGrid` now supports class template argument deduction (https://en.cppreference.com/w/cpp/language/class_template_argument_deduction) if you have a C++17-CTAD-compatible compiler (gcc >= 8, clang 5) - Python bindings have been moved from the `dune-python` module which is now obsolete. To activate Python bindings the CMake flag `DUNE_ENABLE_PYTHONBINDINGS` needs to be turned on (default is off). Furthermore, flags for either shared library or position independent code needs to be used. - Properly implement the `canCommunicate` capability for `UGGrid` and `IdentityGrid`. - The return type of the `IndexSet::size` methods isn't `IndexType` anymore. In general the return type should be an unsigned integral type. The actual type is implementation specific. All implementations in `dune-grid` now return `std::size_t`, following our approach to make all size information be unsigned. - The grid capability `hasEntityIterator` now defaults to whatever the capability `hasEntity` specifies. Most grid manager implementers now only need to implement/specialize `hasEntity`. - Add a new range generator `subEntities` that allows to iterate over the sub-entities of a specified codimension for a given element (codim-0 entity) ```cpp for (const auto& vertex : subEntities(element, Codim)) std::cout << vertex.geometry().corner(0) << "\n"; ``` The returned range is sized, i.e. `subEntities(element, Codim).size()` returns the number of vertices in the element and is equivalent to `referenceElement(element).size(dim)`. ## Deprecations and removals - Remove `Intersection`'s deprecated enums `dimension` and `codimension`. Instead use grid's dimension and 1. - Remove deprecated `Grid::getRealImplementation`. Use the `impl()` member function of the facade classes directly instead. - Remove GeometryGrid's deprecated constructors accepting raw pointers. - Remove deprecated `AlbertaGrid::getRealIntersection`. Use the `impl()` member function of the intersection class directly instead. - Remove deprecated `AlbertaGrid::readGridXdr` and `AlbertaGrid::writeGridXdr`. Instead use `AlbertaGrid::readGrid` and `AlbertaGrid::writeGrid`. - Remove deprecated header `dune/common/universalmapper.hh`. - Support for PSurface is deprecated and will be removed after Dune 2.8. - Support for AmiraMesh is deprecated and will be removed after Dune 2.8. # Release 2.7 - The `YaspGrid` class has a new constructor that takes a `Coordinates` object as its first argument. This object can be of type `EquidistantCoordinates`, `EquidistantOffsetCoordinates`, or `TensorProductCoordinates`, and encapsulates the domain and element sizes. Previously, this data was given directly to different constructors of `YaspGrid`, and the constructor had to match the `Coordinates` object used as the second template argument of the `YaspGrid` class. The new constructor subsumes the previous three, and makes sure by design that the correct information is passed at `YaspGrid` construction. - The `GridFactory` exports the type `Communication` and corresponding object `comm()` that is used to create the grid. In the `GridFactoryInterface`, this defaults to the Communication induced by the process-local communicator `MPIHelper::getLocalCommunicator()`, while `UGGrid`'s factory returns the Communication of the grid. This can be used to steer the grid creation process, see `dune/grid/io/file/gmshreader.hh` for an example. - The number type used by a `BoundarySegment` is not hard-wired to `double` anymore. - The `Grid::getRealImplementation` member function has been deprecated. Use the `impl()` member function of the facade classes directly instead. - The `AlbertaGrid::getRealIntersection` member function has been deprecated. Use the `impl()` member function of the intersection class directly instead. - The return type of all file reader methods that return a grid has been changed from a plain C pointer to the custom pointer class `ToUniquePtr` (from the `dune-common` module). Values of this pointer class cast to C pointers (but with a deprecation warning), to `std::unique_ptr`, and to `std::shared_ptr`. This marks the beginning of a transition period. In the long run, the methods are planned to return objects of type `std::unique_ptr`, to make it obvious that the calling code receives the ownership of the grid object. For the time being the calling code can still store the return value in a C pointer, but that possibility will go away. - Likewise, the return type of the `GridFactory::createGrid`method has been changed from a plain C pointer to the custom pointer class `ToUniquePtr`. In the long run, the method is planned to return objects of type `std::unique_ptr`, to make it obvious that the calling code receives the ownership of the grid object. For the time being the calling code can still store the return value in a C pointer, but that possibility will go away. While this procedure allows full backward compatibility for code that calls `GridFactory::createGrid`, implementors or third-party grid implementations will need to update their implementations of `GridFactory::createGrid`. - The `VTKWriter`s now support custom output data precision for functions (via the provided `FieldInfo`), `VTKFunction`s (via a new virtual interface method `precision()`), and coordinates (via an argument to the writer's constructor) that can be chosen at runtime. Any field can now choose between VTK's `Float32`, `Float64`, `Int32`, `UInt8`, and `UInt32`, represented as `Dune::VTK::Precision::float32`/`float64`/`int32`/`uint8`/`uint32`, the `DataArrayWriter` selects the correct type at runtime. The default for functions and coordinate is `Float32` as before. - The `VTKWriter` now supports writing functions that can only be evaluated globally, i.e., functions that are not defined with respect to the grid. Such functions will be sampled on the grid vertices (`addVertexData`) or grid element centers (`addCellData`). - The Capability `hasBackupRestoreFacilities>` now returns `false` in case the `CoordFunction` is not default-constructible. - The `Geometry` interface now provides the type `Volume` for the return value of the method of the same name. Note that this may be different from `ctype` if you care about dimensions. In that case `ctype` is a length, and not appropriate for a quantity that is a volume. - The `VTKWriter` writer now truncates subnormal floating point values to 0 when writing ASCII files (`DUNE::VTK::ascii`). This avoids Paraview crashes on macOS. For this reasons, most VTK files written by DUNE 2.7 will differ from the same file written in DUNE 2.6. If you are using VTK files for testing results, make sure to use fuzzy float comparisons! - The `VTKSequenceWriter` now exposes the function `clear()` of the associated `VTKWriter` - The `VTKSequenceWriter` allows to get and set the time steps storage, which enables serialization of a sequence writer. The feature can be used to restart a sequence. - UG 3.x is no longer supported. Use dune-uggrid instead. # Release 2.6 - The deprecated `EntityPointer` has been removed completely and `EntityIterator` no longer inherits from it. As a consequence, the dimension `EntityIterator::dimension`, `EntityIterator::codimension`, and `EntityIterator::mydimension` are gone. - Experimental grid extensions are now always enabled: See core/dune-grid!155 - The method `impl` and the type `Implementation` on the facade classes are always public (and documented), now. Warning: Implementation details may change without prior notification. - The method experimental grid extension `boundaryId` has been removed from the intersection interface. Some grid will continue providing it on their implementation, i.e., it may still be accessible through ``` intersection.impl().boundaryId() ``` - The DGF block `general` is now always available and the DGFWriter will always write a boundary id and can write user-defined boundary data, now. - `MultipleCodimMultipleGeomTypeMapper`: The `Layout` template parameter has been deprecated in favor of a function object that indicates which geometry types to include in the mapping. The layout function object is passed in the constructor, so instead of ```c++ MultipleCodimMultipleGeomTypeMapper mapper1(gv); MultipleCodimMultipleGeomTypeMapper mapper2(gv); ``` please write ```c++ MultipleCodimMultipleGeomTypeMapper mapper1(gv, mcmgElementLayout()); MultipleCodimMultipleGeomTypeMapper mapper2(gv, mcmgVertexLayout()); ``` See the doxygen documentation for custom layouts and core/dune-grid!177 - The `MCMGMapper` can now be used to attach multiple dofs to each entity: See core/dune-grid!215 - the Layout is passed into the constructor and returns the number of dofs to attach to the given geometry type ``` MCMGLayout layout = [](GeometryType gt, int griddim) { return gt.dim() == griddim? 2:0; }; MCMGMapper mapper(grid,layout); ``` Note: the layout can still return a `bool` with `true` leading to a single dof being attached. - The new method `MCMGMapper::indices(entity)` returns an iterable range (instance of `IntegralRange`) with the indices of dofs attached to the given entity: ``` for (const auto& i : mapper.indices(entity) ) dof = vector[i]; ``` - Two new method were added to the MCMGMapper: `size_type size(GeometryType)` and `const std::vector< GeometryType >& types (int codim)` returning the number of dofs attached to the geometry type and a vector with all geometry types on which dofs are attached, respectively. See core/dune-grid!215 - The `StructuredGridFactory` now returns a `unique_ptr` instead of a `shared_ptr`. Code that relies on a `shared_ptr` needs to explicitly assign the return value to a `shared_ptr` variable. See core/dune-grid!212 - `SubsamplingVTKWriter` now supports arbitrary refinements, not just powers of two. The old constructor taking a parameter `int levels` has been deprecated, you should now pass a parameter `RefinementIntervals intervals` instead. There are convenience functions `refinementIntervals(int intervals)` and `refinementLevels(int levels)` to construct parameters of type `RefinementIntervals` in dune-geometry. See core/dune-grid!193 - `UGGrid` now supports transferring element data during load balancing. See core/dune-grid!172 - A convenience method `referenceElement( entity )` was added. See core/dune-grid!349 dune-grid-2.11.0/CMakeLists.txt000066400000000000000000000053371511655130300162210ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception cmake_minimum_required(VERSION 3.16) project("dune-grid" C CXX) if(NOT (dune-common_DIR OR dune-common_ROOT OR "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*")) string(REPLACE ${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) # deactivate global include-directories dune_policy(SET DP_DEFAULT_INCLUDE_DIRS NEW) # deactivate global calls to add_dune_all_flags in tests dune_policy(SET DP_TEST_ADD_ALL_FLAGS NEW) # do not making all suggested dependencies required automatically dune_policy(SET DP_SUGGESTED_MODULE_DEPENDENCIES_REQUIRED_DOWNSTREAM NEW) # start a dune project with information from dune.module dune_project() # create the dune library for dune-grid dune_add_library(dunegrid EXPORT_NAME Grid) target_link_libraries(dunegrid PUBLIC ${DUNE_LIBS}) # set include directories to target dune_default_include_directories(dunegrid PUBLIC) # create a dune library for the albertagrid if(Alberta_FOUND) foreach(_dim ${ALBERTA_WORLD_DIMS}) dune_add_library(dunealbertagrid${_dim}d NO_MODULE_LIBRARY EXPORT_NAME AlbertaGrid${_dim}D) target_link_libraries(dunealbertagrid${_dim}d PUBLIC dunegrid Alberta::AlbertaGrid${_dim}D) target_compile_definitions(dunealbertagrid${_dim}d PUBLIC ALBERTA_DIM=${_dim} HAVE_ALBERTA=1) if(Alberta_DEBUG) target_compile_definitions(dunealbertagrid${_dim}d PUBLIC ALBERTA_DEBUG=1) endif() endforeach(_dim) endif() # if UG is found it becomes a required dependency for dunegrid if(dune-uggrid_FOUND) dune_mark_module_as_required_dependency(MODULE dune-uggrid) endif() # create alias HAVE_UG set(HAVE_UG ${HAVE_DUNE_UGGRID}) add_subdirectory("dune") add_subdirectory("doc") add_subdirectory("src") add_subdirectory("cmake/modules") # if Python bindings are enabled, include necessary sub directories. if(DUNE_ENABLE_PYTHONBINDINGS) add_subdirectory("python") endif() # Use a custom section to export path to the grid examples. set(DUNE_CUSTOM_PKG_CONFIG_SECTION "#Export the directory with the grid example for downstream modules if(${ProjectName}_INSTALLED) set_and_check(DUNE_GRID_EXAMPLE_GRIDS_PATH \"\${dune-grid_PREFIX}/${CMAKE_INSTALL_DOCDIR}/grids/\") else() set_and_check(DUNE_GRID_EXAMPLE_GRIDS_PATH \"\${dune-grid_PREFIX}/doc/grids/\") endif() ") # finalize the dune project, e.g. generating config.h etc. finalize_dune_project() dune-grid-2.11.0/COPYING000077700000000000000000000000001511655130300161032LICENSE.mdustar00rootroot00000000000000dune-grid-2.11.0/INSTALL000066400000000000000000000051441511655130300145060ustar00rootroot00000000000000 Installation 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://dune-project.org/releases dune-grid-2.11.0/LICENSE.md000066400000000000000000000510351511655130300150610ustar00rootroot00000000000000Copyright holders: 2015--2017 Marco Agnese 2003--2012 Peter Bastian 2013 Timo Betcke 2004--2025 Markus Blatt 2013 Andreas Buhr 2020--2022 Samuel Burbulla 2012--2023 Ansgar Burchardt 2004--2005 Adrian Burri 2013 Benjamin Bykowski 2006--2024 Andreas Dedner 2018--2020 Nils-Arne Dreier 2010 Martin Drohmann 2003 Marc Droske 2003--2023 Christian Engwer 2004--2020 Jorrit Fahlke 2007--2018 Bernd Flemisch 2025 Nils Friess 2006--2016 Christoph Gersbacher 2015--2022 Felix Gruber 2005--2025 Carsten Gräser 2011--2025 Christoph Grüninger 2006 Bernard Haasdonk 2016--2020 René Heß 2019 Stephan Hilb 2013 Sven Kaulmann 2019 Liam Keegan 2013--2021 Dominic Kempf 2010--2015 Ole Klein 2015 Angela Klewinghaus 2003--2025 Robert Klöfkorn 2017--2025 Marcel Koch 2018--2023 Timo Koch 2005--2007 Sreejith Pulloor Kuttanikkad 2009--2013 Andreas Lauser 2017--2018 Tobias Leibner 2012--2017 Tobias Malkmus 2007--2009 Sven Marnach 2013 René Milk 2023--2024 Alexander Müller 2012 Eike Müller 2011 Thomas Müller 2010--2019 Steffen Müthing 2003--2005 Thimo Neubauer 2011 Adrian Ngo 2008--2018 Martin Nolte 2015 Andreas Nüßing 2004--2006 Mario Ohlberger 2014--2015 Marian Piatkowski 2009--2016 Elias Pipping 2010 Dan Popovic 2018--2025 Simon Praetorius 2009 Atgeirr Flø Rassmussen 2018--2025 Santiago Ospina De Los Ríos 2009 Uli Sack 2003--2025 Oliver Sander 2011--2012 Alexander Schlaich 2017 Jakob Schneck 2004 Roland Schulz 2012--2013 Nicolas Schwenck 2015--2020 Linus Seelinger 2016 Michaël Sghaïer 2008 Nina Shokina 2010 Bård Skaflestad 2020 Leopold Stadler 2020--2021 Kilian Weishaupt 2012 Markus Wolf 2009--2018 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-grid-2.11.0/LICENSES/000077500000000000000000000000001511655130300146565ustar00rootroot00000000000000dune-grid-2.11.0/LICENSES/LGPL-3.0-or-later.txt000066400000000000000000001221621511655130300202020ustar00rootroot00000000000000GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser 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 Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. “This License” refers to version 3 of the GNU General Public License. “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. A “covered work” means either the unmodified Program or a work based on the Program. To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an “about box”. You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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. But first, please read . dune-grid-2.11.0/LICENSES/LicenseRef-GPL-2.0-only-with-DUNE-exception.txt000066400000000000000000000451341511655130300250370ustar00rootroot00000000000000The 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-grid-2.11.0/README.md000066400000000000000000000021271511655130300147320ustar00rootroot00000000000000 DUNE-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 grid classes. More information ---------------- Check dune-common for more details concerning dependencies, known bugs, license and installation. dune-grid-2.11.0/cmake/000077500000000000000000000000001511655130300145315ustar00rootroot00000000000000dune-grid-2.11.0/cmake/modules/000077500000000000000000000000001511655130300162015ustar00rootroot00000000000000dune-grid-2.11.0/cmake/modules/AddAlbertaFlags.cmake000066400000000000000000000041601511655130300221440ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # Module providing convenience methods for compile binaries with Alberta support. # # .. cmake_function:: add_dune_alberta_flags # # .. cmake_param:: targets # :single: # :required: # :positional: # # The targets to add the Alberta flags to. # # .. cmake_param:: WORLDDIM # :single: # # The dimension of the world space # include_guard(GLOBAL) set_package_properties(Alberta PROPERTIES TYPE OPTIONAL PURPOSE "Provides the grid manager AlbertaGrid and file reader AlbertaReader") # set HAVE_ALBERTA for config.h set(HAVE_ALBERTA ${Alberta_FOUND}) # register all Alberta related flags if(Alberta_FOUND) include(GridType) dune_define_gridtype(GRID_CONFIG_H_BOTTOM ASSERTION WORLDDIM == ALBERTA_DIM GRIDTYPE ALBERTAGRID DUNETYPE "Dune::AlbertaGrid< dimgrid >" HEADERS dune/grid/albertagrid.hh dune/grid/albertagrid/dgfparser.hh) endif(Alberta_FOUND) macro(add_dune_alberta_flags) if(Alberta_FOUND) include(CMakeParseArguments) cmake_parse_arguments(_ARG "" "WORLDDIM;GRIDDIM" "" ${ARGN}) set(_ARG_TARGETS ${_ARG_UNPARSED_ARGUMENTS}) # extract dimension arguments set(ALBERTA_DIM ${_ARG_WORLDDIM} ${_ARG_GRIDDIM} 0) list(SORT ALBERTA_DIM ORDER DESCENDING) list(GET ALBERTA_DIM 0 WORLDDIM) if(NOT WORLDDIM OR WORLDDIM EQUAL 0) message(WARNING "Alberta dimension not set. Please set it, e.g. use " "add_dune_alberta_flags(WORLDDIM 2 ). " "Falling back to dimension 2.") set(WORLDDIM 2) elseif(NOT ${WORLDDIM} IN_LIST ALBERTA_WORLD_DIMS) message(STATUS "Found ALBERTA_WORLD_DIMS=${ALBERTA_WORLD_DIMS}") message(FATAL_ERROR "There is no alberta library for dimension ${WORLDDIM}.") endif() # link to ALBERTA libraries foreach(_target ${_ARG_TARGETS}) target_link_libraries(${_target} PUBLIC Dune::AlbertaGrid${WORLDDIM}D) endforeach(_target) endif(Alberta_FOUND) endmacro(add_dune_alberta_flags) dune-grid-2.11.0/cmake/modules/CMakeLists.txt000066400000000000000000000005211511655130300207370ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception include(GNUInstallDirs) install(FILES AddAlbertaFlags.cmake DuneGridMacros.cmake FindAlberta.cmake GridType.cmake DESTINATION ${DUNE_INSTALL_MODULEDIR}) dune-grid-2.11.0/cmake/modules/DuneGridMacros.cmake000066400000000000000000000041601511655130300220520ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # .. cmake_module:: # # This modules content is executed whenever a module required or suggests dune-grid! # include(CheckFunctionExists) check_function_exists(mkstemp HAVE_MKSTEMP) include(GridType) set(DUNE_GRID_EXTRA_UTILS "" CACHE BOOL "Enable compilation and installation of extra utilities from the \"src\" subdirectory.") find_package(METIS) find_package(ParMETIS) include(AddParMETISFlags) find_package(Alberta 3.0) include(AddAlbertaFlags) set(DEFAULT_DGF_GRIDDIM 1) set(DEFAULT_DGF_WORLDDIM 1) set(DEFAULT_DGF_GRIDTYPE ONEDGRID) set(DGF_GRIDTYPES ONEDGRID ALBERTAGRID GEOGRID UGGRID) dune_define_gridtype(GRID_CONFIG_H_BOTTOM GRIDTYPE ONEDGRID ASSERTION "(GRIDDIM == 1) && (WORLDDIM == 1)" DUNETYPE "Dune::OneDGrid" HEADERS "dune/grid/onedgrid.hh" "dune/grid/io/file/dgfparser/dgfoned.hh") dune_define_gridtype(GRID_CONFIG_H_BOTTOM GRIDTYPE YASPGRID ASSERTION "GRIDDIM == WORLDDIM" DUNETYPE "Dune::YaspGrid< dimgrid >" HEADERS "dune/grid/yaspgrid.hh" "dune/grid/io/file/dgfparser/dgfyasp.hh") macro(add_dgf_flags target) cmake_parse_arguments(DGF "" "GRIDDIM;WORLDDIM;GRIDTYPE" "" ${ARGN}) if(NOT DGF_GRIDDIM) set(DGF_GRIDDIM ${DEFAULT_DGF_GRIDDIM}) endif(NOT DGF_GRIDDIM) if(NOT DGF_WORLDDIM) set(DGF_WORLDDIM ${DEFAULT_DGF_WORLDDIM}) endif(NOT DGF_WORLDDIM) if(NOT DGF_GRIDTYPE) set(DGF_GRIDTYPE ${DEFAULT_DGF_GRIDTYPE}) endif(NOT DGF_GRIDTYPE) set(replace_args "GRIDDIM.*" "GRIDDIM=${DGF_GRIDDIM}" "WORLDDIM.*" "WORLDDIM=${DGF_WORLDDIM}") foreach(grid ${DGF_GRIDTYPES}) list(APPEND replace_args ${grid} ${DGF_GRIDTYPE}) endforeach(grid ${DGF_GRIDTYPES}) replace_properties(TARGET ${target} PROPERTY COMPILE_DEFINITIONS ${replace_args}) endmacro(add_dgf_flags target) macro(add_dgf_executable target) cmake_parse_arguments(DGF "" "GRIDDIM;WORLDDIM;GRIDTYPE" "" ${ARGN}) add_executable(${target} ${DGF_UNPARSED_ARGUMENTS}) add_dgf_flags(${target} ${ARGN}) endmacro(add_dgf_executable target) dune-grid-2.11.0/cmake/modules/FindAlberta.cmake000066400000000000000000000104361511655130300213620ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #[=======================================================================[.rst: FindAlberta ----------- Find Alberta, an Adaptive multiLevel finite element toolbox using Bisectioning refinement and Error control by Residual Techniques for scientific Applications. (see https://gitlab.com/alberta-fem/alberta3) Imported targets ^^^^^^^^^^^^^^^^ This module defines the following :prop_tgt:`IMPORTED` target: ``Alberta::AlbertaGrid_[n]d`` Dimension dependent library Result Variables ^^^^^^^^^^^^^^^^ This module defines the following variables: ``Alberta_FOUND`` The Alberta library with all its dependencies is found Cache Variables ^^^^^^^^^^^^^^^ The following variables may be set to influence this module's behavior: ``ENV{PKG_CONFIG_PATH}`` Directory containing the `alberta-grid_[n]d.pc` pkg-config files. An environmental variable to influence the search procedure of pkg-config for finding Alberta. ``Alberta_ROOT`` A directory that contains the sub directories `lib/pkgconfig` with pkg-config files as above. This directory takes precedence over any system path that also contains Alberta pkg-config files. ``Alberta_DEBUG`` If set to `true` try to find and use the debugging library. This requires that a corresponding `alberta-grid_[n]d_debug.pc` file can be found. ``Alberta_FIND_QUIETLY`` If set to `ON` do not print detailed information during search for Alberta using pkg-config. This variable is automatically if `find_package` if invoked with flag `QUIET`. ``ALBERTA_MAX_WORLD_DIM`` Maximal world dimension to check for Alberta library. Default: 3. #]=======================================================================] # text for feature summary include(FeatureSummary) set_package_properties("Alberta" PROPERTIES URL "https://gitlab.com/alberta-fem/alberta3" DESCRIPTION "An adaptive hierarchical finite element toolbox and grid manager") set(ALBERTA_MAX_WORLD_DIM "3" CACHE STRING "Maximal world dimension to check for Alberta library.") set(ALBERTA_WORLD_DIMS) set(ALBERTA_GRID_VERSION) set(ALBERTA_GRID_PREFIX) # search for Alberta using pkg-config find_package(PkgConfig) if(PkgConfig_FOUND) set(_old_cmake_prefix_path ${CMAKE_PREFIX_PATH}) if(Alberta_ROOT) list(APPEND CMAKE_PREFIX_PATH ${Alberta_ROOT}) endif() foreach(dim RANGE 1 ${ALBERTA_MAX_WORLD_DIM}) set(ALBERTA_PKGS "alberta-grid_${dim}d") if(Alberta_DEBUG) list(INSERT ALBERTA_PKGS 0 "alberta-grid_${dim}d_debug") endif() foreach(pkg ${ALBERTA_PKGS}) if(Alberta_FIND_VERSION) string(APPEND pkg ">=${Alberta_FIND_VERSION}") endif() if(Alberta_FIND_QUIETLY) pkg_check_modules(Alberta${dim}D QUIET IMPORTED_TARGET GLOBAL ${pkg}) else() pkg_check_modules(Alberta${dim}D IMPORTED_TARGET GLOBAL ${pkg}) endif() if(Alberta${dim}D_FOUND) list(APPEND ALBERTA_WORLD_DIMS ${dim}) set(ALBERTA_GRID_VERSION ${Alberta${dim}D_VERSION}) set(ALBERTA_GRID_PREFIX ${Alberta${dim}D_PREFIX}) break() endif() endforeach(pkg) endforeach(dim) set(CMAKE_PREFIX_PATH ${_old_cmake_prefix_path}) endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args("Alberta" REQUIRED_VARS ALBERTA_GRID_PREFIX PkgConfig_FOUND VERSION_VAR ALBERTA_GRID_VERSION FAIL_MESSAGE "Could NOT find Alberta (set PKG_CONFIG_PATH to include the location of the alberta-grid_[n]d.pc files)" ) if(Alberta_FOUND) if(ALBERTA_GRID_VERSION VERSION_LESS 3.1.0) unset(HAVE_STDBOOL_H_HEADER) include(CheckIncludeFileCXX) check_include_file_cxx("stdbool.h" HAVE_STDBOOL_H_HEADER) endif() foreach(dim ${ALBERTA_WORLD_DIMS}) if(NOT Alberta::AlbertaGrid${dim}D) if (${HAVE_STDBOOL_H_HEADER}) # Tell Alberta(<3.1.0) that we have a stdbool.h header so that it doesn't # try to define `bool` itself (which would lead to a `typedef bool bool` # and hence a compile error in clang). target_compile_definitions(PkgConfig::Alberta${dim}D INTERFACE -DHAVE_STDBOOL_H) endif() add_library(Alberta::AlbertaGrid${dim}D ALIAS PkgConfig::Alberta${dim}D) endif() endforeach(dim) endif() dune-grid-2.11.0/cmake/modules/GridType.cmake000066400000000000000000000062051511655130300207350ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # Implement the GRIDTYPE preprocessor magic # # .. cmake_function:: dune_define_gridtype # # .. cmake_param:: output # :single: # :required: # :positional: # # String variable grid definition is written to. # # .. cmake_param:: GRIDTYPE # :single: # :required: # # The name of the grid type to register, .e.g. YASPGRID. # # .. cmake_param:: DUNETYPE # :single: # :required: # # The C++ type of the grid to be used for the typedef, e.g. YaspGrid< dimgrid >. # # .. cmake_param:: ASSERTION # :single: # # Condition to be checked by the preprocessor, e.g. GRIDDIM == WORLDDIM for grids like YaspGrid. # # .. cmake_param:: HEADERS # :multi: # :required: # # The header files that need to be included when using this grid. # # This function registers a new type for the GRIDTYPE magic. # # option to enable GridSelector option(DUNE_GRID_GRIDTYPE_SELECTOR "Grid selector definition added to config.h" OFF) macro(dune_define_gridtype output) cmake_parse_arguments(GRIDTYPE "" "GRIDTYPE;DUNETYPE;ASSERTION" "HEADERS" ${ARGN}) if(DUNE_GRID_GRIDTYPE_SELECTOR) if(NOT(GRIDTYPE_GRIDTYPE AND GRIDTYPE_DUNETYPE)) message(ERROR "Both GRIDTYPE and DUNETYPE have to be set") endif(NOT(GRIDTYPE_GRIDTYPE AND GRIDTYPE_DUNETYPE)) set(${output} "${${output}} /* add GRIDTYPE typedef for grid implementation ${GRIDTYPE_DUNETYPE}: defining ${GRIDTYPE_GRIDTYPE} during compilation typedefs this grid implementation as GridType in namespace Dune::GridSelector; also integer constants dimgrid and dimworld are set in this namespace. The required headers for this grid implementation are also included. */ #if HAVE_DUNE_GRID && defined ${GRIDTYPE_GRIDTYPE} && ! defined USED_${GRIDTYPE_GRIDTYPE}_GRIDTYPE #if HAVE_GRIDTYPE #error \"Ambiguous definition of GRIDTYPE.\" #endif #ifndef WORLDDIM #define WORLDDIM GRIDDIM #endif #if not (WORLDDIM >= GRIDDIM) #error \"WORLDDIM < GRIDDIM does not make sense.\" #endif") if(GRIDTYPE_ASSERTION) set(${output} "${${output}} #if ! (${GRIDTYPE_ASSERTION}) #error \"Preprocessor assertion ${GRIDTYPE_ASSERTION} failed.\" #endif" ) endif(GRIDTYPE_ASSERTION) foreach(include ${GRIDTYPE_HEADERS}) set(${output} "${${output}} #include <${include}>") endforeach(include ${GRIDTYPE_HEADERS}) set(${output} "${${output}} namespace Dune { namespace GridSelector { const int dimgrid = GRIDDIM; const int dimworld = WORLDDIM; typedef ${GRIDTYPE_DUNETYPE} GridType; } } #define HAVE_GRIDTYPE 1 #define USED_${GRIDTYPE_GRIDTYPE}_GRIDTYPE 1 #endif // #if HAVE_DUNE_GRID && defined ${GRIDTYPE_GRIDTYPE} && ..") # if disabled print message how to enable else(DUNE_GRID_GRIDTYPE_SELECTOR) set(${output} "${${output}}\n/* ${GRIDTYPE_GRIDTYPE} not available, enable with cmake variable DUNE_GRID_GRIDTYPE_SELECTOR=ON */") endif(DUNE_GRID_GRIDTYPE_SELECTOR) endmacro(dune_define_gridtype output) dune-grid-2.11.0/config.h.cmake000066400000000000000000000033401511655130300161460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /* begin dune-grid 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 the version of dune-grid */ #define DUNE_GRID_VERSION "${DUNE_GRID_VERSION}" /* Define to the major version of dune-grid */ #define DUNE_GRID_VERSION_MAJOR ${DUNE_GRID_VERSION_MAJOR} /* Define to the minor version of dune-grid */ #define DUNE_GRID_VERSION_MINOR ${DUNE_GRID_VERSION_MINOR} /* Define to the revision of dune-grid */ #define DUNE_GRID_VERSION_REVISION ${DUNE_GRID_VERSION_REVISION} /* Alberta version found by configure, either 0x200 for 2.0 or 0x300 for 3.0 */ #cmakedefine DUNE_ALBERTA_VERSION @DUNE_ALBERTA_VERSION@ /* Define to 1 if you have mkstemp function */ #cmakedefine01 HAVE_MKSTEMP /* begin bottom */ /* Grid type magic for DGF parser */ @GRID_CONFIG_H_BOTTOM@ /* end bottom */ /* end dune-grid */ dune-grid-2.11.0/doc/000077500000000000000000000000001511655130300142165ustar00rootroot00000000000000dune-grid-2.11.0/doc/CMakeLists.txt000066400000000000000000000003711511655130300167570ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(doxygen) add_subdirectory(grids) add_subdirectory(recipes) dune-grid-2.11.0/doc/doxygen/000077500000000000000000000000001511655130300156735ustar00rootroot00000000000000dune-grid-2.11.0/doc/doxygen/CMakeLists.txt000066400000000000000000000003671511655130300204410ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # shortcut for creating the Doxyfile.in and Doxyfile add_doxygen_target() dune-grid-2.11.0/doc/doxygen/Doxydep000077500000000000000000000061101511655130300172330ustar00rootroot00000000000000#!/usr/bin/perl -w # SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception use strict; use English; use IO::Handle; # OPTIONS my $defaulttarget = "doxygen-tag"; my $USAGE = "Doxydep [TARGET]". "\tDOXYFILE: Configuration file for Doxygen\n". "\tDEPFILE: Outfile for the dependencies\n". "\tTARGT: Target for the Makefile (default=$defaulttarget)"; my $doxyname = shift || die $USAGE; my $depfile = shift || die $USAGE; my $target; $target = shift; if (! $target) { $target = $defaulttarget }; # write an entry for DEPFILE sub addDep ($) { my $dep = shift; if (defined($dep) && ! $dep eq "") { print DEPFILE "$target: $dep\n\n"; print DEPFILE "$dep:\n\n"; } } # get all files in a directory, except . and .. sub readDir ($) { my $dir = shift; $dir =~ s/\/$//; $dir = $dir."/"; my @entries; opendir DIR, $dir; while (my $f = readdir DIR) { if ($f !~ /^\.\.?$/) { push (@entries, $dir.$f); } } close DIR; return @entries; } # find file matching the pattern sub findFiles ($$$) { my $dir = shift; my $pattern = shift; my $recursive = shift; $pattern =~ s/\*/\\w*/g; $pattern =~ s/\?/\\w/g; my @entries; push (@entries, readDir($dir)); my @existing; while (my $file = pop(@entries)) { if (( -d $file ) && ( $recursive eq "YES" )) { push (@entries, readDir($file)); } next unless -f $file; next if ($file !~ /[\/^]$pattern$/); if (( -f $file ) && ( -r $file )) { push @existing, $file; } else { # warnen (nur nicht bei . und ..) print "Warnung: ignoriere $file!\n"; } } return @existing; }; # read all options from the Doxyfile into a hash sub parseDoxyfile ($) { my $doxyname = shift; my %doxyfile = (); open DOXYFILE, $doxyname || die "Could not open $doxyname\n"; while () { chomp; next if (/^\s*\#/); my $input =$_; my $tag; if ($input=~/^\s*(\S+)\s*=/) { $tag = $1; $doxyfile{$tag} = ""; while ($input=~/\\\s*$/) { $input =~ s/\\\s*$//; $doxyfile{$tag} = $doxyfile{$tag}.$input; $input = DOXYFILE->getline(); }; $input =~ s/\\\s*$//; $doxyfile{$tag} = $doxyfile{$tag}.$input; $doxyfile{$tag} =~ s/\s+/ /g; $doxyfile{$tag} =~ s/^\s*$tag\s*=\s*//; } } close DOXYFILE; return %doxyfile; } # WRITE DEPFILE my %doxyfile = parseDoxyfile($doxyname); open DEPFILE, ">$depfile" || die "Could not open $depfile\n"; # foreach input defined in INPUT = ... foreach my $input (split(/ /, $doxyfile{"INPUT"})) { next if (! defined($input)); next if ( $input eq "" ); if ( -f $input ) { addDep($input); } else { # foreach pattern defined in FILE_PATTERNS = ... foreach my $pattern (split(/ /, $doxyfile{"FILE_PATTERNS"})) { next if (! defined($pattern)); next if ( $pattern eq "" ); my @files = findFiles($input, $pattern, $doxyfile{"RECURSIVE"}); foreach my $f (@files) { addDep($f); } } } } addDep($doxyfile{"HTML_HEADER"}); addDep($doxyfile{"HTML_FOOTER"}); addDep($doxyfile{"LATEX_HEADER"}); close DEPFILE; dune-grid-2.11.0/doc/doxygen/Doxylocal000066400000000000000000000047371511655130300175670ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INPUT += @srcdir@/mainpage.txt \ @srcdir@/modules.txt \ @top_srcdir@/doc/recipes \ @top_srcdir@/doc/recipes/mainpage.txt \ @top_srcdir@/dune/grid/modules.txt \ @top_srcdir@/dune/grid/albertagrid \ @top_srcdir@/dune/grid/albertagrid.hh \ @top_srcdir@/dune/grid/common \ @top_srcdir@/dune/grid/concepts \ @top_srcdir@/dune/grid/geometrygrid.hh \ @top_srcdir@/dune/grid/geometrygrid \ @top_srcdir@/dune/grid/identitygrid.hh \ @top_srcdir@/dune/grid/identitygrid \ @top_srcdir@/dune/grid/io \ @top_srcdir@/dune/grid/onedgrid.hh \ @top_srcdir@/dune/grid/uggrid.hh \ @top_srcdir@/dune/grid/uggrid/uggridfactory.hh \ @top_srcdir@/dune/grid/utility \ @top_srcdir@/dune/grid/yaspgrid.hh \ @top_srcdir@/dune/grid/yaspgrid # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH += @top_srcdir@/doc/grids/dgf EXAMPLE_PATH += @top_srcdir@/doc/recipes # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS += *.dgf # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH += \ @top_srcdir@/dune/grid/yaspgrid \ @top_srcdir@/dune/grid/common \ @top_srcdir@/dune/grid/io/file/dgfparser/test \ @top_srcdir@/dune/grid/geometrygrid PREDEFINED += \ HAVE_ALBERTA:=1 \ HAVE_DUNE_UGGRID:=1 #EXCLUDE += dune-grid-2.11.0/doc/doxygen/mainpage.txt000066400000000000000000000012161511655130300202150ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /** \mainpage dune-grid 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. You can find a collection of brief examples in @ref grid_recipes. */ /** \page modules Modules */ dune-grid-2.11.0/doc/doxygen/modules.txt000066400000000000000000000003201511655130300200770ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /** @defgroup Grid dune-grid */ dune-grid-2.11.0/doc/grids/000077500000000000000000000000001511655130300153265ustar00rootroot00000000000000dune-grid-2.11.0/doc/grids/CMakeLists.txt000066400000000000000000000004471511655130300200730ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(amc) add_subdirectory(gridfactory) add_subdirectory(gmsh) add_subdirectory(starcd) add_subdirectory(dgf) dune-grid-2.11.0/doc/grids/amc/000077500000000000000000000000001511655130300160665ustar00rootroot00000000000000dune-grid-2.11.0/doc/grids/amc/CMakeLists.txt000066400000000000000000000006131511655130300206260ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(GRIDS grid-1-1.amc grid-1-2.amc grid-2-2.amc grid-1-3.amc grid-2-3.amc grid-3-3.amc grid-2-4.amc macro.amc periodic-torus.amc) install(FILES ${GRIDS} DESTINATION ${CMAKE_INSTALL_DOCDIR}/grids/amc) dune-grid-2.11.0/doc/grids/amc/grid-1-1.amc000066400000000000000000000005101511655130300177650ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 1 DIM_OF_WORLD: 1 number of elements: 1 number of vertices: 2 element vertices: 0 1 element boundaries: 1 1 vertex coordinates: 0.0 1.0 dune-grid-2.11.0/doc/grids/amc/grid-1-2.amc000066400000000000000000000005201511655130300177670ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 1 DIM_OF_WORLD: 2 number of elements: 1 number of vertices: 2 element vertices: 0 1 element boundaries: 1 1 vertex coordinates: 0.0 0.0 1.0 1.0 dune-grid-2.11.0/doc/grids/amc/grid-1-3.amc000066400000000000000000000005321511655130300177730ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 1 DIM_OF_WORLD: 3 number of elements: 1 number of vertices: 2 element vertices: 0 1 element boundaries: 1 1 vertex coordinates: 0.0 0.0 0.0 1.0 1.0 1.0 dune-grid-2.11.0/doc/grids/amc/grid-2-2.amc000066400000000000000000000007211511655130300177730ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 2 DIM_OF_WORLD: 2 number of elements: 4 number of vertices: 5 element vertices: 0 1 4 1 2 4 2 3 4 3 0 4 element boundaries: 0 0 1 0 0 1 0 0 1 0 0 1 vertex coordinates: 0.0 0.0 1.0 0.0 1.0 1.0 0.0 1.0 0.5 0.5 element neighbours: 1 3 -1 2 0 -1 3 1 -1 0 2 -1 dune-grid-2.11.0/doc/grids/amc/grid-2-3.amc000066400000000000000000000010251511655130300177720ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 2 DIM_OF_WORLD: 3 number of vertices: 3 number of elements: 1 vertex coordinates: 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 5.0000000000e-01 element vertices: 0 1 2 element boundaries: 1 1 1 element neighbours: -1 -1 -1 dune-grid-2.11.0/doc/grids/amc/grid-2-4.amc000066400000000000000000000011131511655130300177710ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 2 DIM_OF_WORLD: 4 number of vertices: 3 number of elements: 1 vertex coordinates: 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 5.0000000000e-01 0.0000000000e+00 element vertices: 0 1 2 element boundaries: 1 1 1 element neighbours: -1 -1 -1 dune-grid-2.11.0/doc/grids/amc/grid-3-3.amc000066400000000000000000000014441511655130300200000ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 3 DIM_OF_WORLD: 3 number of vertices: 8 number of elements: 6 vertex coordinates: 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 1.0 0.0 1.0 0.0 0.0 1.0 1.0 element vertices: 0 5 4 1 0 5 3 1 0 5 3 2 0 5 4 6 0 5 7 6 0 5 7 2 element boundaries: 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 element neighbours: -1 -1 1 3 -1 -1 0 2 -1 -1 5 1 -1 -1 4 0 -1 -1 3 5 -1 -1 2 4 dune-grid-2.11.0/doc/grids/amc/macro.amc000066400000000000000000000007211511655130300176510ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DIM: 2 DIM_OF_WORLD: 2 number of elements: 4 number of vertices: 5 element vertices: 0 1 4 1 2 4 2 3 4 3 0 4 element boundaries: 0 0 1 0 0 1 0 0 1 0 0 1 vertex coordinates: 0.0 0.0 1.0 0.0 1.0 1.0 0.0 1.0 0.5 0.5 element neighbours: 1 3 -1 2 0 -1 3 1 -1 0 2 -1 dune-grid-2.11.0/doc/grids/amc/periodic-torus.amc000066400000000000000000000052141511655130300215220ustar00rootroot00000000000000# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # Example macro triangulation for a mesh with periodic boundaries: a # topological torus. DIM: 2 DIM_OF_WORLD: 2 number of elements: 8 number of vertices: 9 element vertices: 4 0 1 2 4 1 4 2 5 8 4 5 4 8 7 6 4 7 4 6 3 0 4 3 vertex coordinates: -1.0 -1.0 0.0 -1.0 1.0 -1.0 -1.0 0.0 0.0 0.0 1.0 0.0 -1.0 1.0 0.0 1.0 1.0 1.0 # Neighbours need not be specified, but if so, then the neighbourhood # information should treat periodic faces as interior faces. We leave # the neighbourhood information commented out such that it can be # determined by the geometric face transformations. # example for a torus: # element neighbours: # 5 1 7 # 0 4 2 # 7 3 1 # 2 6 4 # 1 5 3 # 4 0 6 # 3 7 5 # 6 2 0 # In principle it is possible to specify boundary types for periodic # faces; those are ignored during "normal" operation, but can be # accessed by using the special fill-flag FILL_NON_PERIODIC during # mesh-traversal. This is primarily meant for defining parametric # periodic meshes: the finite element function defining the mesh # geometry is -- of course -- not periodic. element boundaries: 2 0 0 0 2 0 1 0 0 0 1 0 2 0 0 0 2 0 1 0 0 0 1 0 # Geometric face transformations. It is also possible to specify those # in the application program. # number of wall transformations: 2 wall transformations: # generator #1 1 0 2 0 1 0 0 0 1 # generator #2 1 0 0 0 1 2 0 0 1 # For each face of the triangulation the number of the face # transformation attached to it. Counting starts at 1, negative # numbers mean the inverse. Expected is the face transformation which # maps the macro triangulation to its neighbour across the respective # face. It is possible to omit this section in which case the # per-element face transformations are computed. # #element wall transformations: # -2 0 0 # 0 -2 0 # 1 0 0 # 0 1 0 # 2 0 0 # 0 2 0 # -1 0 0 # 0 -1 0 # Combinatorial face transformations. These, too, can be omitted. # # You will observe that there are "duplicate lines" below. Indeed, but # this does not matter: you really have to group the vertex-mappings # in pairs, the first two lines mean: # # "map the face defined by vertex 0 and 1 to the face defined by # vertex 6 and 7, in that orientation". # #number of wall vertex transformations: 4 #wall vertex transformations: # 0 6 # 1 7 # 1 7 # 2 8 # 0 2 # 3 5 # 3 5 # 6 8 # (X)Emacs stuff (for editing purposes) # Local Variables: *** # comment-start: "# " *** # End: *** dune-grid-2.11.0/doc/grids/dgf/000077500000000000000000000000001511655130300160665ustar00rootroot00000000000000dune-grid-2.11.0/doc/grids/dgf/CMakeLists.txt000066400000000000000000000021721511655130300206300ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(GRIDS basicunitcube-2d.dgf cube-2.dgf cube_grid.dgf cube-testgrid-2-2.dgf cube-testgrid-2-3.dgf distorted-cube-3.dgf examplegrid10a.dgf examplegrid10b.dgf examplegrid10.dgf examplegrid11.dgf examplegrid12.dgf examplegrid1c.dgf examplegrid1gen.dgf examplegrid1s.dgf examplegrid2a.dgf examplegrid2b.dgf examplegrid2c.dgf examplegrid2d.dgf examplegrid2e.dgf examplegrid5.dgf examplegrid6.dgf examplegrid7.dgf examplegrid9.dgf example-projection.dgf grid2Y.dgf grid3A.dgf grid3Y.dgf helix.dgf octahedron.dgf simplex-testgrid-1-1.dgf simplex-testgrid-1-2.dgf simplex-testgrid-2-2.dgf simplex-testgrid-1-3.dgf simplex-testgrid-2-3.dgf simplex-testgrid-3-3.dgf simplex-testgrid-3-3-large.dgf test1d.dgf test1d-vertex.dgf test2d.dgf test2d_offset.dgf test2ug.dgf test3d.dgf torus-2.dgf torus-3.dgf unstr_cube.dgf) install(FILES ${GRIDS} DESTINATION ${CMAKE_INSTALL_DOCDIR}/grids/dgf) dune-grid-2.11.0/doc/grids/dgf/basicunitcube-2d.dgf000066400000000000000000000005271511655130300216770ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX 1 -1 -1 -1 1 1 -1 1 # SIMPLEX 0 1 2 2 1 3 # GRIDPARAMETER NAME BasicUnitCube REFINEMENTEDGE ARBITRARY DUMPFILENAME basicunitcube-2d.dgf.native # dune-grid-2.11.0/doc/grids/dgf/cube-2.dgf000066400000000000000000000003751511655130300176320ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 1 1 2 2 # GridParameter refinementedge arbitrary overlap 1 # dune-grid-2.11.0/doc/grids/dgf/cube-testgrid-2-2.dgf000066400000000000000000000004751511655130300216150ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX 0 0 0.5 0 1 0 0 0.5 0.3 0.6 1 0.5 0 1 0.5 1 1 1.2 # CUBE 0 1 3 4 1 2 4 5 3 4 6 7 5 4 8 7 # dune-grid-2.11.0/doc/grids/dgf/cube-testgrid-2-3.dgf000066400000000000000000000005121511655130300216060ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX 0 0 0 0.5 0 0 1 0 0 0 0.5 0 0.5 0.5 0.5 1 0.5 0 0 1 0 0.5 1 0 1 1 0 # CUBE 0 1 3 4 1 2 4 5 3 4 6 7 5 4 8 7 # dune-grid-2.11.0/doc/grids/dgf/cube_grid.dgf000066400000000000000000000017371511655130300205030ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception vertex 0 0 0 % vertex 0 38 0 0 % vertex 1 0 51.75 0 % vertex 2 38 51.75 0 % vertex 3 69 138 0 % vertex 4 69 100 0 % vertex 5 138 51.75 0 % vertex 6 100 51.75 0 % vertex 7 138 0 0 % vertex 8 100 0 0 % vertex 9 0 0 38 % vertex 10 38 0 38 % vertex 11 0 51.75 38 % vertex 12 38 51.75 38 % vertex 13 69 138 38 % vertex 14 69 100 38 % vertex 15 138 51.75 38 % vertex 16 100 51.75 38 % vertex 17 138 0 38 % vertex 18 100 0 38 % vertex 19 # Cube 0 1 2 3 10 11 12 13 2 3 4 5 12 13 14 15 4 5 6 7 14 15 16 17 6 7 8 9 16 17 18 19 # boundarysegments 2 0 2 10 12 3 1 3 11 13 4 0 1 10 11 4 0 1 2 3 4 10 11 12 13 2 2 4 12 14 3 3 5 13 15 4 2 3 4 5 4 12 13 14 15 2 4 6 14 16 3 5 7 15 17 4 4 5 6 7 4 14 15 16 17 2 6 8 16 18 3 7 9 17 19 4 8 9 18 19 4 6 7 8 9 4 16 17 18 19 # dune-grid-2.11.0/doc/grids/dgf/distorted-cube-3.dgf000066400000000000000000000005571511655130300216340ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception vertex firstindex 0 0 0 0 # 0 1 0 0 # 1 0 1 0 # 2 1.1 1.1 0 # 3 0 0 1 # 4 1 0 1 # 5 0 1 1 # 6 1 1 1 # 7 # cube 0 1 2 3 4 5 6 7 # # dune-grid-2.11.0/doc/grids/dgf/example-projection.dgf000066400000000000000000000005301511655130300223530ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX -1 -1 1 -1 -1 1 1 1 # CUBE 0 1 2 3 # PROJECTION function p(x) = sqrt(2) * x / |x| function id(x) = x segment 0 1 id default p # # example-projection.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid10.dgf000066400000000000000000000021601511655130300212110ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception vertex firstindex 1 0 0 5 # 1 0 0 0 # 2 0 -10 0 # 3 0 -10 10 # 4 0 10 10 # 5 0 10 5 # 6 30 10 0 # 7 30 -10 0 # 8 30 -10 10 # 9 30 10 10 # 10 25 10 0 # 11 25 0 0 # 12 25 0 5 # 13 25 10 5 # 14 0 0 10 # 15 30 0 0 # 16 30 0 5 # 17 30 0 10 # 18 30 10 5 # 19 30 -10 5 # 20 25 10 10 # 21 25 0 10 # 22 25 -10 10 # 23 25 -10 5 # 24 25 -10 0 # 25 0 -10 5 # 26 # Cube map 0 1 3 2 4 5 7 6 21 14 13 22 5 6 1 15 23 22 13 24 4 15 1 26 25 24 13 12 3 26 1 2 17 19 7 16 13 14 11 12 17 16 8 20 13 12 25 24 17 20 9 18 13 24 23 22 17 18 10 19 13 22 21 14 # boundarysegments 2 1 2 3 26 2 26 4 15 1 2 1 15 5 6 1 7 16 17 19 1 19 17 18 10 1 8 16 17 20 1 20 17 18 9 4 21 10 19 14 4 11 7 19 14 4 5 6 14 21 4 15 5 22 21 4 4 15 22 23 4 23 9 18 22 4 22 18 10 21 # boundarydomain default 3 # # examplegrid10.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid10a.dgf000066400000000000000000000022351511655130300213550ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception vertex firstindex 1 0 0 5 # 1 0 0 0 # 2 0 -10 0 # 3 0 -10 10 # 4 0 10 10 # 5 0 10 5 # 6 30 10 0 # 7 30 -10 0 # 8 30 -10 10 # 9 30 10 10 # 10 25 10 0 # 11 25 0 0 # 12 25 0 5 # 13 25 10 5 # 14 0 0 10 # 15 30 0 0 # 16 30 0 5 # 17 30 0 10 # 18 30 10 5 # 19 30 -10 5 # 20 25 10 10 # 21 25 0 10 # 22 25 -10 10 # 23 25 -10 5 # 24 25 -10 0 # 25 0 -10 5 # 26 # Cube map 0 1 3 2 4 5 7 6 parameters 2 21 14 13 22 5 6 1 15 0 1 23 22 13 24 4 15 1 26 1 -1 25 24 13 12 3 26 1 2 2 1 17 19 7 16 13 14 11 12 3 -1 17 16 8 20 13 12 25 24 4 1 17 20 9 18 13 24 23 22 5 -1 17 18 10 19 13 22 21 14 6 1 # boundarysegments 2 1 2 3 26 2 26 4 15 1 2 1 15 5 6 1 7 16 17 19 1 19 17 18 10 1 8 16 17 20 1 20 17 18 9 4 21 10 19 14 4 11 7 19 14 4 5 6 14 21 4 15 5 22 21 4 4 15 22 23 4 23 9 18 22 4 22 18 10 21 # boundarydomain default 3 # # examplegrid10a.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid10b.dgf000066400000000000000000000023221511655130300213530ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception vertex parameters 1 firstindex 1 0 0 5 5 # 1 0 0 0 0 # 2 0 -10 0 -10 # 3 0 -10 10 0 # 4 0 10 10 20 # 5 0 10 5 15 # 6 30 10 0 40 # 7 30 -10 0 20 # 8 30 -10 10 30 # 9 30 10 10 50 # 10 25 10 0 35 # 11 25 0 0 25 # 12 25 0 5 30 # 13 25 10 5 40 # 14 0 0 10 10 # 15 30 0 0 30 # 16 30 0 5 35 # 17 30 0 10 40 # 18 30 10 5 45 # 19 30 -10 5 25 # 20 25 10 10 45 # 21 25 0 10 35 # 22 25 -10 10 25 # 23 25 -10 5 20 # 24 25 -10 0 15 # 25 0 -10 5 -5 # 26 # Cube map 0 1 3 2 4 5 7 6 21 14 13 22 5 6 1 15 23 22 13 24 4 15 1 26 25 24 13 12 3 26 1 2 17 19 7 16 13 14 11 12 17 16 8 20 13 12 25 24 17 20 9 18 13 24 23 22 17 18 10 19 13 22 21 14 # boundarysegments 2 1 2 3 26 2 26 4 15 1 2 1 15 5 6 1 7 16 17 19 1 19 17 18 10 1 8 16 17 20 1 20 17 18 9 4 21 10 19 14 4 11 7 19 14 4 5 6 14 21 4 15 5 22 21 4 4 15 22 23 4 23 9 18 22 4 22 18 10 21 # boundarydomain default 3 # # examplegrid10b.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid11.dgf000066400000000000000000000013031511655130300212100ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval % first interval 0 0 5 % first corner 25 10 10 % second corner 5 1 2 % 8 cells in x, 2 in y, and 2 in z direction % second interval 25 -10 0 % first corner 30 10 10 % second corner 3 2 4 % 2 cells in x, 2 in y, and 4 in z direction % third interval 0 -0 0 % first corner 25 -10 10 % second corner 5 1 4 % 2 cells in x, 2 in y, and 4 in z direction # BOUNDARYDOMAIN default 3 % default boundary id % ... further domain ... # # examplegrid11.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid12.dgf000066400000000000000000000016411511655130300212160ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Simplexgenerator min-angle 1.1 % quality enhancement max-area 0.5 % maximum element area restriction display 0 % show result using the Tetgen viewer % to use TetGen from a certain path, uncomment this path line % path $HOME/bin % path to Tetgen # vertex 0 0 5 0 0 0 0 -10 0 0 -10 10 0 10 10 0 10 5 30 10 0 30 -10 0 30 -10 10 30 10 10 25 10 0 25 0 0 25 0 5 25 10 5 # boundarysegments % 2 out, 1 in, 3 slip, 4 reflect 2 0 1 2 3 4 5 % ausgang 1 6 7 8 9 % eingang 3 10 11 12 13 % balken 3 11 12 0 1 % balken 3 13 12 0 5 % balken 3 3 4 9 8 % seite 3 2 3 8 7 % unten 4 6 10 13 5 4 9 % sym. oben 4 6 10 11 1 2 7 % sym. seite # # examplegrid12.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid1c.dgf000066400000000000000000000013711511655130300212770ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex % the vertices of the grid -1 -1 % vertex 0 -0.2 -1 % vertex 1 1 -1 % vertex 2 1 -0.6 % vertex 3 1 1 % vertex 4 -1 1 % vertex 5 0.2 -0.2 % vertex 6 # CUBE % a cube grid 0 1 5 6 % cube 0, vertices 0,1,5,6 1 2 6 3 % cube 1 6 3 5 4 % cube 2 # BOUNDARYSEGMENTS 2 1 2 % between vertex 1,2 use id 2 2 2 3 % between vertex 2,3 use id 2 4 3 4 % between vertex 3,4 use id 4 # BOUNDARYDOMAIN default 1 % all other boundary segments have id 1 # # examplegrid1c.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid1gen.dgf000066400000000000000000000011701511655130300216230ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Simplexgenerator min-angle 30 display 0 % to use Triangle from a certain path, uncomment this path line %path $HOME/bin % path to Triangle # Vertex % the vertices of the grid -1 -1 % vertex 0 -0.2 -1 % vertex 1 1 -1 % vertex 2 1 -0.6 % vertex 3 1 1 % vertex 4 -1 1 % vertex 5 0.2 -0.2 % vertex 6 # BOUNDARYDOMAIN default 1 % all other boundary segments have id 1 # # examplegrid1gen.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid1s.dgf000066400000000000000000000015171511655130300213210ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex % the vertices of the grid -1 -1 % vertex 0 -0.2 -1 % vertex 1 1 -1 % vertex 2 1 -0.6 % vertex 3 1 1 % vertex 4 -1 1 % vertex 5 0.2 -0.2 % vertex 6 # SIMPLEX % a simplex grid 0 1 5 % triangle 0, vertices 0,1,5 1 3 6 % triangle 1 1 2 3 % triangle 2 6 3 4 % triangle 3 6 4 5 % triangle 4 6 5 1 % triangle 5 # BOUNDARYSEGMENTS 2 1 2 % between vertex 1,2 use id 2 2 2 3 % between vertex 2,3 use id 2 4 3 4 % between vertex 3,4 use id 4 # BOUNDARYDOMAIN default 1 % all other boundary segments have id 1 # # examplegrid1s.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid2a.dgf000066400000000000000000000013121511655130300212710ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval -1 -1 % first corner 1 1 % second corner 4 4 % 4 cells in x and 4 in y direction # Vertex % some additional points 0.75 0.75 % inside the interval 0.9 0.9 % also inside the interval 1.25 1.25 % and one outside of the interval # Simplexgenerator display 0 % show result using Triangle viewer % to use Triangle from a certain path, uncomment path line %path $HOME/bin % path to Triangle # BOUNDARYDOMAIN default 1 % all boundaries have id 1 #BOUNDARYDOMAIN # examplegrid2a.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid2b.dgf000066400000000000000000000016601511655130300213000ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval -1 -1 % first corner 1 1 % second corner 4 4 % 4 cells in x and 4 in y direction # Vertex % some additional points 0.75 0.75 % inside the interval 0.9 0.9 % also inside the interval 1.25 1.25 % and one outside of the interval # Simplexgenerator min-angle 30 % quality enhancement display 0 % show result using Triangle viewer % area restriction % to use Triangle from a certain path, uncomment this path line %path $HOME/bin % path to Triangle # BOUNDARYDOMAIN 1 1 -1 1.25 1.25 % right boundary has id 1 2 -1 1 1.25 1.25 % upper boundary has id 2 3 -1 -1 -1 1 % left boundary has id 3 4 -1 -1 1 -1 % lower boundary has id 4 #BOUNDARYDOMAIN # examplegrid2b.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid2c.dgf000066400000000000000000000015641511655130300213040ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval -1 -1 % first corner 1 1 % second corner 4 4 % 4 cells in x and 4 in y direction # Vertex % some additional points 0.75 0.75 % inside the interval 0.9 0.9 % also inside the interval 1.25 1.25 % and one outside of the interval # Simplexgenerator min-angle 30 % quality enhancement max-area 0.01 % area restriction display 0 % show result using Triangle viewer % to use Triangle from a certain path, uncomment this path line %path $HOME/bin % path to Triangle # BOUNDARYDOMAIN 1 -1 -1 1 -1 % lower boundary has id 1 2 -10 -10 10 10 % all others have id 2 (could use default keyword...) #BOUNDARYDOMAIN # examplegrid2c.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid2d.dgf000066400000000000000000000012371511655130300213020ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex % some additional points -1 -1 1 -1 1 1 -1 1 0.75 0.75 % inside the interval 0.9 0.9 % also inside the interval 1.25 1.25 % and one outside of the interval # Simplexgenerator min-angle 30 % quality enhancement max-area 0.01 % area restriction display 0 % show result using Triangle viewer % to use Triangle from a certain path, uncomment this path line %path $HOME/bin % path to Triangle # BOUNDARYSEGMENTS 1 0 1 2 1 6 3 0 # # examplegrid2d.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid2e.dgf000066400000000000000000000017221511655130300213020ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception vertex parameters 2 -1 -1 0 -1 1 -1 1 1 1 1 2 1 -1 1 1 -1 0.75 0.75 2 0.75 0.90000000000000002 0.90000000000000002 2 0.90000000000000002 1.25 1.25 -1 1.25 # simplex parameters 1 0 4 3 1 4 0 1 -1 3 4 5 1 5 1 2 1 1 5 4 -1 2 6 3 1 6 2 1 -1 5 2 3 -1 # boundarydomain default 1 # Simplexgenerator min-angle 30 % quality enhancement max-area 0.01 % area restriction display 0 % show result using Triangle viewer % to use Triangle from a certain path, uncomment this path line % path $HOME/bin % path to Triangle # # examplegrid2e.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid5.dgf000066400000000000000000000011461511655130300211400ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 % first corner 1 1 % second corner 4 8 % 4 cells in x and 8 in y direction # Simplex # GridParameter % set overlap to 1 overlap 1 % set closure to none for UGGrid closure none % generate copies in UGGrid copies yes # PERIODICFACETRANSFORMATION % set periodic boundaries in x direction % 1 0, 0 1 + 1 0 # BOUNDARYDOMAIN default 1 % default boundary id #BOUNDARYDOMAIN # examplegrid5.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid6.dgf000066400000000000000000000010251511655130300211350ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 0 % first corner 10 10 10 % second corner 4 4 3 % 5 cells in x, 2 in y, and 10 in z direction # simplex # BOUNDARYDOMAIN default 1 % default boundary id % all boundary segments in the interval [(-1,-1,-1),(11,11,0)] % have boundary id 2, i.e., the bottom boundary 2 -1 -1 -1 11 11 0 # # examplegrid6.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid7.dgf000066400000000000000000000015071511655130300211430ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Simplexgenerator %min-angle 1.1 % quality enhancement %max-area 0.1 % maximum element area restriction display 0 % show result using the Tetgen viewer % to use TetGen from a certain path, uncomment this path line %path $HOME/bin % path to Tetgen # Interval 0 0 0 % first corner 10 10 10 % second corner 2 5 10 % 5 cells in x, 2 in y, and 10 in z direction # BOUNDARYDOMAIN default 1 % default boundary id % all boundary segments in the interval [(-1,-1,-1),(11,11,0)] % have boundary id 2, i.e., the bottom boundary 2 -1 -1 -1 11 11 0 # # examplegrid7.dgf dune-grid-2.11.0/doc/grids/dgf/examplegrid9.dgf000066400000000000000000000010721511655130300211420ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Simplexgenerator % to use TetGen from a certain path, uncomment this path line % path $HOME/dune/modules/tetgen1.4.0 % path to Tetgen % read information from file (uncomment each line separately) % file BBEETH1M.d_cut mesh % file Orb_cut mesh % file bunny.p65.param_skin mesh % file pmdc.1 % all grids are for dimension 3 dimension 3 # BOUNDARYDOMAIN default 1 # # examplegrid9.dgf dune-grid-2.11.0/doc/grids/dgf/grid2Y.dgf000066400000000000000000000010521511655130300177060ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 % first corner 0.8 6.1 % second corner 10 127 % 4 cells in x and 8 in y direction # % Simplex # GridParameter % set overlap to 1 overlap 1 % set periodic boundaries in x direction periodic 0 % set closure to none for UGGrid closure none # BOUNDARYDOMAIN default 1 % default boundary id #BOUNDARYDOMAIN # examplegrid5.dgf dune-grid-2.11.0/doc/grids/dgf/grid3A.dgf000066400000000000000000000016351511655130300176660ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Simplexgenerator min-angle 1.1 % quality enhancement max-area 0.5 % maximum element area restriction display 0 % show result using the Tetgen viewer % to use TetGen from a certain path, uncomment this path line path $HOME/bin % path to Tetgen # vertex 0 0 5 0 0 0 0 -10 0 0 -10 10 0 10 10 0 10 5 30 10 0 30 -10 0 30 -10 10 30 10 10 25 10 0 25 0 0 25 0 5 25 10 5 # boundarysegments % 2 out, 1 in, 3 slip, 4 reflect 2 0 1 2 3 4 5 % ausgang 1 6 7 8 9 % eingang 3 10 11 12 13 % balken 3 11 12 0 1 % balken 3 13 12 0 5 % balken 3 3 4 9 8 % seite 3 2 3 8 7 % unten 4 6 10 13 5 4 9 % sym. oben 4 6 10 11 1 2 7 % sym. seite # # examplegrid12.dgf dune-grid-2.11.0/doc/grids/dgf/grid3Y.dgf000066400000000000000000000010251511655130300177070ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 0 % first corner 10 10 10 % second corner 4 4 3 % 5 cells in x, 2 in y, and 10 in z direction # simplex # BOUNDARYDOMAIN default 1 % default boundary id % all boundary segments in the interval [(-1,-1,-1),(11,11,0)] % have boundary id 2, i.e., the bottom boundary 2 -1 -1 -1 11 11 0 # # examplegrid6.dgf dune-grid-2.11.0/doc/grids/dgf/helix-deprecated.dgf000066400000000000000000000007641511655130300217660ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INTERVAL 0 0 1 1 10 10 # INTERVAL PROJECTION function angle( x ) = 2 * pi * x[ 1 ] function coordfunction( x ) = (x[ 0 ] + 0.2) * (cos angle( x ) * [1 0 0] + sin angle( x ) * [0 1 0]) + x[ 1 ] * [0 0 1] # PROJECTION GRIDPARAMETER name Helix refinementedge arbitrary overlap 1 # GRIDPARAMETER # DGF dune-grid-2.11.0/doc/grids/dgf/helix.dgf000066400000000000000000000007441511655130300176660ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INTERVAL 0 0 1 1 10 10 # INTERVAL PROJECTION function angle( x ) = 2 * pi * x[ 1 ] function coordfunction( x ) = (x[ 0 ] + 0.2) * [ cos angle( x ), sin angle( x ), 0 ] + [ 0, 0, x[ 1 ] ] # PROJECTION GRIDPARAMETER name Helix refinementedge arbitrary overlap 1 # GRIDPARAMETER # DGF dune-grid-2.11.0/doc/grids/dgf/octahedron.dgf000066400000000000000000000007031511655130300206760ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception % This DGF files models the unit octahedron. % Note that this octahedron is borderless, so boundary ids do not make sense. VERTEX 1 0 0 0 1 0 -1 0 0 0 -1 0 0 0 1 0 0 -1 # SIMPLEX 0 3 4 0 1 4 1 2 4 2 3 4 0 3 5 0 1 5 1 2 5 2 3 5 # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-1-1.dgf000066400000000000000000000004101511655130300223430ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex 0.0 0.25 0.5 0.75 1.0 # Simplex 0 1 1 2 2 3 3 4 # BoundaryDomain default 1 # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-1-2.dgf000066400000000000000000000004461511655130300223550ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex 0.0 0.0 0.25 0.25 0.5 0.5 0.75 0.75 1.0 1.0 # Simplex 0 1 1 2 2 3 3 4 # BoundaryDomain default 1 # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-1-3.dgf000066400000000000000000000005041511655130300223510ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex 0.0 0.0 0.0 0.25 0.25 0.25 0.5 0.5 0.5 0.75 0.75 0.75 1.0 1.0 1.0 # Simplex 0 1 1 2 2 3 3 4 # BoundaryDomain default 1 # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-2-2.dgf000066400000000000000000000056301511655130300223560ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX 0.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 1.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 3.4999999999999998e-01 7.5000000000000000e-01 2.9999999999999999e-01 8.3599999999999997e-01 2.0000000000000001e-01 8.3599999999999997e-01 1.4999999999999999e-01 7.5000000000000000e-01 2.0000000000000001e-01 6.6300000000000003e-01 2.9999999999999999e-01 6.6300000000000003e-01 6.9999999999999996e-01 4.0000000000000002e-01 6.5000000000000002e-01 4.8599999999999999e-01 5.5000000000000004e-01 4.8599999999999999e-01 5.0000000000000000e-01 4.0000000000000002e-01 5.5000000000000004e-01 3.1300000000000000e-01 6.5000000000000002e-01 3.1300000000000000e-01 5.0000000000000000e-01 1.0000000000000000e+00 0.0000000000000000e+00 5.0000000000000000e-01 0.0000000000000000e+00 7.5000000000000000e-01 2.5000000000000000e-01 4.8572758664047833e-01 4.6250549019607845e-01 6.2747385620915030e-01 2.5000000000000000e-01 1.0000000000000000e+00 1.0000000000000000e+00 5.0000000000000000e-01 5.0000000000000000e-01 0.0000000000000000e+00 4.4519685039370083e-01 8.6288188976377955e-01 0.0000000000000000e+00 6.2500000000000000e-01 0.0000000000000000e+00 8.7500000000000000e-01 3.7077300037721606e-01 2.6786379332023907e-01 4.2054389993566155e-01 5.0373029073508058e-01 6.0000000000000009e-01 6.1471492017248219e-01 8.2922699962278390e-01 2.6786379332023924e-01 8.2354545454545458e-01 5.2936363636363626e-01 7.5000000000000000e-01 0.0000000000000000e+00 9.6677461139896378e-02 6.6148704663212432e-01 1.4993557735568527e-01 5.5319173918565745e-01 0.0000000000000000e+00 2.5000000000000000e-01 9.6690600522193221e-02 8.3852872062663186e-01 1.2500000000000000e-01 1.0000000000000000e+00 5.4337802736196594e-01 7.5176043560429240e-01 1.0000000000000000e+00 7.5000000000000000e-01 6.0000000000000009e-01 1.4451916932907344e-01 1.1972352813036717e-01 4.0043948257617168e-01 7.7174689682639375e-01 7.6589395416120554e-01 # SIMPLEX 27 0 23 33 7 18 11 29 12 9 8 19 19 28 9 19 34 41 6 5 21 6 36 7 24 16 21 5 24 21 25 33 18 21 37 6 28 12 20 20 38 4 36 37 26 13 28 27 14 27 40 40 27 23 15 40 30 7 33 8 24 4 38 20 29 38 10 30 31 42 31 39 5 4 24 4 9 20 14 13 27 13 12 28 29 20 12 15 30 10 34 19 8 8 33 34 3 26 37 36 18 7 41 34 17 40 23 32 20 9 28 28 19 27 10 31 11 29 31 42 30 1 22 31 30 22 38 29 42 11 31 29 32 1 30 15 14 40 17 34 25 33 25 34 41 17 35 35 0 27 19 41 27 26 18 36 22 39 31 36 6 37 24 38 16 39 2 42 38 42 16 40 32 30 41 35 27 2 42 16 # BOUNDARYSEGMENTS 1 0 23 1 11 12 1 9 8 1 6 5 1 6 7 1 16 21 1 25 18 1 21 37 1 7 8 1 5 4 1 4 9 1 14 13 1 13 12 1 15 10 1 3 37 1 3 26 1 23 32 1 10 11 1 1 22 1 32 1 1 15 14 1 17 25 1 17 35 1 35 0 1 26 18 1 22 39 1 39 2 1 2 16 # # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-2-3.dgf000066400000000000000000000714521511655130300223640ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX 1.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 0.0000000000000000e+00 -1.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -1.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 -1.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 1.0000000000000000e+00 9.7492800000000002e-01 2.2252100000000000e-01 0.0000000000000000e+00 9.0096900000000002e-01 4.3388399999999999e-01 0.0000000000000000e+00 7.8183100000000005e-01 6.2348999999999999e-01 0.0000000000000000e+00 6.2348999999999999e-01 7.8183100000000005e-01 0.0000000000000000e+00 4.3388399999999999e-01 9.0096900000000002e-01 0.0000000000000000e+00 2.2252100000000000e-01 9.7492800000000002e-01 0.0000000000000000e+00 -2.2252100000000000e-01 9.7492800000000002e-01 0.0000000000000000e+00 -4.3388399999999999e-01 9.0096900000000002e-01 0.0000000000000000e+00 -6.2348999999999999e-01 7.8183100000000005e-01 0.0000000000000000e+00 -7.8183100000000005e-01 6.2348999999999999e-01 0.0000000000000000e+00 -9.0096900000000002e-01 4.3388399999999999e-01 0.0000000000000000e+00 -9.7492800000000002e-01 2.2252100000000000e-01 0.0000000000000000e+00 -9.7492800000000002e-01 -2.2252100000000000e-01 0.0000000000000000e+00 -9.0096900000000002e-01 -4.3388399999999999e-01 0.0000000000000000e+00 -7.8183100000000005e-01 -6.2348999999999999e-01 0.0000000000000000e+00 -6.2348999999999999e-01 -7.8183100000000005e-01 0.0000000000000000e+00 -4.3388399999999999e-01 -9.0096900000000002e-01 0.0000000000000000e+00 -2.2252100000000000e-01 -9.7492800000000002e-01 0.0000000000000000e+00 2.2252100000000000e-01 -9.7492800000000002e-01 0.0000000000000000e+00 4.3388399999999999e-01 -9.0096900000000002e-01 0.0000000000000000e+00 6.2348999999999999e-01 -7.8183100000000005e-01 0.0000000000000000e+00 7.8183100000000005e-01 -6.2348999999999999e-01 0.0000000000000000e+00 9.0096900000000002e-01 -4.3388399999999999e-01 0.0000000000000000e+00 9.7492800000000002e-01 -2.2252100000000000e-01 0.0000000000000000e+00 0.0000000000000000e+00 9.7492800000000002e-01 -2.2252100000000000e-01 0.0000000000000000e+00 9.0096900000000002e-01 -4.3388399999999999e-01 0.0000000000000000e+00 7.8183100000000005e-01 -6.2348999999999999e-01 0.0000000000000000e+00 6.2348999999999999e-01 -7.8183100000000005e-01 0.0000000000000000e+00 4.3388399999999999e-01 -9.0096900000000002e-01 0.0000000000000000e+00 2.2252100000000000e-01 -9.7492800000000002e-01 0.0000000000000000e+00 -2.2252100000000000e-01 -9.7492800000000002e-01 0.0000000000000000e+00 -4.3388399999999999e-01 -9.0096900000000002e-01 0.0000000000000000e+00 -6.2348999999999999e-01 -7.8183100000000005e-01 0.0000000000000000e+00 -7.8183100000000005e-01 -6.2348999999999999e-01 0.0000000000000000e+00 -9.0096900000000002e-01 -4.3388399999999999e-01 0.0000000000000000e+00 -9.7492800000000002e-01 -2.2252100000000000e-01 0.0000000000000000e+00 -9.7492800000000002e-01 2.2252100000000000e-01 0.0000000000000000e+00 -9.0096900000000002e-01 4.3388399999999999e-01 0.0000000000000000e+00 -7.8183100000000005e-01 6.2348999999999999e-01 0.0000000000000000e+00 -6.2348999999999999e-01 7.8183100000000005e-01 0.0000000000000000e+00 -4.3388399999999999e-01 9.0096900000000002e-01 0.0000000000000000e+00 -2.2252100000000000e-01 9.7492800000000002e-01 0.0000000000000000e+00 2.2252100000000000e-01 9.7492800000000002e-01 0.0000000000000000e+00 4.3388399999999999e-01 9.0096900000000002e-01 0.0000000000000000e+00 6.2348999999999999e-01 7.8183100000000005e-01 0.0000000000000000e+00 7.8183100000000005e-01 6.2348999999999999e-01 0.0000000000000000e+00 9.0096900000000002e-01 4.3388399999999999e-01 0.0000000000000000e+00 9.7492800000000002e-01 2.2252100000000000e-01 9.7492800000000002e-01 0.0000000000000000e+00 2.2252100000000000e-01 9.0096900000000002e-01 0.0000000000000000e+00 4.3388399999999999e-01 7.8183100000000005e-01 0.0000000000000000e+00 6.2348999999999999e-01 6.2348999999999999e-01 0.0000000000000000e+00 7.8183100000000005e-01 4.3388399999999999e-01 0.0000000000000000e+00 9.0096900000000002e-01 2.2252100000000000e-01 0.0000000000000000e+00 9.7492800000000002e-01 -2.2252100000000000e-01 0.0000000000000000e+00 9.7492800000000002e-01 -4.3388399999999999e-01 0.0000000000000000e+00 9.0096900000000002e-01 -6.2348999999999999e-01 0.0000000000000000e+00 7.8183100000000005e-01 -7.8183100000000005e-01 0.0000000000000000e+00 6.2348999999999999e-01 -9.0096900000000002e-01 0.0000000000000000e+00 4.3388399999999999e-01 -9.7492800000000002e-01 0.0000000000000000e+00 2.2252100000000000e-01 -9.7492800000000002e-01 0.0000000000000000e+00 -2.2252100000000000e-01 -9.0096900000000002e-01 0.0000000000000000e+00 -4.3388399999999999e-01 -7.8183100000000005e-01 0.0000000000000000e+00 -6.2348999999999999e-01 -6.2348999999999999e-01 0.0000000000000000e+00 -7.8183100000000005e-01 -4.3388399999999999e-01 0.0000000000000000e+00 -9.0096900000000002e-01 -2.2252100000000000e-01 0.0000000000000000e+00 -9.7492800000000002e-01 2.2252100000000000e-01 0.0000000000000000e+00 -9.7492800000000002e-01 4.3388399999999999e-01 0.0000000000000000e+00 -9.0096900000000002e-01 6.2348999999999999e-01 0.0000000000000000e+00 -7.8183100000000005e-01 7.8183100000000005e-01 0.0000000000000000e+00 -6.2348999999999999e-01 9.0096900000000002e-01 0.0000000000000000e+00 -4.3388399999999999e-01 9.7492800000000002e-01 0.0000000000000000e+00 -2.2252100000000000e-01 -6.3995999999999997e-01 4.3937900000000002e-01 6.3039500000000004e-01 -5.4372100000000001e-01 7.4952600000000003e-01 3.7759500000000001e-01 -8.7771500000000002e-01 3.4995300000000001e-01 3.2733800000000002e-01 -3.5882900000000001e-01 1.3373699999999999e-01 9.2377299999999996e-01 -8.5750000000000004e-01 4.8765900000000001e-01 1.6395699999999999e-01 -7.0496099999999995e-01 6.7737599999999998e-01 2.1021699999999999e-01 -8.0192500000000000e-01 5.0602400000000003e-01 3.1757800000000003e-01 -6.9879500000000005e-01 5.7667800000000002e-01 4.2323499999999997e-01 -4.3849700000000003e-01 5.1057900000000001e-01 7.3961500000000002e-01 -6.9854700000000003e-01 2.0844199999999999e-01 6.8453200000000003e-01 -7.7817800000000004e-01 3.8351800000000003e-01 4.9734699999999998e-01 -8.3699100000000004e-01 1.8487300000000001e-01 5.1504200000000000e-01 -2.4358600000000000e-01 6.6137800000000002e-01 7.0939799999999997e-01 -5.5532300000000001e-01 3.3858100000000002e-01 7.5959200000000004e-01 -5.2392899999999998e-01 1.7287500000000000e-01 8.3403400000000005e-01 -9.3840900000000005e-01 3.0938599999999999e-01 1.5384800000000001e-01 -9.3818500000000005e-01 1.5345400000000001e-01 3.1025999999999998e-01 -9.8055300000000001e-01 1.3339500000000001e-01 1.4395200000000000e-01 -1.8169500000000000e-01 8.3602100000000001e-01 5.1773999999999998e-01 -5.4228900000000002e-01 6.3262799999999997e-01 5.5290499999999998e-01 -3.8858500000000001e-01 7.5263300000000000e-01 5.3154999999999997e-01 -4.0676200000000001e-01 6.4934700000000001e-01 6.4256800000000003e-01 -3.3240700000000001e-01 8.6831999999999998e-01 3.6813899999999999e-01 -5.0575499999999995e-01 8.3885900000000002e-01 2.0131700000000000e-01 -3.2459800000000000e-01 9.2762400000000000e-01 1.8479699999999999e-01 -1.6858699999999999e-01 9.2746600000000001e-01 3.3374399999999999e-01 -1.7019999999999999e-01 9.7358800000000001e-01 1.5218200000000001e-01 -2.0956600000000000e-01 4.6591300000000002e-01 8.5965499999999995e-01 -1.7528700000000000e-01 2.3351100000000000e-01 9.5642400000000005e-01 -3.8535300000000000e-01 3.1272899999999998e-01 8.6816099999999996e-01 -6.3632299999999997e-01 -6.3690500000000005e-01 4.3525300000000000e-01 -5.1749400000000001e-01 -4.2859000000000003e-01 7.4061500000000002e-01 -8.7635200000000002e-01 -3.3248200000000000e-01 3.4851500000000002e-01 -3.7892799999999999e-01 -9.0037400000000001e-01 2.1386800000000000e-01 -1.6115800000000000e-01 -9.7450199999999998e-01 1.5612200000000001e-01 -6.9590099999999999e-01 -2.1383300000000000e-01 6.8556399999999995e-01 -8.5227500000000000e-01 -1.7293600000000001e-01 4.9368099999999998e-01 -7.9079500000000003e-01 -3.3171699999999998e-01 5.1439999999999997e-01 -6.8147100000000005e-01 -4.5117400000000002e-01 5.7622799999999996e-01 -1.6914499999999999e-01 -8.3651900000000001e-01 5.2117700000000000e-01 -1.8762799999999999e-01 -9.2080099999999998e-01 3.4193699999999999e-01 -4.0176200000000001e-01 -7.7695199999999998e-01 4.8469800000000002e-01 -5.4538299999999995e-01 -6.0393300000000005e-01 5.8122499999999999e-01 -5.5193800000000004e-01 -7.7373000000000003e-01 3.1097700000000000e-01 -5.4394500000000001e-01 -8.2367699999999999e-01 1.6025200000000001e-01 -6.9829200000000002e-01 -6.8511599999999995e-01 2.0737300000000000e-01 -7.7605800000000003e-01 -5.0326499999999996e-01 3.8007800000000003e-01 -8.3698600000000001e-01 -5.1521899999999998e-01 1.8440300000000001e-01 -1.9162899999999999e-01 -7.1525000000000005e-01 6.7208400000000001e-01 -9.3779900000000005e-01 -1.5641099999999999e-01 3.0994800000000000e-01 -9.3828599999999995e-01 -3.1037100000000001e-01 1.5260599999999999e-01 -9.8068699999999998e-01 -1.4403500000000000e-01 1.3231499999999999e-01 -5.3364199999999995e-01 -1.9003700000000001e-01 8.2408300000000001e-01 -3.7026900000000001e-01 -6.0976399999999997e-01 7.0077699999999998e-01 -3.3910200000000001e-01 -4.9078300000000002e-01 8.0258499999999999e-01 -1.8717600000000001e-01 -5.2812099999999995e-01 8.2828299999999999e-01 -3.4229700000000002e-01 -1.3465400000000000e-01 9.2989299999999997e-01 -3.2771499999999998e-01 -3.4328500000000001e-01 8.8020299999999996e-01 -1.6686999999999999e-01 -2.0157100000000000e-01 9.6515499999999999e-01 -1.3109199999999999e-01 -3.6667000000000000e-01 9.2106900000000003e-01 1.3201199999999999e-01 2.0662600000000000e-01 9.6947300000000003e-01 3.3095500000000000e-01 1.8506700000000001e-01 9.2532099999999995e-01 8.4872599999999998e-01 3.6604599999999998e-01 3.8167299999999998e-01 2.3251600000000000e-01 3.8139499999999998e-01 8.9469200000000004e-01 8.4400299999999995e-01 1.7023600000000000e-01 5.0860499999999997e-01 7.1144200000000002e-01 1.6809800000000000e-01 6.8234399999999995e-01 5.2309300000000003e-01 8.2933000000000001e-01 1.9642999999999999e-01 9.3233100000000002e-01 3.2357799999999998e-01 1.6141700000000000e-01 9.3801400000000001e-01 1.5573699999999999e-01 3.0963900000000000e-01 9.8058599999999996e-01 1.3465900000000000e-01 1.4254000000000000e-01 1.7480599999999999e-01 9.6930499999999997e-01 1.7288799999999999e-01 3.6626300000000001e-01 9.1405800000000004e-01 1.7421400000000001e-01 2.1123200000000000e-01 9.0888000000000002e-01 3.5960700000000001e-01 8.3748400000000001e-01 5.1304000000000005e-01 1.8817700000000001e-01 6.9183899999999998e-01 6.9297600000000004e-01 2.0283799999999999e-01 1.6632000000000000e-01 6.2752200000000002e-01 7.6062700000000005e-01 1.7987600000000001e-01 8.1544200000000000e-01 5.5018000000000000e-01 3.9382499999999998e-01 6.7565500000000001e-01 6.2321199999999999e-01 7.7003100000000002e-01 3.1256899999999999e-01 5.5619499999999999e-01 7.0496700000000001e-01 4.4953300000000002e-01 5.4858099999999999e-01 6.7007600000000000e-01 3.2145600000000002e-01 6.6907700000000003e-01 5.4874400000000001e-01 2.1396999999999999e-01 8.0814399999999997e-01 5.9102399999999999e-01 5.9216199999999997e-01 5.4775399999999996e-01 7.2455099999999995e-01 5.6906599999999996e-01 3.8883200000000001e-01 5.4085499999999997e-01 7.3995500000000003e-01 3.9992800000000001e-01 4.0494700000000000e-01 8.5503799999999996e-01 3.2392399999999999e-01 3.4065800000000002e-01 8.1821500000000003e-01 4.6311600000000003e-01 5.4215899999999995e-01 4.5670100000000002e-01 7.0532799999999995e-01 4.0553400000000001e-01 3.7166199999999999e-01 8.3511000000000002e-01 3.5125400000000001e-01 5.1491900000000002e-01 7.8197099999999997e-01 -6.3641899999999996e-01 6.3680899999999996e-01 -4.3525300000000000e-01 -4.2782799999999999e-01 5.1814600000000000e-01 -7.4060000000000004e-01 -9.0027699999999999e-01 3.7915800000000000e-01 -2.1387100000000001e-01 -9.7448400000000002e-01 1.6126499999999999e-01 -1.5612300000000001e-01 -3.3222200000000002e-01 8.7645300000000004e-01 -3.4850799999999998e-01 -2.1283199999999999e-01 6.9628100000000004e-01 -6.8549000000000004e-01 -1.7255599999999999e-01 8.5236400000000001e-01 -4.9365900000000001e-01 -3.3103300000000002e-01 7.9110100000000005e-01 -5.1436999999999999e-01 -4.5007599999999998e-01 6.8222499999999997e-01 -5.7619500000000001e-01 -8.3641600000000005e-01 1.6957600000000000e-01 -5.2120299999999997e-01 -9.2074199999999995e-01 1.8790100000000001e-01 -3.4194500000000000e-01 -7.7653700000000003e-01 4.0253200000000000e-01 -4.8472500000000002e-01 -6.0299599999999998e-01 5.4640900000000003e-01 -5.8123400000000003e-01 -7.7359000000000000e-01 5.5213199999999996e-01 -3.1097900000000001e-01 -8.2363100000000000e-01 5.4401400000000000e-01 -1.6025200000000001e-01 -6.8503899999999995e-01 6.9836799999999999e-01 -2.0737300000000000e-01 -5.0287400000000004e-01 7.7631399999999995e-01 -3.8007099999999999e-01 -5.1519199999999998e-01 8.3700200000000002e-01 -1.8440300000000001e-01 -7.1508000000000005e-01 1.9212899999999999e-01 -6.7212200000000000e-01 -1.5629000000000001e-01 9.3782100000000002e-01 -3.0994500000000003e-01 -3.1036399999999997e-01 9.3828900000000004e-01 -1.5260599999999999e-01 -1.4403099999999999e-01 9.8068800000000000e-01 -1.3231499999999999e-01 -1.8953700000000001e-01 5.3387700000000005e-01 -8.2404599999999995e-01 -6.0927699999999996e-01 3.7101099999999998e-01 -7.0080900000000002e-01 -4.8997499999999999e-01 3.4017700000000001e-01 -8.0262299999999998e-01 -5.2771100000000004e-01 1.8804499999999999e-01 -8.2834799999999997e-01 -1.3453799999999999e-01 3.4236100000000003e-01 -9.2988599999999999e-01 -3.4118599999999999e-01 3.2987699999999998e-01 -8.8021199999999999e-01 -1.9639400000000001e-01 1.7260700000000001e-01 -9.6521299999999999e-01 -3.6539500000000003e-01 1.3355500000000001e-01 -9.2122199999999999e-01 6.3039500000000004e-01 6.3995999999999997e-01 -4.3937900000000002e-01 3.7759500000000001e-01 5.4372100000000001e-01 -7.4952600000000003e-01 9.2377299999999996e-01 3.5882900000000001e-01 -1.3373699999999999e-01 3.2733800000000002e-01 8.7771500000000002e-01 -3.4995300000000001e-01 1.6395699999999999e-01 8.5750000000000004e-01 -4.8765900000000001e-01 2.1021699999999999e-01 7.0496099999999995e-01 -6.7737599999999998e-01 3.1757800000000003e-01 8.0192500000000000e-01 -5.0602400000000003e-01 4.2323499999999997e-01 6.9879500000000005e-01 -5.7667800000000002e-01 7.3961500000000002e-01 4.3849700000000003e-01 -5.1057900000000001e-01 6.8453200000000003e-01 6.9854700000000003e-01 -2.0844199999999999e-01 4.9734699999999998e-01 7.7817800000000004e-01 -3.8351800000000003e-01 5.1504200000000000e-01 8.3699100000000004e-01 -1.8487300000000001e-01 7.0939799999999997e-01 2.4358600000000000e-01 -6.6137800000000002e-01 7.5959200000000004e-01 5.5532300000000001e-01 -3.3858100000000002e-01 8.3403400000000005e-01 5.2392899999999998e-01 -1.7287500000000000e-01 1.5384800000000001e-01 9.3840900000000005e-01 -3.0938599999999999e-01 3.1025999999999998e-01 9.3818500000000005e-01 -1.5345400000000001e-01 1.4395200000000000e-01 9.8055300000000001e-01 -1.3339500000000001e-01 5.1773999999999998e-01 1.8169500000000000e-01 -8.3602100000000001e-01 5.5290499999999998e-01 5.4228900000000002e-01 -6.3262799999999997e-01 5.3154999999999997e-01 3.8858500000000001e-01 -7.5263300000000000e-01 6.4256800000000003e-01 4.0676200000000001e-01 -6.4934700000000001e-01 3.6813899999999999e-01 3.3240700000000001e-01 -8.6831999999999998e-01 2.0131700000000000e-01 5.0575499999999995e-01 -8.3885900000000002e-01 1.8479699999999999e-01 3.2459800000000000e-01 -9.2762400000000000e-01 3.3374399999999999e-01 1.6858699999999999e-01 -9.2746600000000001e-01 1.5218200000000001e-01 1.7019999999999999e-01 -9.7358800000000001e-01 8.5965499999999995e-01 2.0956600000000000e-01 -4.6591300000000002e-01 9.5642400000000005e-01 1.7528700000000000e-01 -2.3351100000000000e-01 8.6816099999999996e-01 3.8535300000000000e-01 -3.1272899999999998e-01 -6.3680899999999996e-01 -4.3525300000000000e-01 -6.3641899999999996e-01 -5.1814600000000000e-01 -7.4060000000000004e-01 -4.2782799999999999e-01 -3.7915800000000000e-01 -2.1387100000000001e-01 -9.0027699999999999e-01 -1.6126499999999999e-01 -1.5612300000000001e-01 -9.7448400000000002e-01 -8.7645300000000004e-01 -3.4850799999999998e-01 -3.3222200000000002e-01 -6.9628100000000004e-01 -6.8549000000000004e-01 -2.1283199999999999e-01 -8.5236400000000001e-01 -4.9365900000000001e-01 -1.7255599999999999e-01 -7.9110100000000005e-01 -5.1436999999999999e-01 -3.3103300000000002e-01 -6.8222499999999997e-01 -5.7619500000000001e-01 -4.5007599999999998e-01 -1.6957600000000000e-01 -5.2120299999999997e-01 -8.3641600000000005e-01 -1.8790100000000001e-01 -3.4194500000000000e-01 -9.2074199999999995e-01 -4.0253200000000000e-01 -4.8472500000000002e-01 -7.7653700000000003e-01 -5.4640900000000003e-01 -5.8123400000000003e-01 -6.0299599999999998e-01 -5.5213199999999996e-01 -3.1097900000000001e-01 -7.7359000000000000e-01 -5.4401400000000000e-01 -1.6025200000000001e-01 -8.2363100000000000e-01 -6.9836799999999999e-01 -2.0737300000000000e-01 -6.8503899999999995e-01 -7.7631399999999995e-01 -3.8007099999999999e-01 -5.0287400000000004e-01 -8.3700200000000002e-01 -1.8440300000000001e-01 -5.1519199999999998e-01 -1.9212899999999999e-01 -6.7212200000000000e-01 -7.1508000000000005e-01 -9.3782100000000002e-01 -3.0994500000000003e-01 -1.5629000000000001e-01 -9.3828900000000004e-01 -1.5260599999999999e-01 -3.1036399999999997e-01 -9.8068800000000000e-01 -1.3231499999999999e-01 -1.4403099999999999e-01 -5.3387700000000005e-01 -8.2404599999999995e-01 -1.8953700000000001e-01 -3.7101099999999998e-01 -7.0080900000000002e-01 -6.0927699999999996e-01 -3.4017700000000001e-01 -8.0262299999999998e-01 -4.8997499999999999e-01 -1.8804499999999999e-01 -8.2834799999999997e-01 -5.2771100000000004e-01 -3.4236100000000003e-01 -9.2988599999999999e-01 -1.3453799999999999e-01 -3.2987699999999998e-01 -8.8021199999999999e-01 -3.4118599999999999e-01 -1.7260700000000001e-01 -9.6521299999999999e-01 -1.9639400000000001e-01 -1.3355500000000001e-01 -9.2122199999999999e-01 -3.6539500000000003e-01 5.5417499999999997e-01 -1.4046100000000000e-01 8.2046399999999997e-01 5.1518900000000001e-01 -3.4628500000000001e-01 7.8400700000000001e-01 8.7026800000000004e-01 -3.4087400000000001e-01 3.5558200000000001e-01 1.2037800000000000e-01 -9.4405399999999995e-01 3.0703700000000000e-01 1.3807400000000000e-01 -9.7798300000000005e-01 1.5647700000000000e-01 3.3565200000000001e-01 -9.0807300000000002e-01 2.5048300000000001e-01 4.0080300000000002e-01 -1.6878099999999999e-01 9.0048300000000003e-01 1.9447200000000001e-01 -1.8697200000000000e-01 9.6292400000000000e-01 3.3030100000000001e-01 -3.3282899999999999e-01 8.8324700000000000e-01 7.0006299999999999e-01 -2.1284000000000000e-01 6.8162299999999998e-01 8.4927799999999998e-01 -1.7618000000000000e-01 4.9768200000000001e-01 7.7393100000000004e-01 -3.4039999999999998e-01 5.3400300000000001e-01 1.5438700000000000e-01 -8.5364099999999998e-01 4.9745600000000001e-01 3.7325300000000000e-01 -7.7450100000000000e-01 5.1071599999999995e-01 8.3502600000000005e-01 -5.1752600000000004e-01 1.8681000000000000e-01 7.0974599999999999e-01 -6.7852400000000002e-01 1.8938400000000000e-01 5.6214399999999998e-01 -8.1083000000000005e-01 1.6293900000000000e-01 1.6603599999999999e-01 -3.9670499999999997e-01 9.0280499999999997e-01 1.6935800000000001e-01 -7.2803099999999998e-01 6.6429499999999997e-01 1.5957600000000000e-01 -5.6333000000000000e-01 8.1067500000000003e-01 7.4003399999999997e-01 -5.3995099999999996e-01 4.0100200000000003e-01 5.6383700000000003e-01 -7.4781500000000001e-01 3.5051399999999999e-01 9.3669700000000000e-01 -1.5827100000000000e-01 3.1232900000000002e-01 9.3808499999999995e-01 -3.1079400000000001e-01 1.5298400000000001e-01 9.8067099999999996e-01 -1.4409600000000000e-01 1.3236800000000001e-01 3.4961599999999998e-01 -6.4161800000000002e-01 6.8271199999999999e-01 3.4245900000000001e-01 -4.7910900000000001e-01 8.0819300000000005e-01 6.4729300000000001e-01 -4.4420100000000001e-01 6.1943300000000001e-01 5.5155299999999996e-01 -6.2159399999999998e-01 5.5624600000000002e-01 4.8911700000000002e-01 -5.3035600000000005e-01 6.9245000000000001e-01 8.2046399999999997e-01 -5.5417499999999997e-01 -1.4046100000000000e-01 7.8400700000000001e-01 -5.1518900000000001e-01 -3.4628500000000001e-01 3.5558200000000001e-01 -8.7026800000000004e-01 -3.4087400000000001e-01 3.0703700000000000e-01 -1.2037800000000000e-01 -9.4405399999999995e-01 1.5647700000000000e-01 -1.3807400000000000e-01 -9.7798300000000005e-01 2.5048300000000001e-01 -3.3565200000000001e-01 -9.0807300000000002e-01 9.0048300000000003e-01 -4.0080300000000002e-01 -1.6878099999999999e-01 9.6292400000000000e-01 -1.9447200000000001e-01 -1.8697200000000000e-01 8.8324700000000000e-01 -3.3030100000000001e-01 -3.3282899999999999e-01 6.8162299999999998e-01 -7.0006299999999999e-01 -2.1284000000000000e-01 4.9768200000000001e-01 -8.4927799999999998e-01 -1.7618000000000000e-01 5.3400300000000001e-01 -7.7393100000000004e-01 -3.4039999999999998e-01 4.9745600000000001e-01 -1.5438700000000000e-01 -8.5364099999999998e-01 5.1071599999999995e-01 -3.7325300000000000e-01 -7.7450100000000000e-01 1.8681000000000000e-01 -8.3502600000000005e-01 -5.1752600000000004e-01 1.8938400000000000e-01 -7.0974599999999999e-01 -6.7852400000000002e-01 1.6293900000000000e-01 -5.6214399999999998e-01 -8.1083000000000005e-01 9.0280499999999997e-01 -1.6603599999999999e-01 -3.9670499999999997e-01 6.6429499999999997e-01 -1.6935800000000001e-01 -7.2803099999999998e-01 8.1067500000000003e-01 -1.5957600000000000e-01 -5.6333000000000000e-01 4.0100200000000003e-01 -7.4003399999999997e-01 -5.3995099999999996e-01 3.5051399999999999e-01 -5.6383700000000003e-01 -7.4781500000000001e-01 3.1232900000000002e-01 -9.3669700000000000e-01 -1.5827100000000000e-01 1.5298400000000001e-01 -9.3808499999999995e-01 -3.1079400000000001e-01 1.3236800000000001e-01 -9.8067099999999996e-01 -1.4409600000000000e-01 6.8271199999999999e-01 -3.4961599999999998e-01 -6.4161800000000002e-01 8.0819300000000005e-01 -3.4245900000000001e-01 -4.7910900000000001e-01 6.1943300000000001e-01 -6.4729300000000001e-01 -4.4420100000000001e-01 5.5624600000000002e-01 -5.5155299999999996e-01 -6.2159399999999998e-01 6.9245000000000001e-01 -4.8911700000000002e-01 -5.3035600000000005e-01 # SIMPLEX 6 0 147 0 6 226 29 0 282 0 29 295 54 0 147 0 54 282 0 77 226 77 0 295 11 1 148 1 11 215 1 12 104 12 1 189 1 30 189 30 1 215 53 1 104 1 53 148 17 2 95 2 17 171 2 18 129 18 2 249 2 65 95 65 2 129 66 2 171 2 66 249 23 3 112 3 23 256 3 24 262 24 3 312 41 3 256 3 41 312 3 42 112 42 3 262 35 4 196 4 35 224 4 36 231 36 4 292 4 71 196 71 4 231 72 4 224 4 72 292 47 5 136 5 47 265 5 48 106 48 5 138 5 59 138 59 5 265 60 5 106 5 60 136 6 7 145 7 6 200 6 145 147 200 6 226 7 8 151 8 7 212 145 7 151 7 200 212 8 9 152 9 8 207 8 152 151 207 8 212 9 10 144 10 9 209 9 144 152 9 207 209 10 11 149 11 10 214 144 10 149 10 209 214 149 11 148 11 214 215 12 13 102 13 12 188 12 102 104 188 12 189 13 14 101 14 13 185 102 13 101 185 13 188 14 15 83 15 14 183 14 83 101 183 14 185 15 16 82 16 15 182 83 15 82 15 183 182 16 17 93 17 16 170 16 93 82 170 16 182 93 17 95 17 170 171 18 19 128 19 18 247 18 128 129 247 18 249 19 20 125 20 19 234 19 125 128 19 247 234 20 21 123 21 20 233 20 123 125 233 20 234 21 22 122 22 21 250 123 21 122 21 233 250 22 23 111 23 22 254 22 111 122 22 250 254 111 23 112 23 254 256 24 25 263 25 24 310 24 263 262 310 24 312 25 26 274 26 25 298 263 25 274 25 310 298 26 27 273 27 26 297 26 273 274 297 26 298 27 28 272 28 27 288 273 27 272 27 297 288 28 29 281 29 28 294 272 28 281 294 28 288 281 29 282 295 29 294 30 31 187 31 30 213 30 187 189 213 30 215 31 32 174 32 31 202 187 31 174 31 213 202 32 33 173 33 32 203 32 173 174 203 32 202 33 34 190 34 33 221 173 33 190 33 203 221 34 35 194 35 34 222 190 34 194 222 34 221 194 35 196 35 222 224 36 37 238 37 36 293 36 238 231 293 36 292 37 38 237 38 37 304 37 237 238 37 293 304 38 39 246 39 38 303 38 246 237 303 38 304 39 40 253 40 39 302 246 39 253 39 303 302 40 41 257 41 40 311 253 40 257 40 302 311 41 256 257 41 311 312 42 43 118 43 42 261 42 118 112 261 42 262 43 44 117 44 43 270 43 117 118 270 43 261 44 45 126 45 44 276 44 126 117 44 270 276 45 46 133 46 45 277 126 45 133 277 45 276 46 47 137 47 46 275 133 46 137 46 277 275 47 136 137 265 47 275 48 49 106 49 48 138 49 50 105 50 49 153 49 105 106 49 141 153 141 49 138 50 51 90 51 50 153 50 90 105 51 52 96 52 51 154 90 51 96 51 153 154 52 53 103 53 52 150 96 52 103 150 52 154 103 53 104 53 150 148 55 54 146 54 55 280 146 54 147 54 280 282 56 55 142 55 56 268 142 55 146 280 55 268 57 56 143 56 57 267 143 56 142 56 267 268 58 57 159 57 58 258 57 143 159 267 57 258 59 58 139 58 59 264 139 58 159 58 264 258 59 139 138 59 265 264 61 60 81 60 61 134 81 60 106 60 134 136 62 61 92 61 62 130 61 81 92 61 130 134 63 62 87 62 63 113 87 62 92 62 113 130 64 63 89 63 64 114 63 87 89 113 63 114 65 64 94 64 65 127 64 89 94 64 127 114 65 94 95 127 65 129 67 66 178 66 67 248 178 66 171 66 248 249 68 67 177 67 68 245 177 67 178 67 245 248 69 68 186 68 69 243 186 68 177 68 243 245 70 69 193 69 70 242 69 186 193 243 69 242 71 70 197 70 71 230 70 193 197 70 230 242 196 71 197 230 71 231 73 72 223 72 73 291 223 72 224 72 291 292 74 73 216 73 74 300 216 73 223 73 300 291 75 74 210 74 75 306 210 74 216 300 74 306 76 75 225 75 76 307 75 210 225 75 307 306 77 76 226 76 77 305 76 225 226 307 76 305 77 295 305 86 78 91 78 86 97 78 87 91 87 78 88 88 78 85 78 97 85 79 83 85 83 79 101 79 97 98 97 79 85 79 98 100 79 100 101 84 80 88 80 84 82 88 80 89 89 80 94 80 93 94 93 80 82 92 81 107 81 106 107 84 83 82 83 84 85 84 88 85 86 90 99 90 86 105 86 91 107 97 86 99 105 86 107 91 87 92 87 88 89 90 96 98 90 98 99 91 92 107 94 93 95 98 96 100 100 96 103 98 97 99 102 100 103 100 102 101 102 103 104 106 105 107 119 108 121 108 119 120 108 123 121 123 108 124 124 108 116 108 120 116 113 109 130 109 113 116 130 109 135 109 120 131 120 109 116 109 131 132 135 109 132 115 110 124 110 115 114 124 110 125 125 110 128 110 127 128 127 110 114 111 119 121 119 111 118 111 121 122 118 111 112 113 115 116 115 113 114 115 124 116 126 119 117 119 126 131 117 119 118 120 119 131 121 123 122 123 124 125 126 133 131 128 127 129 130 135 134 131 133 132 133 135 132 135 133 137 134 135 136 136 135 137 141 139 166 139 141 138 139 159 166 140 142 146 142 140 156 145 140 146 140 145 151 140 157 156 157 140 161 140 151 161 153 141 167 141 166 167 143 142 156 159 143 158 158 143 156 144 149 163 152 144 162 162 144 163 145 146 147 150 149 148 149 150 163 150 154 164 163 150 164 151 152 161 152 162 161 153 155 154 155 153 167 154 155 164 162 155 160 155 162 164 160 155 165 165 155 167 157 158 156 158 157 165 157 160 165 160 157 161 159 158 165 159 165 166 162 160 161 162 163 164 166 165 167 168 179 181 179 168 180 183 168 181 168 183 184 168 184 176 180 168 176 169 173 190 173 169 176 169 190 195 180 169 191 169 180 176 191 169 192 169 195 192 179 170 181 170 179 178 181 170 182 170 178 171 172 175 184 175 172 174 172 184 185 172 185 188 187 172 188 172 187 174 175 173 176 173 175 174 184 175 176 179 186 177 186 179 191 179 177 178 179 180 191 183 181 182 184 183 185 193 186 191 187 188 189 195 190 194 193 191 192 195 193 192 193 195 197 195 194 196 195 196 197 206 198 211 198 206 217 198 207 211 207 198 208 208 198 205 198 217 205 199 203 205 203 199 221 199 217 218 217 199 205 199 218 220 199 220 221 212 200 227 200 226 227 204 201 208 201 204 202 208 201 209 209 201 214 201 213 214 213 201 202 204 203 202 203 204 205 204 208 205 206 210 219 210 206 225 206 211 227 217 206 219 225 206 227 211 207 212 207 208 209 210 216 218 210 218 219 211 212 227 214 213 215 218 216 220 220 216 223 218 217 219 222 220 223 220 222 221 222 223 224 226 225 227 239 228 241 228 239 240 228 243 241 243 228 244 244 228 236 228 240 236 233 229 250 229 233 236 250 229 255 229 240 251 240 229 236 229 251 252 255 229 252 230 239 241 239 230 238 230 241 242 238 230 231 235 232 244 232 235 234 244 232 245 245 232 248 232 247 248 247 232 234 233 235 236 235 233 234 235 244 236 246 239 237 239 246 251 237 239 238 240 239 251 241 243 242 243 244 245 246 253 251 248 247 249 250 255 254 251 253 252 253 255 252 255 253 257 254 255 256 256 255 257 266 259 264 259 266 284 267 259 285 259 267 258 264 259 258 285 259 287 259 284 287 260 269 278 269 260 268 260 278 272 260 272 281 280 260 281 260 280 268 263 271 270 271 263 279 263 270 261 263 261 262 263 274 279 265 266 264 266 265 275 266 275 284 269 267 285 267 269 268 278 269 285 270 271 276 271 283 276 283 271 286 286 271 279 278 273 272 273 278 279 274 273 279 275 277 284 283 277 276 277 283 284 278 285 286 278 286 279 280 281 282 283 286 287 284 283 287 286 285 287 289 296 294 296 289 314 289 297 315 297 289 288 289 294 288 289 315 317 314 289 317 299 290 308 290 299 298 308 290 302 302 290 311 290 310 311 310 290 298 301 293 300 293 301 309 300 293 291 291 293 292 304 293 309 296 295 294 295 296 305 305 296 314 297 299 315 299 297 298 299 308 315 301 300 306 313 301 306 301 313 316 301 316 309 303 308 302 308 303 309 303 304 309 307 305 314 307 313 306 313 307 314 315 308 316 316 308 309 311 310 312 316 313 317 313 314 317 315 316 317 # # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-3-3-large.dgf000066400000000000000000026302101511655130300234500ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Vertex 7.17174e-05 66.8155 79.7895 7.17174e-05 61.9093 85.9635 7.17174e-05 61.9093 76.9564 13.8908 65.3557 79.7895 12.8712 60.5549 85.9635 12.8712 60.5549 76.9564 27.1758 61.0402 79.7895 25.1817 56.5555 85.9635 25.1817 56.5555 76.9564 39.2756 54.0572 79.7895 36.3899 50.0842 85.9635 36.3899 50.0842 76.9564 49.656 44.7077 79.7895 46.0065 41.4269 85.9635 46.0065 41.4269 76.9564 57.8656 33.4093 79.7895 53.6141 30.9562 85.9635 53.6141 30.9562 76.9564 63.5468 20.6473 79.7895 58.8776 19.131 85.9635 58.8776 19.131 76.9564 66.4513 6.98605 79.7895 61.5715 6.4706 85.9635 61.5715 6.4706 76.9564 66.4513 -6.98369 79.7895 61.5715 -6.47201 85.9635 61.5715 -6.47201 76.9564 63.5468 -20.6487 79.7895 58.8776 -19.1324 85.9635 58.8776 -19.1324 76.9564 57.8656 -33.4069 79.7895 53.6141 -30.9538 85.9635 53.6141 -30.9538 76.9564 49.656 -44.7091 79.7895 46.0065 -41.4246 85.9635 46.0065 -41.4246 76.9564 39.2756 -54.0549 79.7895 36.3899 -50.0856 85.9635 36.3899 -50.0856 76.9564 27.1758 -61.0416 79.7895 25.1817 -56.5569 85.9635 25.1817 -56.5569 76.9564 13.8908 -65.3571 79.7895 12.8712 -60.5563 85.9635 12.8712 -60.5563 76.9564 7.17174e-05 -66.8169 79.7895 7.17174e-05 -61.9107 85.9635 7.17174e-05 -61.9107 76.9564 -13.8907 -65.3571 79.7895 -12.871 -60.5563 85.9635 -12.871 -60.5563 76.9564 -27.1756 -61.0416 79.7895 -25.1816 -56.5569 85.9635 -25.1816 -56.5569 76.9564 -39.2755 -54.0549 79.7895 -36.3897 -50.0856 85.9635 -36.3897 -50.0856 76.9564 -49.6559 -44.7091 79.7895 -46.0064 -41.4246 85.9635 -46.0064 -41.4246 76.9564 -57.8654 -33.4069 79.7895 -53.6139 -30.9538 85.9635 -53.6139 -30.9538 76.9564 -63.5466 -20.6487 79.7895 -58.8775 -19.1324 85.9635 -58.8775 -19.1324 76.9564 -66.4512 -6.98369 79.7895 -61.5714 -6.47201 85.9635 -61.5714 -6.47201 76.9564 -66.4512 6.98605 79.7895 -61.5714 6.4706 85.9635 -61.5714 6.4706 76.9564 -63.5466 20.6473 79.7895 -58.8775 19.131 85.9635 -58.8775 19.131 76.9564 -57.8654 33.4093 79.7895 -53.6139 30.9562 85.9635 -53.6139 30.9562 76.9564 -49.6559 44.7077 79.7895 -46.0064 41.4269 85.9635 -46.0064 41.3178 76.9564 -39.2755 54.0572 79.7895 -36.3897 50.0842 85.9635 -36.3897 49.9788 76.9564 -27.1756 61.0402 79.7895 -25.1816 56.5555 85.9635 -25.1816 56.4501 76.9564 -13.8907 65.3557 79.7895 -12.871 60.5549 85.9635 -12.871 60.4495 76.9564 -23.2929 -63.506 70.391 -25.0424 -65.6543 73.6643 -32.379 -63.7355 74.635 -30.8364 -61.3652 71.1209 -38.8541 -59.9995 74.635 -37.5711 -57.4787 71.1209 -44.1854 -54.6004 73.6643 -43.1996 -52.0157 70.391 -24.0115 -71.0684 59.7472 -35.799 -72.8969 61.3463 -33.677 -68.4385 59.4876 -25.3509 -75.7112 61.4253 -45.0583 -67.5543 61.3463 -42.2553 -63.4872 59.4876 -52.7185 -59.9092 61.4253 -49.3699 -56.429 59.7472 -24.8806 -71.8209 55.127 -36.5891 -73.9692 54.6266 -34.121 -68.9351 54.1262 -26.5511 -76.9829 55.5597 -45.6151 -68.7583 54.6266 -42.4885 -64.1042 54.1262 -53.2414 -61.5721 55.5597 -49.6107 -57.5426 55.127 -28.2178 -67.7688 42.6058 -35.9458 -69.2512 41.8383 -34.279 -65.865 41.5373 -29.4218 -71.343 43.0611 -41.8677 -65.8312 41.8383 -39.7683 -62.6933 41.5373 -46.9394 -61.2298 43.0611 -44.445 -58.3967 42.6058 -28.3721 -66.5836 24.8173 -35.7576 -68.3896 25.0581 -34.1135 -65.0824 24.0723 -29.5685 -70.0337 25.9347 -41.2244 -65.2329 25.0581 -39.1814 -62.1553 24.0723 -45.743 -60.6955 25.9347 -43.3539 -57.9301 24.8173 -28.2479 -68.969 10.6519 -36.0135 -69.7779 11.7242 -34.7004 -66.9712 10.3133 -29.0531 -71.945 12.1568 -42.3079 -66.1434 11.7242 -40.5359 -63.6038 10.3133 -47.6656 -61.1997 12.1568 -45.4909 -59.0137 10.6519 -27.9845 -73.2167 -1.91072 -37.3454 -73.8149 0.294033 -35.9458 -70.7335 -1.91072 -28.7521 -76.4975 0.39938 -45.1222 -69.3226 0.294033 -43.1545 -66.5723 -1.91072 -51.744 -63.2238 0.39938 -49.2872 -60.9175 -1.91072 -27.676 -80.1433 -12.4379 -38.8353 -79.1274 -8.83351 -37.7366 -76.3696 -11.9638 -27.9657 -83.187 -9.19094 -48.9636 -73.2807 -8.83351 -47.12 -70.9518 -11.9638 -57.9106 -65.8989 -9.19094 -55.4199 -64.1268 -12.4379 -29.9184 -86.4979 -20.1583 -42.007 -85.531 -15.7638 -40.8331 -82.5738 -19.2628 -30.2044 -89.7298 -16.5803 -52.9179 -79.2328 -15.7638 -50.9426 -76.7383 -19.2628 -62.4555 -71.1135 -16.5803 -59.7993 -69.2474 -20.1583 -37.0895 -91.991 -24.6468 -46.5256 -90.8059 -20.6286 -45.7656 -88.7478 -23.6347 -37.1422 -94.271 -21.6256 -55.2506 -85.768 -20.6286 -53.8509 -84.0787 -23.6347 -62.9409 -79.3757 -21.6256 -60.9957 -78.1868 -24.6468 -42.9626 -93.8459 -25.4369 -49.4828 -92.8714 -22.4834 -49.0125 -91.5358 -24.6431 -42.9438 -95.3433 -23.2961 -55.5929 -89.3461 -22.4834 -54.6711 -88.2663 -24.6431 -61.0032 -84.9177 -23.2961 -59.6977 -84.1841 -25.4369 -49.4339 -95.3471 -25.4106 -52.6507 -94.7865 -23.8718 -52.4438 -94.1694 -24.9779 -49.3963 -96.0506 -24.3345 -55.7058 -93.0257 -23.8718 -55.2731 -92.5366 -24.9779 -58.426 -90.836 -24.3345 -57.7977 -90.5162 -25.4106 66.4626 11.467 70.391 69.1941 11.0268 73.6643 71.207 3.71277 74.635 68.3814 3.86327 71.1209 71.207 -3.76309 74.635 68.3814 -3.91358 71.1209 69.1941 -11.0772 73.6643 66.4626 -11.5174 70.391 73.3666 14.635 59.7472 80.8462 5.33812 61.3463 75.9212 4.94683 59.4876 78.0583 15.7938 61.4253 80.8462 -5.35081 61.3463 75.9212 -4.95953 59.4876 78.0583 -15.8102 61.4253 73.3666 -14.6477 59.7472 74.4539 14.2587 55.127 82.1706 5.19139 54.6266 76.5721 4.80762 54.1262 79.7589 15.3912 55.5597 82.1706 -5.23418 54.6266 76.5721 -4.85042 54.1262 79.7589 -15.4302 55.5597 74.4539 -14.2978 55.127 72.6103 9.3413 42.6058 77.761 3.38921 41.8383 73.9911 3.14089 41.5373 76.3088 10.0825 43.0611 77.761 -3.45081 41.8383 73.9911 -3.19873 41.5373 76.3088 -10.1441 43.0611 72.6103 -9.39914 42.6058 71.6622 8.61516 24.8173 76.9183 3.12208 25.0581 73.2349 2.88881 24.0723 75.2515 9.29991 25.9347 76.9183 -3.19497 25.0581 73.2349 -2.9617 24.0723 75.2515 -9.3728 25.9347 71.6622 -8.68805 24.8173 73.6676 9.91694 10.6519 78.2502 3.59237 11.7242 75.165 3.32525 10.3133 76.6474 10.7033 12.1568 78.2502 -3.67655 11.7242 75.165 -3.40942 10.3133 76.6474 -10.7875 12.1568 73.6676 -9.99736 10.6519 77.2117 12.2684 -1.91072 82.4114 4.45772 0.294033 79.044 4.12663 -1.91072 80.4399 13.2429 0.39938 82.4114 -4.52309 0.294033 79.044 -4.192 -1.91072 80.4399 -13.3083 0.39938 77.2117 -12.3338 -1.91072 83.0585 15.997 -12.4379 87.7577 5.82723 -8.83351 84.8193 5.39832 -11.9638 85.8389 17.2649 -9.19094 87.7577 -5.87002 -8.83351 84.8193 -5.44111 -11.9638 85.8389 -17.3077 -9.19094 83.0585 -16.0398 -12.4379 89.684 17.231 -20.1583 94.8912 6.27872 -15.7638 91.7421 5.81594 -19.2628 92.6262 18.6005 -16.5803 94.8912 -6.31775 -15.7638 91.7421 -5.85497 -19.2628 92.6262 -18.6396 -16.5803 89.684 -17.2701 -20.1583 98.0252 13.7659 -24.6468 101.716 5.00327 -20.6286 99.5528 4.63456 -23.6347 100.027 14.8607 -21.6256 101.716 -5.0724 -20.6286 99.5528 -4.70368 -23.6347 100.027 -14.9298 -21.6256 98.0252 -13.835 -24.6468 102.566 9.60843 -25.4369 104.986 3.47574 -22.4834 103.594 3.21614 -24.6431 103.857 10.3722 -23.2961 104.986 -3.57873 -22.4834 103.594 -3.31913 -24.6431 103.857 -10.4789 -23.2961 102.566 -9.71518 -25.4369 107.104 4.75495 -25.4106 108.229 1.68861 -23.8718 107.589 1.56069 -24.9779 107.695 5.13871 -24.3345 108.229 -1.83675 -23.8718 107.589 -1.70883 -24.9779 107.695 -5.28685 -24.3345 107.104 -4.90309 -25.4106 -43.1695 51.6117 70.391 -44.1553 54.1965 73.6643 -38.8277 59.5955 74.635 -37.541 57.0747 71.1209 -32.3489 63.3353 74.635 -30.8101 60.9612 71.1209 -25.0123 65.2503 73.6643 -23.2628 63.1058 70.391 -49.3549 56.0062 59.7472 -45.047 67.1315 61.3463 -42.244 63.0644 59.4876 -52.7072 59.4901 61.4253 -35.7877 72.4779 61.3463 -33.6657 68.0157 59.4876 -25.3396 75.2921 61.4253 -23.9964 70.6456 59.7472 -49.5731 57.1349 55.127 -45.5812 68.3505 54.6266 -42.4509 63.6965 54.1262 -53.2076 61.1644 55.5597 -36.5515 73.5614 54.6266 -34.0871 68.5236 54.1262 -26.5172 76.5751 55.5597 -24.843 71.4131 55.127 -44.3923 57.9965 42.6058 -41.8151 65.4347 41.8383 -39.7157 62.2969 41.5373 -46.8868 60.8295 43.0611 -35.8931 68.8547 41.8383 -34.2263 65.4648 41.5373 -29.3691 70.9428 43.0611 -28.1651 67.3686 42.6058 -43.2899 57.5375 24.8173 -41.1642 64.8402 25.0581 -39.1212 61.7626 24.0723 -45.679 60.3028 25.9347 -35.6937 67.9969 25.0581 -34.0533 64.6897 24.0723 -29.5083 69.641 25.9347 -28.3081 66.1909 24.8173 -45.4194 58.6248 10.6519 -42.2365 65.7545 11.7242 -40.4644 63.2149 10.3133 -47.5941 60.8107 12.1568 -35.942 69.389 11.7242 -34.6289 66.5822 10.3133 -28.9816 71.5561 12.1568 -28.1764 68.5801 10.6519 -49.2307 60.521 -1.91072 -45.0658 68.9262 0.294033 -43.098 66.1759 -1.91072 -51.6876 62.8274 0.39938 -37.2889 73.4185 0.294033 -35.8893 70.3371 -1.91072 -28.6956 76.1011 0.39938 -27.9281 72.8203 -1.91072 -55.3822 63.719 -12.4379 -48.926 72.8729 -8.83351 -47.0824 70.544 -11.9638 -57.8729 65.4911 -9.19094 -38.7976 78.7197 -8.83351 -37.699 75.9618 -11.9638 -27.9319 82.7793 -9.19094 -27.6384 79.7355 -12.4379 -59.7654 68.8397 -20.1583 -52.884 78.825 -15.7638 -50.9088 76.3268 -19.2628 -62.4217 70.702 -16.5803 -41.9731 85.1233 -15.7638 -40.7992 82.1623 -19.2628 -30.1705 89.3221 -16.5803 -29.8846 86.0902 -20.1583 -60.9355 77.7941 -24.6468 -55.1941 85.3753 -20.6286 -53.7907 83.686 -23.6347 -62.8807 78.9793 -21.6256 -46.4654 90.4132 -20.6286 -45.7054 88.3551 -23.6347 -37.082 93.8746 -21.6256 -37.0293 91.5946 -24.6468 -59.6036 83.8064 -25.4369 -55.5026 88.9684 -22.4834 -54.5808 87.8924 -24.6431 -60.9129 84.5401 -23.2961 -49.3925 92.4975 -22.4834 -48.9222 91.1581 -24.6431 -42.8535 94.9694 -23.2961 -42.8723 93.4682 -25.4369 -57.6698 90.1611 -25.4106 -55.5779 92.6706 -23.8718 -55.1452 92.1815 -24.9779 -58.2981 90.4809 -24.3345 -52.5228 94.4314 -23.8718 -52.3159 93.8144 -24.9779 -49.2684 95.6956 -24.3345 -49.3022 94.992 -25.4106 7.17174e-05 80.1419 6.31385 7.17174e-05 72.8541 10.524 7.17174e-05 72.8541 2.1075 13.9171 78.9266 6.31385 12.653 71.748 10.524 12.653 71.748 2.1075 27.409 75.311 6.31385 24.9183 68.4597 10.524 24.9183 68.4597 2.1075 40.0695 69.404 6.31385 36.4275 63.0945 10.524 36.4275 63.0945 2.1075 51.5146 61.3939 6.31385 46.8305 55.8105 10.524 46.8305 55.8105 2.1075 61.3909 51.5139 6.31385 55.8113 46.8297 10.524 55.8113 46.8297 2.1075 69.4048 40.0725 6.31385 63.0953 36.4267 10.524 63.0953 36.4267 2.1075 75.308 27.412 6.31385 68.4604 24.9176 10.524 68.4604 24.9176 2.1075 78.9236 13.9164 6.31385 71.7488 12.6522 10.524 71.7488 12.6522 2.1075 80.1426 -0.000703104 6.31385 72.8549 -0.000703104 10.524 72.8549 -0.000703104 2.1075 78.9236 -13.9178 6.31385 71.7488 -12.6498 10.524 71.7488 -12.6498 2.1075 75.308 -27.4097 6.31385 68.4604 -24.919 10.524 68.4604 -24.919 2.1075 69.4048 -40.0701 6.31385 63.0953 -36.4281 10.524 63.0953 -36.4281 2.1075 61.3909 -51.5153 6.31385 55.8113 -46.8311 10.524 55.8113 -46.8311 2.1075 51.5146 -61.3915 6.31385 46.8305 -55.8119 10.524 46.8305 -55.8119 2.1075 40.0695 -69.4054 6.31385 36.4275 -63.0959 10.524 36.4275 -63.0959 2.1075 27.409 -75.3086 6.31385 24.9183 -68.4611 10.524 24.9183 -68.4611 2.1075 13.9171 -78.9243 6.31385 12.653 -71.7494 10.524 12.653 -71.7494 2.1075 7.17174e-05 -80.1433 6.31385 7.17174e-05 -72.8555 10.524 7.17174e-05 -72.8555 2.1075 -13.917 -78.9243 6.31385 -12.6528 -71.7494 10.524 -12.6528 -71.7494 2.1075 -27.4089 -75.3086 6.31385 -24.9182 -68.4611 10.524 -24.9182 -68.4611 2.1075 -40.0693 -69.4054 6.31385 -36.4273 -63.0959 10.524 -36.4273 -63.0959 2.1075 -51.5145 -61.3915 6.31385 -46.8303 -55.8119 10.524 -46.8303 -55.8119 2.1075 -61.3945 -51.5153 6.31385 -55.8111 -46.8311 10.524 -55.8111 -46.8311 2.1075 -69.4046 -40.0701 6.31385 -63.0951 -36.4281 10.524 -63.0951 -36.4281 2.1075 -75.3078 -27.4097 6.31385 -68.4603 -24.919 10.524 -68.4603 -24.919 2.1075 -78.9235 -13.9178 6.31385 -71.7486 -12.6498 10.524 -71.7486 -12.6498 2.1075 -80.1425 -0.000703104 6.31385 -72.8548 -0.000703104 10.524 -72.8548 -0.000703104 2.1075 -78.9235 13.9164 6.31385 -71.7486 12.6522 10.524 -71.7486 12.6522 2.1075 -75.3078 27.412 6.31385 -68.4603 24.9176 10.524 -68.4603 24.9176 2.1075 -69.4046 40.0725 6.31385 -63.0951 36.4267 10.524 -63.0951 36.4267 2.1075 -61.3908 51.5139 6.31385 -55.8111 46.8297 10.524 -55.8111 46.8297 2.1075 -51.5145 61.3939 6.31385 -46.8303 55.8105 10.524 -46.8303 55.8105 2.1075 -40.0693 69.404 6.31385 -36.4273 63.0945 10.524 -36.4273 63.0945 2.1075 -27.4089 75.311 6.31385 -24.9182 68.4597 10.524 -24.9182 68.4597 2.1075 -13.917 78.9266 6.31385 -12.6528 71.748 10.524 -12.6528 71.748 2.1075 7.17174e-05 -0.000703104 221.131 74.4012 -0.000703104 176.05 22.992 70.7585 176.05 -60.1906 43.7333 176.05 -60.1906 -43.7309 176.05 22.992 -70.7599 176.05 60.1907 43.7333 103.109 -22.9919 70.7585 103.109 -74.4011 -0.000703104 103.109 -22.9919 -70.7599 103.109 60.1907 -43.7309 103.109 7.17174e-05 -0.000703104 58.0278 15.2641 -0.000703104 219.746 30.0051 -0.000703104 215.642 43.7303 -0.000703104 208.952 55.9731 -0.000703104 199.907 66.3121 -0.000703104 188.816 4.7181 14.5146 219.746 9.27435 28.537 215.642 13.5146 41.5925 208.952 17.2958 53.2333 199.907 20.49 63.0682 188.816 -12.3481 8.97259 219.746 -24.2748 17.6374 215.642 -35.3814 25.7039 208.952 -45.284 32.9014 199.907 -53.6478 38.9776 188.816 -12.3481 -8.97023 219.746 -24.2748 -17.6388 215.642 -35.3814 -25.7053 208.952 -45.284 -32.899 199.907 -53.6478 -38.979 188.816 4.7181 -14.516 219.746 9.27435 -28.5384 215.642 13.5146 -41.5901 208.952 17.2958 -53.2347 199.907 20.49 -63.0658 188.816 71.0301 14.5146 179.568 65.2436 28.537 181.724 57.2448 41.5925 182.454 47.3045 53.2333 181.724 35.754 63.0682 179.568 8.14564 72.0377 179.568 -6.97915 70.8713 181.724 -21.8669 67.2971 182.454 -36.0097 61.439 181.724 -48.9297 53.4929 179.568 -65.9959 30.0081 179.568 -69.5589 15.2633 181.724 -70.7591 -0.000703104 182.454 -69.5589 -15.2609 181.724 -65.9959 -30.0057 179.568 -48.9297 -53.4943 179.568 -36.0097 -61.4367 181.724 -21.8669 -67.2947 182.454 -6.97915 -70.869 181.724 8.14564 -72.0391 179.568 35.754 -63.0658 179.568 47.3045 -53.2347 181.724 57.2448 -41.5901 182.454 65.2436 -28.5384 181.724 71.0301 -14.516 179.568 78.6603 8.97259 164.605 80.248 17.6374 152.306 79.1117 25.7039 139.578 75.2892 32.9014 126.849 68.9119 38.9776 114.554 15.7758 77.5834 164.605 8.02524 81.771 152.306 7.17174e-05 83.1819 139.578 -8.0251 81.771 126.849 -15.7756 77.5834 114.554 -68.9118 38.9776 164.605 -75.289 32.9014 152.306 -79.1116 25.7039 139.578 -80.2478 17.6374 126.849 -78.6601 8.97259 114.554 -58.3658 -53.4943 164.605 -54.5545 -61.4367 152.306 -48.8921 -67.2947 139.578 -41.5705 -70.869 126.849 -32.838 -72.0391 114.554 32.8382 -72.0391 164.605 41.5707 -70.869 152.306 48.8923 -67.2947 139.578 54.5547 -61.4367 126.849 58.3659 -53.4943 114.554 78.6603 -8.97023 164.605 80.248 -17.6388 152.306 79.1117 -25.7053 139.578 75.2892 -32.899 126.849 68.9119 -38.979 114.554 32.8382 72.0377 164.605 41.5707 70.8713 152.306 48.8923 67.2971 139.578 54.5547 61.439 126.849 58.3659 53.4929 114.554 -58.3658 53.4929 164.605 -54.5545 61.439 152.306 -48.8921 67.2971 139.578 -41.5705 70.8713 126.849 -32.838 72.0377 114.554 -68.9118 -38.979 164.605 -75.289 -32.899 152.306 -79.1116 -25.7053 139.578 -80.2478 -17.6388 126.849 -78.6601 -8.97023 114.554 15.7758 -77.5811 164.605 8.02524 -81.7724 152.306 7.17174e-05 -83.1833 139.578 -8.0251 -81.7724 126.849 -15.7756 -77.5811 114.554 48.9299 53.4929 99.5909 36.0099 61.439 97.4313 21.8671 67.2971 96.7051 6.9793 70.8713 97.4313 -8.14549 72.0377 99.5909 -35.7539 63.0682 99.5909 -47.3044 53.2333 97.4313 -57.2446 41.5925 96.7051 -65.2434 28.537 97.4313 -71.03 14.5146 99.5909 -71.03 -14.516 99.5909 -65.2434 -28.5384 97.4313 -57.2446 -41.5901 96.7051 -47.3044 -53.2347 97.4313 -35.7539 -63.0658 99.5909 -8.14549 -72.0391 99.5909 6.9793 -70.869 97.4313 21.8671 -67.2947 96.7051 36.0099 -61.4367 97.4313 48.9299 -53.4943 99.5909 65.9961 -30.0057 99.5909 69.559 -15.2609 97.4313 70.7592 -0.000703104 96.7051 69.559 15.2633 97.4313 65.9961 30.0081 99.5909 12.3482 8.97259 59.4124 24.275 17.6374 63.5171 35.3815 25.7039 70.2067 45.2841 32.9014 79.2514 53.6479 38.9776 90.343 -4.71796 14.5146 59.4124 -9.27421 28.537 63.5171 -13.5144 41.5925 70.2067 -17.2956 53.2333 79.2514 -20.4899 63.0682 90.343 -15.2639 -0.000703104 59.4124 -30.0049 -0.000703104 63.5171 -43.7301 -0.000703104 70.2067 -55.9729 -0.000703104 79.2514 -66.312 -0.000703104 90.343 -4.71796 -14.516 59.4124 -9.27421 -28.5384 63.5171 -13.5144 -41.5901 70.2067 -17.2956 -53.2347 79.2514 -20.4899 -63.0658 90.343 12.3482 -8.97023 59.4124 24.275 -17.6388 63.5171 35.3815 -25.7053 70.2067 45.2841 -32.899 79.2514 53.6479 -38.979 90.343 20.095 14.6011 217.41 35.0429 14.7102 212.12 24.8205 28.7815 212.12 48.9374 14.793 203.911 39.8851 28.9809 205.261 29.1924 41.9725 203.911 61.1464 14.7667 192.943 53.6554 28.9734 195.046 44.1328 42.0778 195.046 32.936 53.5907 192.943 -7.67519 23.6233 217.41 -3.16409 37.8715 212.12 -19.7035 32.4988 212.12 1.05354 51.1151 203.911 -15.2338 46.8899 205.261 -30.8966 40.7346 203.911 4.84979 62.7145 192.943 -10.971 59.983 195.046 -26.3818 54.979 195.046 -40.7879 47.8869 192.943 -24.8392 -0.000703104 217.41 -36.9955 8.69417 212.12 -36.9955 -8.69557 212.12 -48.2864 16.7946 203.911 -49.3022 -0.000703104 205.261 -48.2864 -16.796 203.911 -58.1476 23.9958 192.943 -60.4389 8.09971 195.046 -60.4389 -8.10112 195.046 -58.1476 -23.9934 192.943 -7.67519 -23.6247 217.41 -19.7035 -32.5002 212.12 -3.16409 -37.8729 212.12 -30.8966 -40.7323 203.911 -15.2338 -46.8913 205.261 1.05354 -51.1127 203.911 -40.7879 -47.8846 192.943 -26.3818 -54.9767 195.046 -10.971 -59.9844 195.046 4.84979 -62.7159 192.943 20.095 -14.6025 217.41 24.8205 -28.7792 212.12 35.0429 -14.7116 212.12 29.1924 -41.9701 203.911 39.8851 -28.9786 205.261 48.9374 -14.7944 203.911 32.936 -53.5884 192.943 44.1328 -42.0792 195.046 53.6554 -28.9711 195.046 61.1464 -14.7643 192.943 82.1141 -0.000703104 152.603 82.7274 -8.69557 139.578 82.7274 8.69417 139.578 80.2856 -16.796 126.007 81.9749 -0.000703104 125.721 80.2856 16.7946 126.007 74.6872 -23.9934 112.454 77.6331 -8.10112 111.386 77.6331 8.09971 111.386 74.6872 23.9958 112.454 25.3736 78.0951 152.603 33.8352 75.9919 139.578 17.2958 81.3646 139.578 40.7843 71.1648 126.007 25.3322 77.9597 125.721 8.83415 81.5452 126.007 45.9012 63.6175 112.454 31.6944 71.3304 111.386 16.2874 76.3381 111.386 0.259676 78.4488 112.454 -66.4324 48.2669 152.603 -61.8159 55.66 139.578 -72.0383 41.5925 139.578 -55.0812 60.7769 126.007 -66.3195 48.1842 125.721 -74.8225 33.6012 126.007 -46.3224 63.3127 112.454 -58.046 52.1836 111.386 -67.5686 39.0792 111.386 -74.529 24.4887 112.454 -66.4324 -48.2646 152.603 -72.0383 -41.5901 139.578 -61.8159 -55.6614 139.578 -74.8225 -33.6026 126.007 -66.3195 -48.1818 125.721 -55.0775 -60.7783 126.007 -74.529 -24.4901 112.454 -67.5686 -39.0768 111.386 -58.046 -52.185 111.386 -46.3224 -63.3104 112.454 25.3736 -78.0965 152.603 17.2958 -81.366 139.578 33.8352 -75.9896 139.578 8.83415 -81.5466 126.007 25.3322 -77.9611 125.721 40.7843 -71.1662 126.007 0.259676 -78.4464 112.454 16.2874 -76.3357 111.386 31.6944 -71.3318 111.386 45.9012 -63.6189 112.454 66.4325 48.2669 126.556 61.8161 55.66 139.578 72.0385 41.5925 139.578 55.0776 60.7769 153.152 66.3159 48.1842 153.438 74.8226 33.6012 153.152 46.3188 63.3127 166.701 58.0461 52.1836 167.773 67.5687 39.0792 167.773 74.5292 24.4887 166.701 -25.3735 78.0951 126.556 -33.8351 75.9919 139.578 -17.2956 81.3646 139.578 -40.7842 71.1648 153.152 -25.3321 77.9597 153.438 -8.83401 81.5452 153.152 -45.901 63.6175 166.701 -31.6943 71.3304 167.773 -16.2873 76.3381 167.773 -0.259533 78.4488 166.701 -82.114 -0.000703104 126.556 -82.7272 -8.69557 139.578 -82.7272 8.69417 139.578 -80.2855 -16.796 153.152 -81.9748 -0.000703104 153.438 -80.2855 16.7946 153.152 -74.687 -23.9934 166.701 -77.633 -8.10112 167.773 -77.633 8.09971 167.773 -74.687 23.9958 166.701 -25.3735 -78.0965 126.556 -17.2956 -81.366 139.578 -33.8351 -75.9896 139.578 -8.83401 -81.5466 153.152 -25.3321 -77.9611 153.438 -40.7842 -71.1662 153.152 -0.259533 -78.4464 166.701 -16.2873 -76.3357 167.773 -31.6943 -71.3318 167.773 -45.901 -63.6189 166.701 66.4325 -48.2646 126.556 72.0385 -41.5901 139.578 61.8161 -55.6614 139.578 74.8226 -33.6026 153.152 66.3159 -48.1818 153.438 55.0776 -60.7783 153.152 74.5292 -24.4901 166.701 67.5687 -39.0768 167.773 58.0461 -52.185 167.773 46.3188 -63.3104 166.701 7.67534 23.6233 61.7488 3.16424 37.8715 67.035 19.7037 32.4988 67.035 -1.0534 51.1151 75.2483 15.234 46.8899 73.8938 30.8968 40.7346 75.2483 -4.8534 62.7145 86.2156 10.9712 59.983 84.1124 26.3819 54.979 84.1124 40.7881 47.8869 86.2156 -20.0948 14.6011 61.7488 -35.0428 14.7102 67.035 -24.8204 28.7815 67.035 -48.9373 14.793 75.2483 -39.885 28.9809 73.8938 -29.1923 41.9725 75.2483 -61.1462 14.7667 86.2156 -53.6591 28.9734 84.1124 -44.1365 42.0778 84.1124 -32.9396 53.5907 86.2156 -20.0948 -14.6025 61.7488 -24.8204 -28.7792 67.035 -35.0428 -14.7116 67.035 -29.1923 -41.9701 75.2483 -39.885 -28.9786 73.8938 -48.9373 -14.7944 75.2483 -32.9396 -53.5884 86.2156 -44.1365 -42.0792 84.1124 -53.6591 -28.9711 84.1124 -61.1462 -14.7643 86.2156 7.67534 -23.6247 61.7488 19.7037 -32.5002 67.035 3.16424 -37.8729 67.035 30.8968 -40.7323 75.2483 15.234 -46.8913 73.8938 -1.0534 -51.1127 75.2483 40.7881 -47.8846 86.2156 26.3819 -54.9767 84.1124 10.9712 -59.9844 84.1124 -4.8534 -62.7159 86.2156 24.8393 -0.000703104 61.7488 36.9956 8.69417 67.035 36.9956 -8.69557 67.035 48.2865 16.7946 75.2483 49.3024 -0.000703104 73.8938 48.2865 -16.796 75.2483 58.1477 23.9958 86.2156 60.439 8.09971 84.1124 60.439 -8.10112 84.1124 58.1477 -23.9934 86.2156 53.0121 20.35 169.353 -53.0119 -20.3514 169.353 -53.0119 -20.3514 55.7854 53.0121 20.35 55.7854 12.1864 60.8897 85.6362 12.2955 60.8709 85.64 12.9126 60.743 85.7227 7.17174e-05 62.0485 85.7867 10.546 61.1418 85.5309 0.541855 61.8529 85.5835 10.6777 60.7844 85.0944 11.9645 60.6489 85.26 12.8712 60.5549 85.4932 7.17174e-05 61.9093 85.6099 24.7415 56.8978 85.7227 25.2607 56.7323 85.7227 13.5146 60.3442 85.4932 25.1817 56.5555 85.4895 36.1077 50.419 85.7754 36.4726 50.197 85.7867 27.4053 55.6675 85.5309 25.8326 56.4727 85.64 36.3899 50.0842 85.6061 27.0892 55.4531 85.0907 26.0809 56.0363 85.2412 25.9718 56.1002 85.2562 45.9463 41.5436 85.9071 46.0329 41.4533 85.9146 40.0619 47.364 85.4142 37.1837 49.6628 85.6889 41.2847 46.2277 85.4443 36.8714 49.6515 85.5121 39.7008 47.1006 85.0117 41.5142 45.4715 85.0944 46.0065 41.4269 85.877 36.4689 50.0127 85.5835 53.5802 31.0766 85.9109 53.6479 30.975 85.9146 50.0548 36.3703 85.5798 46.093 41.3103 85.862 49.8103 36.1897 85.2562 53.6141 30.9562 85.8732 58.84 19.6766 85.7265 59.0131 19.1762 85.7867 56.7218 24.9815 85.4443 57.4254 23.4691 85.4105 58.7196 20.0152 85.6889 53.678 30.8132 85.8544 56.0747 25.433 85.0907 57.0642 23.2057 85.0117 58.8362 19.2251 85.5835 58.8776 19.131 85.6061 61.6768 7.22308 85.6362 61.6919 7.11397 85.6437 61.7596 6.48941 85.7265 61.4097 8.86348 85.5309 58.9905 18.593 85.5798 61.1125 8.63021 85.0944 61.3834 7.35852 85.2637 61.5715 6.4706 85.4932 61.7596 -5.9528 85.7265 61.7596 -6.49082 85.7265 61.5715 5.79713 85.4932 61.5715 -6.47201 85.4932 59.1071 -18.76 85.7754 59.0131 -19.1776 85.7867 61.6919 -7.11537 85.6437 61.4097 -8.86488 85.5309 61.357 -7.47656 85.2487 61.1125 -8.63161 85.0944 58.8776 -19.1324 85.6061 61.3834 -7.35993 85.2637 53.7044 -30.8598 85.9071 53.6479 -30.9727 85.9146 57.4254 -23.4667 85.4105 56.7218 -24.9792 85.4443 58.7196 -20.0166 85.6889 57.0642 -23.2033 85.0117 56.0747 -25.4307 85.0944 53.6141 -30.9538 85.8732 58.6143 -19.7231 85.5121 58.8362 -19.2303 85.5835 46.1119 -41.3531 85.9109 46.0329 -41.4509 85.9146 50.0548 -36.3679 85.5798 46.0065 -41.4246 85.8732 49.8103 -36.1911 85.2524 53.5275 -31.0742 85.8582 36.8903 -49.8824 85.7303 36.4726 -50.1984 85.7867 41.2847 -46.2291 85.4443 40.0657 -47.3616 85.4142 37.1912 -49.6567 85.6889 41.5105 -45.4729 85.0944 39.7045 -47.102 85.0154 36.4764 -50.0066 85.5873 36.3899 -50.0856 85.6099 45.8899 -41.5299 85.8544 25.9304 -56.4252 85.6362 25.8326 -56.4741 85.6437 25.2607 -56.7299 85.7227 27.409 -55.6652 85.5309 35.9196 -50.3565 85.5873 27.093 -55.4545 85.0944 25.9681 -56.1016 85.2637 25.1817 -56.5569 85.4932 13.428 -60.5751 85.7227 12.9126 -60.7444 85.7227 24.5383 -56.7638 85.4932 12.8712 -60.5563 85.4932 0.417696 -62.0161 85.7754 7.17174e-05 -62.05 85.7867 12.2955 -60.8723 85.6437 10.546 -61.1432 85.5309 11.8478 -60.6654 85.2449 10.6777 -60.7858 85.0944 7.17174e-05 -61.9107 85.6099 11.9645 -60.6503 85.26 -12.7544 -60.6127 85.9071 -12.8786 -60.5939 85.9146 -4.57499 -61.8656 85.4142 -0.899138 -62.0349 85.6889 -6.23044 -61.6662 85.4443 -0.639534 -61.843 85.5158 -4.43578 -61.4442 85.0117 -6.85876 -61.1884 85.0944 -12.871 -60.5563 85.877 -0.116562 -61.8995 85.5873 -25.0837 -56.6321 85.9109 -25.1966 -56.5907 85.9184 -19.1166 -58.8444 85.5798 -25.1816 -56.5569 85.877 -19.0263 -58.5585 85.2562 -13.0103 -60.5111 85.862 -36.0398 -50.4994 85.7303 -36.4725 -50.1984 85.7867 -31.2089 -53.5507 85.4443 -32.665 -52.7381 85.4142 -35.7388 -50.7101 85.6889 -25.3133 -56.4816 85.8582 -30.4226 -53.5319 85.0944 -32.5295 -52.3129 85.0117 -36.2919 -50.142 85.5873 -36.3897 -50.0856 85.6099 -45.6452 -42.1018 85.6324 -45.728 -42.019 85.64 -46.1493 -41.5525 85.7227 -44.4751 -43.2681 85.5309 -36.7961 -49.7206 85.5835 -44.3697 -42.8994 85.0907 -45.3291 -42.0341 85.2562 -46.0064 -41.4246 85.4895 -53.4597 -31.4919 85.7227 -53.7795 -31.0479 85.7227 -46.4052 -40.8715 85.4895 -53.6139 -30.9538 85.4895 -58.8474 -19.5689 85.7754 -59.0129 -19.1776 85.7867 -54.0955 -30.5024 85.64 -54.8931 -28.9259 85.5309 -54.0353 -30.0095 85.2412 -54.5094 -28.941 85.0907 -58.8775 -19.1324 85.6061 -53.9864 -30.1186 85.26 -61.5902 -6.59993 85.9071 -61.609 -6.47577 85.9184 -60.2508 -14.7681 85.4142 -59.2725 -18.3198 85.6889 -60.5743 -13.1314 85.4443 -59.0129 -18.5004 85.5158 -59.8068 -14.7681 85.0117 -60.3147 -12.3865 85.0944 -61.5714 -6.47201 85.877 -58.9001 -19.0271 85.5835 -61.6127 6.35397 85.9109 -61.609 6.47436 85.9184 -61.8723 -0.000703104 85.5798 -61.5714 -6.32903 85.862 -61.5714 -0.000703104 85.2562 -61.5714 6.4706 85.877 -59.1672 18.6645 85.7265 -59.0129 19.1762 85.7829 -60.5743 13.13 85.4443 -60.2508 14.7704 85.4105 -59.2725 18.3259 85.6889 -61.5413 6.62109 85.8582 -60.311 12.3851 85.0944 -59.8068 14.7704 85.0117 -58.9001 19.0294 85.5835 -58.8775 19.131 85.6061 -54.1444 30.4069 85.6324 -54.0955 30.5047 85.64 -53.7795 31.0503 85.7227 -54.8931 28.9283 85.5309 -58.6517 19.6352 85.5798 -54.5094 28.9396 85.0907 -53.9864 30.121 85.26 -53.6139 30.9562 85.4895 -46.4691 41.1146 85.7227 -46.1493 41.5548 85.7227 -53.2113 31.5055 85.4857 -46.0064 41.4194 85.4857 -36.7961 49.9186 85.7754 -36.4725 50.2008 85.7867 -45.728 42.0176 85.6437 -44.4751 43.2667 85.5309 -45.2276 42.1192 85.2374 -44.366 42.8905 85.0831 -36.3897 50.0804 85.6023 -45.3216 42.0327 85.2524 -25.3133 56.5329 85.9071 -25.1966 56.5893 85.9146 -32.665 52.7404 85.4105 -35.7426 50.7087 85.6889 -31.2051 53.5493 85.4443 -35.8216 50.4077 85.5083 -32.5257 52.304 85.0004 -30.4 53.5343 85.0831 -25.1816 56.5555 85.8732 -36.3069 50.1256 85.5835 -12.9952 60.5586 85.9109 -12.8786 60.5925 85.9146 -19.1166 58.843 85.5798 -12.871 60.5549 85.8732 -19.0225 58.5495 85.2449 -25.0386 56.6006 85.8582 -0.5229 62.041 85.7303 -6.23044 61.6648 85.4443 -4.57499 61.8642 85.4142 -0.899138 62.0335 85.6889 -12.713 60.5699 85.8544 -6.85876 61.187 85.0944 -4.43578 61.4428 85.0117 -0.116562 61.8981 85.5873 -33.8087 -67.7989 8.69168 -32.7139 -68.1262 8.7895 -28.2178 -69.4656 9.18831 -31.5061 -69.9434 4.50038 -28.1162 -71.1211 4.28592 -34.8772 -67.5017 8.58633 -35.2648 -68.683 4.75622 -34.1962 -69.0405 4.68474 -28.9101 -74.1046 6.57722 -28.8047 -73.4199 6.96474 -28.3457 -70.4476 8.639 -28.5113 -72.8894 5.31305 -28.8988 -74.2777 6.13702 -31.6077 -73.3522 6.31385 -37.9135 -65.6694 8.80831 -38.3913 -66.9335 4.60573 -39.9151 -64.567 8.66534 -40.9046 -64.0214 8.59385 -41.7285 -64.9545 4.75246 -38.5832 -66.8282 4.59444 -48.1961 -61.1056 7.55167 -45.9311 -59.2357 9.19584 -48.4745 -61.0604 5.14375 -47.4173 -59.9806 4.28216 -49.5994 -62.1591 6.5885 -49.1292 -61.6624 5.64791 -49.7575 -62.2381 6.12949 -45.2012 -59.9468 9.10178 -44.3923 -60.7143 9.00395 -44.3547 -62.6858 4.54929 -44.9868 -62.129 4.49285 -47.1802 -64.424 6.31385 75.4133 4.41634 8.82336 75.1913 5.35693 8.90237 74.0438 10.1653 9.32376 76.1545 7.65199 4.39879 75.4886 11.1247 4.19186 75.6692 3.43059 8.72554 76.9597 3.69396 4.66216 76.6361 5.28545 4.55681 78.4006 11.8771 6.72019 77.9605 11.7078 6.98355 74.8715 10.5076 8.82712 77.2456 11.674 5.23404 78.6189 12.0239 6.04296 79.4654 7.71595 6.31385 75.6503 -2.46883 8.78574 75.6014 -0.000703104 8.93623 77.0048 0.168604 4.51167 75.6692 -3.51101 8.72178 76.9559 -3.77061 4.66592 77.0086 -0.000703104 4.50414 76.828 -11.2803 7.65702 74.0438 -10.2457 9.31999 76.9333 -11.57 5.04593 75.4886 -11.1976 4.19563 78.4044 -11.9538 6.71266 78.0507 -11.9199 5.71187 78.6189 -12.0968 6.04672 74.2771 -9.3427 9.2297 74.4614 -8.56013 9.16197 76.3163 -7.13795 4.46652 76.2034 -7.68349 4.42889 79.281 -8.20646 6.39662 79.3074 -8.33062 6.25365 79.4993 -7.35993 6.31385 -41.4501 62.9139 8.93999 -41.9091 62.4775 8.99267 -45.7844 58.8054 9.44792 -44.7685 61.8905 4.3085 -47.406 59.6143 4.10533 -40.7804 63.5686 8.8497 -41.6984 64.6032 4.57563 -43.0491 63.4105 4.45899 -49.4414 61.7212 6.84811 -49.3398 61.6384 6.91959 -46.4315 59.302 8.99643 -48.7792 60.8747 5.1588 -49.7537 61.8755 5.95642 -46.3751 64.7198 6.44177 -45.2464 65.7808 6.31385 -46.3337 64.8591 6.2386 -37.684 65.2729 9.06791 -38.7073 66.3866 4.42889 -35.5959 66.5371 8.91742 -38.4252 66.5559 4.41384 -34.7794 67.0299 8.86098 -35.2196 68.3468 4.57186 -39.9264 69.3325 6.38533 -39.8361 69.389 6.37781 -39.8774 69.4115 6.2687 -38.9632 69.9195 6.31385 -41.0739 68.7004 6.31385 -40.0016 69.2874 6.39286 -40.1408 69.2573 6.2687 -40.0242 69.3288 6.26494 -28.6543 71.9511 7.77365 -28.1539 68.9826 9.45544 -28.4398 72.2032 4.93682 -28.0485 70.7923 4.0978 -28.8537 73.6066 6.85563 -28.7333 73.5163 5.69682 -28.8311 73.9565 5.9489 -29.0907 68.7193 9.36514 -32.0329 69.4567 4.37246 -28.959 68.7569 9.37643 -31.6303 69.5921 4.34612 -32.6198 72.4666 6.53207 -32.379 72.6886 6.15583 -34.8133 71.8571 6.31385 -11.9342 -4.58329 59.4124 -17.4837 -6.7128 60.4847 -23.8045 -9.13954 62.411 -34.5461 -13.2631 66.6888 -35.6485 -13.6845 67.257 -38.3725 -14.7304 69.0027 -39.7646 -15.2647 69.9734 -46.8905 -18 74.9435 -50.461 -19.3732 78.1114 -53.0119 -20.3514 80.7225 12.3482 4.7399 59.4124 16.1896 6.21476 60.131 24.5383 9.42031 62.6932 31.9277 12.2571 65.6354 36.4914 14.0067 68.0245 46.6649 17.912 74.6162 47.9818 18.4199 75.6508 53.0121 20.35 80.5457 6.32419 72.3013 10.524 6.32175 72.3015 2.1075 18.7856 70.1038 2.1075 18.7806 70.1052 10.524 30.6709 65.778 2.1075 30.6676 65.7796 10.524 41.6261 59.4545 2.1075 41.627 59.4539 10.524 51.3198 51.3212 2.1075 51.3165 51.3245 10.524 59.4514 41.6309 2.1075 59.4498 41.6331 10.524 65.7754 30.6774 2.1075 65.7752 30.6779 10.524 70.1039 18.7876 2.1075 70.1041 18.7867 10.524 72.3015 6.32954 10.524 72.3016 6.3287 2.1075 72.3017 -6.32719 10.524 72.3022 -6.32147 2.1075 70.1061 -18.7786 2.1075 70.105 -18.7829 10.524 65.7789 -30.6712 10.524 65.779 -30.6711 2.1075 59.4568 -41.6246 10.524 59.4555 -41.6265 2.1075 51.3229 -51.3195 10.524 51.324 -51.3184 2.1075 41.6294 -59.4536 10.524 41.6297 -59.4534 2.1075 30.6761 -65.777 2.1075 30.6773 -65.7764 10.524 18.7859 -70.1051 10.524 18.7912 -70.1037 2.1075 6.32767 -72.3024 10.524 6.32856 -72.3023 2.1075 -6.32606 -72.3025 10.524 -6.32464 -72.3026 2.1075 -18.7843 -70.1056 2.1075 -18.7827 -70.106 10.524 -30.6691 -65.7802 2.1075 -30.6725 -65.7786 10.524 -41.6333 -59.4508 10.524 -41.6254 -59.4563 2.1075 -51.3173 -51.325 2.1075 -51.3189 -51.3233 10.524 -59.4503 -41.6337 2.1075 -59.4502 -41.6338 10.524 -65.7757 -30.6779 2.1075 -65.7753 -30.6786 10.524 -70.1044 -18.7845 2.1075 -70.1042 -18.7852 10.524 -72.3015 -6.32731 2.1075 -72.3014 -6.32806 10.524 -72.3022 6.31988 2.1075 -72.3018 6.32419 10.524 -70.1053 18.7816 10.524 -70.1051 18.7825 2.1075 -65.7786 30.6703 10.524 -65.7782 30.671 2.1075 -59.4564 41.6235 10.524 -59.4548 41.6259 2.1075 -51.3224 51.3184 10.524 -51.3225 51.3184 2.1075 -41.6303 59.4515 10.524 -41.6325 59.4499 2.1075 -30.6764 65.7754 2.1075 -30.6694 65.7787 10.524 -18.791 70.1023 10.524 -18.7895 70.1027 2.1075 -6.3266 72.301 2.1075 -6.33262 72.3005 10.524 10.8124 61.5579 84.977 12.5621 61.8742 84.3474 6.80838 61.1932 81.1987 13.147 61.8483 84.301 13.6338 60.5086 85.7227 31.6411 55.7303 82.782 30.6202 53.4148 82.0025 30.4643 53.5054 81.7184 43.3633 46.3891 83.5382 40.9447 47.553 84.4872 43.0165 47.3986 78.3715 51.961 36.7012 83.385 49.9399 38.7723 83.9116 51.9327 37.4204 78.3721 58.8165 20.0076 85.5834 59.0629 19.7225 85.4454 58.5041 23.3956 84.2 59.6858 24.6545 78.6882 61.8879 8.73818 84.9763 62.7305 7.17077 84.3459 61.5293 9.52279 85.2096 62.8865 6.60869 84.3005 61.7596 5.73505 85.7265 62.7779 -12.874 82.7835 65 -13.8118 79.7895 57.9285 -26.4774 83.2815 57.8765 -24.2465 84.4876 55.9421 -25.7241 82.3918 56.1861 -25.177 81.3572 50.9568 -38.0776 83.3876 52.3019 -35.5161 83.914 48.765 -37.6292 82.9727 51.112 -34.3984 82.9993 37.2125 -49.7518 85.5803 37.0086 -50.0893 85.4356 40.3307 -48.4105 84.203 42.2642 -44.7952 82.4585 27.4366 -56.1577 84.9763 26.2052 -57.4438 84.3461 28.0727 -55.5751 85.2098 25.7198 -57.7636 84.3004 24.539 -56.9645 85.7227 18.2795 -61.9365 78.6883 7.14857 -63.6852 82.785 6.43458 -63.6871 78.3732 -7.28317 -63.2741 83.2828 -5.17674 -62.5373 84.488 -20.4663 -60.2314 83.3856 -20.5319 -63.1998 79.7895 -17.6113 -60.7203 83.9119 -20.7188 -58.0081 82.974 -16.9186 -59.2414 83.0022 -35.8211 -50.7595 85.5837 -36.1966 -50.6718 85.4423 -33.5813 -53.3132 84.2025 -44.9298 -43.4442 84.9762 -46.526 -42.6744 84.3493 -44.1857 -43.8684 85.2114 -46.9882 -42.3076 84.3034 -46.5985 -40.9344 85.7227 -53.2594 -36.5209 78.6891 -58.3567 -26.483 82.7846 -58.6844 -19.566 85.925 -58.5813 -25.8002 78.3732 -62.4297 -12.6285 83.2819 -61.0775 -14.4041 84.4869 -62.6664 -13.0548 78.3737 -63.6084 0.852646 83.386 -63.1911 -2.01182 83.9122 26.9158 55.5542 84.5702 -59.3406 18.3864 85.5851 -59.3718 18.7571 85.4491 -61.0845 15.4636 84.1998 -55.2027 29.3084 84.9748 -54.9639 31.0681 84.3457 -55.3763 28.4659 85.2103 -54.7594 31.616 84.2997 -53.3293 31.67 85.7227 -43.2214 47.315 82.7845 -44.4658 49.3824 79.7895 -31.2998 55.4714 83.2841 -33.2257 57.5487 79.7895 -32.5712 53.6353 84.4871 -18.8631 60.7579 83.3778 -20.537 63.1967 79.7895 -21.4411 59.4768 83.9096 -17.3243 59.0741 82.9567 -21.1277 57.8377 82.997 -4.17349 62.8708 84.202 -4.12798 62.9349 84.1281 -7.86627 61.0806 82.4621 -6.43423 63.6331 78.3732 -57.3113 -91.4372 -24.562 -18.9548 -63.1045 75.3109 -20.5945 -64.7691 77.9205 -19.0203 -58.5585 76.9564 -33.6152 -55.7212 74.0408 -41.0622 -50.8344 73.536 -27.5633 -66.0187 65.6663 -35.7301 -62.6601 65.6211 -25.2803 -74.0233 57.6551 -28.857 -75.1677 59.3042 -40.7043 -70.8288 57.9883 -32.3804 -72.1854 47.0457 -39.6178 -69.2999 47.2892 -46.5388 -59.1525 45.6893 -44.6455 -60.141 48.2714 -31.7054 -70.2786 36.5724 -37.9466 -67.7281 35.4778 -44.0797 -58.5981 28.5104 -43.5881 -58.0303 28.6349 -41.2114 -60.7057 31.2201 -29.8009 -67.9399 14.2052 -28.2826 -68.3026 14.6094 -32.0692 -67.7858 10.4513 -34.4329 -66.1104 16.5838 -28.8324 -70.2078 16.259 -33.4147 -69.8811 17.4543 -36.5618 -64.9707 16.0287 -37.6207 -65.286 10.3133 -39.858 -62.8789 17.1989 -39.0326 -67.2666 18.3915 -45.5472 -59.3892 14.0639 -44.9799 -58.7546 14.0393 -41.7745 -61.1099 16.6886 -43.5782 -60.7856 10.5212 -32.7659 -72.7823 6.84528 -39.2255 -64.6359 9.56127 -40.2328 -69.567 6.42948 -48.6737 -61.0254 3.41492 -43.0612 -61.7117 9.45589 -44.8636 -59.9847 9.71094 -47.0069 -64.6895 6.08468 -31.8123 -75.4368 -7.17248 -40.4476 -71.4673 -6.93355 -54.1943 -63.8257 -8.15789 -54.471 -66.8197 -6.63984 -58.6355 -67.1841 -13.4004 -57.0128 -71.9878 -13.4552 -57.6836 -75.1758 -16.1718 -38.3583 -90.2674 -18.6028 -41.8306 -92.5396 -21.1275 -48.6253 -85.6495 -18.195 -50.8851 -88.2887 -20.6286 -56.8274 -76.6575 -21.8952 -42.1232 -93.7061 -21.9719 -51.0567 -90.0764 -21.5555 -52.3756 -91.2023 -22.4834 -57.8347 -83.2245 -24.6449 -48.1945 -95.6388 -24.5405 -48.0791 -95.0487 -23.6007 -52.5914 -92.9485 -23.177 -56.7991 -89.6558 -25.1362 107.657 -4.02063 -24.5622 68.1669 10.4336 76.6806 64.4135 -10.2676 73.5573 70.7721 9.02894 65.6666 76.5603 15.0128 57.6551 79.341 12.4866 59.3046 78.5194 7.94489 47.0466 74.3111 -10.8341 45.6878 74.2206 -8.70306 48.2768 76.5285 7.57315 36.5707 72.6034 -8.98299 28.5127 71.8657 -8.84068 28.6355 72.9941 -5.44328 31.2168 73.5579 8.13504 14.0545 73.1307 9.56844 14.4442 74.6174 5.73588 10.4371 74.2891 3.1272 16.5569 75.0727 10.0437 16.1559 77.0461 5.88421 17.4303 75.165 -0.0429653 10.3133 74.021 -9.85799 14.0623 73.1885 -9.68454 14.0362 73.4912 -5.93186 17.2441 74.1586 -7.83706 10.5408 79.4706 7.6442 6.34642 75.3832 -1.70558 9.62496 77.0016 -11.7575 3.33875 74.6711 -7.02483 9.50515 74.1723 -9.08356 9.70458 81.0498 10.0575 -7.1705 82.186 -15.1297 -8.1608 84.9174 -13.8706 -6.64097 87.3152 -17.2932 -13.4017 90.6612 -13.4855 -13.4535 93.7591 -12.4767 -16.1719 97.1708 11.8024 -18.6043 100.871 9.93554 -21.1275 94.614 -10.9924 -21.895 102.028 10.266 -21.9718 100.809 -8.57741 -24.6449 106.737 5.97295 -24.5403 106.169 5.77996 -23.6005 105.859 -4.46762 -25.1361 -50.3458 95.0304 -24.562 -45.0814 47.7532 75.3113 -45.6957 50.1526 77.9043 -35.8137 58.6943 77.2133 -31.3605 56.7624 74.039 -23.3163 60.7475 73.5586 -43.2082 56.5621 65.6649 -36.2175 61.9559 65.6192 -51.2809 58.5848 57.6538 -50.4843 62.254 59.3045 -40.8006 70.3454 57.9875 -46.1397 63.8137 47.047 -27.7731 69.5587 45.6875 -29.5759 68.4128 48.2724 -44.8236 62.2755 36.5704 -39.4926 66.4068 35.4718 -28.5229 67.1529 28.5104 -28.2774 66.4436 28.6338 -31.7827 65.7227 31.2191 -43.8058 59.4287 14.0902 -44.8438 58.3308 14.4812 -41.998 61.7942 10.4181 -39.8546 62.5556 16.5595 -46.2267 59.7708 16.179 -43.9591 63.0265 18.8351 -37.8102 63.8255 16.0096 -37.5463 64.8988 10.3133 -34.341 65.6358 17.1943 -28.4738 68.8169 14.0639 -28.2079 68.0088 14.039 -31.8525 66.4103 16.6843 -31.4016 67.5815 10.4826 -36.0924 65.955 9.71669 -43.6502 67.3393 6.01276 -28.3145 72.3543 3.26066 -31.6779 67.7209 9.80806 -36.6106 71.3892 6.05023 -49.2341 64.9487 -7.16917 -41.484 70.4405 -6.93561 -27.991 78.5235 -8.157 -32.6135 78.0958 -4.44536 -44.3026 76.1443 -15.6126 -28.6815 84.0503 -13.4013 -33.6485 85.0477 -13.4571 -36.0772 87.2207 -16.1717 -58.8088 78.0368 -18.6039 -59.0402 82.175 -21.1275 -49.6775 84.6141 -18.1941 -50.8338 87.8919 -20.6286 -37.7883 87.2217 -21.8951 -59.9023 83.0116 -21.9719 -52.2946 88.9349 -21.5556 -52.6101 90.6391 -22.4834 -42.9726 91.3765 -24.6449 -58.5419 89.2346 -24.5404 -58.0919 88.8393 -23.6005 -54.013 91.6994 -23.1775 -49.0545 93.6948 -25.1364 7.54736 75.135 8.82512 5.60699 75.3006 3.80216 20.4779 72.6845 8.82461 18.6049 73.1851 3.80414 32.788 68.0245 8.82494 31.0284 68.8405 3.80382 44.1023 61.2957 8.82511 42.5101 62.4089 3.80335 54.0769 52.7086 8.82453 52.7043 54.0772 3.80437 62.4072 42.5172 8.8244 61.2888 44.1069 3.80246 68.8417 31.036 8.82423 68.0141 32.7959 3.80166 73.1845 18.6063 8.82561 75.2907 13.2763 8.44557 72.6768 20.4843 3.80256 75.3329 13.2837 4.20873 73.538 5.84035 9.83436 75.3463 7.22963 3.91041 75.7498 4.04644 3.98273 77.5037 3.97757 4.99153 79.4723 7.63726 6.31385 79.4111 7.66934 6.28015 77.2393 -4.37491 7.76935 78.7507 -7.53827 6.73707 76.4259 -2.91723 8.31447 74.8295 -7.02134 9.02782 75.9883 -7.18984 4.27973 73.974 -10.169 3.26712 74.8801 -4.17649 3.48769 72.6805 -20.4819 8.82593 73.1823 -18.5946 3.80167 75.339 -13.2843 4.21234 68.0228 -32.7894 8.82528 68.8411 -31.0262 3.80303 61.2986 -44.1019 8.82447 62.4082 -42.5102 3.80321 42.5092 -62.4089 8.82683 44.104 -61.2937 3.80379 31.0328 -68.8422 8.8249 32.7938 -68.0166 3.80232 18.6031 -73.1846 8.8263 20.4864 -72.6762 3.80205 5.61375 -75.3034 8.82574 7.55226 -75.1332 3.80319 -7.5494 -75.135 8.82585 -5.60919 -75.3015 3.80287 -20.4786 -72.6836 8.82494 -26.1643 -71.8869 8.41766 -18.6045 -73.1849 3.80407 -26.1632 -71.884 4.21014 -31.657 -66.7972 9.74785 -31.4587 -68.8695 3.9243 -34.5641 -68.0603 4.2598 -35.2829 -69.108 4.98617 -32.8731 -72.7619 6.31385 -32.2916 -72.2131 5.88346 -42.3212 -64.8781 7.71517 -46.8595 -64.6487 6.31385 -40.7444 -65.0542 8.15652 -43.1459 -61.8962 8.85739 -44.1775 -62.2204 4.26734 -45.8434 -59.1938 3.38451 -41.0342 -62.8576 3.5265 -54.0778 -52.7051 8.82551 -52.6996 -54.0804 3.80264 -49.1746 -58.6043 4.21261 -62.4088 -42.5167 8.82492 -61.2898 -44.1062 3.80281 -68.8415 -31.0356 8.8243 -68.0145 -32.7954 3.80187 -73.1844 -18.6039 8.82561 -72.6816 -20.4806 3.80454 -75.3028 -5.61475 8.82563 -75.1335 -7.54895 3.80375 -75.1332 7.55028 8.82635 -75.2989 5.60428 3.80157 -72.6817 20.4791 8.82537 -73.1827 18.5993 3.80235 -68.0206 32.791 8.82599 -68.841 31.0276 3.80338 -61.2976 44.1024 8.82472 -62.4084 42.506 3.80242 -52.7038 54.0773 8.82567 -48.9631 58.3527 8.60702 -54.0798 52.6983 3.80242 -49.1717 58.6014 4.21004 -41.8605 60.604 9.89915 -44.0371 61.4249 3.84461 -41.3481 63.3293 3.85494 -28.2727 69.0256 3.22629 -31.874 69.2621 4.23241 -33.8778 66.7856 3.42156 -18.6109 73.1866 8.82404 -20.4881 72.6746 3.80137 -26.1645 71.8878 4.2122 -5.61902 75.3059 8.8241 -7.552 75.1318 3.80323 0.528281 61.7867 85.5015 13.7464 59.0819 84.1124 -12.679 62.8915 88.2812 -0.283228 62.3231 86.1041 -0.894862 62.0989 85.772 12.7345 61.1656 86.1474 12.0571 61.3194 86.1688 12.1311 60.3321 84.9554 25.6753 56.9019 86.0788 35.9718 50.2886 85.5437 35.9616 50.2624 85.5096 47.2135 43.4354 88.2778 -61.5714 6.34285 85.8647 -61.5049 6.39383 85.7984 -51.945 31.3322 84.1124 -63.7298 7.38083 88.2799 -58.5973 19.6039 85.4985 -54.641 27.1368 84.401 -54.2208 30.9461 86.0804 -54.5296 30.4281 86.0991 -53.6316 30.1812 84.9512 -36.7142 49.7452 85.5399 -36.6935 49.7282 85.5109 -26.7161 58.3284 88.2788 -39.9046 -14.7397 69.9085 -45.6307 -14.9639 73.3468 -36.7466 -49.6747 85.5018 -45.8503 -39.7201 84.1124 -26.7099 -58.3308 88.2809 -42.6943 -43.5805 84.4015 -42.9321 -44.1942 85.1842 -46.1851 -42.002 86.0792 -45.7891 -42.4541 86.0974 -45.8743 -41.1541 85.1673 -52.2528 -31.2782 84.3794 -58.6868 -19.5606 85.5836 -58.6595 -19.5434 85.5437 -63.7267 -7.38943 88.2773 35.891 -50.2948 85.5018 23.6076 -55.8782 84.1124 47.2217 -43.4293 88.2805 27.5445 -54.4135 84.2922 27.9531 -54.9577 85.1425 25.6514 -56.9687 86.1493 26.2876 -56.6959 86.1707 0.450533 -61.8317 85.5484 0.442774 -61.8029 85.5129 -12.6677 -62.8908 88.2782 15.1656 2.16699 59.9394 51.6104 28.5228 82.6749 49.1482 26.6255 79.8986 46.6006 25.8344 77.4943 53.5618 18.0099 80.4163 58.9283 18.586 85.499 60.439 5.18366 84.1124 55.8962 31.492 88.2808 60.2623 9.37961 84.2914 60.9059 9.60009 85.1417 62.1055 6.7894 86.1484 62.0428 7.47743 86.1695 61.1328 7.10173 84.9583 58.9429 -18.6716 85.5437 58.9169 -18.6703 85.5095 55.8986 -31.4836 88.2786 53.0121 20.35 88.6244 21.4427 8.23035 70.2731 -51.0249 -19.5894 73.1767 -53.0119 -20.3514 72.8752 12.6464 61.8574 84.3531 9.95651 61.459 85.2099 0.609012 61.9962 85.7719 11.0165 60.7489 83.8375 9.68986 60.8885 85.1421 12.8712 60.5549 83.7111 12.1596 60.6287 83.473 7.17174e-05 61.9093 85.4905 13.6369 60.319 85.948 14.9875 59.8659 84.4155 24.6067 56.7422 85.4897 13.3712 60.3911 83.591 35.9834 50.3188 85.5836 36.3899 50.0842 85.4972 25.9111 56.1343 83.6767 25.8222 56.1864 83.6846 41.8893 45.6131 85.5108 39.946 48.3506 84.5851 41.8633 45.1548 82.2492 41.4291 45.5481 81.2435 42.7923 44.3208 82.7791 36.4676 50.0138 85.4464 46.1344 41.3249 85.9062 50.8581 34.7481 82.97 48.5089 37.9844 83.0013 53.5375 31.0615 85.8608 53.6141 30.9562 81.4149 57.2969 23.4208 85.5828 53.7019 30.7873 85.9489 53.7383 30.7988 85.9008 58.5814 20.0159 85.8507 58.7804 19.6749 85.7946 57.4896 24.9207 84.5896 56.9407 23.4858 82.5774 56.4155 24.6629 81.1698 58.8776 19.131 85.5009 58.8369 19.2236 85.4516 57.5475 22.1197 82.8648 58.5035 19.9716 85.7672 58.4983 19.9841 85.4745 53.6461 30.8847 81.4089 62.7414 7.08576 84.3528 61.1767 9.80845 85.5707 61.1891 9.81282 85.5544 61.1835 8.29611 83.8355 60.282 12.5273 81.2649 61.5715 6.4706 83.7113 61.4239 7.1674 83.4756 58.9892 18.5994 85.4778 61.5715 -5.87252 85.4932 60.2645 -12.616 82.0066 60.3019 -12.4368 81.7198 58.9753 -18.6733 85.5837 58.8776 -19.1324 85.4974 61.3978 -7.28555 83.6719 61.4193 -7.19048 83.6783 53.6795 -30.8281 85.9526 53.6719 -30.8239 85.9635 58.3255 -23.0523 84.5839 53.6714 -30.8252 85.9433 53.6685 -30.8318 85.856 53.6141 -30.9538 85.7383 55.4135 -26.9148 82.9077 58.8369 -19.2287 85.4467 53.5552 -31.1119 85.906 46.0842 -41.3176 85.8606 46.0065 -41.4246 85.7148 53.5294 -31.0717 85.6675 41.8882 -45.615 85.5107 41.8924 -45.6176 85.5045 41.9929 -46.1005 84.9659 42.0358 -46.8167 84.2588 36.3899 -50.0856 84.9665 36.4701 -50.0123 84.9552 45.8926 -41.5274 85.6442 26.1286 -57.4808 84.3535 35.9514 -50.5128 85.772 26.7976 -55.6249 83.8365 30.5481 -53.4581 81.2698 25.1817 -56.5569 83.7116 25.7987 -56.1997 83.4746 35.9255 -50.353 85.4782 24.4264 -56.8151 85.9481 17.4336 -59.0732 80.2947 13.4443 -60.37 85.4932 24.6815 -56.7177 83.5932 6.61944 -61.2134 82.0014 6.80118 -61.1959 81.7144 0.458842 -61.8624 85.5877 7.17174e-05 -61.9107 85.4905 12.0422 -60.6447 83.6705 12.1372 -60.6324 83.6781 -7.07971 -61.5242 85.5107 -3.9013 -62.5947 84.586 -7.17851 -61.1555 82.3925 -6.58622 -61.2174 81.3544 -8.47327 -61.0186 82.9091 -0.114507 -61.8997 85.4352 -13.0365 -60.5496 85.9061 -25.0604 -56.5963 85.8648 -25.1816 -56.5569 85.7241 -30.4407 -53.9339 85.5105 -30.4418 -53.9386 85.5048 -30.8685 -54.183 84.967 -31.5371 -54.4441 84.2586 -29.5451 -54.0379 82.4572 -36.3897 -50.0856 84.9702 -36.299 -50.1379 84.96 -25.3103 -56.4833 85.6557 -46.5896 -42.6091 84.3566 -43.0751 -44.4485 85.6058 -43.0898 -44.4678 85.5752 -44.6219 -42.6722 83.8376 -41.4043 -45.5698 81.267 -46.0064 -41.4246 85.0485 -45.4679 -41.9092 83.5562 -36.7911 -49.7251 85.4776 -46.49 -40.78 85.9479 -53.6139 -30.9538 83.7032 -50.7949 -34.8322 80.2933 -53.2574 -31.4443 85.4895 -46.294 -41.0257 83.1102 -58.6981 -19.5734 85.9441 -56.1692 -25.2139 81.9998 -56.0966 -25.3791 81.7143 -58.8775 -19.1324 85.4959 -53.9417 -30.2192 83.4012 -53.9034 -30.3048 83.4091 -60.7018 -12.2797 85.5107 -60.7369 -15.6354 84.5846 -60.1746 -13.0389 83.3326 -60.037 -13.6857 82.0897 -60.5482 -11.2874 83.5822 -61.6155 -6.3144 85.91 -61.5714 6.4706 85.7486 -60.702 12.2775 85.5108 -60.7069 12.2773 85.5051 -61.0724 12.6093 84.9651 -61.529 13.1657 84.2517 -60.3882 12.0362 82.0049 -58.8775 19.131 85.4996 -58.8997 19.031 85.4498 -61.5419 6.61791 85.6695 -54.9248 31.1436 84.353 -58.7722 19.7461 85.7682 -54.3715 29.25 83.8385 -56.132 25.2975 81.2667 -55.2954 27.174 85.1835 -53.6139 30.9562 83.71 -53.9061 30.3009 83.4711 -58.6544 19.6292 85.4772 -53.1504 31.6153 85.9479 -52.3015 32.7445 84.4087 -46.3608 40.9318 85.4857 -53.3009 31.3833 83.5889 -36.739 49.7656 85.5796 -36.3897 50.0793 85.5062 -41.3219 45.5957 81.9817 -41.4535 45.4755 81.7011 -45.3737 41.9688 83.6837 -45.4504 41.8982 83.6916 -25.311 56.4909 85.9524 -33.6366 52.934 84.5843 -30.9768 53.1784 83.3038 -31.5416 52.8383 82.0683 -36.3081 50.1235 85.4611 -25.0391 56.6477 85.906 -12.9939 60.5148 85.8607 -12.871 60.553 85.7134 -7.08035 61.5227 85.5108 -7.08217 61.5274 85.5046 -6.87922 61.9774 84.9654 -6.49086 62.5823 84.2574 -0.114509 61.8983 85.4353 -12.7168 60.5671 85.6419 -31.0635 -68.4377 9.47774 -33.5404 -67.6456 9.42348 -33.3045 -68.2685 7.77381 -32.4168 -68.5732 7.73454 -33.9143 -68.1373 7.59962 -34.6338 -68.0517 7.19181 -35.0234 -67.9473 7.1416 -35.8776 -67.3399 7.45311 -38.459 -66.8284 4.78603 -38.646 -66.7215 4.78645 -49.3999 -61.6728 3.80087 -49.9343 -62.1432 4.03178 -42.0851 -63.5644 7.20996 -44.3612 -62.3438 5.32199 -44.4877 -62.2554 5.26469 -45.3116 -59.5913 9.69235 -45.0258 -61.7323 5.3307 -49.461 -63.8242 3.35808 74.6903 6.85637 9.47765 75.181 4.56037 9.45554 74.802 6.98832 9.04534 75.5433 4.98366 8.04758 75.3781 5.80185 8.02932 75.747 4.26045 7.92538 75.6759 4.60298 7.90713 77.9573 11.7992 6.1497 76.9607 0.0826293 4.65099 76.9536 0.162423 4.67321 76.962 -0.0852849 4.65087 77.9262 -12.0622 3.73019 78.8456 -12.3818 3.94436 74.5695 -9.02649 8.54654 74.7373 -8.34858 8.46354 75.9026 -4.81949 7.18662 74.077 -9.5576 9.69654 74.455 -9.61509 8.49046 74.5635 -9.09598 8.51583 -43.4149 61.0506 9.16956 -43.2466 61.0095 9.62485 -41.47 62.7016 9.39407 -45.6285 59.2788 8.65929 -46.0528 58.9393 8.5637 -41.8146 62.8015 8.43134 -42.2487 62.4078 8.43633 -41.4838 63.1433 8.34742 -41.6629 62.98 8.34378 -46.5641 59.3445 8.33089 -38.5197 66.3957 4.69959 -38.6382 66.3113 4.74227 -38.2437 66.5547 4.70271 -39.9562 69.2864 6.4542 -39.2333 69.389 7.20543 -38.442 69.8279 7.24724 -40.0268 69.2475 6.45299 -40.167 69.1968 6.38067 -28.5119 73.3024 3.65727 -28.7201 74.4212 3.84232 -28.7819 74.7352 3.93376 -29.0305 68.7732 9.26009 -29.1575 68.736 9.25181 -31.7743 67.9223 9.12731 -33.4071 68.2425 6.6182 -29.0229 68.7769 9.25616 -28.9371 68.8058 9.24957 -30.5234 74.4077 3.25582 -34.0279 72.9337 4.18725 -32.8506 72.5275 6.18644 74.9265 3.57586 9.14695 74.4911 3.75118 9.38838 75.1599 2.80964 9.05099 75.9634 5.78307 8.43478 76.4786 5.28378 8.16362 76.9522 4.87891 7.91046 75.576 6.23907 8.63585 75.0082 12.1567 8.66619 74.1004 11.0372 9.24614 75.087 7.03797 8.87781 75.9933 2.82411 4.06071 77.3905 3.19384 4.88574 76.9695 12.3282 5.1067 79.397 7.71463 6.27426 79.4278 7.78309 6.29553 73.9531 10.1504 3.25392 78.0843 12.7947 5.77373 77.8729 13.0625 5.66479 75.1368 -8.51057 8.77448 74.9337 -9.103 8.86163 73.7334 -10.0538 9.50799 73.5571 -9.92356 9.61603 76.0562 7.34043 8.30309 79.4171 7.66148 6.3445 75.1295 6.35348 8.88781 79.4043 7.68224 6.35084 74.1721 -7.01839 9.4073 76.4501 -2.02942 8.34566 77.7395 -12.521 5.55949 78.3145 -12.5236 5.89377 73.7909 -11.8568 3.24771 77.5255 -12.8106 5.4517 -29.1092 68.8038 9.09361 77.5316 -10.7294 5.35132 76.7369 -10.5242 4.87989 75.3349 -2.28051 3.65468 74.4132 2.68968 9.48814 -29.1268 68.7951 9.10327 78.492 -10.6595 5.90211 -36.1984 -67.9861 8.00808 -34.7424 -66.1221 9.34495 -34.3773 -65.8729 9.56644 -32.0361 -69.044 8.47313 -32.4913 -69.1779 8.29129 -35.3619 -66.124 9.1922 -33.1415 -69.4823 7.97088 -33.6275 -69.738 7.71767 -42.2643 62.6628 7.80365 -26.9881 -71.102 8.62838 -27.4603 -69.9344 9.12593 -31.6684 -68.6818 8.75348 -35.4608 -67.7411 4.30965 -35.7201 -68.7515 4.90384 74.9102 -8.6582 7.75089 -27.8031 -72.9749 5.1837 -31.571 -72.1196 5.6581 -30.0075 -71.4176 4.90705 -28.2125 -69.2023 3.30408 75.6914 5.63012 7.16359 -27.9603 -74.0986 5.81327 -45.5585 -59.0399 9.41369 -45.2862 -58.917 9.56123 -43.8228 -62.8917 5.1728 -42.7676 -61.2001 9.31401 -45.1096 59.4447 9.36865 -38.2469 -66.9569 4.76927 -39.9463 -65.5455 8.18977 -49.4246 -61.1639 5.50944 -50.0664 -61.556 5.90956 -47.1724 -58.2414 3.37489 -49.5856 -60.7273 5.35736 -48.1493 -61.7728 5.37468 -47.7055 -61.296 5.00024 -32.7627 -68.7732 6.78757 -48.55 -62.4831 5.8458 -46.8054 -64.4605 6.2065 -46.8858 -64.2429 6.12995 -39.5707 -64.198 3.67584 -12.871 60.5503 85.4885 -41.5499 63.9497 8.41277 -43.4015 67.0718 6.31385 -40.8298 64.432 8.42305 -39.9685 69.2301 6.43106 -39.7561 67.368 7.3845 -42.314 62.8783 8.66764 -42.0836 63.3923 8.50177 -44.5134 42.7543 84.5683 -39.8131 62.9728 9.45622 -39.7995 62.7149 9.58197 -36.3897 50.0777 85.3692 -42.4317 62.7399 8.69418 -42.5384 62.4064 8.81712 -48.0855 58.7254 8.72123 -46.5286 58.4519 9.36836 -43.6143 61.2802 8.99409 -53.6139 30.9562 82.7919 -53.9652 30.1684 84.7886 -40.379 64.2255 3.95781 -54.0702 29.9287 81.1009 -40.4673 68.2817 5.91379 -40.6082 68.3177 5.97788 -55.2267 31.3763 83.8844 -58.8775 19.131 85.3481 -58.6175 19.7122 85.5211 -45.7988 58.8524 3.20869 -61.509 6.77256 85.7504 -42.4486 65.0187 5.02288 -48.1083 59.1313 4.10837 -47.1413 57.865 3.18657 -60.5403 -11.3197 81.6633 -61.5714 6.4706 85.5206 -28.1525 68.6976 9.60548 -38.1997 69.287 6.83273 -31.7579 69.0435 8.54078 -31.3253 69.9445 8.17365 -36.514 71.063 6.31385 -30.7806 70.5137 8.00854 -32.2526 -72.1981 6.7621 -29.0747 68.8373 9.307 -28.9473 68.8796 9.31484 -42.4469 62.0998 8.99311 -47.3119 -39.6241 84.4162 -54.4288 -29.1257 84.568 -28.1582 68.6612 9.62412 -46.0064 -41.4246 83.1299 -36.8608 -49.6623 85.5229 -43.9166 -43.7518 85.5487 -31.3037 67.0226 9.71468 -39.0006 67.6565 7.49286 -38.9442 67.6832 7.49266 -38.1825 68.2768 7.36818 -37.9933 68.5293 7.28271 -50.1102 -61.2386 5.77333 -43.9106 -43.7441 85.5611 -25.4572 -56.3985 85.7425 -27.9911 73.5559 5.53618 -28.4376 73.917 5.83458 -27.662 73.5231 5.43705 -29.6181 72.3177 5.28425 -29.385 71.4297 4.76182 -25.1816 -56.5569 85.5087 -35.7007 66.2548 3.59029 -33.3704 -67.2369 9.09615 -29.2165 68.7346 9.32625 -55.6063 27.2402 85.5745 -30.2307 73.1763 5.88535 -38.9156 69.1917 5.91832 -27.7623 74.2457 5.84182 -8.44367 -61.0223 81.1843 5.59127 -61.3217 85.34 -3.78248 -61.5124 83.3164 -32.0726 69.828 4.57735 7.17174e-05 -61.9107 85.3209 -32.3181 69.7029 4.5716 10.8797 -60.7672 84.5676 -27.6225 -74.0443 5.70159 -7.38766 62.0444 86.1206 -15.7607 61.4847 87.5463 -12.9242 60.4669 85.7937 -7.08219 61.5209 85.4982 -13.0581 60.5377 85.9039 -15.7353 61.5217 87.5767 28.2422 -55.1627 85.5544 23.066 -57.2424 84.416 25.1817 -56.5569 82.7995 26.2354 -57.844 83.888 -3.67901 62.5122 86.0592 36.2657 49.6743 85.2066 36.5983 49.2439 85.0429 46.0506 41.5088 85.9672 42.4423 45.8526 86.1167 48.2245 38.6526 85.7101 58.8776 -19.1324 85.3429 46.1694 41.4089 85.994 61.394 7.30846 84.7953 61.1537 -8.43253 84.5686 46.0065 -41.4246 85.4921 9.14001 60.3113 84.3707 0.218376 62.3245 86.1509 0.00252894 61.8899 85.5866 61.3256 9.22527 85.5398 9.57376 61.2109 85.536 58.8776 19.131 85.351 54.7199 28.4724 84.0715 61.3208 9.22391 85.5461 11.9639 61.3164 86.1404 57.4528 22.3344 81.0912 13.2713 61.0056 86.1627 12.244 60.1637 84.8034 15.2487 59.6211 85.3072 25.1362 57.1199 86.1256 56.3281 25.7491 85.5046 48.2401 38.6638 85.7309 24.6283 57.3073 86.1552 58.5537 20.01 85.8855 15.3199 59.79 85.5301 38.9848 47.7487 83.5327 42.7697 44.3392 81.0912 56.3239 25.7464 85.5108 36.3899 50.0842 84.7894 31.5451 52.9658 85.429 53.6141 -30.9538 85.5236 31.5134 52.8991 85.3359 12.0155 60.6437 84.7928 15.3228 59.7996 85.9138 11.4303 60.7056 82.3022 12.8712 60.5549 81.0335 9.57516 61.2253 85.5544 -60.7013 12.2755 85.4987 -61.2924 12.1467 86.1217 -61.6711 6.38886 85.9768 -61.6123 6.29131 85.9044 -61.6454 6.30975 85.9417 -61.4196 6.47643 85.7139 60.7663 10.2557 85.1736 -36.0374 49.8166 85.192 -35.5069 50.0073 85.0212 -35.9908 50.4523 85.6426 28.5326 -54.623 85.1748 -25.1101 56.7084 85.996 -31.168 54.2742 86.144 -25.1657 56.7328 86.0428 -24.9759 56.6244 85.8552 35.8419 -50.4013 85.5249 -56.5893 -24.2705 85.3361 -47.3783 -39.275 85.3047 -56.0958 28.8828 86.9137 -59.388 19.0232 86.1518 -55.5805 27.2288 85.5398 -36.8748 -49.6497 85.5784 -45.6506 -14.7745 73.3053 -36.3734 50.0572 85.571 -40.7008 45.627 84.7732 -54.5568 30.3374 86.0709 -46.2526 41.9982 86.1477 -46.592 41.5563 86.1609 -58.6038 19.7249 85.5657 -53.9077 31.4404 86.1292 -53.4352 30.2397 84.7992 -51.9946 32.923 85.3016 -54.6311 27.1292 84.3853 -46.9134 41.1343 86.1756 36.372 50.0604 85.5694 -52.1329 33.0425 85.5236 -61.5714 6.2357 85.8545 31.4307 52.5097 84.866 -45.7982 42.5171 86.1687 -41.0109 46.0055 85.39 5.42867 -60.9576 84.8689 -33.7518 66.7186 3.3561 -35.2211 64.8409 2.72922 -45.3727 58.7403 3.01399 -39.6115 61.6349 10.1578 -30.4979 -54.5352 86.1219 -25.1346 -56.6761 85.9767 -25.0241 -56.6511 85.9044 -30.4382 -53.9339 85.4984 -25.0518 -56.6768 85.9416 -25.0882 -56.5176 85.7986 -28.3637 -68.6762 3.06459 -33.6203 -65.2739 10.0673 -53.2889 -17.9798 80.1993 -58.7945 -19.0508 85.4964 -58.5625 -18.6393 85.156 -56.979 -17.0917 83.2266 -58.6359 -19.5284 85.5094 -61.6546 -6.50987 85.9676 -61.2885 -12.1469 86.1167 -61.7334 -2.92216 85.71 77.2829 -2.24471 7.85314 60.258 -9.38038 84.2857 -61.6922 -6.36115 85.9967 74.7192 -4.27824 3.39998 73.8219 -1.99469 2.76656 75.1265 -8.40169 8.786 -44.6077 -43.7352 86.0885 -36.3803 -50.0681 85.5866 -36.4437 -50.5975 86.1498 -43.0712 -44.4478 85.5405 73.233 3.23207 10.1423 -45.7064 -42.5123 86.0675 73.6273 9.82069 3.04893 -46.5582 -41.5539 86.1275 -45.2773 -41.6798 84.9525 -54.2405 -31.0127 86.1493 -53.9191 -31.4727 86.1653 -53.6316 -30.1792 84.9515 -53.6166 -31.9107 86.1783 -47.5349 -39.3694 85.5268 -57.9063 85.7141 -22.204 -53.9624 -30.0346 85.176 -54.5972 -30.414 86.1707 -56.6563 -24.3026 85.4296 42.4421 -45.8557 86.1207 48.8914 -40.4775 87.5455 45.9976 -41.3199 85.792 41.8887 -45.6128 85.4981 46.1509 -41.2985 85.9039 48.892 -40.5228 87.5773 -42.9388 60.9227 10.4824 -0.149799 -61.5168 85.2205 -0.657877 -61.3674 85.0607 -12.8597 -60.6461 85.9675 -7.3867 -62.0416 86.1167 -41.0492 -62.5738 3.39554 -13.0722 -60.4942 85.8591 -43.159 53.6403 76.6968 -13.0154 -60.6383 85.9942 36.8588 -50.2953 86.1484 37.2251 -49.7108 85.772 28.2356 -55.1496 85.5363 36.3754 -50.0701 85.5873 27.9398 -56.0213 86.2652 36.4572 -50.572 86.1738 103.369 7.18692 -22.2038 26.3617 -56.6396 86.1409 12.7336 -61.1662 86.1499 13.2722 -61.0074 86.1638 24.966 -56.3492 85.1729 22.7116 -57.1975 85.3073 25.1246 -57.1538 86.1633 25.6471 -55.9441 84.9578 13.7774 -60.8533 86.1774 22.7532 -57.3762 85.5301 12.0576 -61.3197 86.1713 5.60107 -61.3945 85.4314 20.2321 11.9258 61.824 -45.4621 -93.3274 -22.204 45.933 25.8581 77.0734 53.7554 30.8083 85.9218 53.6052 33.9906 87.5455 53.5134 30.9797 85.7932 56.3221 25.7473 85.4982 60.8225 -9.99415 85.1608 53.5404 31.1306 85.9039 53.6479 33.9777 87.5762 49.2996 17.5568 76.3839 49.3093 17.5416 76.3859 58.5794 20.2855 85.6315 58.772 19.6606 85.6416 58.7398 -19.208 85.489 53.7036 -30.9708 85.9677 57.1174 -25.5856 86.1441 53.4992 -30.9807 85.782 53.4909 -31.1301 85.8553 53.6479 -31.1193 85.9957 -25.0407 -64.3791 76.6809 -12.5395 60.5882 85.733 61.6017 9.0142 85.8111 58.8612 19.1228 85.5829 61.32 9.22413 85.5327 -5.84018 63.297 83.4452 -33.9838 53.7242 83.4974 -22.4151 60.8786 81.8445 62.0131 7.56607 86.1394 -33.4259 55.0944 82.3525 -0.860306 62.1247 85.5803 62.1188 6.23042 86.1646 62.1055 -6.79084 86.1483 62.1186 -6.23191 86.1645 -57.7639 26.1811 83.6262 -57.8916 26.5172 83.3037 -61.5986 -15.7219 83.4956 -62.0082 14.0044 83.4407 -56.5864 -24.277 85.5057 -62.042 14.0552 83.3833 62.0428 -7.47865 86.1694 -43.1066 -46.8656 83.3038 -32.4825 -54.6389 83.4455 -32.5439 -54.6571 83.3873 60.8422 -9.99676 85.1862 -13.0604 -60.4948 85.8252 -17.6471 -62.429 81.8438 -16.5583 -62.0326 82.7452 -42.7493 -46.8484 83.6252 12.4087 4.76284 57.503 12.3631 4.74534 55.7854 -12.0045 -4.60915 57.52 3.54313 1.36009 116.363 5.96152 2.28757 114.185 53.0121 20.35 73.2626 49.4229 18.9729 69.9596 22.595 8.67324 67.6255 -17.5585 -6.74225 58.9158 14.0765 5.40296 109.224 28.5583 -55.9584 84.4849 -24.0064 -9.21675 59.6219 11.4915 4.41045 111.549 45.7616 -41.6454 85.7343 41.9291 -47.7761 83.4465 41.927 -47.8413 83.3863 16.2374 6.2329 59.0655 -4.08515 -63.4397 83.4972 23.872 9.16367 65.4014 24.8282 9.5309 59.1115 57.4564 -22.3237 83.5309 24.2996 9.32797 64.6272 32.228 12.372 60.8277 55.4243 -26.8872 81.183 59.0716 -23.4882 83.4974 35.7154 13.7106 69.701 36.5846 14.0446 63.4598 36.1698 13.8854 68.6353 39.9998 15.3538 65.4254 46.134 17.7091 75.3327 48.4144 18.584 69.426 47.897 18.3853 75.7672 28.6831 -55.4923 84.9144 62.4225 12.5758 83.3049 -42.1139 -16.1668 87.5973 -0.0310349 -0.0126446 169.353 -47.7738 -18.3393 88.5661 -50.7641 -19.4894 88.9515 53.4953 -31.1186 85.82 -48.3336 -18.5543 70.4273 -53.0119 -20.3514 89.2996 58.5779 23.3699 84.1298 9.57382 61.2126 85.5708 9.69179 60.8883 85.1747 0.628616 61.8438 85.5228 0.535188 61.8536 85.4774 19.3114 61.1304 82.7535 25.5117 58.2084 83.8456 15.3668 59.9452 85.7227 13.6337 60.3072 85.9635 15.3543 59.7468 85.5674 27.3006 58.1191 82.9111 31.6412 53.1128 85.6499 41.8933 45.6162 85.5047 41.6283 45.3683 85.9635 45.9014 41.5216 85.9432 53.5631 31.1361 85.8841 53.6172 31.0967 85.8581 53.5428 31.1327 85.9074 48.0782 38.5745 85.5783 48.1006 38.5446 85.9635 58.7016 20.2983 85.5642 53.691 30.7836 85.9363 53.6917 30.7817 85.9635 58.4986 19.9831 85.8455 56.4986 24.4757 76.9564 64.9991 13.8165 79.7895 61.5977 7.70901 85.605 60.9065 9.5982 85.1745 60.8666 9.78325 85.9635 61.337 7.57374 85.5196 61.1122 -10.1433 85.5625 60.7962 -10.1156 85.9635 60.823 -9.99205 85.207 53.9199 -30.9917 85.5902 56.3284 -25.7459 85.5047 46.1632 -41.3184 85.8841 46.31 -41.5407 85.5687 46.1537 -41.3002 85.9074 49.6881 -36.358 81.3139 53.4884 -31.1281 85.8518 40.3415 -46.5259 83.2366 26.3047 -57.8128 83.8788 26.37 -56.1993 85.6049 27.952 -54.9585 85.1747 19.7725 -60.7904 82.9846 13.5747 -62.0908 83.8421 22.8058 -57.5277 85.7227 24.4217 -56.8038 85.9635 22.7427 -57.3475 85.5656 12.0756 -63.0702 82.9054 5.60891 -61.5687 85.6501 5.60011 -61.3214 85.9635 5.59498 -61.3213 85.5081 -7.0817 -61.5287 85.5047 -25.0382 -56.6676 85.8859 -16.3573 -64.5558 79.7895 -25.1962 -56.8691 85.5818 -25.0248 -56.654 85.9076 -19.2243 -58.4923 81.3152 -13.0711 -60.4914 85.8558 -33.2288 -57.5464 79.7895 -30.2893 -53.6078 85.9635 -32.5157 -52.323 85.3993 -44.4659 -49.3818 79.7895 -45.2945 -42.4513 85.602 -42.8256 -44.29 85.2596 -42.8648 -44.2539 85.9635 -51.7046 -37.5902 82.9852 -54.6693 -32.0176 84.0938 -47.6643 -39.4676 85.7227 -46.4802 -40.7724 85.9635 -47.5099 -39.3516 85.5621 -56.1849 -30.8733 83.0357 -56.8201 -24.3662 85.65 -58.6837 -19.5678 85.9635 -56.2466 -25.0411 76.9564 -60.7068 -12.2795 85.5047 -59.8107 -14.752 85.3992 -59.8175 -14.7146 85.9635 -60.2248 -12.8004 76.9564 -61.6325 6.29959 85.8859 -61.8659 6.38704 85.5906 -61.6153 6.29107 85.9076 -61.5714 -2.90674 85.9635 -60.3455 12.2316 85.9635 -59.8076 14.7539 85.3996 -55.2638 31.3101 83.8748 -54.3679 29.9655 85.6021 -55.2943 27.1769 85.2475 -52.3384 37.1462 82.667 -47.4733 42.2469 83.8531 -52.2655 33.1346 85.7227 -53.1401 31.6083 85.9635 -52.1082 33.0245 85.5589 -46.8361 43.9234 82.9144 -41.1337 46.1612 85.6373 -40.9715 45.9595 85.9635 -40.9686 45.9545 85.4581 -30.4195 53.9472 85.506 -25.3073 56.4829 85.9635 -25.306 56.4834 85.9425 -13.0564 60.5607 85.8845 -13.0456 60.8285 85.5666 -13.0593 60.5407 85.9074 -18.8125 58.5701 81.3032 -24.975 56.6212 85.8517 -1.0295 62.0668 85.6297 -5.79995 63.3495 83.3851 -5.29055 61.3521 83.2337 -19.5907 -65.509 76.6587 -16.3801 -65.1387 79.0954 -33.0172 -60.5203 77.2112 -36.9806 -53.7832 74.0378 -32.2576 -64.904 65.3008 -46.5797 -59.5411 57.4681 -34.2096 -65.537 34.2161 -35.8692 -68.9004 35.0077 -36.9395 -63.8885 32.8004 -39.4358 -62.3885 31.6416 -31.185 -67.0229 17.3719 -29.8119 -70.532 4.3932 -34.1582 -67.4745 9.3272 -36.0215 -66.4359 9.6945 -47.947 -60.246 2.52791 -47.1349 -61.5238 1.29416 -49.3672 -63.9592 3.25189 -36.8415 -73.5526 -6.93918 -54.5327 -68.6858 -9.056 -53.1797 -70.4369 -15.8527 -46.1092 -94.1467 -22.9027 64.0367 15.0782 75.3101 62.6726 15.2965 73.6715 60.2257 12.7954 76.9564 9.78919 62.0554 84.4861 74.6667 -10.6742 57.4675 73.6827 3.03807 34.4139 73.5625 -3.06437 31.6371 73.4517 6.40983 17.3488 74.2001 -3.18559 17.192 75.2891 3.87053 9.56866 75.3292 2.07357 9.79504 75.9772 -11.5198 2.46407 76.708 -10.0107 1.25623 76.4076 -7.43256 3.97326 86.563 -12.9911 -9.05605 87.4044 -10.9425 -15.8536 104.403 7.0336 -22.9027 -46.81 49.6169 76.6205 -30.7811 53.2171 76.9564 -27.9977 58.7072 74.0367 -19.0224 58.4511 76.9564 -19.0194 60.6249 74.9564 -39.8937 60.071 65.3014 -28.0875 69.7853 57.4683 -40.0234 68.6398 47.2904 -39.4664 62.0728 34.2128 -41.5497 65.1923 34.997 -36.6751 63.6127 32.8 -34.1283 65.0256 31.6405 -42.1308 60.2632 17.6593 -35.6501 64.3224 20.6452 -34.2106 65.2069 20.3123 -41.1621 63.0018 9.34126 -39.6293 63.833 9.93924 -28.0145 71.3653 2.40019 -29.2129 68.6721 9.38606 -29.0114 68.7072 9.4768 -29.7785 71.2068 1.21649 -31.8688 69.6338 3.99574 -35.7423 72.443 4.05479 -45.092 68.3619 -6.94175 -34.2213 80.9494 -15.8517 -58.2918 86.6855 -22.9024 73.7771 7.88484 9.59298 75.3076 -7.28524 8.73776 -35.5597 -71.5088 6.31385 -43.6524 -62.2018 8.54354 -44.3669 -66.3949 6.31385 -46.9767 -64.1531 6.51027 -44.9409 59.192 9.54491 18.6621 13.5596 61.5854 -12.8152 60.4063 85.7072 -0.157875 61.4225 85.1314 9.13605 60.3 84.3565 23.6655 55.8611 84.1124 48.0758 38.579 85.5389 -4.07272 63.2527 86.9556 -3.67298 62.5309 86.0833 11.6828 60.4601 84.9345 11.6457 60.186 84.6027 26.2274 56.6653 86.0973 36.3478 50.1047 85.5998 31.4263 52.4954 84.8481 -61.4099 6.28397 85.6859 -59.066 18.2502 85.4789 -58.811 18.9916 85.4912 -45.8144 39.7688 84.1124 -58.8597 19.128 85.5829 -58.8508 19.1229 85.5697 -55.7339 30.2155 87.3729 -53.8926 29.792 84.931 -53.6432 29.6718 84.5975 -36.4188 50.0503 85.5968 -40.6906 45.6197 84.7599 -25.1397 -56.4113 85.7152 -25.4873 -56.3811 85.8322 -35.9797 -49.7827 85.1327 -42.6832 -43.5729 84.3857 -51.4768 -28.9723 82.4935 -52.0633 -31.1677 84.1124 -59.9078 -16.0134 85.5105 -54.4082 -13.6365 79.9829 -59.745 -10.7611 84.3277 -61.5714 -2.9505 85.5386 -36.8689 -49.6448 85.5689 -43.5767 -43.6137 85.1423 -52.897 -30.2212 84.2571 -54.0112 -29.9431 85.169 -56.2935 -24.0041 84.8665 45.8763 -41.3362 85.7062 36.2308 -49.5984 85.1323 27.7513 -50.6562 81.4238 27.5421 -54.4054 84.282 24.4837 -53.6 82.3725 13.6899 -59.101 84.1124 35.8221 -50.4037 85.5722 12.1315 -60.3337 84.9557 11.8934 -60.6027 85.1779 11.7911 -60.6214 85.1717 5.42351 -60.9426 84.8504 53.4912 30.8597 85.7075 54.876 28.1239 85.4727 58.7432 19.2037 85.4924 56.7534 10.7367 81.4241 60.2546 9.37984 84.2817 58.5452 6.7222 82.3747 60.439 -5.24528 84.1124 56.9722 -10.5816 81.5837 53.4761 -31.0856 85.817 60.013 11.1857 84.544 61.1157 7.56864 84.9374 60.2548 -9.38048 84.2816 16.5612 6.35631 107.649 53.0121 20.35 130.715 44.95 17.255 77.9223 12.7742 62.2167 83.8844 11.6941 60.9654 85.6046 7.17174e-05 62.2969 85.4743 0.647433 61.8418 85.5784 12.4286 60.6008 81.0092 11.5005 60.6978 85.2003 7.17174e-05 61.9093 84.6354 25.8678 58.0979 83.8419 25.1817 56.5555 83.5384 17.817 58.9471 82.3452 15.3111 59.7608 85.4927 13.1775 60.4546 81.0208 31.6071 53.0564 85.7332 31.5082 52.9027 85.9635 26.2643 57.9408 83.7595 26.4026 56.1809 85.6004 31.5065 52.9032 85.5052 36.349 50.1078 85.6038 25.7364 56.2358 82.7835 39.9776 47.2575 85.583 37.1399 49.5286 85.8513 37.136 49.4129 85.4653 45.8914 41.5306 85.8569 37.0734 49.4682 85.767 46.0065 41.4269 85.7207 43.3456 43.8226 81.7767 36.817 49.7004 84.5443 36.4616 50.0193 84.7888 53.7222 31.0179 85.8067 51.8362 33.6606 85.7718 48.2261 38.6545 85.7531 49.9359 36.0199 81.3116 53.6141 30.9562 85.6454 46.0911 41.3129 85.6592 58.8457 19.5937 85.7625 58.8694 19.5915 85.7367 53.6961 30.881 85.9073 58.4949 20.2744 85.8178 56.8188 25.6964 84.9647 58.6111 20.3048 85.6655 57.0682 23.1963 80.0528 58.8374 19.2225 85.3505 58.6479 19.6472 85.843 63.121 7.07556 83.8859 61.491 7.66146 85.7482 59.038 18.4806 85.9361 59.1742 18.483 85.7695 61.286 7.81591 85.2028 63.1161 -6.63331 84.01 61.5715 -6.47201 83.5345 61.5715 5.43913 85.4932 61.0955 -10.1391 85.5846 61.5915 -7.7378 85.6036 63.0936 -7.07659 83.9196 60.8804 -9.7221 84.2493 61.4395 -7.09492 82.7843 53.8765 -31.1046 85.5826 57.2974 -23.4182 85.5829 58.5814 -20.0167 85.8507 56.3243 -25.7433 85.5107 58.4984 -19.9847 85.8459 58.5032 -19.9729 85.767 55.1038 -27.6098 81.8836 58.6348 -19.6771 84.8451 58.8397 -19.2221 84.867 46.2422 -41.6392 85.5607 49.8125 -36.1862 85.9635 53.482 -31.1547 85.9493 53.4734 -31.1475 85.9372 46.1238 -41.2631 85.9416 53.5308 -31.0697 85.5225 36.7773 -50.6177 85.1348 39.8308 -47.3746 85.5985 39.6594 -47.1409 85.9635 45.9104 -41.5741 85.9025 37.1473 -49.5243 85.8503 45.0308 -45.5489 82.9138 39.8328 -47.5476 85.4365 36.8715 -49.8278 85.7985 44.9201 -46.019 82.5671 39.7158 -47.0896 85.399 36.3899 -50.0856 85.5789 38.9931 -47.7424 83.2856 37.0807 -49.4638 85.7659 37.0896 -49.4548 85.4787 45.8946 -41.5256 85.4908 28.2352 -55.1519 85.5707 25.1817 -56.5569 85.0548 25.7315 -56.2386 82.765 35.9542 -50.3365 84.9507 13.2231 -62.2087 83.8392 12.8712 -60.5563 83.5321 22.7431 -57.3473 85.4932 24.7427 -56.6981 82.7813 5.60268 -61.503 85.7337 11.6697 -60.9692 85.6034 12.8095 -62.3173 83.7576 11.7466 -60.6758 85.2319 12.2354 -60.6222 82.7785 -13.3842 -62.9735 82.8546 -4.56862 -61.7314 85.5828 -0.941613 -61.9015 85.8505 -3.37065 -63.169 83.9336 -1.0009 -61.8051 85.4678 -0.92307 -61.8137 85.7654 -12.871 -60.5563 81.9704 -9.22992 -60.9391 81.8849 -0.590464 -61.8482 84.8591 -0.107014 -61.9004 84.8807 -25.3071 -56.8393 85.5761 -19.0236 -58.5575 85.9635 -13.0399 -60.51 85.9532 -13.037 -60.5024 85.9445 -24.9993 -56.6162 85.9426 -12.9494 -60.5309 81.9666 -36.7757 -50.6156 85.138 -32.5911 -52.6263 85.5828 -25.5173 -56.3894 85.9346 -25.534 -56.4201 85.8918 -35.6265 -50.6291 85.851 -29.4042 -56.9027 82.914 -35.9942 -50.4651 85.7967 -29.8857 -56.9423 82.5663 -32.264 -52.4684 82.5831 -36.3897 -50.0856 85.5793 -33.5561 -51.7206 82.8694 -35.608 -50.6084 85.8852 -35.5903 -50.5468 85.7664 -35.9263 -50.4156 85.8952 -29.5302 -54.3995 85.5767 -35.5795 -50.5531 85.4783 -13.0093 -60.5115 85.7977 -25.3081 -56.4846 85.5076 -13.0378 -60.5021 85.9635 -46.904 -42.8245 83.8883 -1.40829 -61.8968 85.7944 -1.7144 -61.7301 85.3731 -45.2043 -42.3901 85.7369 -36.9683 -49.5978 85.9326 -37.0713 -49.6799 85.7676 -0.944426 -61.8737 85.8848 -12.9036 -60.7119 85.7629 -45.5604 -41.826 82.4224 0.468438 -61.8767 85.9443 18.1431 -58.8426 85.4932 -36.7664 -49.7472 84.9542 39.2492 -47.5119 85.1457 -54.9084 -31.6997 84.0834 -47.5107 -39.3505 85.4895 37.1332 -49.5 85.8847 45.7661 -41.7193 85.8882 48.3646 -38.1801 85.5227 -56.7576 -24.3431 85.7333 -54.3826 -29.9348 85.6007 58.5538 -20.0107 85.8855 39.1491 -48.0935 85.5018 -55.1582 -31.3212 83.9907 51.6583 -33.9288 85.7527 58.9916 -18.6704 85.9441 36.8451 -49.7482 85.8955 61.0751 10.3035 85.5666 -61.6437 -6.47941 85.8745 -59.7713 -15.9713 85.69 -59.8644 -15.9959 85.5688 -61.1195 -16.318 83.9317 -60.4042 -11.9592 80.8611 -59.5292 -16.0734 85.188 -61.544 -6.60089 85.8599 41.9402 45.0879 85.1686 -59.5325 -16.0564 85.2926 37.1257 49.5044 85.8855 -61.5714 -6.47201 85.7441 -60.7242 -10.4594 82.4429 46.0065 41.4269 85.5185 -59.0036 -18.544 84.9243 -61.8725 6.5022 85.5849 8.29287 61.0358 85.2095 -61.7365 -2.92156 85.753 33.7239 12.9452 136.702 -59.3948 19.3001 85.2782 -60.1208 14.7338 85.5831 -61.5439 6.65416 85.9492 -61.5793 6.66528 85.9048 -59.1573 18.2425 85.8508 50.6453 31.5677 83.4688 -61.7826 11.8669 84.2817 -59.1223 18.6322 85.7934 35.707 -50.3854 85.4749 18.0017 -57.6998 84.1124 26.7209 -53.9073 83.447 -62.0507 12.5106 83.7787 -59.9828 13.9293 83.2316 -61.5022 6.80415 85.8339 -58.8994 19.0322 85.3475 -59.6071 15.7074 83.2807 -59.0689 18.2326 85.7674 -53.8272 29.5629 84.7019 -41.6912 -44.6248 84.6025 -61.5424 6.61537 85.5194 50.7353 -31.6923 83.6204 -55.5837 27.2302 85.6059 59.5267 8.75249 83.447 11.4855 60.3278 84.7067 -58.61 19.729 85.5748 -53.8054 30.5268 81.2249 7.96202 60.5027 84.5127 -54.1769 29.6906 85.1983 -45.2884 -61.9066 8.13934 -47.2569 42.5507 83.8486 -46.0064 41.3963 83.5463 -50.6076 35.0515 82.4034 -52.1073 33.0247 85.4857 -53.4119 31.2319 81.2371 -41.0941 46.1175 85.7118 -45.2663 42.4778 85.6021 -46.9874 42.8801 83.7667 -40.9617 45.9591 85.3047 -45.5259 41.8194 82.7779 -32.5883 52.6249 85.5828 -35.6296 50.6263 85.8507 -30.4175 53.9424 85.5122 -34.4022 53.0865 83.9333 -25.2999 56.487 85.8553 -25.1816 56.5538 85.7353 -29.4149 54.0847 83.5491 -35.5124 50.5856 85.4606 -35.5919 50.5425 85.7647 -27.4858 55.1415 78.8084 -13.0028 60.5995 85.8588 -29.8936 53.8275 85.1686 -35.8683 50.3725 84.8059 -43.9257 43.2876 85.1317 -36.3142 50.1128 84.8316 -12.9371 60.8682 85.5601 -19.0317 58.5534 85.9635 -24.955 56.6409 85.9492 -24.9522 56.6297 85.9368 -13.0574 60.4941 85.9418 -61.6204 6.16725 85.9011 -61.6713 6.19245 85.8367 -25.0417 56.5973 85.6639 -21.7819 57.6556 85.5262 -59.559 -15.9337 85.5514 -0.479328 62.4388 85.2353 -4.37859 61.7375 85.5986 -4.37379 61.4491 85.9635 -12.7037 60.6207 85.9023 -0.942407 61.9 85.8504 -46.587 -40.6214 85.5014 -9.65699 63.3158 82.9148 -1.04562 62.0268 85.6779 -0.53989 61.9839 85.7986 -36.9507 -49.5804 85.9022 -9.29018 63.6314 82.5672 -0.937394 61.8106 85.8447 -16.2686 -59.4536 85.5339 -25.1006 -56.6676 85.8617 -0.103689 61.8993 84.6347 -3.58655 61.5321 83.4695 -0.924487 61.8121 85.7651 -1.04597 61.8001 85.4634 24.0906 -56.9094 85.5113 -24.779 -56.8697 85.7442 -12.7196 60.565 85.4871 -60.3455 -12.233 85.9635 -31.5825 -68.4632 8.88985 -30.4774 -69.7939 5.96705 -28.1956 -69.8282 8.11461 51.5442 -33.8043 85.535 -32.2239 -68.8634 7.04953 58.9767 -18.6666 85.9635 58.4954 19.9898 85.9635 52.7876 33.8299 84.6744 -28.4407 -71.8486 6.73076 15.2404 59.7837 85.5628 15.3105 59.7624 85.9635 46.1078 41.2874 85.9447 -28.231 -70.7842 6.4636 8.29961 61.0349 85.288 -50.7741 -19.4918 134.839 51.853 33.6701 85.7487 -35.6865 -68.4471 4.73592 51.7084 33.5791 85.9635 -38.3676 -66.8707 4.81461 -36.3945 -66.586 8.69726 31.342 12.0319 66.959 -39.5793 -65.0884 7.77088 19.1739 7.36036 61.7855 -40.3708 -64.6644 7.68201 -41.1571 -64.3074 7.41641 44.8538 -46.6152 82.0623 -39.6158 -65.0751 7.75052 11.5415 4.42993 62.9303 32.4534 12.4577 137.604 -11.9722 -4.59673 55.7854 27.5052 10.5586 142.031 -50.4392 -62.5763 4.1632 -26.8167 -10.2958 75.7518 -15.7689 -63.893 80.8167 -30.5112 -57.0746 82.025 -15.2245 -63.6948 81.2674 44.8525 -46.6557 82.0249 -44.8574 -61.0593 7.25271 -44.7932 -62.5984 3.81637 -8.88566 64.0758 82.0622 -46.1149 -59.9607 7.11467 -45.1094 -60.8811 7.12853 -40.7834 -51.2251 81.1727 56.3736 -26.7349 86.0924 74.8939 6.24694 9.24383 74.4091 9.73028 8.47137 74.317 10.3467 8.35323 74.9604 6.32472 8.98718 53.0557 20.2779 80.553 75.5075 6.11036 7.42392 10.1038 -60.8546 85.1325 53.6479 31.0819 85.9738 76.0184 3.50186 7.62592 24.0821 -56.8721 85.4468 25.446 -55.884 84.8134 24.0927 -56.9167 85.5024 76.2395 11.1797 6.7567 77.643 11.6928 6.20662 -12.9774 -60.6834 86.0349 75.1798 10.8159 6.51164 -58.7425 -19.7955 85.7589 76.9636 0.269325 4.64178 77.0026 0.338167 4.5189 75.6521 2.56566 8.77865 75.9141 -1.95515 7.95331 73.7451 -2.04327 2.72467 -43.9093 -43.7435 85.5347 75.9188 -1.98095 7.93939 76.2825 -3.63476 6.78841 76.3103 -3.12691 6.70307 -61.5745 -6.26231 85.859 -61.7255 -6.41073 86.0343 -58.1941 -19.1859 85.0007 74.3432 -10.4429 8.25813 -29.5238 -54.3884 85.5626 79.2607 -12.5237 4.05639 -35.1614 64.8092 2.69826 -36.9825 49.7455 85.7584 -61.5714 6.10092 85.8415 74.9432 -8.19074 7.94242 76.527 -6.91038 3.9739 -43.0363 43.2144 84.324 -56.2817 -23.9951 84.8486 -53.5284 29.7121 84.5131 -22.363 -55.3695 83.5089 74.7056 -9.99874 7.44922 -22.8351 59.8905 88.1861 -55.1712 28.2407 85.5345 79.8733 -10.8178 3.32841 27.5366 54.4143 84.2848 35.825 -50.4111 85.582 60.5613 11.218 85.2205 79.7059 -7.84175 5.48846 -61.7494 6.16916 86.0398 79.3444 -8.14338 6.26526 -42.3844 62.0271 9.0485 -44.5641 59.5635 10.2476 35.8902 50.5404 85.7589 -42.5053 62.3551 8.01602 15.4098 59.7624 85.532 -40.9775 63.7906 7.93229 -46.7666 59.5265 8.44869 58.8776 -19.1324 84.8676 58.6786 19.6712 85.9156 53.6141 -30.9538 81.2145 -12.9797 60.6254 85.9735 -14.4666 57.9147 83.4854 10.1023 -60.8464 85.1222 -38.8286 66.2217 4.68756 11.7196 60.0893 84.5188 -39.654 64.1886 8.92908 -38.275 66.4075 5.05261 -55.1817 28.2453 85.5485 -38.9883 68.9935 6.7941 -39.8762 69.2417 6.44535 -38.0984 66.5537 4.93392 -46.0064 -41.4246 82.4552 -39.2829 69.3416 7.2475 -40.4598 68.5063 7.61812 -29.1703 68.8038 9.3012 -54.069 -29.9338 85.1835 -40.5038 68.4935 7.5908 -47.5633 57.7152 3.25511 -29.196 68.777 9.30898 -38.8514 69.3276 6.65157 -29.054 68.9908 9.23141 -53.6139 30.9562 81.2508 -39.0462 67.6325 7.49557 -29.2168 68.7509 9.15113 -32.2655 69.5098 3.99344 -32.435 69.3166 4.39762 -29.2174 68.6816 9.35392 -47.1914 -61.8807 5.10758 -28.8948 68.7424 9.48115 -28.8404 68.7901 9.38807 -29.5841 70.2778 4.20426 -44.5678 62.1773 8.25095 -42.7791 63.3386 8.29437 76.1141 -7.35657 4.93884 -43.4501 62.2971 6.14859 -29.8533 -71.9999 7.45422 76.5126 2.78361 8.27081 74.1172 2.89386 9.64786 -51.383 -34.253 85.6541 53.7053 30.8861 85.9185 79.4102 7.671 6.34803 -35.1012 -65.4777 9.59601 79.4378 7.78912 6.32612 50.6362 31.6516 83.506 -30.8911 69.1968 6.23111 78.2627 -13.1382 5.89281 45.7484 -38.3777 83.5068 45.9229 -41.5857 85.9209 73.805 11.8123 3.25351 46.1376 -41.4169 85.9755 72.619 11.6646 2.56008 35.8268 -50.4143 85.5867 78.4859 -8.26481 6.85283 74.8549 -9.78164 8.87344 -54.4973 33.2341 87.9977 -24.79 -57.0435 86.1942 78.7352 -8.89043 6.67707 -46.5654 -40.6086 85.4591 76.7039 6.19179 7.98629 -61.5136 6.80742 85.8463 74.781 2.34766 9.29313 73.6064 -4.00444 9.88688 74.4847 -2.03365 9.48025 77.0263 -1.71285 8.0286 -28.8873 68.9171 8.96093 78.497 -12.9414 6.01964 -21.8432 57.8106 85.708 76.7006 -12.1574 4.94306 -53.0323 31.7606 85.492 -32.2351 69.278 4.70287 74.4017 -1.42261 3.07247 11.8105 60.6659 80.8916 78.4281 -7.98003 5.72831 10.1763 61.1736 85.5398 78.3166 -7.27745 5.62743 9.42229 -60.2564 84.3239 -38.5259 69.389 8.17663 -38.4965 66.1571 5.38465 -34.0653 -67.3382 8.87117 -34.7793 -65.3284 9.75418 49.0866 -39.342 84.3616 -31.87 -72.1131 6.90083 -41.8739 63.0455 7.75252 48.5192 -38.3094 85.7087 -32.0856 -72.1464 6.83012 58.391 -20.2247 85.13 -42.3309 62.0146 9.192 74.8929 -8.81226 7.6949 28.5286 -54.6254 85.2286 -52.0451 -19.9807 134.771 31.0152 11.9055 138.73 57.0444 23.2528 85.3926 37.0256 14.2117 68.4293 -26.6458 -69.898 3.28427 76.1246 4.92189 6.34157 -29.8539 -69.5717 3.90024 59.0167 18.4774 85.9094 34.0262 -54.7672 82.3293 -53.0119 -20.3514 134.756 10.1761 61.1687 85.546 74.5785 7.92483 9.12741 41.9394 45.0887 85.1767 -48.4464 -18.5984 135.103 -45.9959 -60.8793 8.39172 -47.2882 -64.0713 6.44543 24.6798 9.47359 56.9839 -46.3914 -60.4073 8.48573 -38.7659 -62.3967 10.0777 -38.9781 -64.1718 9.16464 -39.0856 -63.6454 9.37802 -63.0313 12.3882 82.5999 -48.9065 -60.4935 5.02062 -34.0112 -68.4476 6.59821 -63.0574 12.4274 82.5557 -47.1537 -61.4651 4.89726 -44.3781 -61.4608 7.3173 53.7027 -31.0969 86.0366 18.8047 7.21844 62.7679 -46.9454 -64.1783 6.11891 -31.6366 -68.3295 9.23874 -43.3496 -64.7968 5.21674 24.7555 9.50282 58.3057 50.7432 -31.6242 83.5911 -30.4731 -57.0633 82.0612 -13.1007 60.48 85.8498 -40.9634 66.768 7.26875 -42.2736 64.9695 4.94154 -39.5836 63.4382 9.31002 11.7641 -60.6742 85.1864 -42.4541 63.6721 8.24548 -35.5651 50.5534 85.3021 -43.6272 43.5424 83.7378 37.0906 49.4542 85.3068 -36.421 50.0522 85.6003 -21.8494 57.8301 85.7303 -42.9727 63.0115 8.38517 7.17174e-05 -61.9107 84.8815 -12.707 60.6379 85.9211 -43.3743 43.7717 84.0728 -53.0602 31.7113 85.3068 -0.938716 -61.8116 85.3065 28.2906 54.7596 85.1572 -53.226 31.4855 85.175 46.1665 41.4702 86.0339 -45.3016 60.0954 8.99549 24.1623 57.0763 85.7345 46.1475 41.2424 85.8581 -52.1422 33.0487 85.9139 24.1705 -56.8834 85.2241 -46.4447 56.9478 2.51919 -39.636 68.4624 5.72289 -39.551 68.5082 5.71716 -39.7188 68.4122 5.72711 -29.1951 68.6392 9.38164 10.1758 61.1681 85.5328 -41.3032 68.0862 6.09848 -46.9989 56.9244 2.69257 -59.4403 -16.4911 84.086 27.7269 -55.4734 85.5398 -61.7535 -2.92344 85.7326 -53.981 -30.1307 85.1396 -61.5505 -6.61112 85.9527 -35.5445 -65.605 9.42046 -31.7936 68.8877 8.6137 -37.9012 69.7904 6.64207 -46.3674 -40.924 84.68 -37.9492 70.3929 6.31385 -12.871 60.4973 81.0031 -28.9367 68.991 9.25896 -46.0064 -41.4246 84.087 -58.8775 -19.1324 84.3449 -37.1806 -49.3742 85.2233 -44.9385 -42.3869 82.264 -34.6244 64.4767 10.2392 -38.9734 67.6073 7.52538 -46.5545 -40.6661 85.3127 -39.7691 69.261 6.46146 -35.4637 65.3957 9.55156 -35.8767 65.3744 9.46 -25.1816 -56.5569 81.0547 -39.0752 68.8772 6.83349 -36.3897 -50.0856 84.856 -27.2188 55.3 79.1878 -30.4126 71.2416 4.91387 -28.1057 74.3667 5.9892 -39.1851 62.9953 9.65427 -26.1997 -68.7494 2.57296 -27.8358 72.2954 4.83492 -36.3897 50.0714 84.8326 -30.0006 70.9259 4.64785 -16.3158 -59.6299 85.7301 -51.386 -34.2553 85.7897 -38.0147 69.521 5.8725 -35.9766 65.0547 3.02724 -54.0302 -30.0209 85.141 -56.6074 24.8704 85.6358 -39.4426 68.5565 5.71331 -31.7432 70.059 4.61896 -24.7206 -56.7068 85.8305 -38.2502 69.0396 5.67589 -54.94 27.9724 85.1415 -28.8403 68.7481 9.41015 5.45593 -61.3359 85.3465 11.8604 -60.6641 85.1432 -32.1219 70.2878 4.83105 -40.6525 68.2744 6.65618 9.70355 -60.8908 83.7448 -51.2706 -34.1791 85.9635 -13.0503 60.5771 85.9435 -12.5039 60.6053 85.8412 -13.1182 60.5177 85.8973 26.5062 -55.7929 82.596 -61.6517 6.35905 85.8616 -53.0283 31.7575 85.4979 28.7424 -54.861 85.5685 25.9238 -56.1273 84.796 24.5737 -56.7524 85.0235 0.467491 -61.8616 85.9635 -1.04168 62.0097 85.6616 -1.04281 62.0582 85.708 36.3899 -50.0856 84.8474 18.1624 -58.8373 85.9635 -0.529021 61.9694 85.6408 35.9849 49.2068 84.6858 37.4171 49.4252 85.6261 51.6735 -33.9374 85.7306 48.3626 -38.1829 85.4887 59.0347 -22.7258 83.9327 45.9968 41.3118 85.7876 15.8567 6.08674 61.2358 41.943 45.0915 85.1731 49.8719 40.2052 88.1471 -44.0122 43.2049 84.7227 58.4955 -19.9906 85.9635 60.9295 -9.48668 83.8186 59.008 18.5109 85.5214 7.96874 60.5213 84.536 -21.766 -57.6676 85.5325 10.3254 61.7436 86.2669 0.647872 61.8454 85.583 57.8099 21.5301 81.6991 -21.8315 -57.8379 85.7304 58.6572 19.6273 85.5258 58.4003 20.2036 85.713 53.6761 30.8174 85.5933 11.527 60.8009 85.3435 -53.0766 -32.0024 85.7351 11.2419 62.7003 87.7757 -13.103 60.5947 85.9746 58.8054 19.535 85.8381 25.6503 55.94 84.9519 26.0034 56.0138 85.1681 23.7587 56.0728 84.3939 51.7304 33.5478 85.5677 55.0626 28.2166 85.6982 46.1808 41.2663 85.9023 58.6956 19.6749 85.8942 58.4592 20.2667 85.8628 15.2502 59.8114 85.5287 41.7704 45.2409 84.6304 -31.3141 70.0204 4.49353 52.0025 33.1735 80.4728 45.9066 41.5285 85.9526 -39.4255 68.6038 6.89097 46.1351 41.2524 85.8122 26.0316 56.123 85.3204 55.045 28.2053 85.7245 26.1017 55.9632 85.1631 26.5556 55.9041 85.345 -59.1142 -18.0242 85.177 28.2992 54.7777 85.1825 35.6245 50.526 85.5637 36.3615 50.1179 85.6232 8.29294 61.3355 85.5855 -61.5714 -6.26248 85.8556 -61.5982 6.66763 85.9253 -61.7872 6.22896 86.0861 -61.6115 6.16833 85.8917 -51.6212 -19.8181 67.9571 58.8516 -19.1237 85.5695 12.27 60.6172 82.462 9.41417 61.7508 84.9147 35.7037 -50.461 85.5539 -58.4485 -19.9413 85.4833 -59.317 18.0303 85.6326 -59.107 18.6385 85.6421 49.4864 17.071 76.4238 -35.6656 49.3907 84.6519 -35.4373 50.8601 85.6235 -35.2724 49.7089 84.6582 -13.1202 60.5236 85.9041 -13.1148 60.5627 85.8592 3.35855e-05 -61.8793 85.5718 -28.6591 53.4943 84.3084 18.2046 -58.9421 85.8206 -22.8044 59.8822 88.1653 -29.8763 54.7725 86.0917 -24.9954 56.477 85.7169 -29.8949 53.832 85.165 35.7474 -50.4559 85.4489 -45.2818 -41.4695 84.8076 -58.5046 -19.9698 85.5621 36.3702 -50.0588 85.5718 -2.22579 62.3728 85.0865 -50.6955 -33.833 84.675 -59.2238 19.493 86.1771 -59.3277 18.3483 85.7662 58.8511 19.1218 85.5699 -41.6725 -44.6118 84.5757 -58.6132 19.7304 85.5793 -42.8234 -44.2921 85.1913 59.9944 11.1863 84.5206 -14.3828 57.8966 83.4485 -50.2962 -33.6002 84.1124 -43.8816 59.6776 9.66673 -36.3716 -50.0601 85.5723 -37.0314 49.4175 85.4789 -55.7527 30.1359 87.3422 -54.2693 29.7489 85.3445 -54.8049 33.0024 88.1326 -45.2707 41.6784 84.9454 -56.0268 24.5448 84.8083 -45.9866 39.9224 84.3924 -56.0029 24.5264 84.7703 35.5993 50.4408 85.4567 -46.8336 40.5952 85.7099 13.1849 61.468 86.6681 35.6073 50.4669 85.4893 0.029541 62.6913 86.5919 -44.9524 42.5388 85.3447 -45.3263 42.0991 85.3176 -7.38903 62.7718 86.8849 -44.771 44.3093 86.7757 7.15684e-05 61.8779 85.5718 -43.931 43.2944 85.1229 5.29877 -60.9804 84.8867 -36.4262 50.0659 85.6179 -29.6045 69.2503 3.67047 -25.5498 -56.4538 85.9319 -24.8556 -57.0599 86.239 -21.7698 -57.686 85.5527 -38.5843 -62.9843 2.77191 -58.5434 -19.9537 85.9273 -41.3418 -45.9816 85.631 42.6115 -44.894 85.5757 -36.0383 -69.1549 5.19569 -29.5265 -54.3898 85.5893 -35.4685 -50.8452 85.6318 -35.526 -50.9289 85.7289 -16.3124 -59.613 85.7521 -21.7623 -57.6688 85.5706 -35.9949 -50.4471 85.6419 -51.4894 -22.4597 80.0412 -46.934 -22.5765 76.7049 -53.3354 -24.6601 82.417 -54.3677 -14.7812 80.126 -56.7614 -16.2687 82.7631 -59.6098 -16.0775 85.2613 -58.1926 -18.7534 84.8606 -58.8492 -19.1236 85.5693 35.79 50.457 85.9346 -61.4969 -6.38598 85.7889 10.7471 4.12424 66.7928 37.3814 49.3497 85.8152 -60.7169 -10.5617 85.3507 60.1284 -10.258 84.3975 60.1338 -10.2578 84.4045 -63.9887 -3.19939 88.1572 77.8658 -7.74908 7.23732 -36.8342 -50.2998 86.1755 -35.5681 -50.9694 85.8041 -36.8773 -49.6524 85.583 -44.9903 -42.0469 84.9313 -1.36266 -61.7674 85.6711 -45.9238 -43.9714 87.6138 27.7242 -55.4694 85.546 -45.025 -42.4736 85.354 -44.799 -41.8473 84.6004 58.712 -19.5047 85.9122 57.8324 -22.252 85.5655 12.8712 -60.5563 82.8135 -46.5911 -40.6243 85.4956 -53.9343 -29.9362 85.0775 61.056 10.2976 85.5913 -54.0468 -30.1032 85.317 -54.0967 -29.932 85.2619 -54.7542 -28.412 85.1293 53.4725 -31.1486 85.9635 15.4006 59.7317 85.4926 -23.7862 -9.13199 55.7854 46.168 -41.3354 85.9439 42.6027 -44.8843 85.5617 48.3773 -38.1912 85.5076 -39.508 63.7668 10.3133 -40.0002 63.3217 11.3095 53.7374 -30.8088 85.9094 -28.1844 72.5112 1.51903 -40.3577 63.0995 11.4063 39.2725 -47.5411 85.1312 39.1869 -48.6735 85.9811 -38.5488 -66.6889 5.02534 36.8539 -49.8218 85.641 -0.195774 -60.9874 84.7131 -1.79664 -61.885 85.517 -33.7693 -52.7352 86.0595 -59.6573 15.4611 81.3837 -16.3094 -59.6106 85.7095 38.4214 -48.6744 85.5713 -16.7302 -61.8448 88.1555 -59.123 17.9789 85.712 -26.4031 60.8355 72.5545 39.1957 -48.7008 86.0173 27.7241 -55.4686 85.533 -24.7286 -56.7451 85.8725 -4.45332 61.4403 85.3992 26.4736 -55.9485 85.3575 26.0852 -55.7831 84.9378 -43.1466 44.0225 85.1946 27.76 -57.3349 87.7772 -61.542 -6.61 85.9635 13.739 -59.3274 84.3941 -12.5023 60.6532 85.888 77.0725 -11.9519 1.56741 25.954 -55.54 84.6047 -0.532603 61.8542 85.5319 18.1836 -58.9437 85.6245 -21.8424 57.8149 85.7523 -13.1908 60.4506 85.9262 74.1751 7.68268 10.5371 -46.682 40.4897 85.4857 11.7535 -60.7 85.2656 -36.9342 49.625 85.9344 11.9315 -60.7041 85.3195 5.47246 -61.41 85.4399 -56.3684 24.7639 85.3102 -48.6867 36.7768 84.801 -25.1816 56.5513 85.519 18.2109 9.07027 60.9775 58.9399 18.5058 85.4884 -56.5444 24.8456 85.5524 -56.6444 -24.1468 85.3426 37.0515 14.2217 68.3874 -13.203 60.5004 85.8996 55.3028 28.4083 86.0253 53.5807 31.1355 85.9439 4.67004 64.3031 82.3319 55.0389 28.2058 85.6711 53.663 30.8941 85.8845 60.6926 -10.6047 85.1906 51.747 33.563 85.5925 -61.5893 6.82745 85.931 14.0309 -60.369 85.7351 -48.8805 -60.989 1.61918 58.1488 -19.5912 85.0495 58.7424 19.535 85.912 57.6726 -22.0322 85.2605 29.1849 -53.6189 84.5459 50.6107 -29.2123 82.1358 -54.3967 -27.5714 84.3195 51.6572 -33.9253 85.7082 53.7285 -30.8046 85.8988 53.6479 -35.015 88.1505 -39.672 -53.4802 72.5743 -53.076 -32.002 85.7101 -24.9861 56.6172 85.8198 58.8393 19.5902 85.6991 61.1746 9.80924 85.5356 76.9698 5.68382 7.85938 -23.0622 59.9187 82.7449 -15.2431 59.7169 80.1525 -31.1077 69.7673 4.30989 9.99635 62.6413 87.3649 61.3915 7.8229 85.3462 -46.0123 46.1841 81.4855 -2.17213 62.45 84.9973 61.1325 -7.10346 84.958 77.8022 -8.31499 7.24516 -56.5272 27.3645 84.4467 -56.6823 27.7725 84.0553 26.1584 55.9916 85.1789 -58.5182 -19.9392 85.8917 -39.6755 69.379 6.42244 -61.1253 15.525 84.1305 61.421 -7.40758 85.3241 61.3756 -7.96582 85.3481 62.0884 -9.39757 86.522 24.1621 57.0757 85.7109 -38.5668 69.3518 8.20702 -33.6554 -53.3352 84.1322 60.7212 -10.6077 85.2273 -14.3786 -60.0666 84.8608 -22.7848 -57.3362 80.1882 -43.493 -45.3055 84.4464 24.6577 9.4651 55.7854 -23.8088 -9.14066 57.0207 -38.3318 -14.7151 69.0716 -29.8465 -11.4574 80.5973 28.6821 11.0099 140.826 -35.017 -13.4437 59.8675 -35.6172 -13.6742 66.0564 45.1795 17.3432 77.2187 -34.6799 -13.3145 57.4041 -14.27 -5.47907 65.4477 -34.7564 -13.3435 58.2001 -17.7387 -6.8109 70.8557 -39.6428 -15.2182 67.8558 -41.1665 -15.803 68.4719 -35.6117 -13.6717 67.3332 -39.0822 -15.0029 64.9884 40.3281 -48.4892 84.1304 45.4313 17.4399 76.6059 19.5298 7.49696 59.7368 45.529 17.4774 76.397 -41.1647 -45.786 85.2992 45.7401 17.5587 75.9863 45.9802 17.651 75.5729 47.4714 18.2226 76.3464 62.1187 12.7726 83.6262 -13.1936 60.5654 85.8252 -47.2118 -18.1234 79.8985 -50.5666 -19.4137 81.8889 58.3551 25.7316 83.1711 52.6935 -32.222 84.8711 -49.305 -18.9274 67.3871 58.7983 20.2646 85.4723 11.7743 61.0901 85.4385 12.6994 62.2339 83.8765 8.23407 61.0429 85.9635 8.29254 61.3058 85.6233 0.481356 61.8592 84.6202 24.3025 57.2401 85.4827 24.165 57.0853 85.7227 24.0721 56.9158 85.9188 35.9602 50.5944 85.6766 36.2106 50.5372 85.581 35.894 50.5479 85.7694 28.048 54.8996 84.2521 26.5135 55.7861 85.1766 46.141 41.7096 85.5861 42.4929 45.0137 85.5643 37.0836 49.4597 85.8459 53.7229 31.1543 85.707 51.7267 33.5529 85.6126 54.8782 28.1186 85.5151 58.7046 19.52 85.9097 61.7393 7.67172 85.4408 63.1132 7.15177 83.8773 59.0172 18.4753 85.9635 61.7596 5.39721 85.7265 63.2922 -8.16247 83.3871 60.9942 -10.6504 85.575 61.2595 -7.93994 85.3728 58.9764 -18.6681 85.9251 61.3777 -7.3798 85.3175 53.7431 -30.8196 85.883 53.732 -30.8058 85.9029 57.6062 -21.9863 85.1866 58.7459 -19.4278 85.7378 58.7278 -19.4711 85.5486 37.2907 -50.5828 84.733 38.5343 -49.1236 85.0532 45.7212 -41.6817 85.8252 26.3781 -56.3457 85.4401 28.6166 -54.5736 85.9635 26.42 -55.8427 85.4005 14.0128 -60.5949 85.4704 14.0341 -60.3782 85.7227 18.1685 -58.8344 85.75 0.465961 -61.8617 85.9256 -10.0228 -61.9414 84.5969 -13.3227 -62.9857 82.8472 -9.49658 -61.1388 85.676 -0.936698 -61.8121 85.8448 -0.944775 -61.8113 85.9635 -9.5195 -60.9086 85.4791 -21.9822 -57.5963 79.2973 -36.5829 -51.0962 84.7332 -35.5592 -50.9269 85.5651 -25.5043 -56.3706 85.91 -35.5789 -50.5539 85.8454 -45.431 -42.5037 85.436 -46.8492 -42.8845 83.8783 -43.5783 -43.6121 85.1772 -36.9525 -49.5787 85.9635 -45.1799 -42.1694 85.5227 -53.2975 -32.0552 85.4699 -53.0844 -32.0083 85.7227 -51.2717 -34.1762 85.8095 -58.8311 -19.7981 85.6763 -59.7628 -19.7792 84.6094 -58.75 -19.7993 85.7694 -56.5929 -24.2633 85.9635 -60.9624 -10.6363 85.6211 -60.7029 -10.5596 85.3629 27.8422 55.0193 83.8257 -59.8087 18.9549 84.8568 -59.4215 18.0906 85.5665 -61.533 6.65082 85.9371 -61.5326 6.65268 85.9635 -59.0712 18.2195 85.8461 -54.4602 30.0791 85.4362 -54.9391 27.9745 85.1765 -56.3625 24.7812 85.9635 -46.9519 40.7882 85.4714 -46.8421 40.6011 85.7227 -46.7106 40.4572 85.9168 -37.013 49.8307 85.6744 -46.4745 47.5732 79.7895 -37.131 50.4777 84.9668 -36.9887 49.7517 85.7693 -36.9173 49.6083 85.9053 -25.411 56.7694 85.5862 -29.669 54.3272 85.565 -35.5803 50.5504 85.8446 -35.5742 50.555 85.9635 -16.0358 59.4484 79.2717 -0.442129 62.0207 85.7663 -0.432636 62.0423 85.74 -8.86065 64.1084 82.0249 -12.5032 60.592 85.8272 -31.8379 -66.162 34.6275 -46.2027 -61.0542 4.38745 60.3565 -12.1821 76.9564 12.2991 61.1849 85.2498 73.055 5.34131 34.8166 76.6709 -7.10887 3.38552 -27.2783 56.5561 75.9664 -41.1935 60.3291 34.6244 -41.336 68.0361 7.53387 -31.3732 69.8163 3.91164 -32.1826 69.6887 3.53471 74.8772 -7.9337 8.95353 74.6423 -7.80403 9.09606 -30.5996 -67.6176 9.57582 -32.2655 69.1199 4.25255 -12.2664 57.0659 82.067 -5.92887 59.5737 83.5173 27.6702 50.9144 81.583 37.448 49.4517 85.6637 41.666 44.9655 84.8592 46.0865 41.242 85.8082 -5.09161 63.3891 87.1834 11.3196 62.7068 87.8047 27.5356 54.411 84.2807 -0.4035 -61.8682 85.9124 18.2299 -59.0147 85.7227 55.812 -28.6732 84.5971 42.4877 -44.5931 85.264 60.6937 -10.5993 85.2573 -58.9922 18.5967 85.5254 15.6935 59.839 85.7227 -35.4537 50.8994 85.6628 -31.8087 50.0818 82.9028 -30.0571 50.2513 82.2905 -24.9901 56.5795 85.8168 37.5668 14.4213 70.8618 37.1183 14.2488 71.734 -45.2289 42.0362 85.1633 -45.1501 42.1163 85.1575 -43.033 43.212 84.3198 -56.6398 -24.157 85.5164 5.30156 -61.3522 85.532 -0.983783 62.1553 85.5254 52.7757 -32.2202 85.7979 55.9435 -26.496 85.5637 -23.6514 -53.3786 82.0805 -29.283 -54.1898 85.2648 53.6479 -32.7951 86.9226 -30.1566 -51.0325 82.9659 39.7915 15.2735 70.1627 -52.7944 -30.1614 84.1124 -58.9081 -12.6842 83.8771 -61.5365 -6.28959 85.8208 -33.8858 -53.5651 86.9544 -45.9961 -43.927 87.6459 -54.076 -29.9178 85.2282 -54.4001 -27.574 84.3245 39.3307 15.0987 70.8706 46.1894 -41.2448 85.8971 24.11 56.9035 85.4898 -54.4342 -29.5056 85.3759 -34.6178 -13.2901 55.7854 -41.3024 -45.934 85.5526 43.4565 -38.9887 82.0813 39.8131 -44.7148 83.5199 39.0296 48.1287 85.5687 -33.7847 -52.7463 86.0833 -1.82214 -61.9924 85.6199 -13.036 -60.4675 85.8223 40.3161 -49.2233 87.3236 27.7005 -57.3849 87.8072 11.8083 -60.5456 85.0796 11.7434 -60.5842 85.11 0.0482696 -61.9023 85.6033 9.42085 -60.2522 84.3187 18.1287 -58.2853 84.8409 19.0809 4.13713 60.6718 19.4219 7.45581 61.123 -37.1249 -49.2858 85.4307 -44.8016 -41.7251 84.5162 -55.1678 -27.5185 85.1946 41.8298 13.3026 70.8252 42.3694 12.5495 70.944 -25.0655 56.7698 86.038 48.496 30.6784 80.9895 58.5834 -6.75138 82.4098 57.8776 -22.2612 85.5077 54.6834 -23.8882 83.3356 16.0302 59.2953 85.2233 59.0044 18.4927 85.5658 61.315 -7.41364 85.1803 61.298 -7.5167 85.1757 58.884 -19.0875 85.6 -8.67285 -3.33123 64.9332 -53.0119 -20.3514 68.0479 -8.08908 61.3509 85.5619 -52.5821 -34.541 84.354 15.2417 59.7833 85.4927 -35.6455 64.9615 9.73502 36.6469 50.4371 85.4138 35.7777 50.4376 85.9635 26.5862 59.0354 82.3574 -34.0325 69.0273 7.99126 -33.9485 69.3098 7.86375 35.7797 50.4364 85.9063 25.813 56.1909 82.7731 -46.8342 40.5956 85.735 49.8704 40.2362 88.1672 46.2324 41.6325 85.5773 37.5127 50.354 84.761 -49.383 37.103 85.7227 -37.3305 49.702 85.5266 31.7751 12.1975 57.6796 36.7362 49.772 85.864 -13.1813 60.4537 85.8415 53.6756 -35.0037 88.1711 36.4551 50.0251 84.0849 53.7868 31.0552 85.7129 46.1147 41.2918 85.9533 51.4633 33.9172 79.5031 46.0897 41.3148 85.5174 58.8505 19.5238 85.7929 59.3957 19.3003 85.2805 75.9863 -7.87051 4.97 53.6709 30.8469 85.954 31.7181 12.1755 56.6862 53.672 30.928 85.9109 57.5635 23.0563 85.4631 57.3413 29.5466 82.3813 57.5788 23.0596 85.4435 57.6852 29.3376 82.0919 58.8516 19.1901 82.3772 -61.5303 6.69478 85.8535 58.707 19.5144 85.874 58.3046 20.4194 85.412 -22.8032 -59.826 88.1111 -31.8112 69.4062 4.73338 61.6628 7.12259 85.6799 48.5763 32.1326 81.8685 53.6766 30.9305 85.9165 61.4744 6.92906 85.6022 8.2906 61.3021 85.5427 58.9484 18.7935 82.3666 -39.0181 67.5838 7.52804 -39.9937 69.2283 6.54092 61.4728 -7.93157 85.6996 64.046 -7.05024 82.748 -39.6979 69.3245 6.44567 61.2564 -7.95178 85.1852 58.8872 -19.0877 85.6039 61.421 -7.17684 82.7746 -40.0492 69.2121 6.50645 59.0118 18.4932 85.5749 58.8085 -19.5194 85.8433 59.2965 -20.0921 84.9838 -64.0055 -3.22431 88.1761 -25.4944 -56.3916 85.8455 57.5522 -22.1107 85.5526 58.7142 -19.4993 85.8778 54.1308 -29.794 78.6654 76.9686 2.9977 4.63244 76.9014 -0.032741 4.83795 75.9431 -2.76077 7.86181 -16.711 -61.8674 88.176 48.5072 -38.301 85.7265 46.1245 -41.2621 85.9635 53.5164 -31.1025 85.953 51.5415 -33.8075 85.5761 53.5727 -31.0114 81.2139 36.8142 -49.9133 85.7657 36.8193 -49.9361 85.7399 36.9492 -50.8541 84.7671 -44.6442 -61.7492 6.10603 40.151 -47.1223 85.5646 42.6032 -44.8875 85.5893 39.8272 -47.5383 85.4499 25.8369 -55.505 84.5206 26.1102 10.0237 63.6787 42.4865 -44.594 85.2831 37.0898 -49.455 85.8447 36.469 -50.0133 84.8467 36.8048 -49.7121 85.8449 24.0714 56.9162 85.9635 39.2429 -47.5174 85.0972 0.638692 61.8421 85.9116 45.9538 -41.4721 80.9757 -2.10262 61.6882 85.5123 26.3389 -56.0936 85.7387 28.7306 -54.8441 85.5945 -30.5726 -68.7641 8.97944 -29.7328 -54.8318 86.0925 -0.565334 61.9038 85.8957 -0.567023 61.8871 85.9163 -0.398643 61.9644 85.8418 26.4294 -55.8362 85.1943 -61.6262 6.02442 85.8937 24.0902 -56.9095 85.4932 -35.3304 50.6928 85.6995 -61.7162 6.0689 85.78 -35.6105 50.6049 85.8855 -37.0758 49.4619 85.5577 -24.9509 56.6304 85.9635 13.1924 -63.3936 82.3526 -35.3918 50.7958 85.8154 9.35591 -60.9251 84.087 0.0491191 -61.9056 85.6075 12.1535 -60.6328 82.7688 -59.4633 16.3824 82.0338 -29.6653 54.3178 85.5771 -0.756159 -62.7953 84.7508 -61.5184 6.82437 85.936 -56.7773 -14.7754 82.2905 -59.0508 18.5807 85.8937 -61.5548 6.82316 85.8935 -59.0351 18.5737 85.9153 -9.52462 -60.9081 85.4414 -0.397744 -61.8689 85.8782 46.0065 41.4269 79.9587 -12.871 -60.5563 85.7115 -52.3965 -25.182 81.7433 -0.51177 -61.8566 83.806 -53.8741 30.3727 82.7569 -0.0927436 -61.9018 83.8247 -60.7035 -10.5569 85.3365 -55.1723 28.2418 85.5612 -49.3164 37.0566 85.6226 -21.8266 -57.8223 85.7513 -24.9982 -56.6165 85.9635 -16.2724 -59.4523 85.5727 58.7359 -19.5167 85.9294 -51.2753 -34.1713 85.4895 -36.0918 -50.438 85.7649 -36.9487 -50.8537 84.7677 -25.3486 -56.5139 85.9064 -35.4064 -50.7858 85.8185 -41.3092 -45.9376 85.7003 -35.4828 -50.879 85.666 -1.83138 -61.8927 85.7436 -35.9233 -50.3547 85.5309 -35.3718 -50.6729 85.7125 -31.1491 -53.1117 81.1681 -36.3002 -50.1372 84.8554 -35.3826 -50.7592 85.8626 -35.9044 -50.3656 85.8439 -29.0656 -54.6345 85.6133 -35.1681 -50.7904 85.4154 -13.007 -60.5122 85.6521 -25.2422 -56.5222 81.0541 13.9714 -60.1987 85.4932 -36.7486 -49.9594 85.7779 -1.83686 -61.8386 85.8105 -44.9288 -42.3952 85.1871 18.408 -58.7565 85.4932 38.1747 -48.479 85.453 36.7472 -49.8943 85.8411 -46.5871 -40.6212 85.4895 39.0783 -47.9675 85.6784 -46.2626 -41.0693 82.4378 46.1575 -41.2168 85.9353 -59.9131 -19.4697 84.596 57.5986 -22.0036 85.2922 57.7351 -22.2311 85.6884 55.9355 -26.4909 85.5757 -56.1444 -32.081 82.4603 52.7777 -32.2261 85.8734 -55.0188 -27.7971 84.1421 60.9711 -10.6434 85.6058 60.8523 11.2622 85.5904 -60.1219 -14.7315 85.5828 -59.1589 -18.238 85.851 53.51 -31.0971 85.9441 -60.2288 -18.8408 84.369 -16.6815 59.3127 85.5184 53.5052 31.1217 85.9518 -59.1353 -17.9252 85.4381 42.3826 44.6897 85.2457 -59.0699 -18.229 85.7665 -60.1348 -13.2302 85.0651 -58.9941 -18.5884 84.324 61.5715 -4.30544 85.4932 7.23704 61.1471 85.2605 -61.5925 6.01676 85.9366 -61.5822 -6.23833 85.9497 35.8883 13.7761 74.9737 -8.09029 61.3648 85.5759 58.6447 19.6547 85.891 28.2881 54.7611 85.2032 59.5272 -8.7535 83.4474 -59.1251 18.7323 85.7609 -61.5929 6.5778 85.911 5.29353 -60.965 84.8677 -59.2326 18.0034 85.8205 -63.4146 10.1607 82.7114 -59.3531 18.0332 85.666 29.1791 -53.5994 84.5211 -63.589 10.5794 82.3842 -53.9908 -29.8866 85.1076 45.6711 -38.4125 83.4695 -59.8695 14.4722 80.2715 -61.5258 6.69349 85.8486 -58.8853 19.0961 79.9248 -58.996 18.5752 85.8422 -22.4182 -55.3092 83.4726 -37.1845 -49.3162 85.5057 52.4537 -31.3119 84.9976 -56.551 24.8516 85.7109 -1.02324 62.1188 85.7863 46.144 41.2401 85.8537 53.7092 30.7431 85.8445 -41.2921 -15.8514 66.3668 -58.7999 19.3042 79.9189 -53.0281 31.7577 85.4857 -36.8705 50.7484 84.9351 -43.2797 44.2747 85.5948 -47.9315 43.5267 82.3596 -43.9246 43.2883 85.1119 -44.8482 42.4588 85.1695 -45.4599 41.8801 82.7665 -25.3059 56.835 85.5765 -36.3698 51.3032 84.6416 -29.892 53.8284 85.16 -26.8539 55.5157 79.5607 -35.1412 50.7992 85.4034 -35.9797 50.3197 85.8613 53.3655 -31.2972 85.6664 -29.3885 54.1199 85.2538 -35.9426 50.3164 83.6864 4.85613 64.4542 82.1193 -43.1318 44.0036 85.2194 -36.3249 50.0937 83.7084 -36.9195 49.6072 85.9635 -17.4663 -6.70584 57.289 -47.4742 44.1009 82.2073 -13.061 60.5028 85.9519 -13.0587 60.4939 85.9635 -25.0142 56.6186 85.9529 -21.7781 57.6574 85.5664 -56.3631 24.7771 85.4611 -61.5714 6.01547 85.9635 -25.0441 56.5949 85.5173 -4.78434 61.7215 85.5648 -8.08743 61.3544 85.5895 -52.1105 33.0254 85.9635 -2.11221 61.8885 85.7099 -46.7341 41.4134 85.2294 -2.10388 61.978 85.5989 -41.1742 -45.7771 85.4402 -12.4865 60.5953 85.908 -14.3847 -60.065 85.7236 -0.55383 61.8511 85.8447 10.1035 -60.8463 85.1412 -2.07081 61.6921 85.3268 -12.7992 60.5043 81.0024 -28.8665 -69.5599 8.26356 -28.1595 -70.4152 6.37613 52.7274 -32.1756 85.7278 46.1424 -41.382 85.8581 -34.5187 -68.3119 6.53202 54.8707 28.133 85.9635 -28.5873 -72.0119 7.75784 -28.3872 -71.0586 7.80673 24.9348 57.2268 85.2516 46.1564 41.2205 85.9357 -28.292 -70.6054 7.61921 58.4118 25.7118 83.1173 -48.014 -18.4315 92.2705 53.7367 -30.8796 85.8596 63.1044 17.4718 81.1725 -38.924 -65.1129 8.73613 -38.3175 -66.7382 5.2551 54.2419 -29.5433 78.4224 31.8296 12.2186 58.2853 17.9581 6.89318 65.6558 -47.7996 -60.533 5.88739 -46.5652 -59.5535 7.0995 -25.2323 -9.68757 77.6096 63.327 -8.80833 88.0936 -54.7462 -28.4091 85.138 -44.2196 -63.1232 3.82231 -43.7161 -63.2375 4.59869 -40.6428 -51.2184 81.2992 74.859 10.7066 6.42815 9.02539 -60.9839 85.2041 76.1889 4.05402 6.73627 24.3785 -59.4764 88.5778 -38.5914 -62.8514 2.71058 -44.443 59.5293 10.5851 -56.7106 -24.1853 85.4381 79.4342 7.74906 6.37861 79.4459 7.79236 6.32131 79.4501 7.79359 6.30897 28.7347 -56.5548 87.3651 75.9503 2.74407 7.83868 -48.4486 -41.5603 87.9987 75.6273 -1.30499 8.8567 -44.8714 -44.6641 87.1977 -61.7212 -3.1778 85.7214 -58.4249 -15.9036 84.1393 76.1082 -11.2359 5.79696 74.539 -10.5719 7.56359 76.8866 -11.4416 6.20313 -26.2585 -68.5448 2.4798 77.4397 -11.6003 6.68384 -37.2188 49.5261 85.7368 -46.2854 56.9058 2.4464 76.1188 -7.28935 4.96639 -42.4573 43.8124 84.4354 -58.4269 -19.9249 85.4507 -24.6858 -56.348 85.4605 -25.1263 56.7862 86.079 28.3291 54.0267 84.4031 35.7101 -50.4775 85.5756 35.6387 50.6808 85.7398 36.3899 50.0842 84.0854 -43.577 62.1351 6.2604 -41.5107 63.3262 7.87472 13.5536 61.2122 86.509 58.8776 19.131 82.3776 46.0065 -41.4246 80.9764 -46.8949 59.6743 8.66554 43.3068 44.7895 86.065 -13.0719 60.6554 86.0271 36.3943 48.9394 84.6924 -13.0027 60.337 85.6762 9.02103 -60.9603 85.1744 -40.4258 64.0506 8.09355 -37.9514 66.4231 5.51933 -39.5 68.5607 6.89535 -37.7962 66.5517 5.41498 -39.8135 69.3341 6.53661 -39.7363 69.389 6.51484 -28.8444 68.7039 9.43355 -38.0739 69.7633 7.9063 -29.2411 68.879 9.2444 -40.909 67.853 8.55739 -61.5285 6.68102 85.8156 -29.2896 68.8283 9.25908 -45.1594 42.1798 85.1735 -39.563 68.5277 6.8991 -41.6393 68.3048 6.31385 -31.818 69.4028 4.73703 -43.6411 62.2819 8.50946 -42.5914 64.4656 7.8214 -36.123 -68.8121 5.03445 75.9729 -7.5092 5.26858 77.6861 -0.000703104 7.73242 -36.8959 -50.7073 86.6196 77.0503 -9.62565 5.01706 -30.673 69.2928 6.14885 53.3684 31.0136 85.678 -30.867 69.1913 6.27038 -0.671622 -61.0111 84.7197 45.9851 -41.1714 85.6766 75.0337 7.89628 8.86527 -9.55988 -61.4631 86.0318 45.7933 -41.7447 85.9284 74.856 0.0809392 3.26682 74.8595 -0.000703104 3.26417 -61.368 -10.6859 86.0615 72.4903 11.5344 2.47915 36.8237 -50.756 86.6149 28.73 -54.8412 85.5396 -53.0093 31.7409 85.4551 77.6236 5.63688 7.4839 -60.8514 11.2652 85.5629 74.6812 -1.6132 9.38833 78.9004 -0.683185 6.99737 76.6044 -9.81877 4.76789 -55.1477 -27.5076 85.166 -45.942 43.5401 87.2439 78.3885 -8.13904 5.71344 77.6918 -7.68644 5.28839 8.60346 -60.4001 84.4356 -28.5744 74.2546 2.54888 -28.7137 74.8573 2.94841 35.5329 13.6406 60.0259 46.2137 -41.2842 85.8578 46.1946 -41.2485 85.9039 45.9003 41.5225 85.9635 -27.929 -72.3025 7.76675 1.32983 61.7699 85.0322 -30.828 -69.1284 8.72452 76.2521 -6.77814 4.88866 -50.8527 -19.5234 92.1192 53.6638 30.8445 85.9459 33.9644 -54.9982 82.1164 58.3898 20.2278 85.8116 76.8435 0.149139 5.02035 39.6398 15.2155 70.4106 78.6475 -12.4198 2.77445 60.5633 11.2106 85.308 -53.0119 -20.3514 92.0843 42.3809 44.6912 85.2621 16.1388 6.19477 57.3452 74.3508 7.87231 9.86743 -49.8849 -61.9937 3.09714 -44.2623 60.2477 9.2691 -37.9424 -67.0061 5.11419 41.3157 15.8606 61.2496 -35.1338 -68.2837 6.05094 -45.7769 -61.8869 4.64032 -44.3685 -61.9638 6.18071 19.4431 7.46351 58.7796 52.4641 -31.2224 84.9591 62.5316 -6.45647 86.6682 -41.0386 68.0826 6.61917 -41.0429 67.4437 5.70737 -39.114 63.3871 9.49061 -58.8775 19.131 79.925 -42.9239 64.0269 7.92048 -35.2572 50.7283 85.0546 -39.1978 62.7826 9.75005 -24.9699 56.6734 85.9021 -44.1036 63.5793 7.73923 -12.5095 60.6901 85.9285 -1.52943 -61.7494 84.8931 28.829 54.4488 85.1871 15.6509 59.6985 85.9072 48.0641 38.8525 85.7216 -38.9192 67.6354 7.52387 -37.3857 64.7549 3.21385 -40.7602 67.4066 5.59545 -61.1231 8.58514 84.4606 61.3396 -7.55854 85.1904 53.7038 30.7552 85.8102 -61.7431 -3.17761 85.7459 -60.948 -10.6356 85.6389 -29.2182 68.7272 9.32969 -32.9967 70.861 7.28247 -54.9229 -28.0156 83.7225 -45.3672 -41.9998 84.7896 -35.9629 65.0176 9.62652 -39.712 69.3055 6.45209 -29.4381 54.0471 81.6185 -26.8742 -55.5803 84.6037 -45.2379 42.1085 85.1271 -31.2072 69.9384 4.42446 -14.4156 -60.1628 85.8321 -47.5435 -39.3761 85.9139 -29.3283 68.7482 9.29169 -31.8162 70.361 4.79547 11.9815 -60.6486 85.1039 5.29013 -61.3534 85.3545 -9.49165 -61.1211 85.6993 -47.5114 -39.3531 85.9635 -5.76908 62.4724 86.1813 -16.685 59.3287 85.5032 35.5777 -50.7382 85.7614 -43.2926 44.2911 85.5685 -4.02737 60.1958 83.8328 -2.11079 61.8311 85.4569 13.4667 -60.9743 85.2275 -37.2329 49.5402 85.7615 -49.2316 36.9857 85.7496 36.8639 49.8193 85.6417 52.8034 -32.2407 85.8359 46.1523 -41.2239 85.8494 55.6014 -26.4931 85.2442 7.17174e-05 -61.9107 83.8254 55.6023 -26.4909 85.2613 -50.2408 38.5645 83.7591 -9.45344 -60.9159 85.9635 42.3877 44.6974 85.2546 61.3597 -7.4643 85.1474 55.6503 -26.3808 85.9635 59.0138 18.4838 85.5021 -0.441568 62.0124 85.7017 0.645479 61.8343 85.5689 0.403614 62.5587 86.46 -35.9739 50.3237 85.9024 -58.6476 -20.0416 85.7631 -24.7338 -56.7618 85.8915 -58.5171 -19.9418 85.9635 -58.814 -20.0391 85.572 26.0409 55.9115 85.0636 -44.482 60.6709 8.99481 -59.0004 -19.604 85.5805 -37.1482 49.4001 85.8798 25.031 55.5423 84.2574 -2.08084 62.237 85.8463 53.4708 31.1533 85.85 53.7901 30.6977 85.8929 -51.4284 -34.2874 85.7227 13.8075 60.2543 85.4992 42.485 45.0073 85.5763 47.6143 39.2159 84.0606 53.7589 30.6778 85.9393 26.1192 55.9017 85.0975 -41.5377 67.4582 5.87826 -42.9351 -44.1914 85.2476 26.0572 56.05 85.0222 -35.3661 -51.1598 85.4321 12.8712 60.5549 82.4951 7.23914 61.4261 85.6111 13.7538 60.2665 85.3182 -61.5714 -3.18547 85.5611 -61.6031 6.57907 85.9221 -37.2162 -49.3422 85.5562 -63.665 3.64363 87.8527 -61.6106 6.0263 85.8771 7.17174e-05 62.7573 84.895 -61.5749 6.54822 85.8881 53.7403 30.6729 85.9188 12.4015 61.1687 85.2515 -37.0105 49.4024 85.4513 16.0753 59.5126 85.5965 -56.355 -23.8882 84.8841 -59.4132 18.0587 85.7284 10.9646 4.20822 120.051 47.5171 29.2747 79.6254 -32.9771 46.7883 81.1059 -16.584 60.6805 84.3617 0.640794 61.8419 85.9635 58.1383 29.1326 81.6731 22.7566 -57.3859 85.9139 -25.3709 56.5107 85.9094 24.7353 -59.4684 88.7046 62.9849 17.5492 81.2989 25.5623 -55.243 84.1124 -29.3923 54.1283 85.2464 42.8703 -46.4426 86.8839 -45.4526 -61.9977 3.79917 -58.8555 -19.1738 85.5998 35.4662 -50.6182 85.2229 -1.50056 62.1873 85.4158 36.9106 14.169 72.1777 -59.1182 18.7314 85.7003 -30.9234 -55.1232 86.884 -11.9324 -4.58167 69.0578 -59.1695 17.7641 85.4136 -48.3232 -41.9224 88.1335 -48.2632 36.3989 84.1124 36.3758 13.9635 73.4791 -47.0927 41.558 86.6565 -55.2363 26.0233 84.576 -15.6355 -6.00349 73.7837 -45.0847 40.9731 84.2559 -23.8846 -9.17057 58.3572 5.13942 -61.0084 84.9084 -32.0598 69.0104 4.14569 -42.4806 -16.3088 58.1744 -12.7878 -60.7522 85.7273 55.1938 -26.0403 84.6174 -44.2602 -22.122 74.5494 -25.1816 56.4883 80.1892 -25.3557 -56.5291 85.9245 -22.8385 -59.8348 88.1351 -45.4151 -60.6613 3.93865 -56.8054 -24.2255 85.7385 -37.3471 -49.441 85.7587 42.9791 -44.524 85.6122 53.8152 30.7155 85.9258 -31.7558 -49.9149 82.748 -29.0609 -54.6221 85.6294 -35.231 -50.9638 85.5817 -14.4098 -60.1345 85.869 -16.7311 59.5116 85.7088 -24.713 -56.7093 85.9097 -58.3185 -15.5014 83.9128 -59.3438 -17.8463 85.5986 -55.6948 -19.5239 82.8655 38.7213 47.9833 85.2933 -55.4647 -18.336 82.2708 38.7079 47.9957 85.1873 -60.331 -13.6503 85.3072 -36.7544 49.7767 85.944 35.554 50.6036 85.9233 18.4465 -58.8535 85.6191 -61.5761 -6.6638 85.8981 60.0588 -10.7877 84.4762 79.3041 -1.2641 6.73424 -37.1227 -50.3807 86.4857 -35.7795 -50.7588 85.771 -36.0941 -50.3692 85.8388 -36.0878 -50.4314 85.703 -36.6342 -49.9596 85.6851 -33.3529 -51.8395 81.098 36.7887 -49.7255 85.532 -44.7533 -42.0559 84.704 -59.1775 17.7231 85.6562 -14.6967 -61.1844 86.9725 60.8206 11.2524 85.6315 60.7014 -10.5633 83.5974 -14.4049 -60.1305 85.7975 11.2475 -60.8857 85.3768 38.2612 -48.5691 85.4022 -58.8745 -19.1765 85.6232 41.3856 -47.1516 86.1813 42.9679 -44.5116 85.5942 75.4283 8.51671 6.0933 -38.6971 -66.6348 4.94252 60.0521 -10.7879 84.4676 38.0047 -45.8727 83.1304 13.8058 60.2496 85.505 38.5952 -48.9649 85.8945 -38.6718 -66.4979 5.35295 -60.4379 -11.8277 85.1729 -55.2204 26.011 84.5507 -53.5479 -27.4898 83.5299 -1.22357 -61.9807 85.6268 77.2874 -7.88688 7.56433 -8.83734 -59.6805 83.9867 -35.2099 -51.254 85.7884 -12.9509 -60.4242 85.7575 -9.52567 -60.928 85.462 36.8089 -49.9068 85.7022 -31.1129 69.5048 4.17355 -0.44808 -0.173683 63.1499 -21.8109 -57.6729 85.5572 36.445 -50.8696 86.4821 -44.5547 -63.1768 2.98271 -38.2 -67.0406 4.61493 -2.12191 61.6859 85.6947 26.1673 -55.56 84.7094 75.5183 -0.649698 9.19841 -58.8288 -19.1624 85.5635 12.4006 -59.6451 84.2579 14.0307 -60.3684 85.7103 -49.2238 36.9923 85.4857 1.34851 61.645 85.3924 -37.1725 49.4241 85.9216 48.582 32.081 81.8457 -55.1306 -17.0723 81.5591 0.0447652 -61.922 85.6276 5.30726 -61.4298 85.4509 -59.0617 18.7555 85.8354 -40.5832 45.7484 84.7958 26.2456 10.0758 63.373 7.00838 63.0451 83.6049 53.7544 30.6668 85.8441 53.657 30.9261 85.8964 60.5972 -11.0527 85.2124 58.4564 20.5225 85.5812 77.7785 -7.23992 5.31513 35.3807 50.6667 85.5502 58.7936 19.5139 85.6221 58.2827 -19.1025 85.0412 58.4111 -20.6104 85.5627 58.7975 -19.4917 85.6186 35.4372 -50.5902 85.5127 48.0811 38.8647 85.7441 76.6929 -6.73124 3.5861 76.9236 -0.155093 4.77197 -23.6676 57.0343 84.8551 58.8386 19.5058 85.6724 60.8156 11.2531 85.5429 77.3587 6.00043 7.61858 35.4738 -50.6146 85.8779 -13.1354 60.6056 85.9938 58.7175 19.4918 85.5452 -43.1942 63.7495 7.96116 58.2874 20.4572 85.6537 62.4018 -6.02768 86.51 -54.3887 30.604 85.2488 -32.4513 69.5522 3.69075 -29.3299 68.6482 9.34394 26.4391 55.8295 84.9533 -59.4749 18.1711 85.4757 16.0887 59.554 85.5459 -45.9086 -42.2731 85.2486 -43.9268 -45.3263 84.0562 -35.4609 -51.1879 85.3423 58.9001 -19.096 85.6226 60.6324 -11.0564 85.2575 31.7015 12.1691 55.7854 -34.632 -13.2956 56.5629 -35.6011 -13.6677 67.3528 -38.6786 -14.8494 64.2488 38.7723 48.0457 85.2615 46.7026 17.9279 77.8656 62.871 -10.0118 87.6648 -42.2833 -16.2331 56.7327 -42.3281 -16.2501 57.1986 44.5502 -42.7364 84.5996 -42.1727 -16.1894 67.3942 -43.8498 -16.8335 61.8386 47.46 -39.4248 80.1264 38.5312 -49.2174 84.9666 26.0121 -56.7279 85.2529 46.9053 18.0058 77.372 46.9841 18.036 77.2037 26.3148 10.1022 62.2622 -42.0907 -44.952 85.239 47.1541 18.1014 76.8729 47.3476 18.1758 76.5399 65.2534 -8.90456 80.7659 61.7575 10.7809 84.5966 61.9887 7.20759 85.2543 62.1381 10.5343 84.194 -55.6808 26.3084 85.229 -53.0119 -20.3514 84.2546 0.642096 61.8626 85.9372 26.1202 59.2439 82.3624 24.6044 56.7429 85.9403 26.1744 55.9822 85.2272 45.769 41.8762 85.7445 45.6574 41.8338 85.8784 38.7404 47.9683 85.5649 36.7419 49.7679 85.6335 36.7148 49.792 85.5399 56.4502 32.6389 81.8111 46.1084 41.2866 85.9635 53.4981 31.1158 85.942 59.5255 19.8179 84.8618 53.6487 30.8789 85.9045 61.7596 -4.3097 85.7265 61.5715 -4.28691 85.9635 60.8904 -11.0968 85.586 61.4733 -6.93564 85.5981 61.4689 -6.95239 85.6217 56.5065 -32.575 81.7875 56.6447 -24.1456 84.0324 54.3248 -29.3574 78.1726 58.2465 -20.5488 85.3933 35.4708 -50.6162 85.9635 13.6906 -63.2879 82.3568 14.058 -60.1705 85.9157 -12.5645 -60.7051 85.816 -12.528 -60.6493 85.891 -1.81256 -61.7198 85.7339 -12.5139 -60.5938 85.9119 -0.319808 -61.8769 85.7396 -0.367787 -61.8723 85.553 -29.285 -54.1885 85.2831 -25.5075 -56.3687 85.9635 -36.6091 -49.8885 85.7584 -36.5927 -49.9032 85.5967 -55.8785 -32.5433 82.4652 -52.9088 -31.9239 85.9172 -54.605 -28.7281 85.9635 -61.5985 -6.65997 85.881 -61.7196 -6.61014 85.7442 -61.58 -6.665 85.9025 -60.1363 -13.2241 85.2023 -59.074 -18.2087 85.9635 -61.5423 -6.6086 85.9435 -61.5714 -6.23767 85.9635 -61.4977 6.81643 85.9127 -48.2729 43.1484 82.3643 -44.8186 42.4867 85.326 -36.743 49.7655 85.9245 -45.3066 42.049 85.3111 -25.3691 56.523 85.8826 -25.3683 56.505 85.9028 -32.4818 52.3352 85.3891 -35.979 50.3181 85.6344 -36.0108 50.2977 85.5376 -0.374209 62.0036 85.7966 -2.77929 61.6165 78.9017 -30.7908 -53.3183 76.9564 -35.4387 -52.0173 75.957 -45.6144 -61.5742 4.43844 79.437 7.68057 6.41551 79.4749 7.76962 6.25641 74.5645 -7.80537 9.33068 76.2745 -8.01132 3.98198 76.1569 -6.80933 4.3579 -43.5478 -62.7275 4.30075 -39.6937 69.4755 6.36737 -29.17 54.5799 85.6042 -29.2313 55.8382 84.1904 -1.3761 -61.7658 85.7892 -62.1088 -10.3241 84.2854 17.9988 -58.8895 85.7568 53.457 31.1724 85.9343 43.0003 44.5039 85.6146 24.0746 57.1026 85.7091 -43.9561 64.5037 7.34954 35.8362 -50.4053 85.9118 61.053 10.298 85.5381 -6.09829 -2.34284 61.3114 17.874 -59.0499 85.6309 -7.42852 -61.1327 85.173 -13.7636 -59.0794 84.5405 -59.7276 15.1418 85.0927 -58.4476 -20.1891 85.9169 -10.3297 -3.96642 71.5328 30.4214 11.6779 68.8051 18.4484 -58.8588 85.8256 -28.7591 55.2035 86.0465 -35.3202 50.7002 85.8063 15.4702 59.7091 85.5721 -61.6111 6.09654 85.8843 53.809 30.5813 85.931 -28.8584 -54.4347 85.3538 42.9891 44.4949 85.6317 53.8397 30.601 85.8853 -58.665 -22.1389 84.6637 -56.8686 -24.2513 85.653 -13.1986 60.4908 85.8884 -12.5143 -60.6159 85.9356 -61.5414 -6.67179 85.948 24.0748 57.1032 85.7363 -29.3315 68.7343 9.29819 19.3531 7.42871 57.2092 58.2819 20.4704 85.778 -54.7468 -28.4079 85.1187 77.6618 -7.98753 5.28622 -12.5324 -60.6718 85.9158 -61.1825 9.03633 85.7046 -31.414 69.5245 4.75342 76.4186 -8.17705 4.57836 35.7141 -50.4846 85.5859 -30.9265 69.1794 6.24991 -39.8474 69.1895 6.47985 45.6875 41.8618 85.9226 -39.2125 65.7 5.50604 75.981 -7.39505 5.31535 -56.3429 -23.879 84.8658 -58.6322 -20.0337 85.7415 35.1981 13.5117 57.8877 58.1698 29.1216 81.6432 57.0121 23.3222 85.9635 -37.2666 -49.2959 85.8676 -1.49545 62.006 85.6443 -1.50579 61.8945 85.7827 -46.7113 40.4566 85.9635 -58.5695 19.8225 85.902 -13.0009 60.5193 85.9556 -40.835 -45.516 84.7741 -62.6624 11.7427 83.2242 35.4186 -50.5274 85.4327 -61.7247 -3.17529 85.768 5.13401 -60.9926 84.8889 -59.1508 -17.8491 85.6836 -61.5803 6.27803 85.9521 53.7283 -30.7341 85.9444 58.3257 -20.6293 85.8306 38.3503 -48.541 85.7556 40.5669 15.5729 58.8047 -1.4125 -61.8553 85.8458 -35.1325 -50.811 85.6535 -14.3911 -60.0629 85.7889 -4.36098 -61.8677 85.4399 -25.0014 -56.6248 85.9521 -60.4338 -11.8262 85.1686 -12.5102 -60.5943 85.9635 7.23865 61.3825 85.6666 -52.9317 -31.8925 85.4895 -7.42867 -61.1285 85.1686 -60.8638 11.2682 85.5769 -59.0079 18.7168 85.911 -58.3263 -14.7717 83.6819 -60.8532 11.2677 85.5895 -53.2252 -27.6691 83.2984 1.37511 61.7035 85.466 -59.1771 17.725 79.5537 -29.1651 54.5675 85.6202 -35.218 50.9198 85.7896 -0.417431 61.9052 85.9134 -35.1059 50.8217 85.6435 38.1536 -48.4974 85.2902 39.1274 -48.0569 85.5544 -43.5771 64.9539 7.26169 38.1997 -48.4553 85.6564 53.546 -31.0485 83.9584 52.7258 -32.1768 85.7975 46.1677 -41.2232 85.9483 58.2344 -20.5778 85.7641 57.5418 26.0995 83.923 56.9244 26.4747 84.4425 58.415 20.5128 85.7874 35.1042 13.4754 56.5429 58.5193 20.5497 85.6458 48.0679 38.8521 85.7681 -23.6572 57.049 85.7857 -16.6781 59.3138 85.4844 35.152 13.4939 57.3784 35.5396 50.575 85.8837 -5.82321 -2.23723 69.7571 -37.088 69.2177 7.1418 61.2339 -7.47724 85.0815 -45.1453 42.1928 85.2227 59.0089 18.4595 85.5611 -59.7266 15.147 85.0622 29.6709 11.3896 70.6311 8.60127 -60.3937 84.4277 -44.1164 -63.4574 3.26685 -14.0841 -5.40788 75.9436 -1.47008 61.9381 85.5796 -13.844 -59.0954 84.5758 41.8586 -44.3128 84.5553 -42.247 -16.2189 55.7854 -4.36025 -61.8755 85.4303 -54.745 -26.9237 84.4233 -42.2577 -45.1313 85.5461 38.0766 14.6173 69.9838 -28.8556 -54.4366 85.3287 -29.2106 -53.5045 84.555 53.3737 -31.3088 85.8459 -59.4085 -3.88423 83.3081 -44.7809 -17.191 63.2168 -45.1185 42.0404 85.0571 -21.8334 -57.8372 85.7305 30.7125 11.7898 68.1826 53.6479 -31.504 86.2085 -24.8451 56.5165 85.6931 -40.7076 46.1899 85.4869 -31.1283 47.9728 80.9121 -35.2934 51.0052 85.6483 -42.4523 43.8089 84.4289 -43.1288 44.0057 85.1637 39.0536 48.1693 85.5104 28.3274 54.0211 84.3962 -8.90813 59.6252 83.9471 45.908 39.3863 84.3494 -41.4902 67.6456 8.25118 -29.0202 54.3391 85.9635 24.524 53.6309 82.4094 24.983 55.4333 84.1124 39.5032 44.5743 83.2295 -8.16691 61.0491 85.2643 43.1132 40.1401 82.6162 47.5484 34.5464 82.2555 -60.4335 -11.8273 85.1766 -60.8372 -11.4413 85.5641 -7.42757 -61.1286 85.1767 -61.5866 -6.6658 85.9096 18.413 -58.7549 85.7402 18.4749 -58.9351 85.7227 17.8991 -59.1222 85.7227 53.9627 -30.5918 85.7465 42.849 -44.2677 85.3267 60.5987 -11.046 85.2943 64.008 -7.89538 82.5719 24.0779 57.1135 85.7227 60.5679 11.1874 85.9635 -29.8645 48.4078 80.7224 38.8636 14.9191 71.6749 38.4527 14.761 72.4739 -45.0852 42.1138 85.0906 76.825 0.60778 5.079 -13.1741 -60.4579 85.7421 -5.96348 -2.29062 58.7197 -58.4153 -20.1703 85.8712 -1.44742 62.2703 85.3194 55.6098 -26.4954 85.2538 -61.4639 9.07468 86.0116 53.889 -30.5 85.8788 -55.9097 26.4147 85.5441 -59.4016 -17.8513 85.6527 53.4936 31.1941 85.8958 -57.9626 -5.67648 81.929 -33.1428 -54.2727 87.1814 -43.0277 44.1329 85.2055 -29.3865 54.1211 85.2366 -54.2531 -29.5185 85.172 -58.8583 -19.1756 85.6038 -59.2764 17.2537 79.2211 46.2335 -41.3147 85.9824 48.3476 -38.2325 85.5128 16.0761 59.5124 85.4924 61.3608 -7.57655 85.269 -37.2295 -49.3564 85.5806 -1.77592 -61.724 85.5824 -59.3787 -3.93744 83.282 35.9854 50.3355 85.9441 -35.2519 -51.2845 85.8536 -4.01475 -60.1582 83.7963 -5.60385 -59.0104 82.966 41.6703 -48.4924 87.6649 -45.1679 42.2102 85.2607 60.8615 -11.0879 85.6245 -59.3003 -17.7888 85.7944 -40.8098 -45.4984 84.7379 28.7923 6.83514 63.9162 30.9221 4.35002 64.3939 -59.4581 18.0915 85.7984 -24.0722 56.0881 84.9417 -24.0725 58.1367 86.9723 -35.2755 50.9404 85.5889 46.0447 28.8185 78.2363 28.8415 54.475 85.2237 26.1836 56.0077 85.2636 -59.7501 15.1478 85.0835 58.4811 -20.6524 85.6376 55.2665 -21.8911 83.0121 -7.91984 -61.3934 85.5642 -23.6924 57.1469 85.8318 61.4775 6.91439 85.3785 61.2481 -7.5507 85.1138 45.8364 39.4187 84.3163 46.5176 17.8568 78.4324 -52.9085 -31.9248 85.9635 -8.58792 61.2666 85.5935 7.17174e-05 61.9093 80.3615 -36.3897 50.0582 83.7093 26.3391 59.1582 82.3816 13.806 60.2495 85.4931 -55.948 26.4313 85.5954 -36.907 69.6695 6.94936 35.9785 50.3217 85.9249 -49.3211 37.0598 85.8189 40.4682 46.4101 84.0313 -45.4899 -62.6554 4.91054 44.676 42.6248 79.3666 53.691 -32.7776 86.9549 36.79 49.7247 84.0651 -25.3399 -56.4655 85.9373 -63.8677 11.0671 81.9126 56.4721 32.605 81.8132 46.0357 41.3876 79.9583 59.6846 19.3941 84.8984 57.576 31.2759 81.2209 57.766 31.1605 81.0611 61.6442 6.85914 85.7704 -31.6535 69.3703 4.99001 61.6275 6.87074 85.7895 7.23582 61.3771 85.5483 64.0919 -6.73582 82.7752 -45.7907 -62.0384 4.71701 59.7531 -19.4177 84.8077 53.6141 -30.9538 79.0855 61.3361 -7.57561 85.2355 -63.6428 3.6087 87.8256 59.0188 18.4601 85.5733 56.4881 -32.6119 81.7899 58.748 -19.5193 85.9142 58.8809 -19.5554 85.7427 59.9739 -20.1808 84.156 -61.5714 6.03068 85.8348 -29.0574 -54.6203 85.5954 57.0448 -23.2507 85.3952 -55.6956 -19.7478 82.9381 76.8181 -0.194885 5.10072 -14.6672 -61.2193 87.004 76.2824 3.55574 6.79473 53.5934 -30.9826 79.0852 36.75 -49.9393 85.7956 42.9687 -44.5157 85.6295 53.4974 31.1168 85.9635 7.24707 61.1458 85.3737 25.9215 -56.7764 85.2563 -1.45642 61.7562 85.651 35.8454 -50.4238 85.9373 -28.6641 -55.2462 86.0515 -1.51029 61.8501 85.8377 -59.0727 -18.216 85.8455 13.4644 -63.3465 82.3757 -25.0121 56.6103 85.9438 -61.6233 6.0964 85.8974 -12.4826 60.5958 85.9635 7.17174e-05 -62.9736 84.6246 -35.1886 50.8869 85.8433 -40.6988 46.1962 85.3219 10.2186 -60.8342 84.7445 -46.0064 41.3876 82.8188 -46.5093 41.8785 85.1137 -29.9961 53.716 80.826 -5.76957 62.7352 86.4574 -0.640388 -63.4109 83.9913 -1.62171 -65.0617 81.7833 -59.2004 17.9891 85.8647 -5.46019 -61.3364 84.0334 -12.5152 -60.5937 85.8307 -61.5714 -6.47201 80.0541 35.3581 50.5888 85.4521 -59.1336 -18.2268 85.8852 -61.0383 8.97727 85.546 -36.1114 -50.4496 85.7396 -36.1358 -50.3859 85.7942 -25.3463 -56.4747 85.9493 -35.0667 -51.0277 85.7684 -37.2941 -49.323 85.9151 -35.2655 -51.0224 85.6466 -32.5323 -52.313 80.0564 53.5813 31.2046 85.9827 -36.359 -50.1033 79.6696 -35.0346 -50.9919 85.8277 -28.5095 -54.9156 85.6572 -12.9829 -60.52 84.1093 -35.2519 -50.7421 79.3307 -36.7131 -49.8129 85.9462 17.8366 -58.9423 85.4932 38.6073 -49.0023 85.9441 13.013 -61.2179 85.1137 -36.5173 -49.971 79.6644 -56.0097 -32.3355 82.4842 -55.4477 -27.5628 85.5911 -54.2982 -29.8691 85.7321 58.2466 -20.549 85.6323 53.376 -31.316 85.9379 -54.6988 -28.5156 84.7379 -61.7404 -6.48956 85.752 -60.46 -13.7099 85.4337 -60.4144 -13.697 85.4933 53.4666 31.1804 85.9476 45.6187 41.7761 85.8094 -58.9747 -18.6759 85.864 38.9799 48.0436 85.6888 -61.1874 -8.27915 79.4429 61.5715 5.10134 85.4932 25.452 57.1625 85.1302 1.39083 61.7634 85.5426 -61.5793 -6.30026 85.9534 -8.58941 61.2843 85.6112 28.8253 54.4509 85.2536 -59.1422 18.7473 85.7356 -59.0894 18.7898 85.7902 -61.5535 6.59021 85.9542 -61.6009 6.52643 85.9147 -59.311 17.7544 85.7889 53.3823 30.8868 85.6218 -59.4172 17.8002 85.6477 -24.7663 -56.2601 85.4075 35.6469 50.6969 85.7625 -61.5519 6.56796 82.7153 53.3129 -31.1217 85.6862 -54.3449 30.6968 85.253 -58.5916 19.834 85.9325 -2.06662 62.2811 85.9033 47.9373 38.7698 85.5614 53.7448 30.6633 85.8331 -32.943 -46.2874 80.7104 -48.1232 43.3296 82.3829 -29.3214 68.6302 9.40464 -45.0273 42.6032 85.6869 -36.0663 50.3963 85.8263 -28.9465 54.3758 85.3284 7.28762 63.2718 83.2859 -43.0114 44.1121 85.2327 -16.7282 59.4976 85.7265 -55.6777 26.3162 85.3241 -12.9985 60.5133 85.9486 -25.1297 56.5048 80.1886 -23.6637 57.046 85.718 -0.446392 62.7395 84.8612 -8.58575 61.2711 85.6285 -55.4663 -27.5696 85.5663 -4.2794 61.8671 85.4497 -4.2784 61.8779 85.4364 -42.0972 -44.9459 85.3392 -35.5724 -50.5575 85.9635 -8.16438 61.0497 85.2832 -13.1826 -60.4552 85.8446 -0.0459395 61.9049 80.3612 9.02452 -60.96 85.229 53.3637 -31.2997 85.8315 58.6863 20.5382 85.4585 53.5429 31.2061 85.8527 47.9396 38.7654 85.6041 53.4992 31.1983 85.9033 42.5176 16.3205 63.5601 22.233 8.53418 121.82 -1.9655 -65.192 81.5734 -48.3442 -61.0816 6.27059 8.93004 3.428 122.134 -48.6628 -61.3841 6.59944 -50.236 -62.3233 3.42634 -19.5651 -7.51196 84.2545 -55.1463 -27.5107 85.2179 -43.0082 44.1144 85.1715 45.659 28.8325 77.9932 53.6479 31.1925 86.035 -32.0567 -53.9307 86.1817 79.2009 -12.5883 3.15431 -40.7532 46.2447 85.4135 76.3873 -6.76415 4.48865 -0.945221 61.8722 85.8848 76.0922 -8.23035 4.39259 -46.9462 41.9726 86.8138 28.8079 53.7925 84.4745 35.4515 -50.6268 85.5612 35.4103 50.8083 85.7225 44.3881 42.8831 79.0239 53.6141 -30.9538 83.9595 -40.8752 67.8628 8.57827 -54.2161 -29.6034 84.9318 -61.1041 -8.66904 79.0897 -61.5714 6.4706 82.7162 -44.9131 42.3988 84.9428 -39.9224 69.1501 6.48431 -31.1107 -70.2972 8.04114 79.4585 7.79493 6.31385 -37.2861 49.2724 85.544 -30.6518 69.2862 6.1887 -30.8437 69.186 6.30836 43.2904 -44.8151 86.072 79.0027 -0.895204 6.92744 -35.3668 50.7679 85.8611 46.2424 -41.3829 86.0365 -61.349 6.39243 85.63 35.4891 -50.6452 85.9201 -36.5861 -49.8961 85.5851 -58.9762 -18.6693 85.9039 -47.2454 41.1491 86.5139 -23.6821 57.1142 85.7944 76.3053 -8.22613 4.51504 -55.3781 -26.9903 85.1932 20.0799 7.70751 123.506 60.7675 10.2512 85.2286 45.6108 41.7832 85.887 -5.99392 -2.30173 57.7743 45.5938 36.12 81.7817 -45.2508 -63.2371 5.10892 45.6304 41.8093 85.9222 -43.7862 64.6781 7.32397 -33.3866 51.7905 83.5512 37.7416 48.868 84.6971 -8.67048 61.7052 86.0725 -1.26007 61.8969 85.8122 -30.8805 69.1679 6.32794 13.796 60.2268 85.463 -37.5182 64.6695 3.21813 -29.2879 68.5681 9.39629 -45.3354 42.0182 85.0849 76.6775 -7.78234 4.70763 61.2734 -7.86987 84.9689 53.7333 30.6891 85.7599 -61.6185 -6.24238 85.9062 -60.8274 -11.4408 85.5761 -35.5704 67.399 8.47256 -28.3417 -54.7329 85.4395 -12.7321 -60.5795 85.9527 -45.2473 42.0988 85.027 -45.9885 -42.1975 85.2519 -9.20697 -3.53541 73.2667 -13.1987 -60.5041 85.8974 -54.0269 -30.0284 85.0752 -7.20145 -61.1523 84.6306 -7.91733 -61.3842 85.5762 -5.54202 62.1896 85.8299 -3.82708 61.5445 85.1282 22.7448 -57.3486 85.9635 -0.382031 61.944 85.6218 -34.9842 -50.8973 85.7588 37.8334 45.7504 82.9408 -44.4222 -64.6924 5.52395 53.4075 -31.3337 85.8922 55.79 -26.0695 84.1531 53.8242 -30.4822 85.8067 53.8287 -30.4722 85.8877 -63.8873 11.0967 81.8792 45.6419 41.8133 85.8513 61.3869 -7.34314 85.1066 61.3621 -7.45286 85.053 60.7488 -10.336 83.2144 -0.359732 61.9836 85.6729 -21.8071 -57.6542 85.5367 -58.4138 -20.1738 85.9635 -53.0236 -32.0729 85.7368 62.0063 7.10552 85.257 -1.48404 62.1342 85.7668 -53.0325 -32.0797 85.7227 58.3719 20.5036 85.8417 25.9478 56.1141 85.0036 13.4915 60.3517 85.1877 1.40608 61.9277 85.7526 -61.606 6.52707 85.9203 -61.6102 5.96063 85.8703 53.784 30.5747 85.9033 25.8217 -54.5703 83.5989 -40.5728 45.7408 84.782 23.9882 56.943 85.9154 35.6346 50.9815 85.4584 28.7931 54.4695 83.6005 -59.0395 18.7661 85.623 33.9952 -45.8824 80.9897 16.5871 6.36668 126.644 -33.222 46.5903 81.1021 58.7812 20.5051 85.3683 -21.445 53.3286 81.098 -28.9519 54.3879 85.3177 -2.18934 61.6788 79.5541 15.6623 58.4598 84.1124 38.2625 14.6879 72.8802 -59.0693 18.7982 85.6741 -36.557 -49.8695 85.5374 37.7725 14.4997 74.0724 35.3503 50.5634 85.4204 77.262 -8.35462 7.55508 -44.0287 -16.9015 72.9475 54.2618 -18.4895 81.1865 -32.074 -53.5695 85.8298 44.3719 -43.1224 85.7501 53.8736 30.625 85.9297 -30.9988 -47.5689 80.5334 -28.5035 -54.9 85.6774 -34.9262 -51.116 85.5174 -13.1915 -60.4685 85.9439 -36.0967 -50.3426 85.6232 37.2821 49.2801 85.707 37.744 48.8648 85.3577 35.336 50.7391 85.9128 25.9997 57.0409 84.9121 60.0009 -11.1962 84.5315 75.8507 -8.07668 4.24511 -36.1373 -50.3612 85.675 11.3129 -60.7204 85.1761 58.3736 -20.6367 85.7716 59.0543 18.4145 85.9333 -55.86 -28.8897 86.6425 -56.5068 -30.0776 88.1904 38.9228 -47.8965 85.2249 41.0364 -47.0568 85.83 44.3512 -43.1 85.7174 -42.2872 -45.1628 85.6008 53.9245 -30.5197 85.9224 -38.8067 -66.4487 5.27758 35.9066 -44.3554 80.8038 -60.5659 -11.2471 85.2544 36.7209 -49.8869 85.6221 -61.6928 6.48321 85.8123 -0.365822 -61.9426 85.6197 -35.3658 -51.0937 85.7591 -43.5711 -62.2889 4.09833 -12.5277 -60.6349 85.8758 36.726 -49.9317 85.6735 -36.7032 -49.8032 85.9292 -46.2248 42.3579 84.9033 -1.64038 61.7368 79.9354 -23.6808 57.1215 85.8686 -37.2171 49.2257 85.4432 -57.7531 -21.6573 85.4734 53.7138 30.7448 85.8496 60.5196 -11.4172 85.2302 17.8757 -59.0546 85.8139 77.1341 6.42924 7.72574 57.3753 22.606 85.1389 54.3429 -18.1934 81.1815 58.7457 -19.8408 85.6653 -54.7401 -26.92 84.4159 61.2941 -21.6857 81.858 76.8389 -0.309104 5.03914 -9.15444 60.9449 83.3637 -53.023 -32.0725 85.7083 59.0152 18.4938 85.5793 29.3561 -54.1476 85.306 61.6296 7.16331 85.5671 61.6402 6.83748 85.5791 15.4805 59.7407 85.5334 60.5601 -11.4214 85.282 35.0902 13.47 55.7854 -42.2553 -16.2221 56.2405 -43.5844 -16.7326 61.3521 37.8708 48.9634 85.504 -2.56982 -65.5668 81.0221 -45.3995 -17.4284 63.9384 -40.4838 -15.5409 75.3691 14.0589 -60.1704 85.9635 0.213489 61.8871 80.3548 37.0761 51.5312 83.9455 45.8932 41.5969 85.9018 39.7399 47.0687 85.3954 36.5656 49.9263 85.7988 59.8795 -19.0885 84.734 60.7153 -11.8491 85.6046 58.472 -20.0425 85.4661 13.5976 -60.3202 85.9343 2.77091 -62.5996 84.7299 0.333202 -62.9874 84.5643 3.04751 -61.7895 85.7119 11.2739 -60.7234 85.3307 11.9446 -60.6551 85.3129 -4.48695 -61.4382 85.395 -12.7319 -60.5709 85.9434 -35.8974 -50.3699 85.8918 -53.3878 -31.2649 85.9487 -54.2685 -29.4824 85.3255 -53.9948 -30.1002 85.3105 -58.9454 -18.8154 85.739 28.5943 54.5851 83.2213 -61.0359 8.98348 85.5943 -61.5563 6.54591 85.9108 -58.5686 19.8249 85.9635 -46.3634 40.9353 85.9399 -45.6553 41.7375 85.599 -45.6423 41.7506 85.624 -36.1823 50.2023 85.7973 79.4967 7.68139 6.25 -54.1064 -29.8468 85.4835 36.4788 50.8452 85.0741 15.8684 59.6216 85.5414 35.3924 -50.6616 85.8703 59.0233 18.461 85.5791 -40.3454 45.9941 84.8416 42.8421 44.2946 85.3379 -26.885 -55.5737 85.6811 44.5413 -43.2806 86.0002 45.8573 41.5787 85.9471 42.8317 44.2853 85.3493 29.4738 -54.3824 85.6303 -37.4127 49.3461 85.719 75.8593 -9.37503 4.31661 14.8246 5.69077 128.448 -8.63216 61.0005 85.3508 -3.71897 61.8726 85.517 -25.0697 56.5679 83.9224 -13.196 60.4658 85.9436 35.4225 50.8323 85.7562 -1.46675 62.1878 85.8361 42.8342 44.283 85.3244 1.44769 61.7568 85.8457 -28.4992 -54.8978 85.6345 -61.5714 5.96492 85.8285 -46.8872 40.5203 85.7368 -53.3877 -31.2652 85.9635 45.5582 36.1361 81.7653 53.4493 -20.5646 80.9909 -35.0322 51.061 85.5368 60.6767 -11.8371 85.6561 -20.6065 54.6281 82.0316 -37.3279 -49.2738 85.5799 23.7541 57.0191 85.4899 -28.9436 54.3774 85.3036 55.2106 -27.9242 85.6761 16.1319 59.6965 85.7227 65.6615 -7.27839 80.6889 -20.5765 54.6601 82.0509 -35.0826 51.1444 85.6292 37.1955 14.2791 69.3606 26.767 10.2752 65.9952 -26.8784 -55.578 85.6242 -54.9764 -26.4873 84.4895 7.21857 2.7701 105.601 35.3179 50.703 85.8629 40.2957 15.4685 56.9197 -24.6107 56.7403 85.8969 9.61052 3.68788 95.8832 40.2616 15.4553 56.3248 53.3611 -31.3021 85.9162 46.1318 -41.2681 85.9517 -28.5166 54.8911 85.6761 38.9171 -47.809 85.5346 38.3829 -48.6086 85.6657 -35.0132 51.0658 85.7592 7.11308 60.6747 84.6566 -13.1849 -60.4544 85.9275 -34.8388 -50.9804 85.5811 -25.1118 -56.5832 85.9591 2.87863 -61.3821 85.1889 40.3284 15.4811 57.2823 58.2807 20.472 85.9635 -61.5111 6.82405 85.8453 26.4241 10.1434 66.7278 -3.71608 61.9038 85.4784 -28.5233 54.9074 85.655 -25.6843 56.4671 85.7445 -55.1893 -27.4156 85.9635 -12.4953 -60.5958 85.9092 17.5964 -59.0203 85.7731 -12.4987 -60.654 85.889 23.765 57.1976 85.7028 35.351 -50.6319 85.4994 57.3375 22.5914 85.1552 53.8021 30.5756 85.8377 -46.9188 40.1639 85.4857 -3.84649 61.5042 85.4761 17.6358 -59.1317 85.6358 -8.02069 -61.0749 85.2546 59.9932 -11.1964 84.5216 76.9872 -7.18474 4.85589 -57.8343 -21.6965 85.8503 -32.2106 -54.1433 86.4573 34.9806 13.4281 71.1746 -34.8713 -50.9625 79.0272 -25.6959 56.3853 85.9226 -59.5123 17.8705 85.7563 58.0162 31.0473 80.8298 15.8542 59.5844 85.5875 -61.5882 6.5193 85.9 -61.5297 -6.66818 85.9347 -57.6026 -21.536 85.2412 -35.1988 -51.3616 85.3169 -57.9299 -21.74 85.7187 48.3327 -38.2241 85.4936 29.4916 -54.4091 85.5897 -16.6372 59.3447 85.5085 -12.4957 -60.619 85.9342 23.7653 57.1986 85.7425 59.0309 18.411 85.9039 38.4677 14.7655 69.5223 -0.789969 -57.9426 81.7836 29.4724 -54.3781 85.5445 -31.6653 69.3646 4.99625 34.3214 45.8457 81.1314 -24.12 58.1496 87.0044 -61.5765 -6.22116 85.8571 -57.5849 -21.5225 85.2144 -57.8592 -21.7038 85.6194 55.9881 25.6226 85.9635 -49.2351 36.9831 85.9635 -12.684 60.5745 85.9365 -28.6756 54.4978 82.3977 -37.2727 -49.2244 85.488 -55.9134 26.4195 85.6417 35.2416 -50.6145 85.4069 -61.5859 6.15793 85.945 55.1951 -27.9143 85.6994 38.88 -47.8441 85.2513 76.7156 0.133709 5.42358 -42.2643 -45.1322 85.6492 -37.4333 49.3666 85.7551 -24.7186 -56.7315 85.9342 -60.5575 -11.244 85.2456 1.45541 61.8034 85.9038 -12.871 -60.5563 84.1054 -8.02101 -61.0662 85.2457 -61.2097 9.0431 85.7354 -61.1864 9.04203 85.7631 -35.9889 50.352 85.9234 -3.82493 61.5071 85.1427 -61.6288 5.96045 85.8904 38.8687 -47.8541 85.1635 42.8461 -44.2702 85.3526 35.1591 50.7946 85.5379 -24.8291 56.6669 85.7049 -13.2741 -60.7224 86.1448 -13.1852 -60.4634 85.8539 46.1666 41.2269 85.9484 -16.6301 59.3295 85.4893 41.5403 -47.3636 86.457 -55.4054 -27.0051 85.2321 34.3817 13.198 72.6321 53.5396 31.0694 85.9555 -13.1261 -60.3144 85.6832 35.2129 13.5173 70.6777 26.7189 53.9157 83.4508 -8.63561 60.9997 85.3251 -60.557 -11.2462 85.262 -8.01879 -61.0664 85.2621 -6.40456 -0.000703104 58.6088 17.5111 -60.7137 83.9605 17.6595 -59.2 85.7227 44.277 -42.982 85.5745 60.5213 -11.4092 85.3243 -59.4435 4.011 83.3588 -57.9991 5.78424 81.9805 -58.4877 12.7711 83.516 -58.9621 18.738 85.5444 -57.7058 14.7748 83.1244 -54.4604 17.1416 80.9779 24.0016 57.4746 85.3181 -18.1591 55.8914 82.2482 -59.5403 17.903 85.4689 3.03354 -61.5912 85.7166 53.8643 -30.4933 85.8523 53.7651 -30.7415 85.8978 -29.8309 -47.9714 80.359 38.5561 14.7992 69.3623 15.8568 59.5836 85.4925 36.6879 -43.3189 80.6206 -6.00017 -61.279 85.0651 16.5605 -58.6576 84.6813 -59.3512 17.8027 85.5892 56.5694 -24.3171 85.053 52.6787 -21.6655 80.801 23.0748 56.358 84.4673 -24.6333 56.7981 85.8836 -12.4826 60.6088 85.8399 -36.3897 -50.0856 79.6699 37.3232 51.3685 83.9668 -49.3323 37.0438 85.8192 37.8156 50.9902 83.9069 -46.8963 40.5266 85.7227 44.1752 43.0757 78.6716 40.8714 46.0489 85.0651 53.7 -31.4828 86.2475 -61.5463 6.58803 85.9463 -32.0718 -71.1595 7.35255 57.3414 22.583 85.1011 61.7227 6.82953 85.6814 58.4966 -19.9875 85.3106 1.39436 61.7923 85.579 60.1962 -19.5615 84.2216 65.6738 -7.0052 80.7458 -15.6196 56.0066 81.7597 58.8776 -19.1324 82.9599 61.4774 -6.9161 85.3785 59.0683 18.2277 85.562 61.5087 -20.3818 82.2803 56.5665 -24.3255 85.2469 76.673 -0.477451 5.55863 58.6934 -19.5457 82.9429 58.8488 -19.2005 82.9595 -13.2374 -60.7659 86.1841 44.3526 -43.1074 85.7817 27.8212 10.6804 64.7514 -27.0464 -55.8735 85.9894 -2.14147 61.8253 85.7851 -59.1549 -17.8305 85.7958 7.17174e-05 -63.4278 84.0533 -0.365895 -64.8707 82.1905 -12.7399 -60.5701 85.8599 -46.8865 40.5198 85.7081 -25.1326 -56.5945 85.9372 -59.2622 -17.772 85.8458 -25.111 -56.5798 85.9554 -34.7313 -51.2666 85.719 -34.7917 -51.335 85.6043 -34.461 -51.1993 78.5065 -35.9151 -50.403 85.916 -34.6911 -51.2217 85.7933 -26.9639 -55.6971 85.779 -34.8704 -50.9622 85.3698 -34.1141 -51.3986 81.7049 12.4978 -61.4409 84.9016 3.04969 -61.6888 85.8384 -53.5368 -31.2228 85.8432 59.234 18.2254 85.7631 -61.0424 -8.95892 78.7261 -58.9263 -18.9034 85.9136 -61.5953 5.95662 85.9331 24.1349 9.2639 120.47 -12.4814 60.6566 85.8865 -60.0399 15.44 85.4954 -60.0637 15.4502 85.4637 -58.7141 19.5328 85.9458 53.7864 30.5699 85.8199 -45.6639 41.7261 85.369 -35.9987 50.363 85.9055 -36.1075 50.4548 85.7378 -36.1432 50.2258 85.9021 -25.635 56.2929 85.887 35.2532 -50.6793 85.4843 -22.651 -8.6952 88.305 -24.6185 56.7367 85.8154 -12.4869 60.6191 85.9335 -3.8166 61.5081 85.0942 -1.49073 -0.573306 105.447 -55.3762 -26.9944 85.2639 28.8058 53.7856 84.466 35.1319 50.6994 85.4184 -60.586 11.0964 85.2652 -12.4679 60.6223 85.932 -3.97638 -1.52647 108.309 -28.3494 54.7215 85.4291 -54.3888 -31.535 86.6705 29.3591 -54.1456 85.221 -34.983 -51.2087 85.6214 -34.9172 -51.1342 85.7464 35.195 50.9285 85.7061 53.7767 -30.748 85.9121 59.1153 18.1671 85.9229 -35.5185 66.909 8.02426 37.7703 48.8402 85.5667 -34.8891 67.3581 7.79215 -36.3168 67.022 8.48561 -36.112 66.5405 8.09584 53.8732 30.5357 85.8802 53.8429 30.5163 85.9253 57.3286 22.6137 85.4812 17.6373 -59.1361 85.809 54.9861 -27.8741 85.4789 -34.2469 67.5004 7.99078 -40.3342 45.9861 84.8269 34.323 52.5413 84.5793 -37.4782 49.0993 85.5315 -30.6313 69.2798 6.22726 -30.8211 69.1808 6.34513 75.484 -9.73554 8.51167 -53.914 -32.704 87.041 -24.6253 56.7571 85.8388 76.9474 -7.38961 4.84362 -36.1132 50.3258 85.6197 14.9962 5.7559 116.428 -57.7561 -21.6504 85.7395 30.3606 -55.2647 84.1028 45.8502 41.5677 85.9333 -43.5544 -16.7199 98.4037 61.3125 -22.0664 81.6407 53.3246 -31.0214 85.6431 11.4052 -60.7119 84.9353 45.8987 41.6021 85.91 53.7677 30.6118 85.701 -12.4984 -60.6377 85.8718 -53.977 -30.1395 85.0517 -56.8394 -28.853 87.7686 -54.0233 -30.0363 85.0059 3.01732 -61.5929 85.4642 11.8717 -60.6629 85.0514 -35.3451 -50.6889 85.8114 34.0664 46.0123 81.1273 -46.9633 40.1092 85.9001 36.0275 44.4446 80.9382 40.7831 46.5041 85.3073 53.7137 -30.7302 85.9283 45.8903 41.5932 85.8968 59.0544 18.2928 85.3662 -57.7525 -21.6589 85.9635 57.5538 22.7237 85.6447 -37.2695 -49.2932 85.9635 -37.3116 -49.2563 85.55 -61.5742 0.438878 85.3015 53.8135 30.5085 85.8928 1.45246 61.7565 85.9635 -28.3571 54.7386 85.4141 22.9573 56.091 84.1124 -42.7955 -15.1093 71.7163 -42.8324 -14.7574 71.6393 -45.8482 41.7593 85.5755 35.1244 50.6747 85.3875 -45.3668 42.031 85.2959 2.88601 -61.404 85.216 -25.1816 56.5324 83.9238 13.6041 -60.5149 85.7264 -26.9548 -55.6725 85.8108 -34.7579 -51.2 85.4819 33.4226 51.9282 85.8206 59.8774 -12.0693 84.6497 -54.2385 -32.4444 87.1775 44.248 -43.0083 85.9635 25.1817 56.5555 82.8186 45.73 -41.693 85.8402 55.5002 -28.0847 86.0318 -0.46162 -57.9264 81.7792 -5.66193 -61.5959 85.3073 13.604 -60.5147 85.7191 -24.6192 56.7676 85.928 7.10476 60.6508 84.6267 -37.3702 49.2575 85.9111 3.03358 -61.7024 85.6018 58.9795 18.2304 85.452 -58.2939 -20.4428 85.5373 60.4301 -11.8379 85.2507 58.667 -19.8699 85.6005 56.8508 -24.3102 85.2813 -54.9705 -26.4828 84.4806 76.6912 -0.577465 5.50468 55.5899 22.1289 83.3718 61.6405 -6.84052 85.5794 61.4317 -7.32163 85.3232 60.4767 -11.8427 85.3103 40.2517 15.4515 55.7854 -36.1665 -13.8835 73.8275 -15.57 55.996 81.7378 61.4889 -22.7837 81.0686 45.9137 41.6047 85.8772 40.8767 46.0454 85.2026 37.0885 49.4552 85.9635 36.4471 50.0324 85.6885 53.5347 31.0653 85.9488 55.7132 26.2443 85.2189 59.2278 -18.5666 85.6771 61.6819 -19.8553 82.3038 59.1634 -18.5183 85.7694 61.3974 -7.29354 85.3161 13.5988 -60.5809 85.649 13.605 -60.5176 85.7227 0.169212 -64.8725 82.2138 12.4006 -60.6051 85.5984 12.3839 -60.6082 85.6214 -53.8085 -30.5176 85.5961 -53.8152 -30.5027 85.6184 -58.9187 -18.94 85.8272 -60.5851 11.0987 85.2835 -58.7646 19.3831 85.7716 -58.7646 19.383 85.5929 -45.3587 41.9999 85.2909 -36.3484 50.1048 85.7737 0.296074 -63.4142 84.0322 44.4999 -42.9483 85.7306 3.26537 -61.3374 85.1642 -54.0287 -31.8061 86.5126 3.65786 -61.5254 85.4333 -37.1967 49.2109 85.4164 14.1728 -60.3205 85.738 -47.1205 40.1863 85.6998 -47.1357 40.1969 85.7227 55.0034 -27.8843 85.4617 -59.6818 15.6022 85.1701 -60.0926 17.0305 85.015 -55.1103 14.7802 80.7931 -8.99453 61.198 85.6192 3.68365 -61.5227 85.6637 33.3911 51.8152 85.4399 -61.8479 0.597618 85.6109 53.8581 -30.4846 85.9228 44.2707 -42.9875 85.628 -58.4025 -20.5301 85.7052 35.4604 -50.6429 85.5843 37.661 14.4557 68.9109 53.8352 30.5121 85.8333 39.2891 -47.4739 85.4715 -32.8438 52.6129 85.437 -25.6518 56.3208 85.923 46.0925 -41.3172 85.9554 33.3716 51.8265 85.6803 -26.9481 -55.6689 85.7434 -32.849 52.6189 85.4271 -61.5714 0.439199 85.2984 -2.23037 61.8873 85.6957 33.4706 52.0095 85.7013 -28.3454 54.7238 85.3942 59.0462 -18.4488 85.9347 59.0807 18.2301 85.578 -13.1545 60.4772 85.9461 -9.02378 60.9594 85.4074 59.2505 -18.8209 85.5822 -37.3943 49.0427 85.4091 54.9839 -27.879 85.4397 6.87183 2.63713 98.0976 -36.0897 67.6412 8.21753 -30.8586 69.1624 6.36508 -3.49196 61.6004 85.1924 -59.4046 4.08024 83.3231 35.4091 -50.6949 85.9163 -37.5958 49.1762 85.7023 -58.2151 -20.3812 85.4165 37.3627 49.3177 85.8603 17.597 -59.0201 85.4932 -47.1216 40.187 85.7447 -24.7622 57.1873 86.3233 -59.5546 17.9014 85.8223 -37.2202 -49.1878 85.4128 -3.24247 -57.7992 81.5671 22.1538 57.5387 85.4905 23.7698 57.2137 85.7227 36.8292 43.3813 80.7497 -24.0108 56.1537 84.9812 -28.3379 -54.7354 85.4061 59.0412 18.226 85.5285 3.81228 1.46244 100.858 25.541 9.80419 68.8768 3.25823 -61.3166 85.1384 -58.7015 19.5262 85.9284 58.0336 31.0412 80.8133 -34.0397 -51.4424 76.9564 -25.6691 56.3527 85.8792 14.1464 -60.1418 85.9121 -35.2917 -51.3892 85.2289 22.1838 57.683 85.6705 -60.141 17.1032 84.9328 28.0014 10.7498 64.0721 -47.1388 39.8612 85.4857 14.1726 -60.3197 85.7074 -34.7689 -51.7074 85.8714 -13.0289 -60.2951 85.6406 -59.6323 15.589 85.1904 -61.5714 -6.22142 85.8517 -58.555 -20.2608 85.7573 35.0679 -51.0457 85.7471 -12.4854 -60.6207 85.9334 22.1846 57.6856 85.7746 59.0838 18.1623 85.8834 -51.2331 -19.6693 105.728 -53.0119 -20.3514 105.699 -60.9242 10.775 85.5941 -24.819 57.2026 86.3617 -58.1946 -20.3656 85.3855 -48.8946 -18.7698 105.852 -37.3579 -49.2137 85.8576 -61.5891 6.08817 85.9409 37.784 48.8292 85.7271 -61.5522 6.83947 85.8924 -3.48864 61.5424 85.2149 58.9839 18.6246 85.0733 57.6749 22.7236 85.5055 57.7024 22.7297 85.4701 -59.6301 15.6004 85.1231 -37.3397 49.2274 85.8587 41.1112 45.2917 84.7207 -9.02799 60.9583 85.376 14.1768 -60.3318 85.7227 59.0238 -18.4455 85.9067 -59.9097 11.2394 84.554 -55.1319 13.4815 80.6109 59.0844 18.1592 85.9635 -58.7567 19.3793 85.5814 53.757 -30.7393 85.8891 37.7137 14.4758 68.8164 37.8868 48.9753 85.7396 -4.65646 -57.3661 81.3592 12.4179 -60.6033 85.3766 55.7125 26.246 85.2061 36.3899 50.0842 85.719 40.8533 46.6286 85.4337 40.8236 46.591 85.4932 -32.4534 -71.2186 7.22742 65.6886 -6.90357 80.7546 61.6355 -20.0285 82.3177 61.7226 -6.83246 85.6812 61.4006 -7.27866 85.2847 59.1019 18.0702 85.5543 57.0175 -24.3436 85.4301 56.9635 -24.3236 85.5025 46.087 -41.3138 85.9485 45.7355 -41.7003 85.9337 -3.73009 61.7629 85.6527 7.17174e-05 -64.8803 82.2259 -5.64547 -61.7367 85.4337 -25.1402 -56.6114 85.9146 -33.6994 -52.0014 85.5668 -33.7297 -52.0356 85.5094 -36.0434 -50.3322 85.9125 56.0064 26.3522 85.5407 -33.6342 -51.9286 85.6874 -33.6731 -51.653 85.1866 -53.8 -30.5365 85.3748 -61.8445 0.597233 85.6152 -58.7253 19.3611 85.5345 53.8154 30.5049 85.8107 -45.9238 41.8025 85.6805 -36.3897 50.0823 85.7804 59.8675 -12.0696 84.637 -45.3669 41.9921 85.2679 -61.5714 0.580547 85.9635 -24.8189 56.6718 85.8358 -12.6842 60.5861 85.9489 17.4814 6.71008 114.482 -8.99196 61.2032 85.6602 33.3301 51.5807 85.1494 -3.47572 61.544 85.1396 35.273 -50.7299 85.5512 34.9327 -50.8345 85.4347 53.8883 30.429 85.9177 -8.99627 61.2187 85.64 59.2447 18.1797 85.762 33.4256 51.9161 85.5718 58.8776 19.131 84.5721 -36.5415 65.9646 8.98557 -36.1484 66.5103 8.12031 22.1322 57.5458 85.8406 -37.6595 48.9358 85.5197 -54.5751 -32.1908 87.325 -30.6115 69.2736 6.26464 -30.7992 69.1758 6.38078 -24.8224 56.6825 85.848 30.2554 -55.657 83.7413 -58.2858 -20.461 85.8453 -53.9744 -30.1456 84.992 -32.749 -71.31 7.10708 11.9893 -60.6478 85.0327 2.91248 -61.6039 85.4693 -47.332 40.5313 85.2735 59.082 18.1634 85.2742 57.4409 23.0299 85.6175 53.8531 30.4197 85.8788 36.7414 49.7677 85.9039 55.4005 25.8996 84.7258 -25.366 56.5018 85.8986 -58.8134 19.4298 85.6707 33.3241 51.561 85.1249 0.497592 -61.8234 85.542 -25.1298 -56.5967 85.8949 44.5205 -42.9729 85.7648 -33.7004 -51.7282 85.2587 59.0072 -18.2172 85.4822 -53.9972 -30.1566 85.2976 -53.8548 -30.728 85.5648 -37.037 65.5502 9.33167 12.544 -60.7359 85.5788 11.9984 -60.6731 85.2993 -37.56 49.0974 85.9009 2.7638 -61.7348 85.6197 -46.714 39.0749 84.5025 59.0022 18.0734 85.4313 59.0703 -18.2273 85.562 54.5431 22.891 82.8177 55.5725 22.1545 83.3677 57.2488 -24.6149 85.7294 56.0166 26.3566 85.5522 56.0091 26.3518 85.5634 59.1552 -18.517 85.7591 12.0091 -60.6457 85.2946 -53.9688 -30.1581 85.2932 2.64826 -61.4458 85.2484 58.982 -18.218 85.4497 35.3679 -50.6751 85.5565 44.5003 -42.9572 85.7979 -34.3083 -51.6539 85.5611 60.438 -11.801 85.3567 -37.5236 49.0615 85.8384 37.303 49.2622 85.8087 -25.6785 56.3479 85.8784 22.1966 57.7251 85.7227 15.8331 -59.7501 85.6731 15.8014 -59.6038 85.8454 34.9911 -50.9546 85.8962 59.063 18.0679 85.5064 15.7842 -59.6094 85.4932 -37.5614 48.87 85.377 59.1196 18.0737 85.5772 -25.5202 -56.3787 85.8437 -58.5325 -20.2492 85.7257 -47.2965 39.9355 85.6937 53.8772 30.4316 85.8276 -25.4075 56.4427 85.9441 45.7213 -41.6814 85.9084 -47.3158 39.949 85.7227 3.95612 -61.2161 85.0699 36.4255 50.0519 85.7922 3.69201 -61.6235 85.5581 -61.5762 0.743883 85.3329 -47.1744 39.8186 85.8861 -37.5421 48.856 85.3515 15.8339 -59.7526 85.772 -44.612 -17.126 106.338 53.9182 30.4481 85.8733 -59.6424 16.9816 85.5836 -59.4724 16.9957 85.4355 -12.4548 60.6135 85.8381 21.6691 56.9441 84.6182 22.8035 58.4085 84.663 -61.8382 0.83595 85.6234 -60.9398 10.7788 85.6118 -30.8374 69.1571 6.40109 10.3453 3.97055 103.462 -60.9264 10.7781 85.6277 -37.6225 49.2027 85.7491 -25.6253 56.2986 85.8061 35.2853 -50.7521 85.5831 -34.7348 -51.9214 84.9972 -59.8757 17.1802 85.8584 -58.3201 -20.5025 85.903 -2.35797 61.9663 85.5799 2.64054 -61.4233 85.2206 -24.8121 56.6751 85.9204 -33.6577 -51.6619 85.2899 -61.5714 0.744424 85.3277 -2.36542 61.886 85.6795 34.9673 -50.9071 85.8306 -37.7707 49.0137 85.6863 58.6183 21.6046 84.9888 37.8586 48.927 85.8077 -37.3882 -49.2437 85.9101 -47.2978 39.9364 85.7507 -34.8028 -51.732 85.9239 20.8836 57.9512 85.4909 3.94962 -61.1972 85.0464 -61.5088 6.83957 85.8443 -25.4339 56.4718 85.8976 20.9128 58.0732 85.6445 -59.5929 17.982 85.3796 -37.4747 -49.3306 85.7547 -2.33006 62.2799 85.8795 20.9139 58.0771 85.8004 59.1165 18.0085 85.8706 -48.3761 -18.5706 97.8558 34.9151 -50.7753 85.3592 58.8411 19.2141 84.5716 -37.9304 49.459 85.2474 -59.334 16.991 85.3098 37.9374 49.0608 85.617 -12.4553 60.5971 85.821 2.76627 -61.6193 85.7384 12.0191 -60.6447 85.274 -24.8321 56.7244 85.8946 36.5991 49.8956 85.9034 59.1289 17.9434 85.5481 22.13 57.5469 85.9635 12.578 -60.8138 85.6799 -61.4956 6.8348 85.8299 -25.1175 -56.5777 85.8705 -25.5474 -56.4134 85.8907 -53.9376 -30.775 85.6813 -53.9649 -30.1669 85.2732 -58.88 19.4908 85.7748 -2.3171 62.3201 85.9314 53.8521 30.4225 85.799 -25.3974 56.4305 85.9271 54.5415 21.4279 82.2313 60.3474 -12.2267 85.2696 60.3996 -12.232 85.3365 59.8437 -12.307 84.6819 20.9318 58.1362 85.7227 59.1531 18.014 85.9165 34.9619 -50.9096 85.5338 23.6858 57.0412 85.9032 58.7053 21.5743 84.9061 -37.8328 48.7796 85.5084 -30.5922 69.2676 6.30087 -30.7779 69.171 6.41538 -59.5649 16.9482 85.6867 -53.8961 -30.3211 85.4306 -34.2656 -51.4459 85.378 -25.6635 56.3264 85.8504 2.74289 -61.6218 85.4775 -37.3907 -49.185 85.5448 53.8882 30.3408 85.8663 -58.9984 18.5626 85.9635 35.1292 -50.8128 84.9521 45.7553 -41.7303 85.8871 53.9657 30.4821 85.9359 -25.5382 -56.379 85.9328 -24.8176 56.6928 85.9405 59.0447 17.778 85.3922 54.5686 21.383 82.2358 36.4441 50.0354 85.9127 -58.9677 18.7065 85.9088 -58.9973 18.567 85.8909 0.487906 -61.7951 85.5069 -37.8033 49.0461 85.7433 -9.3466 61.1385 85.6415 53.9553 30.3757 85.8676 -61.5775 0.946103 85.3537 53.9169 30.3556 85.8222 -30.8168 69.1519 6.43603 20.5032 57.4302 84.7433 -37.7211 48.7051 85.3463 59.104 17.7707 85.4648 59.151 17.9477 85.5765 -37.8684 48.7506 85.8003 53.9258 30.3568 85.9114 20.8726 57.9548 85.7898 59.8333 -12.3073 84.6684 59.34 17.7693 85.7518 -34.2616 -51.6011 85.6497 -61.8335 0.835412 85.6294 60.3496 -12.2164 85.3911 15.8467 -59.7891 85.7227 58.2138 21.3651 85.5801 -61.5499 6.85472 85.8913 -58.4272 -20.5632 85.7494 58.1355 21.3478 85.6809 -34.8223 -51.9474 84.9143 -59.9086 17.2042 85.9097 -2.51803 61.7631 85.3789 -9.36676 60.9233 85.457 -25.5331 -56.3723 85.8428 4.42805 -61.4442 85.3961 -53.9059 -30.2995 85.463 20.2943 56.9557 84.1124 58.0663 21.3329 85.7681 -37.7022 48.6914 85.3214 -61.8309 1.01416 85.6327 -37.3458 -49.1483 85.4734 -58.3948 -20.5467 85.704 34.9802 -50.9424 85.5811 -37.4095 -49.2052 85.5793 -25.5236 -56.3602 85.8267 -61.5714 0.946791 85.3471 -25.5532 -56.3424 85.9019 -11.2435 60.7248 84.8259 58.0795 21.2489 85.427 -9.41558 61.5082 86.0445 -37.9556 48.842 85.6694 -59.1319 18.2312 85.8857 20.6882 58.0147 85.4909 -61.5066 6.85419 85.8434 20.7169 58.1333 85.6405 57.9562 21.2013 85.4799 59.1792 17.7139 85.8463 -51.0091 -19.5834 97.7156 -53.0119 -20.3514 97.6828 -58.9961 18.7115 85.9272 59.1649 17.7743 85.5399 35.9877 -50.3172 84.3374 -59.5026 16.9204 85.7723 -61.5786 1.10652 85.3703 58.1229 19.0608 84.8847 -58.9667 18.7126 85.8722 53.8867 30.3447 85.7879 60.2995 -12.4517 85.2806 60.355 -12.4572 85.3516 59.813 -12.5239 84.7113 -9.34365 61.1444 85.6877 -9.34796 61.162 85.6649 57.9326 21.2558 85.6692 -38.0159 48.6145 85.4965 -30.5736 69.2617 6.33608 -30.7573 69.1663 6.449 -25.4289 56.4647 85.8884 0.558577 -61.8519 85.5829 59.1338 17.9202 85.1011 53.9118 30.2878 85.8579 36.3899 -50.0856 84.352 -37.9158 48.7974 85.8819 -61.5476 6.8691 85.8903 -61.8252 1.01351 85.6399 59.802 -12.5243 84.6971 59.1927 17.7797 85.5757 -37.8897 48.5308 85.3139 54.0178 30.2538 85.858 -37.9944 48.8806 85.7373 -30.7968 69.1469 6.46999 -25.5684 -56.364 85.9302 53.989 30.2354 85.9009 53.9803 30.2341 85.8137 59.2254 17.7209 85.9041 -25.5844 -56.3946 85.8878 -9.37163 60.9221 85.4206 -60.4618 16.0668 86.0232 -10.9412 60.8692 85.7423 4.44869 -61.5327 85.5079 4.72376 -61.0813 84.9651 59.0806 17.9405 85.4885 0.605513 -61.8044 85.5272 59.1802 17.7093 85.9635 -10.9398 60.7579 85.6844 -25.5691 -56.3544 85.8402 4.44933 -61.442 85.6014 60.5661 -12.4903 85.6205 59.3865 -18.312 85.5477 -37.8713 48.5176 85.2896 -59.9767 15.7665 85.4885 57.9688 21.1737 85.3036 -61.8249 1.16129 85.6403 -61.8183 1.16055 85.6486 -61.5714 1.10732 85.3625 60.5193 -12.4756 85.683 -38.1176 48.6916 85.6546 20.4982 58.0764 85.491 4.71795 -61.0645 84.9442 -61.5046 6.86805 85.8425 20.5264 58.1917 85.6366 -59.34 16.9606 85.4898 58.9771 18.6568 84.5567 -61.4794 15.8865 87.1277 0.747285 -61.832 85.9027 -59.3529 16.8938 85.6753 59.1856 17.6768 85.5351 36.464 -50.0179 84.3513 -59.813 15.8226 85.6773 53.9421 30.2203 85.7703 -12.3641 60.6082 85.8903 -61.5455 6.88274 85.8893 0.679683 -61.8391 85.5771 -25.6225 56.3506 85.857 -10.9805 61.0944 85.9858 60.2555 -12.6581 85.2906 60.3141 -12.6639 85.3655 59.7847 -12.7237 84.7384 -10.9418 60.8773 85.8127 -10.9437 60.9046 85.7778 0.751267 -61.8561 85.9327 -38.1764 48.4699 85.486 -30.5554 69.256 6.37028 -30.7372 69.1617 6.48168 -59.6351 19.4248 86.6279 -59.9418 15.7514 85.5349 53.8965 30.3224 85.4806 -61.5795 1.24252 85.3843 53.6733 30.8237 85.2 53.9461 30.2108 85.8457 59.2168 17.6829 85.5752 54.0471 30.1967 85.8536 -59.392 19.7457 86.4917 -61.9845 12.3702 86.8854 54.1172 30.2472 85.946 53.6141 30.9562 85.1845 0.815993 -61.9683 85.749 0.776003 -62.1049 85.6162 0.818118 -61.9816 85.7658 1.01628 -61.8037 85.5608 59.7732 -12.7241 84.7235 -60.4795 16.0798 86.0508 59.3575 17.6943 85.7499 59.1175 17.6728 85.4511 20.5475 58.2612 85.7227 -25.6358 56.3696 85.8818 -10.9477 60.756 85.6253 0.98284 -61.7096 85.4411 -12.3658 60.6286 85.8325 60.2286 -12.7848 85.4382 60.4868 -12.8312 85.6289 -61.5714 1.24342 85.3756 0.395848 -62.2672 85.4623 -61.3658 10.832 86.0746 -61.5026 6.88124 85.8417 20.5277 58.1961 85.8082 59.195 17.6397 85.8401 -62.0276 14.7442 87.4083 -38.2066 48.4456 85.763 -59.9017 15.8787 85.551 -59.9412 15.8957 85.4986 0.992025 -61.7366 85.4745 54.0186 30.1785 85.896 54.0099 30.1774 85.8097 -30.7773 69.142 6.50301 -38.2172 48.1926 85.2509 60.2267 -12.7937 85.2972 60.2872 -12.8 85.3747 -12.3647 60.6395 85.9239 -12.3702 60.6745 85.8787 -61.199 13.82 86.1817 -38.5539 48.1296 85.4615 -30.5377 69.2505 6.40357 -30.7177 69.1573 6.5135 -60.8602 13.9481 85.8298 1.08191 -61.9364 85.7313 59.2436 17.647 85.901 59.364 17.6662 85.7492 59.0596 17.6746 85.3785 -38.6024 47.7946 85.1768 -61.4491 13.9007 86.4576 59.2351 17.6094 85.5748 -61.5435 6.89575 85.8884 20.4894 58.0792 85.7744 -61.4869 6.87557 85.8245 -12.3666 60.6064 85.8095 -59.6267 15.9691 85.24 59.2374 -18.2001 85.7616 -38.5861 47.7829 85.1553 -38.6443 48.2026 85.6064 -61.5007 6.89387 85.8408 -61.4964 6.83173 85.7083 59.2118 17.5608 85.8336 59.2014 17.6028 85.5315 59.263 17.5686 85.8977 59.2525 17.5394 85.5745 59.3905 17.5522 85.7464 -30.7584 69.1373 6.53515 -38.5792 48.1095 85.7219 59.1376 17.5276 85.4308 1.2768 -61.7762 85.5482 0.736755 -61.7814 85.5093 -38.7061 48.2641 85.7146 59.1337 -17.9294 85.5475 59.2186 -18.1971 85.7376 59.0475 -17.9322 85.4436 -39.0088 47.7195 85.4319 -30.5205 69.2451 6.43599 -30.6986 69.1529 6.54449 -59.5554 15.9502 85.2692 -38.1997 48.18 85.2279 -39.0308 47.7022 85.672 -39.1155 47.7858 85.8177 59.0805 17.5293 85.3593 -39.1773 47.8559 85.6996 59.2741 -17.9165 85.7187 59.3024 -17.9209 85.7547 0.826898 -61.8236 85.57 -12.4263 60.6001 85.6538 -59.5521 15.9666 85.1723 -39.0987 47.7807 85.5648 59.225 17.4988 85.8284 59.2164 17.5323 85.5281 59.2782 17.5068 85.8951 -30.7399 69.1326 6.56646 59.2671 17.4805 85.5742 -38.2874 48.534 85.639 -39.066 47.3157 85.0876 1.24617 -61.692 85.4398 59.0231 -17.933 85.4121 59.5259 -18.0886 85.4341 -39.5553 47.2269 85.3963 -30.5037 69.2399 6.46758 -30.6801 69.1487 6.57472 59.1768 17.7179 84.9572 59.4041 17.4938 85.745 0.896197 -61.7534 85.4876 1.23719 -61.6656 85.4072 -39.0511 47.3049 85.0679 -39.6282 47.2891 85.5164 59.2373 17.4409 85.8237 59.229 17.4731 85.5252 59.2808 17.4254 85.5739 -39.6219 46.7415 84.9807 -30.722 69.1281 6.59699 -39.5731 47.2131 85.6122 59.1535 17.4124 85.4147 -40.2088 46.6378 85.3537 -30.4874 69.2348 6.49839 -30.6619 69.1446 6.60421 -30.7044 69.1237 6.62677 59.2924 17.4493 85.8927 59.0971 17.4141 85.3441 59.4168 17.4391 85.7436 -39.6086 46.7318 84.9632 -40.2713 46.6921 85.4576 59.2489 17.3866 85.8192 59.2409 17.4175 85.5225 59.2938 17.3734 85.5736 -40.2233 46.6268 85.5404 -30.4714 69.2298 6.52848 -30.6443 69.1405 6.633 59.2384 17.4354 85.9635 59.1607 17.3598 85.4073 59.3057 17.3952 85.8904 -30.6873 69.1194 6.65587 59.261 17.3296 85.8144 59.252 17.3652 85.52 -30.4558 69.2249 6.55784 -30.627 69.1366 6.66112 59.3074 17.3186 85.5734 59.2725 17.2757 85.81 59.2638 17.31 85.5173 -30.6705 69.1152 6.68425 -30.4405 69.2201 6.58654 -30.6101 69.1328 6.6886 59.1684 17.3044 85.3996 -30.6542 69.1111 6.71203 59.1127 17.3061 85.3298 59.3203 17.2667 85.5731 59.2834 17.2246 85.8057 59.2749 17.2578 85.5147 59.1756 17.2519 85.3922 -30.4256 69.2155 6.6146 -30.5936 69.129 6.71547 59.3326 17.2173 85.5729 59.2855 17.2081 85.5123 59.1825 17.202 85.3853 -30.4111 69.2109 6.64204 -30.5774 69.1253 6.74177 59.1275 17.2037 85.3162 59.2937 17.1759 85.8017 -30.6225 69.1032 6.76572 -30.3968 69.2064 6.66892 -30.5616 69.1217 6.76753 59.3443 17.1703 85.5726 59.2956 17.1607 85.51 59.1891 17.1544 85.3786 -30.3828 69.2021 6.69524 59.3036 17.1295 85.7979 59.3555 17.1252 85.5724 59.3688 17.1393 85.8796 59.4815 17.1607 85.7367 59.1954 17.1089 85.3722 59.1409 17.1105 85.3039 59.3052 17.1154 85.5078 59.2495 17.3764 84.7143 59.3131 17.085 85.7942 59.3662 17.0821 85.5722 59.2014 17.0652 85.3661 59.3145 17.0719 85.5057 59.3222 17.0423 85.7907 59.3765 17.0406 85.572 59.2072 17.0233 85.3603 59.1532 17.0249 85.2926 59.3234 17.0302 85.5036 59.3309 17.0013 85.7873 59.3864 17.0006 85.5718 59.4003 17.0118 85.8742 59.3323 16.9943 85.9635 59.2128 16.9829 85.3546 59.5111 17.0334 85.7335 59.3319 16.9899 85.5017 59.3393 16.9618 85.784 59.396 16.9621 85.5716 59.3402 16.9512 85.4998 59.2181 16.944 85.3492 59.3474 16.9237 85.7808 59.4053 16.9249 85.5714 59.1768 16.8614 85.271 59.3553 16.8868 85.7778 59.3482 16.9137 85.498 59.4142 16.889 85.5712 59.2301 16.8574 85.3371 59.3559 16.8775 85.4962 #vertex Simplex 2903 819 820 818 784 2355 541 542 2517 2518 1493 2516 2920 1554 1898 2534 1604 1256 451 1257 1388 112 120 110 1785 2926 2407 2867 574 2901 791 794 1236 422 1237 420 316 3603 317 314 1986 1996 1985 443 110 1384 103 102 849 3065 772 2885 1224 1553 1550 404 515 2355 670 514 3220 5926 2638 3713 2338 3672 838 3093 675 2355 849 674 4999 5943 3805 1800 2113 5624 3516 3709 4611 5215 4610 4996 80 83 282 1479 2030 2523 1917 1148 5396 5830 4087 5610 1367 2465 1369 2298 5582 2422 2722 2423 501 2355 500 848 614 837 46 959 993 1667 58 1666 1699 2280 2275 627 1196 4362 1195 635 670 2355 668 514 126 1391 127 128 818 3971 819 3480 449 1601 1254 1255 719 2323 721 585 2659 4931 1758 1757 2422 984 988 1804 906 4675 3736 1695 232 1457 230 1455 401 1548 400 399 1850 3577 1652 3176 933 3952 930 931 496 4885 617 572 34 933 931 945 848 698 549 548 3697 5398 4683 4388 1383 100 107 99 4456 2459 3274 3588 3734 4889 4609 626 2702 2704 1794 2697 3234 4190 2368 1712 139 4307 140 1097 2916 4285 2927 1967 1293 1295 12 15 5457 5728 5230 5686 555 2901 554 763 597 5321 613 495 4410 5110 2324 2332 682 2355 680 683 543 2355 491 522 645 5237 831 3659 3173 3605 1188 2529 1041 3820 76 2171 2263 2408 40 1674 4845 5315 810 5311 2790 4798 1699 1684 3366 5472 4876 3761 1374 1434 184 174 2550 2611 4 2549 3544 3801 46 3669 3720 2642 3722 3735 693 848 501 697 1115 2918 1969 1900 1103 136 1102 3082 251 1471 259 260 632 2840 1070 2102 688 2355 518 498 3229 4835 4637 4176 331 1163 1155 1162 766 2901 767 2355 216 1443 217 1442 340 346 338 348 870 3695 3248 867 934 3368 2757 3202 1039 76 1045 1040 3749 3533 28 913 3261 5225 3897 3625 1001 2230 61 2229 375 1534 1530 374 3349 4650 4047 2742 817 3795 3590 2825 452 1604 1256 451 3540 4309 835 951 5311 812 5227 3578 405 1558 1459 235 1803 2715 2085 2417 1093 3011 1095 1091 1402 1403 134 1400 1347 3873 1833 1016 50 5032 47 1798 1941 3144 3040 2996 1676 2404 951 1677 2108 3192 1322 1788 676 849 536 535 1828 3855 1005 1021 5212 625 4473 5150 1223 1549 397 1548 3568 4613 4054 4487 1667 3650 58 1666 651 2355 649 848 5693 3659 5397 5237 723 3078 726 722 43 2262 955 954 2355 583 558 489 1984 4093 3965 1885 20 4213 18 3738 2392 4287 3341 4265 2859 3948 2910 1372 743 4842 742 740 2453 5321 3578 3938 797 2355 568 543 5132 5660 5118 5382 914 5432 4404 5264 1290 5072 1723 4461 1527 2532 353 1522 65 2436 1827 1345 3820 3577 1041 76 596 2323 741 744 97 2424 57 96 562 5683 727 3078 114 1389 117 116 2355 519 688 518 770 3074 772 769 3243 7 3227 3226 3759 5321 2716 642 4742 4810 3910 4434 366 1530 374 375 635 5311 3472 809 1890 4923 3096 1594 178 1432 171 181 2571 2848 2438 2769 1251 2873 439 1084 1934 2083 1933 1183 1056 5589 5445 3312 136 1407 1404 134 303 2515 1488 302 527 848 754 526 210 1444 221 213 832 5315 830 833 1447 216 217 1445 1328 5576 5402 970 1776 3535 1316 2677 1829 2762 2067 2433 4165 2161 3589 3590 848 548 549 757 645 5114 840 644 2355 762 761 765 4152 2242 2396 3654 106 1385 109 108 1824 2740 2069 1340 3356 4734 3798 4411 2355 514 679 678 2453 4058 1649 1048 2252 2739 49 2717 2200 3389 3174 2719 1383 98 1380 101 2536 1984 131 1991 867 5734 5624 10 108 1383 100 107 574 3066 575 791 1519 339 342 350 1431 2490 172 1432 265 1474 272 273 588 849 589 774 230 1453 227 1451 609 4430 64 827 2355 653 652 848 1013 2216 67 1836 1553 1224 1550 1552 1094 1095 1093 141 83 1481 81 1363 2355 504 505 659 1531 1535 368 369 1774 942 939 938 1178 3163 2082 1632 4120 4177 4904 1732 1292 2141 11 1722 172 1429 175 180 146 155 154 157 142 1410 139 441 2860 5381 2543 4208 1691 2807 2595 845 815 3577 2562 1043 1438 195 189 196 1393 127 1391 1392 448 1605 447 1604 5572 930 2398 5472 4901 4743 5305 5005 2340 5356 5018 2344 1927 3175 1167 3172 2197 3058 2033 1626 116 1390 118 119 244 251 242 243 2312 2913 2424 1816 3830 2725 3346 2732 371 1533 373 363 2161 4441 1063 2160 2389 1699 621 4622 539 2355 685 540 1766 3750 2669 2670 214 2496 222 2497 991 55 990 2221 974 966 49 967 3410 4385 3933 4230 976 2418 2415 2200 2604 753 549 550 192 4381 1306 24 146 155 157 147 3958 4677 4397 3204 5228 5099 2614 3655 3754 28 3749 3533 913 2764 912 28 2285 3688 28 3255 199 206 203 198 859 852 4 853 637 5532 1672 5531 1090 438 1095 1094 540 2355 686 541 2355 584 718 583 3682 3753 3431 925 858 3503 3075 2363 1531 358 360 368 139 2536 441 1410 1302 4384 1300 1747 389 1541 1214 1540 4206 3590 3265 3263 376 1535 368 366 3533 4334 3534 929 3063 4063 3719 4043 947 953 40 952 1496 313 312 311 188 189 195 198 3039 4062 230 2214 1880 1990 1082 1882 3668 5048 836 4984 2939 1560 1131 1911 1981 4052 3036 407 779 2323 781 595 183 1433 1429 182 4977 3200 2626 3339 781 2355 782 785 3078 780 778 779 3379 4579 972 1796 360 1531 368 361 110 2475 102 103 719 4842 2355 2323 96 105 103 104 807 2374 1646 598 981 2747 1801 2737 3915 3925 81 3922 533 2355 489 512 1983 4966 3452 1978 1426 2489 161 1421 1601 1603 444 1602 3480 634 1194 2903 3547 5216 3550 4139 241 1466 1465 239 593 2355 542 491 255 252 244 251 265 256 264 257 3671 5496 5136 5239 2281 4678 2282 1687 3753 4523 3209 3857 1084 4077 3949 1092 3075 3503 4 3214 3901 5060 4513 3578 5230 5728 5719 4225 28 3528 2876 2764 5316 2758 5134 3567 1319 3191 1780 1320 1866 2300 1362 1867 3937 1873 2101 1872 948 956 40 953 220 2498 221 1453 1870 2462 2105 1068 533 3078 777 2355 679 2355 678 680 2390 5024 3733 3736 691 2355 520 689 247 239 246 236 910 1695 1689 22 776 3078 773 777 418 1237 417 1236 1440 196 203 195 3128 1925 2982 1926 848 652 651 655 73 5743 5303 5442 3463 2988 2073 2989 649 848 652 651 1881 2087 1588 1880 865 4174 3226 7 1418 143 144 142 4764 5713 3649 4828 635 4362 3471 3483 130 4077 133 3785 1101 143 140 142 1475 1476 277 269 1194 3480 2903 818 1096 3317 2892 3084 1125 4449 1959 1117 458 1608 457 456 923 2665 2395 2287 3503 3618 4 3223 156 1424 159 164 1053 3305 2031 1055 4240 5179 4456 3917 1217 1543 1542 1216 3549 5050 2706 4157 4358 918 1756 913 2355 786 539 849 970 2414 2248 1795 124 2480 125 1399 416 1570 1233 1232 167 1424 159 158 709 2901 708 710 2227 58 1341 1820 1255 1602 1601 1254 675 2355 674 671 155 146 154 156 846 4676 3527 3744 3400 3638 2849 2866 1571 416 1570 1233 984 2201 1804 1805 1897 1948 1450 227 55 991 990 983 3769 2678 834 2679 849 677 517 516 778 5321 3078 2323 2344 4407 1308 2340 131 2011 134 1096 130 1396 133 1394 2188 3907 1855 2817 332 3102 1155 1154 981 49 967 974 4350 3001 2098 1169 633 4224 3478 3689 251 1471 260 1470 831 5693 4953 5237 1457 224 225 1455 584 4842 585 2355 255 251 260 252 2069 3557 1818 2740 1957 2927 1118 1125 4343 4730 4143 4464 492 2604 1699 622 684 2355 849 681 927 31 921 920 3989 1341 1820 2227 1939 2194 1276 2072 689 2355 520 519 1085 3071 2872 2481 648 2355 498 503 1832 3133 2307 1834 952 946 40 947 4420 5683 2422 1663 47 5278 4747 45 1322 2699 2405 2108 2537 3091 1597 1890 499 2355 688 498 254 2506 247 255 3144 1941 3005 2064 725 5321 722 726 2440 1348 1834 2771 3933 5181 4635 3901 192 199 201 193 848 525 655 524 2700 3637 2413 3409 796 2355 797 544 164 1422 156 155 673 516 677 849 4003 4935 3456 4630 149 1415 138 146 2671 3952 1769 931 3560 4274 825 997 4805 5923 3171 1847 3151 2430 1341 3357 3350 5683 3650 611 2452 3115 1358 1855 2664 4714 4713 847 3677 4964 3476 4961 506 2355 661 664 2243 2672 647 2239 4073 4646 4553 3760 31 1762 1760 1759 4732 5744 5275 2547 2837 4812 1053 4435 4564 5111 3696 4979 1023 5156 4998 4796 881 3077 2373 1719 695 2355 691 692 2689 4550 2581 3775 1506 1509 326 328 620 3524 22 2302 2402 5614 3187 2330 3717 4340 2641 891 263 1472 265 1474 1149 1921 1920 1624 2703 5049 962 2589 4079 5092 4679 4087 3933 4230 3578 3297 956 2263 40 953 634 2903 1195 1194 559 3078 720 718 3938 2454 3189 3123 454 1609 453 1608 1596 2895 1594 1099 751 2604 580 749 3385 3260 2555 4225 635 3471 1659 1197 3078 562 561 727 1927 4116 1925 1167 4027 1936 1185 1187 1013 2216 2211 67 5330 2194 2947 1629 5045 1789 5450 5806 106 1383 109 1382 916 3529 3459 919 3078 719 2355 2323 3491 4084 3677 3653 733 3078 565 566 2187 5677 5426 5561 1585 2883 1587 2879 3549 5321 4157 613 354 1524 356 362 5714 5689 5502 2615 4114 3240 3903 3122 1291 1292 9 1290 22 907 902 910 560 3078 723 720 736 3074 732 3065 1341 2854 1820 1002 1206 3068 625 2347 1189 2090 1190 1182 2725 3832 3323 3830 204 206 207 211 3315 4757 4420 52 4744 3158 1363 4129 4589 5189 4167 3031 3395 4638 3961 2573 1762 31 920 1759 2376 4835 4176 4637 1475 2507 269 266 1844 4962 4952 1036 2324 4842 2323 616 162 1422 165 154 3078 565 566 780 1311 2399 934 1314 2323 615 616 746 1428 172 163 171 155 1423 164 1422 158 148 151 147 722 2323 725 721 4330 5318 4752 5111 4876 5573 1675 34 2959 3601 238 2503 1001 2753 1003 2429 1535 375 366 1478 562 3065 768 592 2834 2839 1871 2463 712 5299 715 2784 4072 5161 3056 4152 266 2259 1471 260 2416 1377 1330 2317 2337 4749 1328 2095 1738 3718 1751 2127 287 1485 294 295 164 1425 163 1424 1097 140 139 1101 1419 2489 1420 161 4842 587 586 758 204 1441 203 211 2901 488 553 528 4017 4737 3930 88 887 3122 1725 2882 96 102 104 103 260 254 255 263 108 1384 100 103 151 1417 145 153 251 242 243 253 243 247 254 246 1774 941 938 1773 3979 4059 1557 3070 4999 5943 1800 959 5724 3961 2444 5355 3065 770 772 2885 58 4226 2227 3650 356 1526 359 364 2724 2079 3829 2715 1193 3480 818 3478 581 2784 580 711 1560 3050 1147 1561 841 4380 3491 4379 929 4714 3533 4334 993 3560 998 58 3682 4718 922 3355 4405 5432 3451 5264 847 913 28 619 3113 88 1069 2852 960 2269 2261 43 1369 4820 2298 2465 857 2365 1705 2364 236 244 243 247 1099 2537 1412 1597 342 1519 350 343 361 352 360 353 161 168 160 169 452 1605 1604 450 514 2355 668 513 2832 4476 3793 3799 724 5321 725 604 92 1381 95 93 495 1663 642 612 61 5294 5053 5092 4424 1669 3280 4534 331 1516 339 342 102 95 96 94 4483 1826 1345 65 1384 108 111 103 356 1529 364 355 3784 5169 3539 5077 976 5577 2199 5281 516 849 681 684 114 1389 125 117 170 173 2272 2490 1990 1083 1879 1988 659 2355 504 658 721 2323 724 586 927 3962 921 1764 363 370 371 372 492 1646 598 627 670 2355 669 668 504 2355 648 503 1983 1139 1908 1140 1095 3011 133 1091 719 2355 584 718 3580 1046 2186 3702 2412 961 43 2269 172 1433 180 171 168 1430 176 169 171 178 180 172 1749 2656 1303 910 3390 4826 1080 1076 4729 4732 4308 2860 2604 750 550 551 94 3438 2473 95 964 4319 1792 3801 2291 2470 1375 1376 5321 614 744 613 981 2747 967 1801 778 5321 597 3078 1159 1151 1152 333 4391 2631 1290 3514 1099 2895 1594 1890 3156 2988 2075 2984 3080 3094 2019 3003 355 1529 364 363 777 3078 558 2355 995 3556 3352 1337 569 2355 568 797 2269 2412 614 43 1093 2004 1090 1094 327 4907 326 1168 5315 2840 2324 5110 431 1578 430 429 829 5508 830 832 1645 5561 2112 2187 2656 22 910 1689 288 295 297 289 2355 532 489 512 848 754 526 755 1890 3096 1100 1594 896 1737 4555 1736 5218 4263 3848 3401 1015 3870 1017 3245 2341 5107 4661 3773 4398 4637 4176 4460 4226 5724 5536 5355 2218 406 407 2936 4842 616 747 746 5965 814 2786 1031 1470 260 252 258 350 1527 1522 351 988 2423 984 2422 4886 4465 4086 3359 2786 5868 5301 814 3004 3144 329 1179 164 1428 163 1425 1560 4266 1147 1132 1002 1668 58 999 1107 4843 1106 2019 2271 3968 3093 2327 5034 3495 4239 2354 1026 2444 1024 2213 3934 5355 3574 1650 3834 1334 986 3327 4218 5440 3335 1010 252 1470 250 251 198 203 199 195 792 2901 793 796 1949 1114 1902 1901 948 3192 2693 1322 3549 837 46 614 5916 5977 5524 5456 1032 3808 2792 3282 5594 3943 4737 5178 1983 2959 4043 4066 586 4842 758 759 673 2355 670 515 4274 3560 825 3353 4324 3249 3737 3257 505 2355 650 504 1917 2035 1499 2029 570 5080 743 740 41 36 39 38 2764 5480 619 5431 121 1393 120 1391 855 1705 1 857 979 2565 987 52 1485 1488 295 292 1497 2520 1501 1498 1484 1487 293 291 1383 106 98 1382 1133 236 1130 235 512 2355 667 511 615 2323 614 745 4955 5321 3926 2457 3356 4411 44 1786 1551 2930 1553 2927 3539 5315 2324 5110 200 2495 209 201 170 1427 162 1423 212 1441 211 213 5502 5689 2614 5398 699 2784 698 2604 3078 736 733 2885 275 1476 277 267 2495 206 198 208 815 3577 3176 1652 3285 4805 3171 1847 389 1540 388 387 3547 5216 5145 3550 3609 2204 1250 1251 715 5299 599 714 1306 27 193 192 892 2277 2143 2136 226 1449 1448 229 5511 5586 5442 1651 3344 1560 230 1561 184 1434 176 174 484 1634 483 1633 298 1489 301 300 3448 905 1300 2653 1238 1575 421 1574 1023 1027 70 1022 1474 1477 271 270 2412 3886 2590 3311 772 3078 849 2885 1385 109 108 107 4644 3803 72 3381 1925 3128 1167 1165 723 3078 722 720 4206 5321 4603 3590 2821 2823 1863 2815 3856 4554 3429 3753 5683 562 727 607 2049 1151 1918 1625 3998 1973 3021 1976 4792 5317 3613 5213 533 3078 849 777 1344 2435 64 1825 751 2899 579 2784 681 2355 679 682 167 1425 166 175 3713 5926 3517 4696 172 1433 171 1429 4242 5683 495 5321 849 771 775 772 819 3472 822 821 2272 1423 164 163 1560 4266 230 1147 1228 3063 1229 1998 40 953 947 948 4059 1558 1559 1968 930 2396 1768 2242 1195 5420 820 2903 4437 1054 3633 1057 1467 2506 1468 257 388 1540 1214 1215 2019 1106 1102 4843 2243 5595 647 2672 2189 5183 4521 3253 391 1545 390 1544 3818 5277 4746 4154 2152 3737 2126 2362 96 95 103 97 889 2377 884 885 149 155 147 157 141 140 1085 138 1055 4435 3912 816 698 2604 700 699 1066 85 1073 1059 232 3032 3028 1145 262 270 271 267 410 1569 409 1568 1107 2019 1106 1108 1882 2087 1250 1986 913 918 929 28 1396 131 132 1879 5836 2648 1741 2384 208 2495 207 209 418 1572 1235 1234 176 169 177 168 8 5057 2371 3701 1438 197 186 187 2851 5110 3611 3612 275 267 274 276 541 2355 686 687 1183 2090 1182 1184 258 1471 260 266 3566 4505 4166 3564 779 2355 781 2323 818 4224 638 3478 2201 2422 988 1804 528 2901 507 2355 2395 4155 3640 2665 1462 2535 1560 230 47 5032 48 45 881 5547 2374 5424 87 3591 3445 1366 5063 5588 79 1052 348 1525 356 347 174 1430 176 166 2324 2851 602 2332 3273 4664 3797 2460 308 1489 307 309 2428 3826 3692 3014 678 2355 513 518 475 2993 1620 1621 4074 4608 2603 2374 172 1432 178 1431 1437 4381 3598 1306 1807 2729 1336 989 2019 1889 1107 2016 122 1389 125 114 848 756 752 755 1566 3758 2936 2217 1384 100 1381 99 2313 3836 1808 2314 95 1381 102 103 276 270 279 275 1472 264 257 265 573 2899 848 2784 406 3013 407 2224 1163 474 1160 1161 5461 5342 4009 1288 223 1447 1445 222 7 4669 3241 2621 5114 5242 3433 843 986 3553 2736 3323 259 268 262 263 251 1471 1470 259 5689 2615 5888 2366 1516 334 331 332 259 254 263 262 262 1474 1472 263 1551 3024 404 1553 445 1602 1254 446 3720 1731 2274 2383 1883 3953 1991 1884 844 621 19 891 200 199 192 198 2901 788 789 790 759 5080 760 762 3539 3666 616 2323 2104 4829 4607 1079 4199 4942 860 1708 79 4512 2457 4065 65 3565 3146 63 4799 5686 5685 5230 76 1039 1044 1038 2355 664 665 661 2570 5092 4679 2357 1184 480 1190 1182 5270 5566 4715 5266 119 1386 118 116 1350 1026 1024 2213 188 26 24 23 848 651 654 655 740 5080 738 569 4334 5016 928 3750 2536 4095 1591 3321 2679 4204 2332 2324 589 849 771 774 771 849 775 774 2101 4745 2851 4141 5390 3412 3587 5133 1153 2524 2026 324 92 1380 99 2474 335 3175 334 1167 3165 1512 3006 2528 1812 4126 1338 3145 96 102 94 104 649 2355 499 648 94 3438 54 2473 102 2475 104 103 3206 3871 2774 3235 2978 3978 2921 3946 11 5251 14 1292 2901 789 791 792 4410 5725 5707 2581 6058 6054 6047 6048 3539 4919 2323 2324 957 43 955 954 2735 3322 2198 3786 8 1287 9 6 554 2901 553 767 5424 5563 5039 2374 2521 316 1502 1500 2188 3189 2454 2452 843 2603 2598 842 262 1472 264 254 254 1472 1469 255 3309 1081 1 2124 280 1477 272 270 254 260 255 251 1270 1619 469 1618 285 2251 83 81 2822 4816 2177 2458 3087 4841 3969 2015 785 2355 540 541 732 3074 731 729 2488 2489 153 151 736 3078 733 737 3480 1193 818 1194 175 1430 166 167 647 2672 932 2239 777 849 534 776 1184 1182 1190 2090 5311 5683 4420 5321 347 338 339 349 232 3452 3032 1134 1161 1151 1159 1163 2576 2937 2223 3558 208 1443 1442 209 1266 1615 1614 1267 4424 5053 1669 1823 875 1725 13 887 171 178 179 180 5821 5909 1637 5905 1763 5372 4926 5357 1209 4678 2919 1699 1032 3261 1352 1028 12 4697 14 1295 1550 404 403 1225 753 2604 549 848 1071 1069 88 1078 319 1494 321 320 2604 753 752 848 533 849 534 777 1683 3968 838 3672 2266 953 40 2263 3111 1992 2035 2969 251 244 242 252 2456 4640 4144 1360 4063 1137 1461 1979 2767 1013 1012 1020 976 2719 2418 2200 1344 3566 1825 1004 2355 506 507 664 1897 1948 1114 1115 34 3025 931 930 5264 4930 914 5417 654 848 523 502 848 487 523 502 95 2472 93 1378 1532 2533 365 362 316 2518 315 2516 1012 67 1020 1013 97 2424 59 57 1554 2920 2003 1227 199 204 203 206 694 2355 522 521 3351 3540 949 3539 2111 2851 804 2850 37 1779 950 937 306 1492 309 308 1021 5056 1015 1005 2587 5437 5436 43 514 2355 513 678 361 1531 368 369 3783 2257 3394 2260 634 5420 1195 2903 699 2604 700 702 1748 6125 3493 6097 2434 5316 2309 2758 4185 2223 3286 2426 2437 4610 1831 1019 54 3438 1379 2473 1893 3082 136 1103 1407 1406 1405 1404 136 3080 2539 1113 3647 4429 1018 2438 888 2546 2116 1294 1734 3441 2648 2284 3954 5851 5863 5920 875 882 13 874 367 1529 1526 366 347 341 349 339 343 1519 350 351 923 4407 1308 926 2105 3186 3100 2843 4648 4903 3744 4119 736 5531 3074 3065 1005 3865 1015 827 395 1544 394 393 260 1470 252 251 1100 2011 1596 441 2834 2839 1069 1871 70 3934 4877 3574 668 2355 508 513 3976 4772 2913 1816 3772 3540 2266 3399 3168 4686 3142 3140 1231 1568 1567 1230 3018 2928 1903 1959 2195 478 479 2947 1121 5013 4342 1117 2715 3843 3155 2726 2881 5155 4477 4113 1424 167 159 164 156 1422 154 155 166 1430 1426 167 1107 2013 1108 1106 166 1426 168 158 1704 3257 1707 2126 699 2784 575 574 917 2660 2315 2278 585 4842 586 759 643 5114 644 3338 120 1393 119 118 1558 1459 235 5065 2538 1414 134 1595 2015 3969 1603 1102 1146 4066 3048 2963 3666 3539 616 3394 1530 367 372 375 3206 3235 2774 881 1352 3625 1353 3261 386 1539 1538 384 872 3241 873 7 1177 1175 477 1176 3156 3175 2984 2075 1148 2033 1149 1920 2982 4024 3172 4022 1626 4021 2033 2042 1159 1151 333 1163 2084 1512 1180 1181 4811 4489 1513 1509 1425 167 172 175 1429 175 180 183 110 2475 111 112 696 2901 545 2355 164 1428 172 163 120 1388 121 1387 170 2272 1423 164 493 1637 632 602 4905 1836 4779 2941 602 4204 2324 2332 2134 2881 2369 1636 2058 4489 1509 3139 4114 2116 2636 2379 87 2512 288 289 250 1470 261 253 284 1484 285 283 751 3066 754 579 286 1485 287 284 3857 4718 4160 3753 1457 224 232 222 2391 2393 915 2315 188 1438 187 195 2263 2925 40 2266 3040 4029 2061 1977 308 1492 309 307 2015 4841 3969 1102 577 5299 2784 704 2877 844 19 2974 178 171 179 181 3200 5557 4977 5331 179 183 180 182 653 848 656 652 180 1433 183 179 258 1470 261 250 1178 2082 480 1632 1611 457 1263 1610 507 2901 657 2355 1005 5297 4880 64 1097 441 1101 139 531 2355 666 667 686 2355 682 683 805 2363 858 2122 314 1502 1501 317 5060 5683 3578 606 2355 511 510 663 726 5683 727 606 822 5420 5034 3472 2646 3960 1736 2131 116 1389 117 115 236 1956 235 1120 1217 1543 1216 388 3767 5767 4219 2695 1520 2532 1521 353 3074 728 849 588 127 1406 128 129 927 3962 1763 920 1909 3063 1998 1964 190 1437 191 192 2343 1307 1309 1765 79 1046 1047 1049 1603 445 446 1602 1795 2248 4157 4916 4199 859 853 3599 5932 5699 5834 5868 1030 2153 1838 1839 2030 3105 323 2024 3046 4061 2935 4053 5077 5169 5023 5162 509 2355 658 508 1312 2399 1311 1314 116 2477 115 1390 682 2355 679 680 1503 323 1502 326 1169 5332 4686 4566 473 1618 472 471 2387 906 2390 3448 990 5580 55 4269 4919 2408 2584 3539 93 1380 90 91 4417 46 959 975 5277 4154 4738 5046 4206 4623 813 4594 3247 4950 2144 4330 901 4701 1693 3733 2164 4108 3931 1869 1118 237 1125 1117 236 238 235 1133 2890 1885 1087 1984 1102 3079 2912 2911 567 5321 495 3078 2767 2773 1020 1012 402 1550 399 1552 410 3995 1975 1565 61 5323 2229 2230 3022 2672 934 646 2318 2720 2317 1333 1043 1848 1357 1355 663 2355 662 660 1043 3294 76 2812 320 1493 310 318 1518 343 337 335 506 2355 653 505 7 3244 868 871 980 2861 1331 1333 671 2355 674 511 969 2741 837 2707 542 2355 687 522 100 2474 1381 99 3557 1818 1812 1338 533 3078 2355 849 346 1523 357 349 2003 1556 1946 1227 585 2323 721 586 4826 5143 4825 4918 238 2503 239 240 306 1492 317 309 524 848 654 655 1465 1466 240 248 907 4703 4701 3736 1128 1972 1460 1562 1484 293 282 283 75 80 77 78 1858 5589 1656 3109 687 2355 683 521 224 1447 222 1445 197 1438 186 194 214 2496 215 211 245 251 243 253 207 215 211 214 2659 5264 4930 914 4865 2442 69 1349 2784 698 848 573 742 4842 739 740 712 4885 716 4839 583 2355 532 489 947 1679 40 1678 794 3473 574 2901 897 1735 896 892 2282 2919 1209 1687 356 1523 348 347 31 2286 921 920 4878 5492 4410 5069 356 2533 364 362 474 1162 1161 1163 1349 4751 1350 68 3252 5298 3934 4194 4197 4998 4796 3885 1033 5059 1027 2158 1036 2559 73 2556 2786 5971 5948 814 1652 3578 2185 76 2787 4433 3728 3806 3737 2152 3257 3249 730 3074 728 3065 244 247 255 254 262 1474 264 1472 1472 2506 257 1469 1524 2234 355 356 2871 2875 1995 1881 1403 1399 124 123 1881 1990 1988 1880 347 1524 1523 355 1617 1268 466 467 1612 464 463 1265 3473 4954 4885 788 1210 1537 1211 379 1161 1160 1157 1156 1051 5308 82 5064 405 2933 1130 2932 333 1151 1152 330 564 3065 728 2885 5027 5418 1305 5042 4405 5567 5416 25 77 2450 80 75 2406 4771 2697 2696 433 1580 434 1244 3815 4386 3330 2357 4282 5440 1005 64 1978 4966 3452 4043 2959 3398 2503 240 657 2355 653 506 1556 3988 3013 1955 3063 1909 1228 1914 2942 4432 3751 1672 1287 4668 2147 2145 577 4885 4839 572 3066 754 848 2899 4615 4614 3621 4474 660 2355 658 509 1006 5760 5438 5584 93 2291 53 51 930 2398 2396 2242 2433 1345 62 60 900 2650 2387 2390 2784 751 848 2604 5416 25 911 4404 189 1436 23 21 5032 2095 47 1798 46 614 959 958 1159 474 1157 1160 4024 2075 3172 4022 4607 1874 2855 3691 1282 3599 2148 1283 466 1614 1267 1266 242 243 253 245 741 2323 742 745 192 1437 193 1306 4619 3526 3465 3624 2904 50 2317 2720 3829 4757 2724 4241 5536 3065 592 5531 334 3168 1173 2091 1061 2832 1063 2831 2829 1059 1073 1869 83 1481 285 81 104 2475 113 105 499 2355 690 688 710 5080 2901 555 773 3078 560 559 96 105 97 103 1349 5835 5781 5817 397 1549 398 396 849 538 787 539 768 3074 769 591 2727 5580 4269 2222 4166 4630 3318 4471 697 2355 696 693 662 2355 659 660 853 1640 4 854 4251 2716 2739 4528 2716 5683 1663 5321 2246 4047 3549 3378 849 535 534 776 1058 2829 1066 2828 866 3510 1715 3509 744 2323 741 745 2876 3354 28 3209 2670 5269 4715 2669 3533 4714 913 3749 4054 4906 4611 4122 132 1984 1087 131 3854 5117 2675 4073 2427 2568 1662 2354 738 2355 593 568 343 1517 337 345 4572 5035 43 2585 219 2496 211 1444 4955 812 2457 2557 1296 2284 1297 890 1394 2480 1398 1395 3860 4692 3363 2672 1133 239 236 238 4205 4848 626 4667 529 2355 664 665 766 2901 2355 763 367 1531 358 359 235 1464 237 243 1118 237 1117 234 808 4472 4231 4224 1060 5470 4440 2824 1658 2323 493 603 4842 585 586 2323 2001 3011 2872 2000 3616 4677 3958 3204 898 4345 4331 1739 1385 1386 115 107 1023 4944 2155 70 665 2355 661 662 1379 2913 2424 54 3148 59 2424 57 2100 1999 1585 1587 993 58 999 994 1255 1602 445 1601 1487 298 290 1486 22 2656 910 1304 4190 1286 2368 1285 2399 1311 934 1313 4647 2615 2366 5888 312 2515 310 1491 4226 5724 3989 5536 5355 4809 2422 4828 1030 2797 1035 1034 1347 4780 4260 1016 3878 5525 5173 4432 2356 3495 2572 2354 2069 3557 2748 1818 254 260 259 263 220 2497 219 2496 276 268 267 274 206 2495 198 199 1466 239 240 238 761 5080 2355 4842 296 2514 305 297 81 1481 285 284 287 294 288 295 146 147 157 149 3087 4841 1104 3969 570 5080 740 569 1923 2197 2033 1920 4037 4109 4010 3007 848 3473 754 3066 969 837 46 2707 1801 2316 2250 981 533 2355 674 849 587 4842 493 557 1167 331 332 1165 3603 308 2517 1492 2658 4930 914 2659 8 3697 2371 6 22 910 902 1304 2231 5053 61 1003 728 3065 849 2885 4463 1163 1155 3010 1488 1485 295 294 318 1505 1503 326 199 196 195 203 5051 4414 4486 4909 1821 4773 4423 2762 5391 2267 3427 5035 286 2510 1482 287 2329 5595 2603 3503 1885 2890 1087 1989 236 1557 1121 1120 220 3600 221 218 1119 3012 1950 227 1909 3063 1228 1998 232 1458 1455 230 3162 3950 439 2873 140 1997 1591 1088 2554 2189 3934 1648 1588 2018 1881 1880 1248 1587 1584 440 1100 2022 1887 1101 741 4842 742 2323 1360 6030 6005 2456 3280 4679 4424 3183 2215 2393 2278 917 3778 862 3121 2138 5245 3185 2292 3595 1039 76 1044 1045 76 2185 815 1649 1040 1048 76 1045 3562 4939 4936 2232 2118 5205 3703 3119 1300 4383 2119 1301 199 207 204 206 405 1147 238 230 236 238 246 235 2506 2505 246 247 405 1133 235 238 1441 202 210 204 680 2355 678 519 528 2355 507 664 202 1441 210 213 196 203 199 204 2728 3843 3099 1808 436 1586 437 435 139 1415 141 147 3001 4350 2098 3000 2528 336 334 1942 1944 1190 480 1189 4408 5422 30 27 4059 3012 1557 405 2018 5617 1085 5564 787 3078 563 849 672 2355 670 849 3410 4513 3297 3933 537 849 490 588 139 2536 131 1408 2687 937 950 1784 1783 3191 1320 1780 5077 3784 3190 3987 85 2164 1869 1059 849 517 538 684 412 1571 411 1570 1864 2461 85 2460 1767 2662 2358 1770 325 1501 323 1502 673 849 676 672 513 508 486 2355 584 2355 764 583 515 2355 514 679 540 2355 685 686 564 3078 787 783 909 911 25 908 515 849 516 673 353 1521 1520 352 344 2532 1521 345 4739 3590 4440 2824 1519 339 1516 342 1866 1362 1062 1065 5299 2380 1646 3703 1053 4144 3114 2455 552 2604 551 748 902 2302 1693 22 657 848 526 656 722 3078 719 720 189 1438 186 187 1418 143 151 1417 2132 4 1286 1711 1326 2410 1790 1325 547 2901 697 848 3693 2140 2880 2616 2095 5032 2337 1798 2804 4802 2055 2781 1100 143 1101 142 2875 3609 1250 1588 669 2355 510 509 496 1675 647 617 3817 2997 2447 2040 4580 5316 5109 4884 3922 81 2297 83 2984 3052 2076 2057 848 527 657 526 311 2519 2518 1493 3463 5333 4115 2075 5289 4130 2715 2726 315 2519 318 2518 1182 1189 480 1190 1178 2083 1183 1180 2475 110 102 112 562 3065 2885 768 419 1572 1235 418 231 1560 1131 230 2672 3098 646 2603 412 1571 1233 413 199 200 192 201 2666 5016 2667 3754 206 2495 207 208 1330 3551 2419 1377 1385 106 114 108 840 1700 838 644 2854 2430 2432 2233 596 5321 744 597 1715 3509 2968 866 1780 1321 951 1319 3192 948 956 1323 5664 616 3539 3987 2006 2911 1109 2005 1229 3037 406 1228 807 10 599 867 1130 235 405 1133 1460 1562 231 1128 4324 3257 2782 2494 5943 1791 3112 2097 532 2355 667 512 361 368 360 369 1160 474 1157 1156 2489 2488 150 151 779 2323 595 596 2427 3650 58 3350 5166 5836 5553 3523 3074 5532 736 735 1433 180 171 179 2185 3578 2453 76 3914 5348 5202 5312 2451 4743 2815 2814 695 2355 694 691 1430 1434 176 177 888 2878 1726 1293 1075 2469 1875 1080 2139 3881 2974 2877 5836 2648 3218 1741 549 2604 550 700 1071 2834 1870 1068 3574 5683 1650 5355 3302 4 1640 2132 3502 4188 2151 2606 3526 4278 3465 2660 3460 3741 3527 915 1007 4775 4425 2236 2231 5054 826 3358 2767 1836 1013 1025 562 5683 3078 5536 3360 5364 2759 4914 5689 5502 2614 5099 2787 3728 3573 2788 1863 4743 5005 2815 405 1956 1557 235 1902 3070 1556 2003 3988 4041 3012 1129 5461 5342 1288 2147 237 236 235 1117 235 1557 1120 1956 2390 2596 22 2389 911 1752 25 908 24 188 23 21 951 1319 3391 3790 1430 166 168 176 3078 772 849 776 334 2528 1942 1943 130 1395 1394 133 4082 1733 2139 2384 2318 1331 1333 2317 1801 2717 2252 49 1330 2291 1375 1376 1072 2847 1367 1369 22 2596 1689 1699 4609 2546 2379 888 17 4696 15 4396 21 2386 1748 2353 602 4842 717 557 5 2366 6 3 857 3215 2609 2364 1343 1826 4884 3861 643 5114 828 644 3390 4825 1076 2850 4911 993 1817 999 503 2355 486 508 405 1558 235 1557 191 192 198 190 188 23 189 26 211 204 212 207 207 212 211 215 844 4940 4557 3233 4040 4982 1565 1229 5774 5040 2112 5677 166 1430 168 1426 2784 714 581 2604 1892 4890 1111 1891 3807 4318 2356 2357 1414 3094 2486 1895 4139 5145 4916 4673 1000 3562 3222 2232 2241 3623 1773 941 1984 2536 441 3321 2106 2324 1637 2323 518 2355 513 486 716 5299 712 4839 4285 3018 1967 5013 868 3570 3512 1351 2259 266 1473 269 236 246 243 235 909 2304 908 25 4133 3382 3466 3166 2702 3356 2410 2704 3315 4420 3823 52 5420 2903 635 3472 52 979 977 987 106 1385 114 117 2355 509 668 508 3560 998 58 2228 4521 1022 1647 2156 457 1608 1260 1261 543 2355 522 694 1541 1215 385 386 2556 3385 2801 2555 116 1386 108 111 730 3078 733 2885 5050 968 4529 2706 93 2474 92 1381 94 1381 92 102 449 1602 1601 447 2468 2864 1371 2469 2837 4144 3909 3924 2104 4829 1079 1872 2851 4732 2860 4308 3138 2890 1885 1989 5409 3565 3146 4483 4902 1144 3719 3009 4255 3133 2772 3245 3127 1177 331 3126 2215 3527 2392 917 652 848 656 655 158 2489 151 159 2255 3190 2107 2352 4374 952 947 946 190 200 192 198 288 294 286 296 974 5279 5051 966 956 3792 2926 2867 581 2784 2604 580 480 1632 481 1178 87 2512 289 89 2528 4069 3372 336 2999 2990 1937 1982 1161 1160 1163 1159 4049 1898 2920 1954 1159 1160 1163 333 294 2514 296 295 3269 4957 4603 3629 412 1567 413 1231 2355 761 584 764 1727 4697 1295 2637 4205 1699 1685 3680 689 2355 519 688 124 3596 125 122 172 1433 1429 180 4079 2357 2439 2870 2123 4387 4164 4208 3067 3725 3723 897 58 1341 1002 994 974 3814 2747 2737 2576 3468 1665 1339 2036 3062 1917 1499 2541 3338 1700 798 2323 2106 632 493 739 5080 738 740 139 143 142 140 957 5436 2587 5559 314 1502 317 316 1508 1509 326 1506 907 3736 1695 22 1750 3522 2649 21 5270 5566 5263 5260 2491 3963 18 20 2665 2914 2395 2287 1744 2649 1749 1750 1675 5595 647 2243 901 5024 900 4383 262 1472 254 263 266 1473 258 1471 2178 2560 76 1654 286 1485 294 287 1058 5626 4438 2828 5015 5242 2603 843 2452 2816 2188 2450 2425 3560 992 2743 4842 587 493 2323 2355 531 532 667 477 1170 1175 1177 5227 5311 3578 5060 1386 1388 111 119 2754 3014 2233 2432 62 3859 2433 60 61 5635 1003 1001 888 2886 886 2635 94 1381 95 92 995 2427 2220 2078 39 2699 2109 41 593 2355 784 542 140 2487 139 1416 2438 4781 4260 3864 162 1422 154 156 1999 2883 1587 1086 3785 133 130 1878 690 2355 689 688 300 1487 292 299 139 1593 1095 141 139 1415 140 141 595 2355 781 594 3621 4474 3270 3980 3768 2912 3003 2813 1605 1257 448 449 2815 4742 2821 2823 634 4231 809 3971 2990 2999 1937 2994 1477 280 1435 270 1570 415 416 414 5299 577 496 618 2317 2906 2720 2318 2899 712 709 2784 1924 1151 1152 1159 409 1568 1230 410 1071 2852 1069 1078 3903 4807 4181 4114 4829 2104 3937 1872 5734 4150 3709 5040 1030 2445 2154 1838 2013 4843 2077 1106 162 1423 164 170 696 2901 697 546 1692 2295 3442 2388 2245 5777 3544 1681 1286 4012 1711 2368 2596 2605 1699 2594 1312 2399 1314 30 2496 219 211 214 1686 4848 2273 2605 542 2355 541 687 3856 4985 4554 4523 1816 4356 3148 2312 1733 3881 3232 2139 786 2355 540 785 4795 2787 3251 3574 770 3078 561 560 1048 1854 1359 76 71 1349 69 66 2016 1888 1107 1104 120 1386 110 118 1346 2771 1348 2054 1821 4773 1830 4423 952 4374 3191 3538 2439 5830 827 4087 544 2355 694 695 64 1004 609 1005 768 3078 562 561 1225 1552 1550 1224 4464 3258 4007 4343 1551 3977 403 3024 1900 2918 1898 1554 800 4571 1700 624 358 1531 1527 359 1925 4899 1926 1165 5311 2354 821 4809 869 7 863 865 2210 3456 1344 1671 947 1679 946 40 1104 2017 1411 1105 2018 5617 5564 1991 1397 1403 124 1400 2907 3781 2896 33 1883 1984 1087 1884 2001 138 1085 2481 302 1491 304 303 2284 894 1734 890 288 295 296 297 304 2514 303 305 3889 5240 3572 3260 3260 2801 1032 2789 753 2604 750 550 2679 5110 4953 4410 700 2604 550 703 1892 3768 1598 1894 932 3437 2672 647 285 1484 282 283 5649 5995 5550 5978 1888 3003 1411 2017 1275 3058 1626 1992 1163 3010 1161 1151 4028 2057 3052 1930 1097 2022 443 1101 3252 5183 2964 4521 818 3478 638 1193 472 1622 471 1620 100 1384 1381 103 485 1630 1279 484 1124 4090 229 226 1183 2081 1184 1182 671 2355 672 849 1733 2645 2283 2643 2195 5330 1629 2086 4171 1915 4010 2039 331 1515 332 333 1507 1509 1508 1506 4482 5360 3713 5335 1630 1632 480 1631 479 4127 478 3694 2712 48 50 2093 2514 302 294 304 2251 1361 1479 83 2718 3664 981 2420 4579 5050 968 4529 2140 2970 2368 2370 232 2535 1462 230 864 1711 1286 4 865 7 863 862 10 867 807 877 1408 3057 133 3011 2538 134 142 1410 2004 1093 1091 1999 106 1385 117 109 3834 3839 2733 2567 159 148 156 151 2769 3864 2438 1014 4285 2916 2927 2930 1093 1091 1095 1090 3078 727 723 726 1955 5186 4052 4627 405 1459 227 235 843 5114 842 840 875 3704 2630 3514 623 3338 628 2898 2438 2769 1014 2571 5227 5766 5311 5060 356 1526 355 1525 823 2354 635 636 2658 3525 3460 2659 2225 3650 2743 1667 2161 4165 3263 3590 849 673 676 677 657 2355 506 507 302 2514 294 295 4651 5525 4432 4586 603 5321 724 604 3549 2706 837 2248 362 2234 1524 356 363 373 371 370 687 2355 686 683 2355 530 531 666 1363 2510 1482 286 1737 4507 3497 3960 694 2355 521 691 533 849 674 534 1283 4199 3599 2148 101 1380 90 98 2753 5741 5635 1006 1450 227 228 1897 1466 239 247 1465 766 2355 767 529 3724 1737 2128 1743 1227 4285 2226 2534 674 849 675 534 2851 5381 601 5351 677 849 517 537 672 849 676 675 212 1444 213 211 2169 3416 1343 2237 2899 573 574 2784 787 849 539 786 2252 5203 2739 4975 3225 4340 3441 3717 2477 3596 116 1389 167 1424 158 166 2444 5724 1672 4432 4340 3225 3441 4331 588 849 774 537 673 2355 849 670 786 2355 539 540 3979 1557 1120 3070 1146 1138 408 1145 1983 2963 1146 2959 1980 3758 2218 2940 1461 4043 2959 2503 1565 1966 1229 410 246 236 243 247 239 1466 247 246 4851 1908 2959 4085 2272 170 1427 173 2000 3060 1095 3057 1881 3609 2875 1588 2722 4969 985 984 3058 4346 3010 1992 1179 1181 482 1627 1842 4802 3888 71 849 535 775 536 719 2323 722 721 1619 473 1618 1271 341 1515 330 338 1624 3290 1275 1274 2293 2650 2299 2389 1685 5644 1699 1209 303 1488 300 295 3059 2757 932 3368 3059 4073 2239 3760 4882 5312 4339 4821 4579 3833 837 3663 5269 5356 2340 29 45 1325 42 1326 49 2247 967 966 2389 2807 2596 2594 2832 2162 1061 1063 188 26 190 24 804 4825 2111 2850 284 1485 287 285 292 2513 1485 291 2462 3267 3186 3266 2899 577 576 788 1321 3388 1677 951 649 2355 500 499 317 1502 1501 325 764 2355 531 532 572 5080 4954 747 975 46 959 964 2408 4212 40 3666 2157 5183 2844 4521 2290 921 31 2286 341 1515 338 339 1525 348 1519 347 347 338 348 340 339 1519 340 347 267 275 274 277 2713 4999 1800 4418 848 525 755 526 797 2901 2355 796 198 189 195 199 198 191 189 199 23 188 189 21 24 191 26 190 191 1437 24 26 2623 3510 3248 1716 1131 2535 1911 1560 1139 1974 1140 1138 1146 3032 1138 1145 719 4842 2323 585 750 2604 748 551 2901 578 708 553 585 2355 761 584 4451 4902 4497 4493 501 2355 693 500 663 2355 660 510 801 5114 799 802 3531 5372 3436 1762 2289 3866 935 2400 1172 477 1170 1171 464 1612 1264 1265 754 848 751 755 677 849 536 676 2074 3239 3156 3172 1888 2017 1104 2016 5536 592 494 5531 547 2901 794 546 544 2901 545 796 848 487 573 548 1170 2027 1928 1175 791 3473 789 2901 366 1531 368 358 1160 1161 1157 1159 1881 2871 1083 1995 235 1464 236 237 1625 2196 1918 2049 849 538 563 787 2517 3603 317 2516 1272 1622 1273 472 4171 3007 1916 2039 579 3066 709 2899 1539 386 1538 1212 189 196 195 199 191 190 188 26 188 1438 195 189 1306 193 29 1437 5080 2901 555 763 198 191 190 188 948 3192 1322 1323 2253 4056 37 2258 943 2677 1775 1316 2356 3329 2354 2569 1003 3561 1000 2429 2206 3495 1200 823 64 4643 1344 4282 58 3560 2228 3276 2772 4659 4255 4520 782 2355 786 785 3855 3874 2780 3146 3855 1828 3146 2780 358 1531 360 1527 768 3078 2885 562 737 3078 566 567 360 1531 361 1527 348 1525 351 356 1527 360 353 361 1044 4804 2041 4349 1434 1430 176 174 1039 1654 76 1653 280 270 278 1435 504 2355 503 658 926 1308 923 1307 268 259 262 267 274 1476 268 267 260 2507 268 266 3715 1726 1293 2637 1550 1553 1551 404 1463 1963 1458 232 3970 2911 1102 3969 4231 4845 809 3971 1595 4923 2538 1414 1694 2302 1693 620 1699 627 622 1690 819 4231 639 3480 762 2355 766 765 127 1393 1391 126 2401 1774 1317 2334 1936 4027 1982 1940 433 1583 432 1582 767 2355 528 529 331 2051 1162 1155 4341 4886 4086 2159 1163 3010 1151 1155 1161 474 1160 1156 90 2291 93 91 2291 2470 91 1375 145 1418 144 1417 215 2497 214 1447 860 1708 2148 4199 439 1587 1584 1585 138 2001 141 1086 1026 2574 2213 1350 874 2630 882 2628 1617 470 1616 1269 1117 3070 1555 1121 237 1464 236 234 885 889 16 884 756 848 753 757 3609 3949 3785 2872 1173 3168 2530 3142 58 998 993 999 994 1002 58 999 3644 988 2422 2423 1889 4844 1895 2902 5674 5768 2756 5573 1145 1561 1147 2965 1978 3998 1983 3996 5315 5401 833 832 5194 5973 2781 4118 1138 1146 408 1140 857 855 2608 861 2169 5208 2237 1343 1547 394 1221 1546 171 2272 172 163 1925 3172 3127 2982 3294 1043 76 1041 2812 3576 2041 1355 3476 4678 4365 2273 3078 564 565 783 3973 4846 4824 4774 267 276 275 270 1875 2469 1079 1372 270 1474 272 262 1662 5355 2431 2427 4079 4425 61 4087 4877 2158 3574 4433 623 3205 1202 1203 3078 722 719 2323 1890 3085 1099 2895 1598 1894 1112 1892 1134 3995 3994 1569 844 1699 622 1690 2604 582 581 748 3145 1812 2069 1818 2888 3207 886 2380 4348 4402 620 4401 2899 5299 4839 712 5589 2160 82 4436 2388 905 1691 1692 3813 3514 12 2631 4127 4899 4116 478 2116 2636 886 2137 473 1618 1271 472 3431 4671 3682 3203 331 1515 333 339 596 2323 595 741 216 1447 217 215 206 1443 208 207 199 192 191 193 1967 227 1450 1951 5706 5744 5721 2548 4425 826 3652 4294 3750 5411 924 5016 199 192 198 191 868 3512 2371 3246 915 2393 917 2315 1649 5227 812 3578 4959 2468 2469 2864 320 1496 312 310 3618 3503 4 2369 1835 4531 4292 1019 298 1487 301 1486 1962 2927 1551 1957 5097 5315 2840 4664 1610 1611 461 1262 2355 657 653 848 344 2532 345 1517 352 1522 353 1521 875 2630 887 882 385 1541 384 1540 533 2355 558 489 921 935 31 927 669 2355 509 668 370 1533 364 363 648 2355 499 498 696 2355 545 695 4297 5558 641 4469 3879 2596 2603 842 3338 838 644 643 1524 354 356 1523 627 1699 622 492 933 34 931 930 1523 356 348 354 1526 359 364 367 356 1526 1525 359 3247 3510 3509 1715 2153 4539 2445 1838 359 1526 358 367 1136 3996 1139 1978 3720 3015 1732 2642 2391 4278 2660 1305 2659 4903 1757 2120 577 5299 496 4839 1065 4440 3628 3629 1699 4402 1689 22 1487 290 1484 293 1055 3911 3310 2837 5100 4641 4456 2830 5781 5835 5592 5817 2427 3284 2803 2568 189 188 26 191 914 2311 2303 25 2784 580 711 709 3669 1681 3544 1680 61 5066 4775 4425 2433 4778 1007 2067 487 848 523 548 704 2784 577 576 198 2495 200 199 697 2355 693 848 544 2355 543 694 2061 2090 1178 2083 745 4842 2323 742 1291 2141 880 1720 228 3012 2501 2934 1554 2224 1227 1946 1914 5346 1913 3063 2016 4843 1107 2019 767 2901 528 2355 2282 4375 3262 4365 898 3718 1739 1297 1747 23 21 1750 564 3065 730 728 3661 5039 876 2625 4065 4812 3308 79 4894 5249 2141 4693 1155 331 1151 1163 2029 3111 2035 323 1627 2056 482 1179 1151 331 332 333 4021 2033 3161 2032 1192 4629 4466 638 1601 1603 1602 445 2943 5297 64 3334 130 1878 133 1396 4692 5595 1698 2603 148 2487 1416 147 4465 1746 3359 3442 141 1415 140 138 237 236 1117 234 3576 1044 2812 2041 772 3078 770 773 544 2901 2355 545 139 1416 143 140 1237 418 417 419 2132 4 854 1286 4 1641 853 852 701 2604 699 702 3957 862 1713 865 409 3995 1569 1975 1016 2870 1019 1831 2173 3820 3577 2958 4 4012 2132 3302 315 326 318 323 319 1496 1494 318 323 1503 1502 1500 813 5508 810 630 783 3078 786 782 4712 4861 2662 4406 877 807 10 2626 158 1426 1421 159 2648 1733 1741 2384 1036 2785 1029 1844 1025 67 1013 1020 579 2901 578 708 386 1538 385 384 2302 1304 3524 22 40 1323 956 948 2928 3018 2927 1959 2899 848 751 754 4184 2051 331 3102 3604 1511 1174 4035 2033 1148 1922 1923 820 3471 1197 822 765 2355 530 531 245 1464 234 242 2642 3722 2634 3423 404 1551 1550 403 1998 5346 1963 3063 1965 2944 1913 1135 860 2148 859 4199 1567 1569 1568 409 1963 1463 1458 1142 1345 2433 1343 60 1343 1827 1345 1826 1343 1345 60 63 2048 2785 1853 1847 1108 444 1113 1106 1259 1607 1606 1258 127 1392 129 1391 2007 2249 1890 1600 110 1388 112 111 3440 2167 1073 2466 3407 4436 3586 3585 812 3635 813 816 813 5321 4955 812 557 5080 758 4842 739 5080 740 4842 46 969 959 837 5771 5498 5733 3679 2151 3502 3 2610 239 4337 238 1132 1139 1978 1907 1136 2049 4000 2196 1919 1620 2993 476 1623 2937 2576 995 3558 3062 4037 1916 1499 1388 120 119 118 1390 2478 126 2479 112 2475 111 113 2000 5255 3057 2872 1607 455 1606 1258 136 3079 2813 1102 3404 1967 1450 1896 2901 797 569 793 58 2228 999 1668 10 4687 3696 4652 1001 5741 61 5635 2236 1006 61 2229 1125 4285 1118 1117 1902 3979 1556 3070 2334 2907 1318 2896 3028 3452 232 3344 1229 2956 1966 1565 1081 2608 1710 1876 768 3078 770 2885 4679 5610 5396 4087 3566 4166 3318 609 2337 4749 2095 1798 135 1596 134 1099 46 3812 959 3620 3812 4999 4417 959 5111 4965 4564 3199 1100 441 142 1101 2008 3083 2249 1252 1413 3079 1110 2813 1187 3004 2064 2527 1412 2537 1110 1597 1252 3091 1253 2008 298 1489 309 301 592 3074 768 591 5099 5228 2614 5689 4545 4920 3945 3789 699 2784 701 575 4915 970 2414 1327 752 2604 749 750 2888 4782 3425 2635 975 3268 46 964 3682 922 847 3355 30 2399 32 33 2248 5576 837 970 1037 5443 5442 2558 5092 4424 1000 5053 1854 3938 2453 3189 1846 2447 1852 1356 4222 5837 3897 4952 2445 2786 2446 1030 604 5321 725 605 1913 3029 1135 2944 893 3067 892 897 1 861 1081 855 2699 1322 2405 39 1728 4835 4176 2376 3384 3731 978 642 2048 3415 3285 3410 1710 1081 861 2608 939 3771 834 2678 938 2241 1771 1772 1491 2515 311 303 984 2423 989 985 1335 2730 2721 983 989 5704 4248 5583 5360 4482 5141 5335 5977 6000 5916 5524 1502 1503 326 318 315 1503 1502 318 358 1527 360 350 3971 634 635 809 875 2118 2114 13 530 2355 665 666 2355 765 764 531 719 3078 2355 718 1474 1477 273 271 22 2596 1695 1689 3635 4232 816 2557 3175 2995 3168 2091 2959 4451 3601 2503 2071 1339 995 2937 4410 5110 4953 3539 3718 891 1739 1738 302 2514 303 304 4813 5350 5064 5307 3403 3868 2977 2840 19 898 891 899 891 904 19 899 904 3718 2652 1751 1122 3986 1903 1126 5398 2615 2366 8 279 270 276 271 264 1474 272 265 1131 1562 230 1560 3037 3758 3038 1131 1905 1130 405 1904 4296 1560 1911 2535 2058 4124 1939 3699 339 338 340 1515 3013 3988 1981 1955 1509 2058 326 328 1944 4124 1189 1191 4532 5321 4721 4157 2412 4572 2193 2590 3590 5306 817 2825 2207 5440 5056 1021 288 294 296 295 4544 5121 817 4739 1726 2886 2878 888 133 1095 1091 1090 4075 438 2100 1585 2045 1176 331 1174 1401 2011 1096 134 730 3078 2885 564 875 882 887 13 346 347 338 348 1272 1622 1620 1273 438 4075 2100 1091 272 265 273 264 2901 696 545 546 1474 262 264 272 1412 2537 134 136 1132 405 238 1133 239 1132 238 1133 1972 3039 230 2214 4402 1689 3681 2596 2390 2653 906 2601 4589 1329 4304 3217 904 2294 19 899 845 2390 905 2389 517 849 538 490 684 849 517 516 445 2014 1603 446 2898 3968 3205 623 1143 5349 2951 5147 1250 2205 2087 1588 1217 1543 388 1542 1581 1245 430 431 573 2901 547 848 5321 596 744 2323 493 1658 603 632 596 3078 779 2323 5683 567 737 612 577 5299 704 618 904 3283 19 2294 2351 1207 2273 1208 849 563 588 728 831 5508 832 2582 495 1682 613 642 5099 5502 5138 5228 854 864 4 860 2606 2617 2366 1285 598 2604 492 582 2984 4128 4026 3743 5868 5916 5899 5301 1845 4998 2781 1837 1044 3576 3294 2448 3078 730 733 565 1049 5061 4232 79 312 1496 311 310 1516 342 335 343 347 346 338 349 1281 1634 1633 1280 5595 2243 2603 2672 3640 5400 3858 5101 739 2355 594 738 457 1611 1263 458 823 5034 635 2354 288 287 295 289 4546 4739 4476 4440 3739 4862 1164 4115 3066 4885 712 4839 931 1769 945 933 761 5080 759 762 683 2355 680 520 2355 764 583 532 2898 4303 497 643 380 1633 379 378 761 2355 765 764 4954 617 747 4204 617 4842 4204 616 738 2355 594 593 1890 1594 1100 2895 2355 738 569 568 139 1101 142 441 2355 785 784 541 1988 1083 1881 1880 1986 3088 1882 1883 1098 2011 1409 1596 441 2538 142 1410 685 849 539 684 704 5299 705 619 1714 2606 1708 1285 141 140 139 1085 364 1530 363 1529 363 364 370 372 339 338 341 349 347 338 340 339 708 2901 553 554 853 4199 854 860 3473 848 754 2901 885 4326 16 889 4849 4971 2383 4247 2592 5581 4556 3422 2990 1185 1937 2063 1178 1189 328 1182 329 2996 2527 328 4027 4900 1982 1977 3143 1368 4207 3445 1013 1836 67 1025 68 1350 1349 66 973 4297 4535 4612 1879 1991 1990 131 1637 2324 602 2323 46 3268 2245 1681 971 3805 3116 2713 1951 2915 1115 1450 2024 2523 1153 324 1095 1094 1093 1090 2000 141 1095 1593 5351 601 4885 4839 5232 5455 4634 4617 1329 3155 51 2417 1426 168 161 169 3491 3678 3490 3677 2477 2478 1390 2476 716 5299 600 715 4010 1624 1915 3290 4574 809 808 4231 4601 5093 4889 2380 119 1386 116 111 1853 3571 2047 2785 1270 1619 1618 1271 286 3386 2510 287 1482 83 1481 285 3276 3675 1662 58 522 2355 687 521 1062 1866 1065 1064 1244 1581 1245 430 391 1542 392 1217 2743 3650 58 1667 1331 2419 1329 1333 2202 5125 2199 3823 53 2472 1378 93 5224 1034 2445 2446 2787 5254 3574 4795 1893 3079 1413 136 3261 1032 2792 1028 1781 5353 3073 5767 1842 4695 4516 3086 2813 1413 1407 1110 5024 5025 4675 4937 950 937 944 37 943 937 37 944 3666 40 3539 3394 2677 3196 2695 1775 2515 1489 308 300 1491 2515 310 311 284 1484 283 291 849 535 675 534 849 772 775 776 535 849 675 676 539 2355 849 685 4746 5575 4154 5277 1769 2671 2121 2397 2396 4152 3654 4072 4374 1319 3191 3538 521 2355 683 520 5311 821 641 5234 933 3952 1768 930 697 2901 2355 848 54 4772 56 2913 1716 3695 2144 3510 876 5563 5371 5562 5085 5111 4859 4564 2122 3503 2363 2884 9 1289 1288 1287 158 151 150 147 154 1422 165 157 3511 4687 3700 2968 156 1424 164 155 159 1424 155 158 254 251 244 243 673 2355 515 849 312 1491 313 1490 236 1557 1120 235 1491 304 312 302 313 1496 1494 1495 3193 3620 46 3549 246 236 239 238 1946 3988 1945 1981 3977 4055 1960 2226 236 235 1117 1121 1327 4749 2337 1798 3459 4931 4930 2658 967 1801 49 981 2456 3909 2819 3308 3914 1869 1059 2829 1900 2918 1969 1898 4745 2851 804 3617 1059 2829 1073 1066 733 3074 3065 732 1312 2399 30 1311 801 5508 5487 3611 3363 5357 4099 1760 867 4150 883 3695 2279 5427 4398 1728 3700 4687 3696 2112 4785 5039 2374 4393 1719 3206 3077 2373 5040 2112 4394 3709 121 1393 1391 1392 2633 4395 3695 1724 878 3235 1291 1290 878 2374 881 1719 54 4772 3976 5246 2901 790 792 793 3011 1093 1095 2000 188 1438 189 187 1692 1747 1302 905 844 2877 19 621 3158 3602 86 2833 1056 5589 2176 5445 1051 4261 1050 82 3114 1861 1360 1860 670 849 673 672 1511 2051 2025 1162 1053 3208 1055 2031 331 1155 1151 332 730 3078 564 565 929 3255 28 918 287 294 286 288 826 5066 2577 4425 3078 849 728 563 4719 1201 4386 3330 2163 5614 1780 1781 609 1825 3318 3566 1379 3438 96 97 102 95 103 96 332 1151 333 330 334 1516 342 335 635 3971 809 3472 1176 3126 331 1177 332 4117 1165 331 3928 2823 2455 3910 1151 331 333 1163 942 1774 939 1317 5814 5767 5697 5527 2678 3769 834 939 127 1391 129 128 501 848 654 502 697 848 501 502 848 487 547 573 653 2355 652 650 260 259 263 268 1471 2259 259 260 260 251 254 259 4208 2543 1 3780 3994 5079 4063 1137 5508 4912 629 5487 241 1466 239 240 674 2355 512 511 675 849 671 672 2355 533 674 512 1005 1828 1021 1010 2762 4773 4423 2753 640 5311 833 4845 822 3472 2354 821 92 1380 91 99 388 1543 387 1542 415 1573 414 1572 1231 1568 409 1567 1231 1568 1230 409 1851 2040 1358 1857 5743 3281 73 5303 191 188 198 189 1250 2872 1589 2204 2862 1802 1803 5739 2001 1093 141 1086 1086 2481 138 2001 210 1441 212 213 251 242 253 250 586 2323 724 587 1440 202 194 1439 3492 1207 2273 2351 660 2355 659 658 2355 593 568 491 2355 660 510 509 653 2355 650 505 2355 666 667 663 4804 1851 1846 1358 490 849 563 588 2572 3496 3495 2356 5005 1053 2031 2821 3114 3449 2455 1360 2180 79 1047 2179 849 537 490 517 3435 3498 1312 2874 79 2180 1047 1046 5321 725 722 2323 79 5386 1049 1047 3590 5306 5196 817 575 2899 574 2784 2903 5420 819 3472 3079 1102 2912 2813 3003 4690 2539 3094 1443 216 217 215 548 848 523 757 848 2899 751 2784 751 848 752 755 523 848 524 757 685 2355 681 682 492 5299 2604 598 487 848 547 502 848 501 654 651 848 657 653 656 2355 692 690 689 549 848 757 753 529 2355 528 664 5463 5253 1760 4522 500 2355 693 690 293 1484 282 290 652 2355 649 650 500 848 651 501 650 2355 649 648 506 2355 505 661 777 3078 559 558 576 2899 575 2784 697 848 502 547 4204 601 602 717 3895 4433 3573 2158 1496 320 312 1494 575 3066 2899 789 1149 2197 1920 2033 1497 2520 1500 1502 472 1622 473 471 1159 3007 1157 2972 58 1666 994 993 538 849 563 490 538 849 684 539 428 1576 427 426 2629 4394 2113 3709 1736 3960 1298 2361 721 2323 725 724 2901 848 527 657 108 1384 107 100 1380 101 90 91 3514 3813 12 3704 1005 827 609 64 1024 3135 2213 2783 4109 2969 4037 4010 1835 1019 1346 1833 4254 2209 2357 3993 2792 4321 3884 2172 849 677 536 537 1982 3129 1937 2999 482 1632 1179 481 5114 629 4565 4912 4568 4437 3634 4435 2038 2972 1924 2037 276 267 268 271 108 1386 1384 111 116 1385 115 117 5389 5763 5731 5652 803 5114 800 3879 3885 5059 4796 4197 7 3226 806 4174 207 214 211 206 2458 4002 2177 2457 282 2251 285 283 1364 4893 1064 1865 493 2957 1658 632 691 2355 521 520 1535 1531 368 366 1210 1537 379 1536 503 2355 498 486 211 203 204 206 3078 772 770 2885 202 1440 196 204 3957 3655 2614 1713 244 254 243 247 1499 2035 323 2029 587 2323 603 493 2781 2788 4998 4031 5257 901 5025 4701 1174 4101 2045 3181 4022 4899 4116 1164 1927 4116 2982 1925 3240 3231 1725 3122 1167 4899 1925 1165 1242 1579 427 1578 2897 3317 2022 3085 1179 1632 1181 1178 135 1596 1099 1098 5002 5135 4416 4414 136 3079 1102 3082 4331 3441 2648 3729 2327 2541 624 2271 645 3659 831 646 4614 4263 3543 3848 718 2355 583 558 2323 779 2355 3078 2375 5373 2628 5354 599 5425 807 598 3232 890 894 1733 65 3874 3133 3867 5426 883 867 5040 880 1720 876 1291 4136 3173 3606 3605 776 3078 777 849 1186 3000 2096 2529 1167 335 332 331 565 3078 783 780 457 1611 456 1610 460 1613 459 1612 125 2477 123 1389 123 127 124 126 128 1390 118 126 696 2901 2355 697 119 2479 2478 1390 4386 4256 2209 4258 2370 4477 2134 3364 693 2355 692 690 870 3248 1716 2623 1481 2509 83 1482 4628 3466 4133 4279 1003 2753 1821 2429 5680 4314 3821 5671 284 2251 285 81 972 5402 1328 968 1961 1122 1126 402 1584 1586 435 438 1244 1581 1580 1245 4449 1125 1126 237 1903 3986 1959 1126 4603 817 2824 3590 1489 301 300 299 317 2517 315 1492 3406 3408 3179 962 325 4109 3007 1161 766 5080 2355 762 2901 507 657 527 4023 2074 3172 3239 3126 3172 2998 3053 1157 325 1161 1156 189 1436 186 23 2538 441 142 1100 5292 4280 961 2701 1594 2813 134 2537 646 5693 2603 5114 2686 3771 939 2678 5110 2679 2329 2332 4300 5528 4157 3550 2684 3377 940 936 941 4577 2679 3774 2498 1453 1448 1452 216 1447 215 214 231 2499 1457 230 221 2498 218 1452 1448 2498 1452 1449 219 2496 221 220 55 4756 2222 983 2735 4717 4249 3840 1434 183 174 1374 354 1523 357 346 1582 436 437 435 433 1583 1247 434 466 1617 465 1616 4955 3635 2557 4596 6053 6095 1699 6081 333 1515 341 339 2365 4196 3505 2608 5201 5342 4009 5461 4 1286 864 854 1712 2617 2366 2615 1747 1302 905 1300 3018 1970 1127 3984 904 2652 891 2651 3529 4405 3451 3527 1122 1961 1126 1903 5065 1958 1127 4449 1893 3082 3079 136 860 853 4 854 860 853 859 4 1087 2483 1984 132 1397 1403 131 1399 1994 1092 1084 2873 4157 5321 1682 613 1966 3995 410 1565 5536 494 637 5531 2901 573 547 794 232 4966 4296 3452 3313 5344 4871 1276 4894 5249 1720 2141 897 1736 1735 1298 903 2389 2129 905 724 2323 603 587 5928 5903 5849 5927 546 2901 795 545 5321 4623 4955 4206 85 1066 1058 1059 1569 3994 1976 3043 2851 2548 804 2547 3709 2113 2629 3516 202 1440 205 1439 202 1441 205 204 204 1440 196 203 2429 1003 1823 1821 1520 344 352 1521 380 1634 1633 378 1802 3174 2203 2719 94 1381 102 95 3312 1056 1859 1051 1329 3551 1330 3467 988 2729 1808 1807 2729 1807 1336 2313 2728 3843 51 3099 5378 5764 5537 5180 81 2300 83 1363 1858 5589 1050 4436 1647 1837 2189 3188 1481 1482 285 287 4106 4595 3915 3627 268 267 262 271 1443 208 216 206 2115 5563 807 878 5922 5917 3713 3724 866 4687 1715 2623 2623 3510 1715 866 4336 3240 3122 3231 601 5299 716 4839 1736 4555 1735 3497 4782 4849 2280 4726 3704 4697 3813 12 1775 2687 2677 943 1071 2852 1078 1871 1639 4854 1638 3902 1 861 855 857 842 3262 2594 841 2493 20 2491 2492 187 2386 1436 18 817 4603 603 3590 2017 3969 1105 1104 3274 3804 2835 3588 1051 817 604 82 4130 5289 2715 5866 3078 783 780 782 599 5299 7 2619 3472 5311 5223 2354 4458 4996 4611 1835 4828 5683 4042 612 266 269 2259 2507 5491 2354 636 5223 3574 5223 5058 2445 3395 4432 2942 1672 1109 3082 1893 1103 3369 323 324 3370 4135 2994 2999 4032 477 1172 1170 1177 4566 4024 3175 1169 535 849 775 776 327 3698 1168 326 1631 481 1278 1630 2064 2527 2063 1187 1627 2068 482 2056 1815 3847 1337 997 1683 3338 2898 643 536 849 537 774 1337 4126 1815 1338 781 2355 785 784 3752 3829 2724 2079 4355 998 993 992 3853 1340 2428 57 1818 3557 1812 2740 752 2604 751 749 750 2604 749 748 5080 4204 747 4842 3940 1046 1856 1049 326 4686 2060 3699 1361 1860 81 1360 76 1048 1040 1359 625 5212 4473 4590 1855 2818 2450 2816 2355 671 672 669 2716 4469 4157 4532 2700 961 2269 2411 675 2355 671 849 2422 4921 4248 2423 4741 963 961 2099 2760 4523 847 3209 231 1560 230 1462 332 2051 331 1155 332 334 331 335 2979 4502 3053 4117 2030 3105 3008 323 1918 1919 1158 1924 1917 2035 2029 1149 2033 4021 2971 2032 328 3144 1178 1179 1252 3091 2008 2908 479 3694 2195 3169 1105 3970 3969 2911 1307 4407 2344 1310 142 1416 139 150 1085 140 139 1089 1101 140 139 142 5281 5283 52 5125 977 1803 987 979 3826 2428 1822 2066 1803 3829 1811 2715 3793 4544 3264 3799 5538 4195 4736 4478 2611 2148 1706 1282 2459 1062 1362 1065 2550 1642 4 2133 4612 5050 1795 973 2824 1062 817 2165 3264 4666 4544 3793 212 3600 1444 2496 621 4986 2652 5295 3646 4540 2569 826 3289 4140 1662 2354 3565 3867 3855 3146 5048 3668 836 3667 960 5437 5049 2701 2268 2926 2407 2108 44 3798 2410 42 568 2355 491 543 4585 5116 4552 4777 1994 3950 439 1993 242 251 252 250 43 5637 957 955 235 1464 243 236 3408 5366 4137 5292 1958 5065 1127 1559 480 1944 1189 1191 1183 2090 2083 1182 1983 3996 1134 1978 1630 1632 481 480 1461 4063 4043 2503 1632 481 482 1631 766 2355 529 530 2886 4782 4762 2635 2636 3207 886 2137 888 2637 1293 1726 194 1440 1439 197 581 2604 748 749 3016 4342 1559 4059 5836 4082 2877 2384 7 3513 806 3226 7 2135 863 862 4204 616 2679 617 698 2604 549 700 1966 3995 409 410 698 848 573 548 1973 3998 3996 1976 2784 711 714 715 2393 2657 915 2392 797 5080 569 2355 308 2515 311 307 1496 319 1494 1495 311 2515 310 307 1493 2518 318 2519 1075 3390 2851 1079 2477 2478 123 1390 1841 2797 1034 1842 5823 5766 5776 3810 419 1573 1235 1572 414 1570 411 1571 4646 3056 3368 3059 959 3620 969 46 3846 5050 4529 2706 4417 4999 975 959 351 1525 359 356 343 2532 1517 345 671 2355 511 510 1515 332 333 330 2355 671 669 510 777 2355 558 533 221 1453 1452 229 2935 4061 3990 1129 1483 2298 1366 84 2511 1483 2298 1366 1075 2469 1080 1079 3930 2106 4017 5084 4460 3425 3229 3518 1071 2834 1068 1069 4325 4946 4198 4808 1169 3001 2098 1939 1278 1631 1630 1279 1447 223 1445 1446 92 1381 99 102 219 2499 220 1451 223 1445 225 224 92 1380 93 91 1807 3099 1808 2728 1806 1808 1807 988 2472 53 2421 51 545 2355 544 695 5034 822 2354 4239 733 3078 566 737 501 2355 848 693 1196 4362 635 3483 5316 2169 5109 4884 5080 747 571 743 3777 3850 2765 37 136 1595 134 1113 1413 2813 1407 136 1315 3377 1316 936 3777 940 2681 2765 701 2784 704 576 4410 2679 616 4056 622 2604 707 552 1695 2596 845 1689 362 1528 354 1524 354 1528 357 1524 347 1524 356 1523 1489 2515 307 299 3473 5080 788 2901 2355 4842 595 2323 1634 1281 484 485 322 1498 1497 325 1518 335 336 334 337 1518 335 336 334 1516 335 332 619 3825 3209 28 1478 1535 376 366 848 756 753 752 756 848 757 524 848 525 756 755 2912 3079 1109 2911 2912 3090 3003 2911 145 1418 143 144 148 155 146 147 150 1416 147 151 158 148 159 151 928 3750 2669 3534 3965 443 2022 3317 5088 5405 4541 5122 190 1437 24 191 2788 5254 1033 3573 2006 2908 1252 1110 1591 3321 139 2536 1997 140 1591 139 1645 5677 4687 2112 3430 3717 844 891 1801 2718 49 981 1100 4453 2007 1600 286 1485 284 294 736 3065 733 2885 2245 4418 975 4417 3000 1186 2096 2098 959 1800 975 1792 1871 2839 2023 2463 1365 4562 1072 1368 3014 4178 3692 2428 1069 1071 88 1068 4362 5420 3471 820 1659 3471 1198 1197 2743 995 997 2427 2758 5363 3567 4244 271 1474 262 263 276 270 267 271 5683 5311 3578 5321 1563 3037 1911 1971 1142 1964 1909 1963 2535 4503 2950 1911 2312 3976 1816 2319 2901 754 578 527 1837 1027 1033 4197 775 849 536 774 1641 4 853 1640 2901 547 697 546 859 4199 853 860 874 882 13 2375 2505 2506 249 247 2391 3624 2657 2393 998 3847 3560 3352 70 1647 1022 1027 838 3338 644 1700 613 2248 837 1682 1406 126 127 128 1403 1406 126 1402 128 1393 120 118 1305 4381 1306 1754 1393 128 120 1391 123 2479 126 2478 714 5299 598 2604 190 1437 192 24 4130 5289 4765 2726 4706 1112 4217 4096 1752 3451 911 25 5420 635 4362 3471 848 524 654 523 635 5311 811 3472 76 2183 1045 1048 1623 1620 1273 476 5322 5132 4814 5118 5351 496 4885 617 4246 4991 4970 4369 5321 603 724 2323 3908 4442 2836 2162 1489 298 306 300 298 1489 306 309 2832 4441 1063 2161 81 3922 2297 2827 753 2604 752 750 3023 4876 34 4051 940 4273 2689 2690 1967 4090 1896 3404 2453 76 1048 2183 1699 4848 2605 3879 1284 4324 3876 2782 4769 5218 5496 1786 3654 5161 3854 4646 2975 4723 4712 3764 685 2355 682 686 2253 3765 2684 936 5016 4334 3749 4714 623 3968 2541 3338 1027 3188 1022 1023 3495 2356 3329 2354 1022 2441 1647 2156 13 3204 887 2882 4795 3885 4944 4192 2275 2635 886 2886 1725 2630 887 875 300 1488 299 292 1485 1488 292 291 302 1488 295 294 413 1568 1567 411 285 2513 1484 284 1487 292 299 291 1488 2515 299 302 408 1569 409 1134 229 3404 1448 226 1474 1477 272 273 271 262 268 263 270 278 279 275 2191 1052 2820 4812 1655 2812 1044 2561 1036 1029 73 1037 963 5048 4984 836 5292 5637 4771 5559 2701 5366 3104 3406 477 4454 1172 1173 331 334 1167 335 3053 3172 2982 3127 4477 3626 2149 4113 2679 4995 4288 4953 4650 4047 4457 3349 3092 3762 3363 31 2757 4646 3059 3760 116 1390 115 118 525 848 656 526 849 516 681 515 848 525 656 655 525 848 756 524 684 2355 685 849 681 2355 515 679 1257 1605 1604 1256 1609 458 1608 1260 455 1607 1606 453 938 2241 1772 1773 1319 2402 1780 2330 3660 941 2686 942 1005 4880 1015 64 439 3997 1250 440 818 3971 2903 819 3139 3699 2058 1939 1942 4069 1512 3372 2098 4124 3180 1191 4496 4136 3236 3173 1512 3006 2528 2525 3643 3711 2672 3437 5299 492 627 1646 1042 5627 5443 5442 2899 5299 712 2784 2298 2511 1366 2465 1367 2465 2298 1365 1068 2464 2462 2105 3879 800 803 625 696 2355 695 692 7 873 865 869 1173 2530 334 1514 334 1516 331 342 4962 4222 1353 4952 2288 31 927 1762 496 1698 618 647 5412 5571 923 5570 4407 5412 1308 925 10 599 867 866 4461 4088 3515 4158 3074 770 772 3065 1708 4188 2606 1714 925 4672 3753 3856 2666 5016 2664 2667 3577 3820 1041 2958 692 2355 691 689 4024 4116 3169 4022 3181 3747 1932 2992 155 148 146 156 2272 170 1423 1427 1422 164 156 162 254 244 251 255 250 244 252 242 1477 279 270 1435 279 1477 270 271 5299 716 712 715 706 2604 702 703 148 158 159 155 2967 4171 4092 3120 4039 140 1997 139 154 148 156 146 159 148 155 156 158 148 147 155 1976 3996 1134 3998 1210 1537 1536 1211 382 1536 383 1210 383 1536 1211 1210 386 1538 1212 385 392 1542 1216 1217 3030 5321 605 3295 3338 623 628 798 2390 5024 906 900 1545 395 1544 1218 394 1544 1218 1219 398 1546 1220 397 398 1547 1220 1546 398 1546 397 396 2911 3082 1102 3079 1549 401 1548 1222 401 1549 1548 399 3205 3413 2893 1203 2499 219 1453 1451 1550 1553 402 1551 1225 1552 1224 400 219 2499 1453 222 2928 1961 1125 1957 1573 1234 415 416 1837 2055 2189 2845 3085 1890 2249 2895 2916 3977 2917 2930 3413 3673 2271 2893 1959 2928 1903 1125 232 5346 4966 1134 443 3083 442 1253 409 3995 1134 1569 415 1570 416 1232 2380 5299 4074 2603 419 1572 418 417 420 417 1237 1236 1236 421 422 420 421 1575 420 1574 421 1575 1239 422 428 1576 1240 427 424 1574 425 1238 425 1574 1239 1238 1238 1575 1239 421 5080 713 717 556 1578 431 430 1242 431 1579 1243 1578 427 1579 1243 428 1244 1581 430 1580 430 1581 429 1580 4887 5087 4783 4608 434 1580 1245 1244 436 1582 437 1246 1246 1583 1582 1247 440 1584 1248 439 1583 437 1582 1247 1399 1403 124 1397 1249 1586 1248 437 439 1587 440 1584 1586 1249 436 437 1298 5256 897 1740 1086 3950 3069 2002 3985 1123 3984 1122 1985 1885 1590 1883 136 1103 137 1893 135 1594 1099 134 448 1601 449 1255 1255 1602 1254 445 452 1604 451 450 452 1605 1256 1604 1609 1261 454 455 5111 4752 4564 4965 2604 752 751 848 454 1606 1258 1259 461 1610 1262 460 5117 5472 3761 2675 4073 2675 3854 3654 461 1610 460 459 464 1612 463 462 464 1613 1264 1612 469 1616 1269 1268 470 1616 469 468 469 1619 468 1618 473 1619 1618 471 5080 790 793 570 1272 1622 472 1620 472 1622 1273 473 1620 1623 1622 474 766 2901 763 767 476 1620 1273 1272 1274 4000 1275 475 2036 3062 2065 1149 1919 2540 1918 1150 1918 2972 1924 1158 2197 1149 1920 1624 1992 2197 1624 1275 3159 5344 2061 4871 3142 4028 1514 1930 3770 4873 3320 4725 5306 5307 817 1061 485 1631 1279 1630 485 1630 484 483 747 4842 746 743 858 3221 1282 856 380 1634 1280 1633 313 1496 312 1494 380 1633 1280 379 1707 3257 2782 2126 3949 4868 1092 4077 858 1706 1704 1282 2980 805 2363 2550 1878 4868 4077 133 837 4526 3846 3549 858 1704 856 1282 3819 5157 2573 2773 3421 5036 3923 1284 2 3923 3 0 3252 4521 70 3934 2611 1706 858 1282 3282 3808 2792 2172 854 4942 864 860 4 4012 2369 2132 3697 3701 2624 8 1286 4942 854 1285 3214 3249 2362 3504 1642 2550 4 2549 3729 3430 1734 2648 2371 1351 868 2620 11 1287 9 8 3027 2168 950 1779 2343 5422 1307 30 6 1289 8 1287 9 1289 11 1288 8 11 1287 1289 2626 3614 877 807 9 1289 1287 11 3844 5044 3396 1787 2626 3614 807 3339 1290 2142 1721 1722 2888 3734 3019 1699 2631 4691 12 3813 1292 1720 1291 9 4689 5371 5252 1291 5110 2329 2851 2332 1290 9 12 1292 2279 4837 2376 4637 2141 1291 1292 1720 4950 3247 4008 4330 4395 883 4150 1724 1294 1295 12 1293 1639 3787 2857 1638 888 1294 886 1293 1692 4886 3442 2159 1293 3715 2637 1295 1726 3715 1293 3237 3735 885 16 2922 894 2645 2381 2283 1740 897 1298 1736 2361 1736 1740 1298 3736 5024 4675 906 5140 5415 897 5256 2884 3504 3503 2362 1738 891 898 899 894 2284 1296 890 904 3072 2652 2651 897 1735 893 1298 904 3718 1751 891 3858 5184 2914 4160 2131 3960 2361 1299 5806 1325 5045 1789 20 2646 1299 2385 2661 5565 3742 5261 871 3882 868 7 2650 905 2389 903 3718 1739 2647 2127 187 2491 2386 18 2162 2832 1061 2825 3523 3072 19 2651 19 3523 2651 621 905 1302 903 1300 903 2295 905 2129 5571 4160 923 2287 20 4013 3738 18 907 1303 902 910 3525 2391 915 2660 4160 5571 923 5267 914 5432 5264 5417 1303 1304 902 910 3525 4278 2660 3210 4162 4443 3592 3789 4890 2909 1111 3974 2665 5267 926 4160 1437 4381 26 3598 27 1306 193 29 2665 5267 923 926 2395 923 1307 926 2288 31 1762 1760 925 1761 922 1308 4407 5412 925 5241 1766 4714 3750 4707 2344 4407 2340 1310 4666 5105 4546 5095 2146 3962 1763 1764 2400 3866 935 2599 1764 2662 2146 2394 4042 5580 5287 2222 1307 4407 1310 1309 3966 4406 2343 2668 3431 4409 3203 3532 2340 5422 2344 1310 5422 2343 4408 30 921 1767 31 935 934 1312 932 1311 33 2399 32 35 3403 4817 3868 2840 2672 3711 647 3437 936 4301 1316 3766 1777 2680 945 2333 2672 3022 934 2757 30 2399 33 1311 2688 3535 3485 4373 1311 1314 934 1312 37 3278 950 1673 1764 935 921 927 2760 4985 847 4523 3447 3504 3214 3503 940 4273 3377 2689 1316 4273 2690 1776 2683 2686 939 942 1316 2687 943 2677 3465 4619 3424 4359 3609 3949 1084 3785 1767 3866 2673 3762 1767 2290 31 3762 2334 2401 2335 1317 2675 4048 2240 3761 3660 941 2679 2686 938 2401 1774 942 3623 4618 4577 3774 938 2401 942 941 4458 5190 4996 1835 3781 2685 33 2682 1319 3391 949 951 3391 3783 3540 2403 3540 3772 835 3399 40 2265 948 1678 1677 1780 1321 951 1679 3783 3666 2260 2352 1677 2255 2163 3539 4410 2324 616 951 1321 949 1319 39 2694 41 2109 3798 2702 3356 2410 4212 4919 2408 3980 953 3192 948 956 1782 2402 2110 1783 41 1786 44 1324 4281 5199 5185 4989 3396 5515 5035 4412 1782 2110 1778 1322 42 2405 39 1324 2585 5044 5035 43 39 2699 41 2405 2269 2411 961 614 5292 961 2099 2702 5293 5929 5047 614 1326 2410 1325 42 1325 1790 1326 1789 5238 1328 4915 4749 3981 2249 3083 1253 1328 2337 2095 1796 37 2258 937 2253 972 1796 968 1328 4749 5402 5238 1328 3548 4295 2710 2707 2317 2419 1333 1377 2095 2708 1796 2337 1329 3213 980 1332 980 2419 1329 1332 980 1331 978 1329 2291 1330 1375 1377 1329 3551 2419 1330 1377 2904 2416 50 2252 49 967 1801 2862 2868 2085 2415 2747 4913 2316 4628 2316 5204 4913 2250 1377 2317 50 1333 5189 4530 4253 4167 1329 4934 2868 4304 979 2565 52 2203 1329 1333 980 1331 4528 5211 4576 5123 48 2712 50 2711 3552 5291 54 4763 2797 3894 2310 3381 2301 3400 2849 3198 989 1807 985 1336 2313 3836 2314 2729 3327 3839 986 2733 4756 4270 3827 4755 1810 4976 3834 990 2208 4880 3334 4430 1809 2730 2721 990 3842 4237 3814 2747 5578 5582 2722 2423 1812 4911 1817 1340 4720 5268 4062 5186 990 2721 1810 1335 1807 989 985 984 1820 4140 2431 2854 984 1807 988 1806 3830 3555 2725 2732 1820 4140 2854 4134 994 2227 1666 58 828 5508 4912 830 4912 638 639 4472 2066 3141 1340 1824 997 1815 1339 1337 1667 2743 2225 992 4778 1009 1007 2067 3347 4649 2858 4193 997 1339 995 1337 1814 2937 1813 2223 995 3558 997 2427 2576 825 997 3558 1379 2913 56 2424 2602 3342 2215 2392 1341 1817 994 1340 3851 2066 2233 2754 4126 4911 1817 3145 3720 4849 2922 16 1666 3650 58 2227 62 4423 1342 1822 1823 5294 1000 5053 3490 4624 3488 625 66 4864 68 4786 1345 2433 62 1827 65 1827 1826 1345 5016 2667 928 5411 4079 5830 5396 5829 2572 3495 823 2354 4785 2374 2625 807 5167 3653 3677 4084 1283 4199 2148 1703 2354 2572 636 823 2574 2444 1026 2213 1019 4610 4531 4292 1833 1346 1016 1019 1018 1832 1014 1347 1018 4260 1347 1014 3133 4636 3333 2770 66 1346 63 1348 3286 4185 1664 1665 1026 1349 4751 1350 5476 1349 5705 71 68 1349 71 66 872 4669 4390 3455 3758 2217 1911 3037 1026 1350 1024 1349 4779 4751 66 1350 2283 4834 2645 2381 868 4792 4668 2619 868 3570 1351 2371 868 3570 2371 3512 3696 5111 2619 4979 842 3262 841 2605 3251 3809 3806 2788 1028 3282 1032 2792 1843 1029 1036 1037 5223 5311 811 5552 3281 1029 73 2172 1042 5743 1853 5627 2173 3176 1850 1357 1030 2797 1841 1035 2448 1038 76 1044 1031 1841 1354 1035 3572 2555 1032 3260 1030 2446 1031 2786 3752 4757 3829 4694 1039 1654 1038 76 335 4350 2530 1169 5443 2785 2047 1843 1851 2447 1846 2046 1178 2090 1182 2083 1043 1357 1041 1355 2621 4352 3455 4186 2453 5321 3295 3578 3176 3454 3453 1357 1359 3115 3044 1048 4804 1044 1039 4349 1049 5061 1046 1856 1358 2818 1857 2046 3001 2098 1939 3045 1359 3118 1040 1358 282 2251 283 1479 3107 3449 1360 1861 1479 3583 1480 2508 288 2512 1483 289 1362 1866 1062 1364 2297 4893 1364 1865 84 3602 1363 2510 1364 4893 1866 1064 1064 1865 1060 1364 1062 1364 1064 1060 2461 1058 1066 2828 1051 3908 2034 3584 4207 87 3445 1365 4735 1869 85 3931 1072 1367 1070 1365 1877 2852 1078 2292 1072 2465 1365 1368 1365 2465 2298 1366 84 1483 288 1366 1059 1869 85 1073 4134 3167 3563 2430 1869 3440 1073 2846 1367 2465 1365 1369 2512 87 288 1366 4562 5229 3868 1072 2542 1071 88 1078 1178 3040 1179 3144 1365 1369 1072 1367 4896 4938 4510 4511 1075 2469 1079 1875 1015 4520 3872 3870 1075 1875 1079 1874 1079 1875 1372 1874 2296 2469 2468 1371 1076 1875 1080 1075 3302 4 1641 1640 4549 3101 2051 2025 4545 4920 1081 3945 4111 4295 3379 3663 1987 3095 1995 1083 1075 2104 1872 1873 4444 2 89 1373 2839 1871 2023 1877 1875 2910 1372 2859 3612 1079 2851 3390 1875 2469 1372 2296 2910 3948 3594 1372 1918 1152 1924 1151 184 174 182 1374 183 1434 174 175 183 1374 182 174 2291 90 93 53 1819 2745 2070 2721 90 2291 91 1375 2720 3546 2711 2705 2471 1376 1375 2470 1375 90 53 1377 50 1377 90 1375 1330 2419 2317 1377 1665 3468 2223 1339 2421 2473 1378 94 94 2473 1378 95 95 2472 94 92 1381 92 99 2474 1380 1383 101 99 98 1383 1380 100 99 1380 91 101 1381 1384 99 102 98 1383 1382 101 1383 108 109 107 106 1383 100 108 106 1383 108 109 101 1382 109 1383 106 1383 98 100 1380 1383 99 100 1384 1386 107 110 100 1384 107 99 1381 1384 102 103 111 1384 103 110 116 1386 1385 108 114 1385 116 117 114 1385 108 116 1386 118 116 115 1386 108 1384 107 118 2479 1390 1393 1384 1386 110 111 1386 116 1385 115 1385 1386 107 108 1388 120 121 119 112 1388 1387 113 112 1388 120 1387 1388 120 118 1386 113 1387 121 1388 112 1388 113 111 1388 1386 110 120 1386 1388 119 118 1386 1388 110 111 1393 121 120 119 128 1393 1390 126 128 1393 118 1390 2480 124 125 122 128 1393 126 1391 2477 3596 125 2476 119 2478 2476 1390 127 2479 1393 126 2476 125 123 124 2480 1399 1394 1398 124 2480 1399 1397 133 1396 131 1394 124 1403 1402 1400 1399 1394 133 131 1397 1396 131 132 1396 1397 131 1394 904 3414 3072 1688 133 1987 1396 1878 124 1402 127 1400 131 2890 1096 2483 1401 131 134 1096 125 1399 1398 133 123 1403 1399 131 1394 1399 133 1398 1394 1398 133 1395 1584 1587 438 1585 125 2480 122 1398 1249 1586 436 1584 124 1399 125 123 1394 1399 1397 131 127 1403 1402 124 1403 124 126 123 1399 2480 1394 1397 127 1403 126 1402 135 1402 134 1400 126 1406 127 1402 1406 134 135 1402 132 1400 131 1397 131 1401 134 1400 1403 1397 131 1400 134 1401 135 1400 135 1596 1409 134 131 1401 1400 132 1406 134 1403 136 136 1403 126 134 134 1406 1403 1402 2894 3084 1098 2897 127 1403 124 126 131 2011 1096 1410 136 1407 137 1404 131 1403 1400 134 1404 1406 1405 129 1406 1407 134 1404 1101 1887 1100 441 1403 1406 136 126 128 1406 1404 129 126 1406 136 128 136 1406 1404 128 134 1406 1404 136 1407 2537 1412 136 3060 2000 1095 1593 1407 1406 134 135 135 1412 134 1407 1405 1407 1404 137 1880 1991 1990 1882 2536 1408 139 1592 4923 2539 1595 2538 1880 3088 1882 1250 3964 1098 3084 2892 134 1409 135 1401 442 3317 3084 3085 142 3096 2538 1100 1596 135 1409 1098 1087 1991 1883 1882 135 1594 1412 1099 1410 1984 1096 131 1099 1596 134 1594 3768 4690 1894 1892 1102 3970 445 1103 3404 1450 229 1448 1888 2019 1895 2016 134 2538 142 1414 2539 4923 2813 1594 136 1412 1407 134 4097 3091 2813 2537 1892 4890 1891 4097 136 1413 137 1407 2539 2538 134 1595 4217 4706 4096 3003 2485 4091 1411 3428 141 1415 149 147 148 147 146 1415 149 1415 146 147 141 1415 138 149 142 1416 150 143 147 148 151 1416 142 1416 143 139 143 1416 150 151 139 1416 147 150 143 1418 151 150 2488 2489 1419 153 1417 1418 144 152 145 1418 1417 143 143 1417 145 151 1417 2488 153 151 1417 2488 152 153 143 1418 150 142 1417 2488 151 1418 160 1426 168 161 160 1421 161 1420 161 1420 1419 160 1419 152 160 1420 158 2489 1421 1420 160 1426 161 1421 168 1430 169 1426 154 1422 157 155 155 1423 163 164 155 1423 1422 163 1423 162 164 1422 162 1427 173 165 165 1423 1422 162 155 164 163 1424 164 1425 167 172 175 1428 1425 174 156 1424 155 159 164 1425 1424 167 175 1428 172 1425 166 1425 174 175 166 1426 158 167 167 1425 1424 166 1426 2489 159 161 167 1426 158 159 168 1426 1421 158 160 1426 1421 168 162 1427 165 1423 170 1427 173 162 175 1429 174 183 172 1429 171 1428 164 1428 1425 172 172 1429 1428 175 174 1429 182 183 169 1430 176 177 175 1429 1428 174 167 1426 169 1430 1430 1434 177 175 174 1430 166 175 1431 1432 181 173 1431 2490 173 170 172 1431 178 170 179 1432 181 171 164 2490 172 170 178 1432 181 1431 1685 4667 1686 2605 1432 172 178 171 183 1433 182 179 180 1433 1429 183 184 1434 185 176 1430 1434 175 174 176 1434 185 177 1434 1374 184 185 183 1434 185 1374 280 1477 1435 281 279 1435 278 270 1853 2047 5443 2785 4425 4540 826 4294 189 1436 188 187 21 1748 23 1747 189 1436 21 188 1436 189 186 187 2493 3963 1748 2386 191 1437 193 192 1438 1440 197 195 194 1440 1438 196 195 1438 187 197 1440 194 1438 197 1440 204 205 203 202 1440 204 205 197 1439 205 1440 202 1440 194 196 1438 1440 195 196 1441 205 204 203 212 1441 204 211 202 1441 213 205 210 1441 204 212 208 1443 216 1442 1443 216 215 214 1443 214 206 216 209 1442 217 1443 208 1443 209 207 214 1443 207 215 214 1443 206 207 210 1444 213 212 218 1444 221 210 1447 214 222 2497 214 2496 219 222 2917 2226 2534 1226 222 1445 223 224 216 1447 224 1445 217 1447 1445 1446 223 1446 225 1445 1447 216 224 214 224 1447 214 222 2496 219 221 1444 223 2497 222 220 220 2498 1453 1451 229 1450 227 1448 1450 1451 228 227 1453 1448 229 227 1450 1451 227 1448 1949 2500 1114 1950 223 2499 222 1457 1451 1454 228 227 222 1453 219 227 1448 1453 229 1452 1448 1452 229 1449 220 1453 221 219 1453 2499 1451 230 2928 3018 1123 2927 1448 1453 1451 227 220 1453 219 1451 230 1453 222 227 1453 2498 1448 1451 230 4041 1454 227 1128 4061 2935 3038 1451 1454 227 230 1458 1457 1456 1455 232 1458 233 1455 1562 2214 1972 230 224 1457 225 223 224 1457 232 1455 232 1457 222 230 1457 1458 230 1455 1964 1463 1142 1141 1457 1455 225 1456 224 1457 223 222 4267 611 3831 3991 1969 1954 1896 1951 1458 1457 230 231 231 1462 230 1458 1456 1458 1455 233 1136 1979 1461 1137 1901 3012 1119 2923 1897 1949 1114 1948 1562 1460 231 230 230 1460 231 1454 1567 1569 408 1568 4493 3048 3344 4066 240 2503 239 241 237 1464 245 243 1979 1136 1907 1978 3063 4063 4043 2956 1461 4085 2959 1907 1910 2219 1142 1963 232 1462 1458 230 3758 1128 3038 1131 1560 3344 3050 1561 232 1463 233 1458 244 243 242 1464 236 1464 243 244 245 1464 242 243 237 1464 234 245 2505 2506 1467 249 241 1466 240 1465 247 1465 241 249 1568 413 1567 1230 239 1465 241 247 1465 2505 249 247 1465 2505 248 249 239 1466 246 238 1465 2505 247 1466 256 1472 264 257 256 1469 257 1468 257 1468 1467 256 1467 248 256 1468 254 2506 1469 1468 256 1472 257 1469 260 2507 2259 268 250 1470 253 251 258 1470 250 252 1471 258 260 1470 258 1473 269 261 261 1471 1470 258 1472 2506 255 257 263 1472 254 255 264 1472 1469 254 264 1474 265 1472 256 1472 1469 264 258 1473 261 1471 274 1476 267 277 279 1477 281 1435 266 1473 269 258 270 1474 262 271 268 1475 274 266 1476 274 268 1475 1475 2507 268 1476 274 1476 277 1475 1477 1474 272 270 272 1477 281 273 280 1477 281 272 376 366 374 1478 375 1535 366 367 375 1478 374 366 4022 3150 1164 4115 2251 282 285 83 1361 1861 83 1860 2615 5689 5502 5398 1860 1361 81 83 1861 3583 1361 1479 2251 2508 1479 1480 1361 2251 1479 1480 1481 284 287 285 284 1481 287 286 3602 84 1363 2833 286 1482 1363 1481 1363 3602 1482 2510 1485 291 284 294 84 3602 2510 86 286 1482 1481 287 86 2510 84 1483 1483 3386 288 289 290 1487 1484 292 291 1484 283 293 290 1487 1486 293 1487 300 301 299 298 1487 292 300 298 1487 300 301 293 1486 301 1487 298 1487 290 292 1484 1487 291 292 291 292 299 1488 1485 1488 291 294 303 1488 295 302 300 1488 292 295 1492 3603 306 314 1489 2515 308 307 306 1489 308 309 306 1489 300 308 1491 312 313 311 304 1491 1490 305 314 1492 317 306 304 1491 312 1490 1491 312 311 310 312 2515 302 310 305 1490 313 1491 304 1491 305 303 2515 1491 302 303 312 2515 1491 302 311 1493 307 310 308 1493 307 311 356 1529 1526 364 308 2517 307 1493 310 2519 1493 1496 320 1496 318 1494 320 1496 1493 318 320 1496 310 1493 318 1494 319 320 2519 316 315 319 319 1495 321 1494 311 2518 2516 1493 319 2519 1496 318 2516 317 315 316 1497 1502 323 1501 3805 4111 2713 3816 2466 5613 2842 5593 2683 5469 3771 3374 1500 3373 1497 323 1162 2025 1511 323 323 2523 324 1917 2029 3111 1992 2035 323 3369 324 2524 2521 1503 318 1505 1510 4907 327 1166 318 1502 315 323 1501 323 1497 325 1497 1501 325 1498 316 1502 317 315 1501 2520 1502 314 1504 326 323 1503 1497 1502 1500 323 2521 318 319 2522 326 1502 318 323 1502 2521 1500 1503 3739 2998 3053 2028 1508 326 327 1505 327 1505 326 1503 1503 2521 318 315 1504 3370 1503 323 316 2521 1502 315 2982 3128 3053 3126 326 1504 327 1503 1157 3007 1161 325 1505 2522 318 2521 2527 2994 1185 2526 318 1508 326 328 328 1508 1506 320 1411 4217 2486 2485 1506 1508 1507 321 321 2522 320 1508 1509 329 328 1506 329 1509 1507 1506 2075 5488 2076 3463 320 1508 1506 321 318 1508 328 320 1508 318 326 1505 326 1508 1506 328 1509 327 1508 326 327 1513 326 1509 5607 3153 3694 5334 326 1510 327 1504 4136 5170 3173 4702 2051 331 1162 1511 1180 2084 1178 2083 1191 3180 2098 1943 3006 1512 1181 2525 46 4417 3268 975 1630 1632 1631 481 1509 3139 326 2058 2059 4032 2058 2999 2061 4029 328 2059 1191 3180 1943 1944 332 2531 1515 331 333 1515 330 341 339 1519 1516 340 340 2531 1516 339 1516 1519 343 340 1517 2532 342 1521 337 1518 336 1517 343 1518 1517 342 343 1518 337 1517 1517 1518 344 342 1517 1521 342 344 343 1518 342 335 1517 1518 336 344 336 2528 335 337 352 1527 360 353 335 1518 342 334 335 2530 334 1169 347 340 348 1519 348 1525 1519 351 1519 1525 347 350 1516 1519 342 343 339 1519 347 350 345 1521 344 1520 352 1527 353 1522 350 2532 1522 1521 2532 343 1517 342 1520 2532 345 1521 350 2532 343 351 348 1523 346 347 346 1523 349 347 354 1523 346 348 359 1525 350 358 2389 3442 3359 1745 357 1524 1523 354 347 1524 355 356 364 1534 372 363 356 355 347 1525 1525 351 359 350 356 1529 355 1526 1519 1525 350 351 358 1526 366 367 359 1526 1525 358 1527 2532 351 353 359 1527 350 351 360 1527 1522 350 358 1527 350 359 352 1527 1522 360 362 1528 365 354 2234 362 1528 365 364 1534 1530 372 354 1528 365 357 364 1530 367 372 364 1529 1526 367 364 1530 1529 367 367 1530 366 375 364 1534 363 1530 367 1530 1529 366 359 1527 361 1531 1532 1533 373 365 1531 1535 369 367 366 1531 358 367 370 1533 363 373 364 1532 370 362 1533 370 364 1532 375 1534 372 1530 1532 2533 364 1533 370 1533 373 1532 371 372 374 1534 363 1534 372 371 375 1534 374 372 376 1535 377 368 1531 1535 367 366 368 1535 377 369 1535 1478 376 377 375 1535 377 1478 1536 1537 378 381 382 1536 381 383 379 1537 380 378 383 1537 1211 1536 1537 1211 379 380 383 1537 1536 381 379 1537 378 1536 1538 1539 381 384 1213 1539 1538 1212 385 1538 1212 1213 382 1539 383 381 382 1539 1213 383 1213 1539 1212 383 1539 382 1213 1538 382 1539 381 1538 1215 1541 1540 1214 389 1540 1214 388 388 1543 389 387 389 1541 1540 387 1215 1541 385 1540 387 1540 384 1541 1215 1541 1214 386 385 1541 386 384 1542 1543 387 390 1542 1543 392 1216 391 1542 390 392 1543 1216 388 389 1543 1542 392 390 1545 1219 391 392 1219 1545 1544 1218 395 1544 1218 394 395 1545 1544 393 1219 1545 391 1544 393 1544 390 1545 391 1545 392 390 1546 1547 393 396 1219 1545 1218 392 1221 1547 1546 1220 397 1546 1220 1221 394 1547 395 393 394 1547 1221 395 1548 1549 396 399 398 1547 1546 396 394 1547 393 1546 1221 1547 1220 395 1223 1549 1548 1222 400 1548 1222 1223 401 1548 1222 400 1549 1223 397 398 1223 1549 1222 398 397 1549 396 1548 404 1550 1224 1225 400 1552 399 1550 400 1552 1224 401 881 3077 1719 2374 1225 1552 400 1550 1551 2927 1123 1952 1124 2930 1952 2927 1125 1959 1126 1903 400 1552 401 399 1124 2927 1967 2916 1553 3977 1118 2930 1551 2930 2927 1952 1553 3977 2930 1551 1960 4285 2226 1555 1553 1550 402 1552 1953 3977 2917 403 2534 2917 1116 2916 1967 4090 4049 1896 4285 1227 2920 2534 1119 3988 1945 2923 1118 4285 1960 1117 1896 2918 1898 1969 3988 1947 1981 3036 1946 1114 1902 1899 4052 1905 1130 2932 956 2924 2408 2263 1117 5013 1559 1958 405 4059 1558 1557 3012 3988 1129 2934 236 1557 235 1121 1899 1949 1114 1902 1962 1957 1551 1553 1127 5065 1459 1558 1958 5065 1559 1117 5065 1559 1117 1121 1968 1127 1558 1559 4425 4775 5054 5066 4285 3076 4049 2916 4144 3114 3310 3208 1131 2535 1462 1563 1127 1968 1558 1459 1557 5065 1558 235 1115 1948 1899 1900 5135 5528 3550 4157 405 4874 4266 230 1142 4450 3607 3608 1968 4059 1558 1459 231 1560 1462 1131 1998 1228 1909 1910 232 1561 230 1145 1560 4329 1911 1132 1904 3757 405 1905 1147 1561 230 1560 1458 2535 1462 232 2963 4493 2959 4066 1147 1561 1145 230 231 1562 1131 1128 2938 3046 3038 2935 231 1562 230 1131 3988 4052 1981 1955 1910 3608 1142 3607 1560 2939 1131 1562 1229 2950 1911 1971 1131 2535 1563 1911 3037 1971 2217 1911 1141 3029 1912 1135 1566 2939 1911 1132 3063 4040 1229 1998 4066 3344 3028 3048 3758 1566 2218 2940 2938 1128 1972 2935 2938 3046 1980 2218 1229 3037 2217 2936 2217 3758 1911 2939 413 1567 1230 1231 412 1567 411 413 1567 1569 409 408 1567 1568 408 411 1978 3998 3996 1139 1466 247 246 2505 1966 2956 1913 2944 1137 3995 3994 2956 416 1571 1570 414 1232 1571 412 1570 412 1571 413 411 1232 1571 1233 412 1232 1571 1570 1233 1234 1573 1572 1235 419 1573 1572 417 1234 1573 415 1572 417 1572 414 1573 1234 1573 1235 416 415 1573 416 414 421 1575 422 420 1574 1575 420 423 1574 1575 425 1239 424 1574 423 425 1238 1575 1574 1239 1575 1574 425 423 1576 1577 423 426 1241 1577 1576 1240 427 1576 1240 1241 424 1577 425 423 424 1577 1241 425 428 1577 1240 1576 1577 424 1241 1576 428 1577 1576 426 424 1577 423 1576 1241 1577 1240 425 431 1578 1243 1242 1242 1579 1578 1243 431 1579 1578 429 427 1579 426 1578 429 1578 426 1579 430 1581 431 429 427 1579 428 426 1242 1579 1243 427 1580 1581 429 432 1580 1581 434 1245 433 1580 432 434 1581 1580 434 432 437 1582 1247 1246 437 1583 1582 435 1246 1583 433 1582 435 1582 432 1583 433 1583 434 432 1246 1583 1247 433 1249 1586 1584 1248 439 1584 1248 1249 2879 4075 3955 1091 3997 2204 439 1251 2001 3950 2481 2872 1408 3011 133 1095 2501 3012 1129 2934 1585 3069 1993 439 436 1586 435 1584 3055 1986 443 2205 1587 1248 1584 1586 1086 2879 2001 1093 1587 1584 438 1586 1250 2205 443 1986 1883 1986 1590 1985 1881 2087 1880 1083 1084 4077 130 3785 2205 1588 1250 1251 2000 5564 3060 5255 3138 3965 1885 1096 1987 3095 1878 1995 2871 1881 1083 1588 1881 2087 1083 1588 1588 2018 1250 1881 1991 3953 3088 2536 1590 1986 1882 1250 2022 2889 2010 443 2019 2902 1889 1895 2536 139 131 1410 140 1591 139 1089 1991 2482 1879 1082 140 1591 1089 1088 139 1408 1095 1592 1880 2018 1990 1991 1883 3953 1590 3088 1083 1990 1082 1880 139 2000 1085 1593 1593 2536 139 1592 1593 2536 1089 139 1593 139 1095 1592 1592 2062 1095 1593 141 2000 1095 1093 1089 1593 139 1085 3921 3588 2835 3804 1093 2001 141 2000 2435 4087 64 609 139 2000 1593 141 441 2538 1410 1594 2539 4923 1595 2020 135 1594 134 1412 134 1596 1410 1594 134 1414 1113 1595 1412 2537 1594 134 2538 2539 134 1594 2286 3092 31 2290 441 1596 1100 1594 1102 3080 136 1106 1414 4890 2021 2020 4243 5001 1253 3768 1598 5001 2007 4453 1409 2011 134 1596 1410 1596 441 1594 1098 2894 1596 1099 1407 2537 1110 1412 3442 4886 4465 2159 2022 2895 1100 2894 1598 1892 1111 1891 1411 3428 2484 2485 3363 4160 4099 2603 1252 2912 2006 1253 1599 3970 446 2014 3597 3969 3090 2911 3970 1102 445 1603 4890 1892 1111 4690 2890 3138 1885 1096 448 1601 447 449 1601 1603 445 444 1601 1602 444 447 444 1603 445 1102 449 1602 1254 1601 2486 4091 3428 144 3970 1599 1105 2014 1257 1605 448 1604 450 1604 447 1605 448 1605 449 447 1257 1605 1256 449 1606 1607 450 453 455 1606 454 453 451 1607 452 450 455 1606 1258 454 451 1607 1259 452 1259 1607 1258 452 1607 451 1259 1606 451 1607 450 1606 1261 1609 1608 1260 458 1608 1260 457 458 1609 1608 456 1261 1609 454 1608 456 1608 453 1609 454 1609 455 453 1610 1611 456 459 1261 1609 1260 455 1263 1611 1610 1262 460 1610 1262 1263 457 1611 458 456 1611 1610 461 459 1263 1611 1262 458 460 1613 1264 461 464 1613 1612 462 1265 1613 460 1612 462 1612 459 1613 1265 1613 1612 1264 460 1613 461 459 1265 1613 1264 460 467 1614 1267 466 1614 1615 462 465 467 1614 466 465 463 1615 464 462 463 1615 1266 464 467 1615 1267 1614 1615 463 1266 1614 467 1615 1614 465 463 1615 462 1614 1266 1615 1267 464 1268 1617 1616 1269 470 1616 1269 469 470 1617 1616 468 1268 1617 466 1616 468 1616 465 1617 466 1617 467 465 1268 1617 1269 467 1618 1271 472 1270 1619 1270 469 470 471 1618 468 1619 469 1619 470 468 1270 1619 1271 470 1620 1623 474 1621 1620 476 475 1272 475 2540 1919 1150 3290 4000 1274 2540 1621 1159 474 1157 1924 2993 2052 2053 1620 1622 471 474 1621 1623 474 1159 1620 1623 1273 1622 1621 2052 2037 1623 3102 4038 2971 3101 1132 1147 405 4266 3058 1626 1155 1154 1148 2033 1922 2032 3763 4151 3201 3639 1147 1132 405 238 2059 4032 1509 2058 1920 2030 1992 2029 1164 4899 478 4103 4021 4107 3161 2033 2971 2024 1153 2026 2530 3175 334 1169 1166 5333 4907 5330 3140 4028 3142 1930 3159 6039 2061 6023 1169 2060 1191 1514 334 2528 1943 335 3606 1942 3159 3605 2998 4022 2073 3739 4351 2999 3002 3129 3149 2194 1276 2947 5517 5754 5608 5502 1630 1279 484 1278 485 1631 1630 483 481 1631 1278 482 1178 3163 2080 2082 1181 3163 1178 1632 483 1630 480 1631 3163 1181 1178 1180 3040 4900 1277 2068 1278 1631 1279 482 1179 1632 1178 481 1632 482 1179 1181 1633 1280 379 1281 1281 1634 484 1633 378 1633 483 1634 7 2551 868 2621 484 1634 485 483 1281 1634 1280 485 1703 1709 1708 1283 1282 3502 1706 2494 2108 3792 2268 2926 3507 3462 862 3121 2888 4609 2380 888 1367 3110 3042 1070 961 3978 3800 1325 855 2123 1638 1 2367 4980 4788 2614 3130 3075 2126 2363 857 2608 1705 2365 1075 2104 1079 1872 2106 2840 2324 2323 1959 1970 3018 4285 1 3309 1635 2543 898 3718 891 1739 602 3304 2547 601 3304 4545 1638 1 2857 1077 1639 1074 4917 804 2851 3936 2860 4896 4732 4854 1758 3746 2661 2659 2867 4919 4210 2408 3501 859 2611 2148 3247 4950 4008 3509 4 2132 854 1640 2130 3618 4 1641 1707 2884 2126 2782 4017 4514 88 3930 860 2133 864 4 860 1642 4 859 1283 3502 1706 1282 7 2619 868 2551 860 2133 4 1642 3249 4533 3447 4189 600 2551 2135 1643 869 2551 1643 7 7 1643 869 863 4306 4923 4890 1414 4646 2757 3059 3368 5426 883 2112 2187 4687 5561 866 10 3549 5558 5168 4655 13 2114 875 874 2275 3207 1699 627 1147 3048 2965 1561 2155 4521 70 3252 1027 1648 70 1647 5995 6021 5994 6006 2155 3574 3252 70 1941 3144 3005 3040 2781 4802 3888 4118 1851 2046 1358 2040 2160 5445 5064 2176 2185 2954 76 815 80 2450 78 75 2183 76 1045 1655 2155 4521 1022 70 2189 70 1647 4521 658 2355 503 508 3625 3897 2801 2556 606 3901 3171 2171 5627 1037 5442 1029 1042 5511 1651 4513 1038 2178 76 1654 714 2604 582 581 2452 3044 1855 2188 76 1653 1040 1039 2098 4350 1169 2530 2418 4530 976 2202 829 5114 645 644 2182 76 1359 1854 1655 76 1045 1044 2183 2954 76 2562 75 74 77 1849 1067 5445 2176 5064 5292 5638 5559 4137 3585 4436 3586 2948 1858 3109 1859 1050 3908 1051 2034 1868 5321 2457 812 2557 3582 3999 3796 2948 3273 4735 1073 85 603 2165 817 1658 493 2106 632 1637 85 2166 1058 1864 1870 3267 3100 2462 3471 635 1196 1197 3343 5724 5355 3751 651 2355 500 649 1660 3495 823 1199 634 5420 635 1195 5034 3495 2175 1660 2447 2810 2043 75 652 2355 848 649 3327 986 2727 982 1822 4423 1342 3692 3439 3562 1000 3561 5133 5479 5696 5762 1002 1820 1341 58 1830 4423 62 1821 3563 4140 2432 3280 4167 2415 2200 3389 2911 3082 1109 1103 4757 2724 4241 3314 2568 2427 825 1664 3363 4692 1698 2603 2543 4308 4145 2860 2424 3148 2312 1816 1664 3558 825 2576 5693 2679 5397 2329 4581 3658 3942 3831 3351 3388 951 2404 4518 2783 3343 2444 2078 2220 2071 1813 993 1667 992 58 4753 4430 64 4880 3391 3783 2403 949 1668 3276 1662 58 2431 3033 1002 2854 592 5536 494 562 4774 5316 5208 5134 3332 4386 2357 2209 1006 61 4775 2236 3454 1850 3176 3453 1670 4282 4172 1004 2254 2684 936 2253 67 2211 1013 1012 710 5080 713 2901 4428 3340 4426 4264 5056 5440 1005 1021 3566 3456 1344 1825 4586 5222 2354 636 2854 4140 2431 3033 2432 3280 2170 2754 1780 2330 1321 1319 2355 661 662 659 4947 1674 40 2584 956 2926 1323 2867 1782 2109 1322 1788 956 1785 1323 40 1322 2699 2108 1788 1311 3202 934 1313 5464 5674 3537 2580 4842 602 717 4204 3101 4549 2051 4038 3200 2629 877 2627 2258 37 937 1779 5315 2584 4919 3197 4947 40 3540 3539 2543 4308 2860 4729 949 3388 3351 3134 1678 40 947 948 4896 2866 4575 3194 1678 3666 40 2265 5515 5682 5035 5452 2109 2402 2110 39 2107 3351 2257 2692 1676 2404 1677 2163 3258 4464 2793 4343 1679 3783 946 40 1325 3978 2270 2411 1681 3669 3544 3268 3544 46 958 2749 43 5737 5637 955 2718 4299 3664 2739 2250 2718 981 2420 4991 5397 5200 5272 5223 5355 2445 3574 800 1700 798 624 602 5351 4204 2332 4661 2341 1204 838 3172 4023 3127 2073 5557 5331 3200 5031 2355 781 594 784 886 2888 888 2635 3869 5427 4398 2378 1736 4555 3497 1737 3240 4336 3122 4114 2275 4849 4782 4762 5415 4508 5337 3067 4198 1731 2383 4182 2273 3492 2351 1686 878 2374 1719 2115 1732 4080 895 2382 2305 4635 4385 3453 625 3632 2345 3631 841 4380 2349 3491 1564 3719 1144 3009 2390 2807 2389 845 5299 496 3711 1698 552 2604 707 551 3297 4293 3578 3299 845 2601 2390 1695 26 5565 5261 24 2995 3175 2984 2091 910 2656 1303 1304 920 3371 1759 2286 492 5299 627 2604 4074 13 2375 3238 2341 3672 3093 2893 4509 5720 5098 4245 19 3523 621 1699 3442 2295 1745 2388 2677 4143 1779 3275 903 2295 1302 905 2632 3705 879 3108 5086 3195 4896 4938 3736 5025 4701 907 1301 4937 4383 2119 2596 4402 1689 2603 5199 3536 1317 4989 2653 2119 1747 1300 4937 5024 4383 4675 5920 3954 5851 1699 4086 4465 4341 3359 621 2302 620 22 1695 2807 2390 845 2965 1146 408 1145 4920 2849 3400 3198 3359 2293 1746 2766 910 1695 22 907 2361 3727 3216 18 1747 2653 1300 905 3533 28 913 929 618 2287 847 1698 912 3528 28 2764 4472 638 4231 4224 1798 5032 2337 1327 1764 1767 921 935 4620 2661 3525 3742 2534 4285 2226 2916 3761 4876 1675 34 2347 2891 839 2345 620 1699 621 22 705 2604 702 706 819 4231 3971 639 70 4877 2158 3574 3413 3968 2271 2541 2679 3665 3387 834 50 2906 2904 48 840 5114 1700 644 2784 699 698 574 1692 4886 1691 2388 858 3221 4 2611 621 2389 22 1699 2374 807 1646 2115 621 2604 706 707 628 4303 2898 3338 855 2123 1 1705 852 2130 4 1641 3135 1024 2213 1350 2364 4196 1705 4076 2494 1707 1706 1704 4751 4779 66 4427 4727 2782 3212 3876 1706 2494 1704 1282 859 4199 2148 3599 5299 620 705 619 1022 70 1023 2155 200 2495 201 199 1706 1707 858 1704 3075 858 856 4 2152 3075 2362 2126 5191 5259 4943 4189 4815 2150 1284 3047 1024 2783 2213 2444 3256 3502 2610 3047 3502 3256 1709 2150 1703 2606 1708 1709 2608 855 1081 861 5714 5502 5608 5688 2608 2863 1876 2849 2608 4920 2849 1876 1710 2608 857 2365 864 2369 2133 1636 3077 4180 2374 4088 3931 4108 3679 2841 706 2604 703 707 2329 5693 5381 2603 5766 2556 5511 5060 1351 3570 1717 2371 2368 4190 1285 1712 3235 3515 2373 3206 2551 600 2135 599 1286 4190 4179 864 862 4389 865 7 3240 4336 4114 4181 4010 4037 3007 2039 4389 3462 3508 3121 2366 2606 1285 3 1709 2148 1283 1706 3248 3695 3510 867 2371 5398 3697 2624 2603 5550 2876 5015 1716 3695 883 1724 2969 1921 2035 2036 870 3695 883 1716 3705 877 3200 3614 1289 2371 1287 6 3 2617 2151 5 3258 4464 4007 2961 863 4788 865 3957 3697 3701 8 2371 3503 4960 2881 2603 3462 3507 862 3506 2128 4556 3422 2592 3518 4045 3019 3229 2373 3235 878 1290 2373 4180 3206 3515 5355 5223 5311 2354 3705 879 2633 2632 4393 4598 3661 4364 3108 4150 879 877 1292 2141 9 11 4181 4336 1294 3704 5251 2142 1292 1722 1291 2141 1292 1722 1874 5020 4607 2855 4836 4114 3958 4560 1290 1722 1291 1292 875 2630 882 874 2142 5251 1292 4860 3821 5248 4149 3706 2968 4008 3247 3700 880 4689 2141 1291 1290 1722 1721 1291 3655 3508 3462 4462 1290 2142 1722 1292 1292 2631 2142 12 877 2629 879 2627 1002 3851 2854 3033 2116 4181 1294 2546 1728 2377 884 889 2851 3788 3304 1 1699 3019 2888 2790 1294 2637 1295 1293 1690 5176 844 1699 1293 1727 888 1294 2634 3220 895 2638 15 3715 1295 17 1728 5427 4398 2276 3938 1854 3030 3123 2116 888 1294 886 1294 2637 1727 1295 2592 5560 2128 4556 1295 4396 3237 15 892 2644 2277 2136 888 2886 2878 886 1728 2376 2279 884 2638 3517 2377 2634 2114 4074 3238 13 1737 4555 3726 2128 4396 17 1743 1729 4637 4398 4176 2279 893 844 892 1730 4229 5177 605 4881 889 5427 1728 2276 1295 4396 1293 3237 2283 4347 4328 3730 1732 2642 2634 895 1299 2646 1737 2385 896 5176 892 2143 4120 5010 895 3904 1984 4291 3965 441 3724 4556 2128 4555 1743 3726 3724 1737 2392 5015 2603 2598 908 1752 4402 4401 26 5565 24 23 2284 4345 3218 1297 890 1733 844 894 5942 5298 5592 3934 894 3218 1741 1742 3067 3725 893 3723 19 3729 2593 3520 871 3882 2960 3117 890 3232 894 1734 3430 1734 2648 3232 1733 3881 2648 3232 1741 3218 2284 2648 1735 897 893 892 2422 5582 3649 5288 1736 896 897 1735 1296 3218 1297 2284 891 1738 904 899 1731 4080 2383 3720 1166 5607 5333 5334 4696 5926 3517 4396 1436 2493 23 2386 3500 1742 1296 2381 4321 5837 4952 4962 4345 898 3729 2593 1742 2381 894 1296 894 2648 1733 1741 891 1751 904 1738 894 3218 1296 2284 3710 2463 3494 2023 4347 5836 3730 3219 891 1739 1738 898 3441 1734 890 2284 3500 5726 1742 4956 1299 3216 18 2361 1299 3216 20 18 5140 3723 897 3067 3441 890 2640 2641 2679 4550 2755 3775 1741 2283 894 1742 1742 3500 1296 1297 1686 4678 4365 1685 1743 4209 1737 17 3809 5982 2050 2781 1301 4937 2119 1744 4044 4702 4496 4302 902 5025 4937 907 3527 4709 4648 3744 4675 4937 2119 4383 2390 3448 2650 2387 891 3072 19 904 903 2389 2293 2129 5199 1317 3374 4989 1692 4382 2159 1302 2389 4465 3359 3442 23 2386 21 1436 1749 2649 1303 21 1744 3522 1750 1301 4072 2121 1769 4152 906 3521 2653 3448 1744 1750 1749 1301 2386 23 21 1748 4342 3443 3070 4059 914 25 3741 2311 1850 4818 2173 4385 23 1749 21 1750 907 1749 1303 910 2649 1744 1749 1303 2596 22 1695 2390 728 3078 564 2885 1739 3718 1738 2127 874 3514 875 2630 4493 4966 3719 4043 3525 2660 2120 3210 1752 3451 25 2597 4402 2596 3681 2603 1684 3680 1699 2790 2697 1787 957 4147 1305 1754 1306 1753 3435 932 2672 934 2878 888 886 1293 1754 5430 1306 1753 2235 5742 2231 5651 2392 5590 5146 5395 1306 3598 1437 29 3354 4332 3209 2876 4381 1437 26 24 4623 4955 4206 813 913 1766 929 1756 4160 2287 618 1698 4403 5221 5096 4658 3745 918 28 3688 913 1756 929 918 3745 5484 1755 912 911 2655 1752 2654 2655 4930 1758 2654 3533 4332 3429 3754 1303 3524 1304 2656 1983 3452 3032 1978 2655 5264 2654 911 4930 2658 914 3459 67 2942 2216 2211 920 3531 3436 1762 1728 4398 4176 2276 5264 2655 2654 4930 3435 3763 934 2672 919 5417 3459 4930 574 3473 3066 791 2680 1777 1769 2671 31 1762 920 927 646 5114 843 645 1699 2604 620 621 935 2400 2358 2289 31 2288 927 935 3473 709 712 710 2687 937 1784 2677 1308 2344 2340 1761 5422 2344 1310 1307 4926 4927 4099 5357 1308 2340 925 1761 1762 920 927 1763 921 2662 1767 1764 2289 4833 2674 2400 1307 2343 1309 1310 4714 929 3533 913 4861 2394 4406 3622 3938 5321 5177 3030 3092 2286 31 1760 5116 4803 3900 4099 1307 4407 926 1308 3433 2603 646 3098 2682 3367 1773 3320 929 4714 4334 1766 2117 3750 1766 2670 3763 4552 3900 2805 2680 931 2671 1769 1078 3595 2292 3185 3951 4585 3639 3920 925 5241 4718 3683 933 5572 1768 2240 4876 2243 3761 1675 5674 5768 5573 5655 3076 2916 1124 4049 1763 3530 3436 920 3318 4471 609 4166 933 2580 34 2240 4152 2675 4048 2240 2242 4152 2675 3654 2662 3920 1770 2676 1767 1770 935 1764 3763 3951 2874 3900 925 3682 1761 3431 938 2686 2679 941 1774 2401 941 1318 1772 3770 1771 2238 1007 3656 2067 1009 938 2241 1773 941 4990 834 3769 939 941 1774 1318 1773 2691 4014 2121 2671 2238 938 1771 1772 931 2680 34 945 2241 938 1771 941 943 1776 1316 1775 838 3968 3093 3672 3376 4994 4291 2022 937 2687 950 944 1096 4291 2011 2892 938 2401 941 1774 1316 3776 3535 1776 2334 2401 1318 2335 1676 3540 951 3539 2690 3535 1315 1316 952 4728 947 2693 1006 5616 5584 2762 4273 1315 940 3377 3655 3957 3506 1713 4432 2216 3343 3878 2671 1769 2121 1777 2924 4919 2408 1674 4160 5400 5184 2914 5682 5663 3197 5338 4728 947 2693 953 835 2795 1676 2583 1321 2352 2255 2107 1779 3275 1784 2677 4384 2159 1692 4382 38 4081 36 3073 1782 2693 1322 1778 3973 4824 3676 3362 4382 1748 2353 4384 41 2405 1324 39 2262 43 615 2267 1778 1783 1782 1320 2108 2698 2405 2268 1782 2110 1322 2109 1783 2110 1782 2109 2265 40 1323 1785 3197 832 2584 2794 3388 1321 949 951 937 1784 1779 950 1323 3192 1322 3124 3197 5321 615 2323 2265 40 948 1323 956 3792 3124 2926 2686 5469 2678 2679 2408 40 956 2263 2264 4919 2867 2924 4927 5455 5339 4634 1676 3539 2404 3064 2109 2699 1322 1788 4160 3363 1698 2603 957 1787 43 954 2796 4516 3086 1842 2710 4457 2246 3349 3792 2264 2867 2924 2405 1786 41 1324 3178 1325 2094 2270 3408 5292 960 2701 961 3978 1325 2411 1790 47 44 1326 5943 4738 3112 5046 2028 4021 2981 2026 47 1790 1789 1326 1326 2410 44 1790 4787 21 1749 1303 3409 4320 1325 2411 3978 961 2700 2411 5679 5592 5379 5476 2245 3544 3193 46 5944 2445 4539 2154 2262 43 955 2261 959 964 1792 975 4771 5559 957 2697 5943 2097 3805 1800 3801 1680 3544 1791 2709 2710 971 2246 1325 5870 5806 5045 5292 5638 4137 3408 4212 4919 3539 2408 957 5637 4771 955 3355 4523 3857 847 405 4627 4041 1956 2262 2269 43 2261 2712 1799 3811 3545 968 5576 837 2706 3833 4526 2741 4415 968 4529 2706 837 2708 4840 2337 2095 2530 2098 1191 1169 2881 5946 600 5736 4579 3379 3663 1796 972 4749 2095 1328 1327 2712 1799 2093 2930 1124 1952 2917 4915 4673 2414 4468 5194 5691 5195 5533 4299 981 2718 3664 1797 2093 1327 1799 1327 4749 1798 1797 2718 5123 2739 3664 2093 5032 1327 48 3092 5328 4522 4993 2410 3800 3182 1325 46 4417 959 3812 3805 5943 959 4738 2679 4656 1675 617 3382 1331 978 2861 1070 4817 2102 2840 4628 2747 2737 2316 978 3326 2716 980 2733 5052 2567 3839 3948 2855 87 3143 5281 52 2199 5125 5801 5761 5583 2731 979 2862 977 1803 2868 3155 1332 2417 3950 3997 2204 2873 1807 984 988 989 2201 4419 2422 2945 984 2422 2198 1804 55 3291 990 2221 1198 5034 4967 4239 988 2423 989 984 1807 2728 1808 2726 984 2198 1805 1804 3647 4610 1019 2870 3155 2715 2726 51 4435 4657 3305 4568 2201 4419 988 2422 2201 984 1804 988 2198 5149 2422 4850 2423 985 984 2722 982 4268 986 2727 4969 824 2722 985 5151 5291 54 4272 629 5508 5487 630 2472 4445 53 1378 3644 988 2423 989 3845 3345 55 4768 4565 4224 638 4472 2313 2729 2314 1336 2079 5740 5669 5805 2721 990 1810 1809 2357 3815 2356 2569 3323 2733 986 2725 2721 4271 1819 3845 998 4911 993 1817 4527 5124 3841 2567 4415 4529 3379 3833 4272 3464 2729 2731 809 5311 4845 812 822 4809 825 821 3662 5656 3380 5522 2735 1806 1805 2201 3839 986 2725 2734 5076 4461 4088 4481 2715 1803 2085 1811 2049 3125 1919 2053 4257 5331 4018 4393 2723 4694 3554 4420 993 1817 999 998 828 5487 5114 4912 3557 1815 1338 1337 1338 4911 4126 1812 4079 5092 4425 2357 3374 5199 4989 5185 3558 2937 2223 1813 498 2355 518 486 2174 2858 996 2575 3828 3837 3157 2721 5941 5907 5886 5878 3758 1972 1128 1562 2721 3147 2070 2751 3677 5106 839 4582 825 2427 997 3558 59 1379 56 1816 4772 54 3976 2913 3352 2425 998 3556 5021 3167 4178 3014 56 2424 1816 1379 3280 4140 2170 3289 59 2424 1379 1816 1341 1817 1002 994 4126 1815 3847 1337 5054 1009 3656 4425 994 1817 1002 999 2740 1812 1818 2069 3168 1514 2060 1169 825 3560 997 2427 4776 5043 3429 2667 2730 983 990 991 4458 4751 66 4427 2567 5052 4828 55 994 2227 58 1341 2354 2568 1662 822 4679 5347 4936 3183 2468 4959 0 1371 2854 4134 2432 2430 715 2784 711 712 1668 2431 58 1662 1011 5742 5651 5634 3809 5982 2781 5540 5439 5635 1006 5438 1340 3151 3141 2066 2432 4178 3563 3014 3973 4492 3676 4064 1822 62 59 1342 2577 5053 1823 1669 3293 3578 2560 606 4492 4064 3973 3652 2066 3357 2430 3151 3145 1824 1340 3141 1930 3140 1173 3142 2740 3145 1812 2069 59 2428 1342 57 1004 1344 64 1825 609 1004 64 1825 3697 5398 8 2624 3653 4582 3631 625 5447 5674 5397 5655 2907 3781 33 35 5524 5301 5899 5916 4824 3676 4778 3861 4924 2673 2290 1767 3033 2170 2431 1662 1831 4906 2212 2870 1780 5614 2330 3187 3046 5414 5268 1980 4425 4540 2357 2569 2618 4792 2622 2619 3432 5753 5023 5324 4784 5297 2208 4880 65 4483 63 1345 3279 4220 3941 4146 1344 4282 1004 64 2758 5363 4244 4484 1345 2433 1827 1343 5362 5742 5634 5584 3605 3173 1188 3236 3960 1736 1298 3497 4265 4619 3624 2392 5092 1669 3646 2570 1829 3859 62 1830 58 2431 1002 1820 3387 3852 2679 3375 855 4933 3593 2608 4638 3647 2356 2573 672 2355 669 670 2438 4260 1018 1014 1019 2437 1016 1831 4432 3395 2942 67 2425 998 3560 3352 2942 4790 4432 67 1014 2571 1018 2438 4781 827 3864 2439 1017 3855 1015 2780 2797 1841 1354 2308 5414 2938 1980 2940 65 2307 1348 63 1346 1833 1016 1347 1347 2307 1834 1832 2214 4266 230 1560 1346 4292 1019 1835 1018 4260 3873 1347 4425 4988 61 4087 2250 4913 2316 1801 2307 3133 65 1834 1026 1349 5476 71 933 2580 945 34 2054 1346 1833 1835 1346 1834 1833 1347 1346 2054 1833 1834 637 5592 5355 3343 4428 5157 4431 4487 1346 4786 66 2778 1346 2771 2054 1834 2443 2441 1022 2156 2783 3992 2213 2574 5815 3942 3658 3831 2786 5965 1031 1030 1027 4998 3188 1023 1027 3188 1647 1022 1030 1841 1034 1840 4433 5975 5058 4877 1030 2446 1034 1035 2446 1030 1034 2445 1030 2154 1839 1838 2153 1030 1838 1034 1837 2781 2055 2442 1030 2797 1034 1841 5963 3159 3165 5913 2740 3145 2069 1340 2218 4061 3038 3046 2308 3086 1842 2796 1031 1841 1035 1030 69 4865 1349 71 1029 1844 1843 1036 5974 5826 5891 5946 2412 5731 5293 3193 2796 2797 2308 1841 2310 3894 1842 3089 2958 3176 1357 1041 25 4100 2303 2304 3251 4795 2788 2787 2781 4865 2055 2442 5554 5442 2558 2559 1349 5379 1024 1026 1036 2785 1844 1353 1846 4804 2041 1851 2796 2797 1841 1842 3803 5728 5518 2800 2781 1837 2055 1845 1179 482 481 2056 1358 2818 2046 2450 4804 2041 1356 1846 1789 4020 1325 3800 5683 2445 1650 607 1044 4804 1039 1045 2812 1848 1043 1355 3571 3906 72 2305 1176 2045 1932 1174 1042 4513 2181 2809 5226 4275 3575 3385 1036 2785 1353 1029 72 1849 74 75 2457 3308 2819 3909 4314 5248 3821 2817 2881 2134 5155 3684 3577 1850 1652 2449 1846 1852 1851 1356 1849 3454 2306 3453 2048 3285 1042 2809 1857 3118 1358 1851 5540 3809 2050 5129 1852 2046 1851 2040 2450 2817 1855 2816 76 2954 1649 815 2562 1655 76 2183 1851 2046 1846 1358 2305 2785 2048 1847 3176 2958 1357 2173 2048 3571 1853 2785 1037 5627 1843 1029 74 4104 72 3896 5628 5473 2553 2619 1855 3118 3115 1358 1040 2182 76 1359 1649 3578 2453 2185 2450 2817 2816 2188 1053 4812 3308 2191 3926 5321 604 2457 5348 5593 5312 5113 1046 3940 1856 3579 2188 3907 3189 3044 1624 2969 1992 1275 76 2453 1048 1854 3407 4436 3926 3586 3279 4631 4220 3947 2160 5064 82 5308 3945 2865 3198 3400 5091 3301 3702 3581 1359 3118 3115 1048 79 3909 3308 2457 1050 2034 1051 1859 4813 5350 5307 4441 2268 3792 2698 2867 1868 1067 1051 1859 1051 1859 1067 1056 3042 3402 1070 3110 4958 3921 4455 4215 816 3911 2837 2952 1479 1861 80 83 40 4212 2265 3666 3583 1861 80 1479 1861 1361 83 1479 1861 3583 80 3449 1360 1861 1361 1860 3418 4817 2102 4252 4232 5061 3298 2557 5923 606 3578 3901 2821 3913 2455 1862 5091 3581 3702 4512 1367 4674 4339 3110 4435 3635 4232 816 4437 4626 4588 3634 3114 4640 3393 4597 1275 3058 2197 1626 1058 4439 1864 4211 80 4156 78 2450 2952 4435 3635 2837 4493 3601 2963 2959 2455 4742 3910 2823 2826 3272 2459 2165 3223 3503 601 3447 4318 4386 3496 2357 1058 2461 85 1864 4165 5306 2825 3919 3106 3264 1061 2831 1062 1866 1064 1364 1363 5179 4129 3917 1051 5307 817 4813 1866 2300 1867 1364 2162 3915 3106 2836 3916 4215 3274 3921 1065 2830 1866 1362 3093 3413 2893 3205 4106 5095 4666 3918 3602 2509 1363 1482 2698 4263 2409 3848 1050 2034 1859 1858 5445 1067 1051 5064 2034 3908 3164 3584 5594 3397 3113 4110 496 1698 647 3711 604 5196 817 3590 3273 5696 4664 5309 3521 906 2653 2119 3798 3802 2410 2704 1071 4819 2103 88 2976 4514 1068 88 2106 2840 632 2102 1068 4819 88 4514 3100 1870 2843 2103 1075 2851 2101 1872 1068 4819 2105 1870 1071 2542 88 2103 1637 2323 602 493 3390 4826 1076 4825 1907 4085 2959 1908 2104 1874 1075 1079 1074 4162 2857 3198 3691 4829 2104 3937 5275 3939 4732 4308 2293 2125 1745 1746 83 4682 3925 81 1722 4689 1721 1291 1874 2104 1075 1873 1875 5020 2855 1372 1875 1076 1080 1370 2469 2296 1370 1371 2468 2469 1372 1373 3592 4443 3593 1638 830 4845 640 833 899 19 898 2294 4664 5104 2840 5097 2001 3011 2883 2872 2018 1590 1250 1589 2482 1991 1879 131 2204 3609 1250 2872 3949 1251 1084 2873 131 2482 1087 132 442 3138 443 3017 1590 2018 1089 1589 1937 2063 1185 1936 4118 5533 4754 5319 2875 1085 1589 2872 4433 5129 3035 3809 1988 3095 1987 1083 1083 1988 1881 1987 1986 1996 443 1590 1250 3088 1590 2018 3088 1880 1991 2018 4101 4184 4102 3101 1991 2482 1087 131 1883 3054 1882 1985 1883 1986 1985 1882 2062 1592 1095 1408 2045 4102 4101 3131 1118 4285 3977 1960 1894 5001 4243 3768 3011 5255 3057 133 1984 2536 1410 441 1883 1996 1884 1885 1883 1996 1885 1590 1089 5617 1991 2536 1986 1590 443 1250 1986 3088 1883 1590 1590 4095 1996 1088 1082 3054 1882 1087 1984 4095 1885 1884 1805 3322 2201 1804 4095 1591 1089 3953 1087 1984 1885 1884 1985 1996 1885 443 1087 1989 1985 1885 1879 1991 1082 1990 1883 1885 1884 1087 1890 3085 2249 3083 1097 2022 1101 1886 1991 3953 2536 1884 441 1886 1097 1101 2898 1202 643 497 4095 2536 1984 3321 3321 4093 1984 4039 1101 1887 441 1886 2893 2271 2341 1204 1889 2019 1107 1108 144 2485 143 145 1900 1951 1115 1948 2902 1895 144 4844 2895 1596 1100 2894 1099 2008 1890 1597 1099 2537 1890 1594 1886 2022 1101 1887 1890 2007 1600 1100 1890 4923 2537 4097 4923 2539 2538 1594 1318 2907 38 35 1598 2007 1891 1111 1099 2537 1594 1412 1892 1598 1111 1112 3091 2813 1110 2908 2019 2902 1108 1889 1413 136 137 1893 2016 3969 2017 1104 2813 3091 1110 2537 2021 1113 1414 2020 2912 4243 3768 1894 3003 3969 1102 2911 1599 3970 2006 446 1888 3003 2016 1895 2908 3768 1253 3091 1889 2016 1888 1107 1411 4091 1895 1888 1105 3597 1411 2484 2909 4890 4690 4306 4049 1967 1896 1954 1896 1967 1951 1954 3016 1559 1127 1968 1948 1897 1450 1115 1946 1114 1899 1115 2500 3012 1119 227 1554 1900 1115 1899 1094 1090 438 2004 1554 2920 1898 1900 1948 2003 1949 1900 1554 2920 1227 2534 1127 3016 1968 1459 1325 4020 2094 3978 1557 3012 1956 405 1114 1950 1901 1949 3443 1949 2003 1950 2003 1899 1949 1900 1897 1949 1948 227 1949 1899 1114 1948 1946 2003 1554 1899 1556 2003 1946 1902 4722 1950 2923 3012 1902 3070 2003 1950 1114 1945 1901 1119 4342 1121 1559 4059 1907 4043 1461 1979 2224 1556 407 1227 1951 3034 2920 1967 1898 4049 1896 1954 1121 3070 1120 1557 2917 2534 1116 403 1899 2003 1949 1902 4342 2003 3443 3034 2924 956 2408 2867 1554 2003 1900 1899 1948 3034 227 1949 1450 1967 1951 1896 1125 1961 1903 1126 2928 3018 1903 1123 1551 2927 1553 1957 1962 1123 402 1551 3757 1904 405 1906 1128 3758 3038 2938 4053 4083 3757 4052 405 1904 1130 1133 3831 5537 3942 5377 405 1904 1133 1906 1132 1980 1906 1133 2408 2924 1674 2263 1133 4266 1132 405 1566 3758 2218 2936 2218 4061 406 3038 4041 5414 5268 4062 1980 3758 2940 2938 1983 3998 1139 1138 1139 1983 1908 1978 3063 5079 4063 2956 1983 2946 1140 1908 1913 5346 1964 3029 1625 1155 1151 3010 1964 5346 232 3029 2950 4503 2217 1911 1141 1966 1142 1909 233 3029 232 1135 1910 2950 1228 1971 4329 1911 1132 4078 2881 2880 2370 2134 4982 4040 1565 3719 1909 1971 1910 1228 5531 592 3074 3065 3037 1563 1911 1131 4078 2217 1911 1566 3050 1560 1147 1132 1463 232 233 1912 2886 3518 888 3425 1999 4075 1091 2100 1914 5346 1964 1913 1141 3029 1463 1912 1228 3063 1966 1229 1141 1965 1913 1135 1966 1141 1914 1909 3062 4037 1499 2036 1967 3404 1450 229 1983 4043 2959 1978 3994 4966 4043 2956 3982 4171 2967 325 4963 3291 4421 4879 1159 2037 1157 1621 1923 2030 1148 1922 1921 2969 1992 1624 1059 3914 2829 3587 2029 1499 1917 323 3062 1915 2065 2966 323 1917 324 1499 1925 3127 1167 3126 5855 5884 4710 5592 1992 4010 1275 2969 322 3120 325 2967 1918 2196 1919 2049 1561 3344 3048 3028 2065 4037 2969 2039 3950 1587 1086 3069 1925 3128 2982 3126 1924 2053 2052 1152 1919 2037 475 2038 2196 3290 1274 1275 2153 4539 4536 4060 1158 1919 1918 1150 2029 3008 2030 1992 2035 3111 2969 2036 4892 2051 1162 4549 1161 4010 3007 1151 2024 2026 324 1153 2197 1626 479 1275 3111 4346 323 3008 4171 2244 3007 325 3956 3011 2879 3955 4677 4887 4608 4074 3739 4502 3053 1164 1275 3058 1992 2197 2033 1148 1923 1920 4107 1626 2197 2033 2029 1992 1920 1921 1151 2972 1159 1924 2030 2523 1148 2024 1626 3010 1155 1625 3959 3950 2872 3949 1148 2029 1920 1149 2032 4011 2971 2033 2032 4011 1922 2971 2052 1924 1159 2037 3120 4015 3007 2972 1924 2038 2037 1919 1932 2027 1175 1931 4867 1177 3126 1176 2087 1882 1250 1880 1883 3054 1087 1882 331 3131 2045 1174 2998 3172 3127 2073 1164 4502 4103 2981 1830 5616 2762 1821 3126 4867 1176 3128 1176 2027 1177 1175 4184 2051 3101 2025 2059 4032 2999 4029 1340 3853 2740 57 2984 3052 2057 1929 2086 2986 1169 1927 1177 2985 1170 2027 4482 5336 4971 4479 2075 3463 2988 2074 4441 5064 3919 4813 1189 4136 4124 3180 328 2061 1178 2996 3172 2982 1927 2986 2073 3739 3463 2998 1165 4899 2979 2042 901 5257 1693 4701 1166 5333 1510 4907 2091 3743 2984 3457 4128 1171 4026 3743 4023 2073 2989 2998 1175 2027 1928 1931 1182 2082 1178 2080 2037 2993 1621 1623 1176 477 1174 1932 1175 1932 477 1176 1512 3372 2525 2528 4069 1942 1512 1933 3159 1190 1942 1943 2083 1933 1183 1180 1942 3372 1512 2528 1934 2090 1183 1184 3045 3180 2098 1939 1978 3994 1979 1136 4900 3040 4027 2068 4029 1982 2063 2990 4029 4811 2527 328 1982 4029 2063 2996 3996 4043 1978 3994 326 4686 3698 4028 1276 5489 5345 4897 2098 2530 1191 1943 3325 3384 978 3166 935 3866 31 2288 1191 2098 1939 1169 4235 4499 1276 3020 2947 5330 2195 3153 3541 5666 5662 5218 3139 5340 1939 1938 4821 5113 4561 4882 3040 4029 2996 2061 1982 2996 2063 1977 3040 1941 2996 1977 1908 1978 1907 1139 2068 3040 2056 1627 1276 4872 4871 4046 3005 2064 1187 3004 5344 3159 3165 4871 1935 2090 1184 1942 1934 4070 1942 1935 1792 5943 1800 2097 1942 2090 1184 1190 335 2530 1943 334 335 4350 3606 2530 1190 3180 1944 1943 47 5278 3816 4747 2923 1945 1119 1901 1114 1946 1902 1945 2781 4031 1845 2050 5792 6025 5850 4698 1902 1945 1901 1114 1902 2003 1946 1899 1901 1946 1945 1902 1121 4342 1559 1117 227 1967 1450 229 1115 1946 1554 1899 1946 3988 1981 2923 1114 1948 1899 1115 1940 2063 1982 1936 1450 1951 227 1948 2915 1951 1896 1450 227 5013 1967 229 1899 1949 1900 1948 1902 3979 1946 1556 1950 2500 1114 1119 2500 1949 227 1950 1885 3017 1989 1985 4539 1839 2154 1838 1123 4448 229 1967 3012 4059 227 405 227 4059 1950 3443 1949 2500 227 1897 4343 4498 4007 4464 1902 1950 1949 1901 1114 1950 1119 1901 2022 4286 1887 3376 1951 3034 227 1948 1450 1951 1948 1115 5013 227 3034 4342 1954 1969 1896 1898 1948 3034 2003 2920 1559 1970 1127 1958 1951 2915 1896 1969 3101 4035 4184 2025 1116 2917 1124 2916 1951 2920 1948 1900 1962 2927 1123 1551 4627 2933 4052 1955 1951 2920 1900 1954 1125 4285 1959 2928 1124 4090 3076 4049 1954 1969 1898 1900 1957 2927 1125 2928 1945 3988 1947 1981 3013 3979 1946 2923 3950 2481 1086 2883 1901 3012 1950 1119 405 2933 235 1130 235 3756 1956 236 3012 4059 1557 1950 1961 2928 1125 1903 1958 4285 1959 1117 1957 2930 1118 2927 1117 4449 235 237 1125 4449 1126 1959 1117 5065 1121 235 1123 1967 229 1124 3018 3986 1127 1959 1125 4449 1117 237 1341 3989 1820 2430 4405 5416 914 4404 1123 1962 402 1961 1122 1961 1123 402 2928 1961 1957 1962 1122 1961 1903 1123 1551 1962 1553 402 441 3376 1887 4286 2219 4450 1142 1458 2535 3607 1458 1462 2219 1458 1142 1963 1463 1964 1963 232 1342 3692 2428 1822 1585 3950 1993 3069 1909 1963 1910 1142 1463 1964 1142 1963 1458 2219 232 1963 1093 2004 1091 1090 1463 3029 232 1912 410 1228 409 1966 1914 1964 1141 1913 1909 1964 1141 1914 2182 3295 2453 3030 1463 3029 1964 232 1142 1964 1141 1909 1966 1141 1913 1914 2774 3871 3077 3615 1141 1966 1913 1965 410 3995 409 1975 1229 1966 1228 410 3995 1966 2956 1565 1228 3063 1914 1966 1909 1966 1228 1914 3076 4285 4049 2920 3070 4059 1557 1121 1121 5013 1117 3070 1115 2918 2915 1969 1951 1900 1115 1969 1954 1969 1900 1951 2918 1115 1554 1900 1123 3985 3984 3018 4025 4500 4023 3740 1559 3016 1127 1970 3016 4059 1559 1968 1909 1971 1142 1910 4041 4310 230 1454 1966 1971 1909 1228 1971 3037 1229 1228 1966 1971 1142 1909 1129 5268 4041 2935 1460 1972 230 1562 2996 3040 1178 3144 1128 3990 1460 1972 1460 3039 230 1972 3869 5427 2378 5210 3036 407 406 1981 1974 3998 3021 1138 3043 3996 1973 1136 1569 3996 3994 1134 1974 3041 1140 1138 3021 3998 1976 1134 1139 3998 1974 1138 409 1975 1569 410 1569 1134 408 1976 2806 3577 76 2449 1134 3021 408 1976 3760 4553 2239 3761 2061 4897 2059 4499 1977 4029 2061 1982 77 2997 75 2810 3006 4871 3165 4044 2081 3160 1182 2092 2483 1096 131 1401 1940 2064 1187 1941 2944 1135 1134 3029 2815 5620 5520 5142 1560 4296 1911 3344 1136 1979 1907 1461 2959 1908 1978 1907 1137 3995 1565 1975 3453 1849 2305 2306 2503 4085 1461 3398 1998 5346 4966 1963 2938 3038 1128 2935 1911 3758 3037 1131 1904 4053 4052 1133 1509 2059 2058 328 4053 406 407 3046 2112 3696 3199 4687 2923 3013 1981 1946 3142 4686 2060 4028 1982 2063 1937 1936 1168 5340 1938 2072 1140 1138 1146 1983 1139 1983 1138 1140 1908 2959 1978 1983 3032 1146 1138 1983 1134 3032 1138 1983 3065 736 733 732 2536 4095 1984 1884 1984 1410 1096 441 2022 2889 1097 2010 131 4868 1988 133 131 2483 1401 132 1882 1991 1082 1087 1985 3017 1986 443 1985 1883 1087 1885 2087 1880 1083 1082 4907 5340 3698 1168 2205 1250 2087 1986 443 2205 1251 442 1082 3054 2087 1882 131 5564 1990 5255 1987 133 1396 131 1083 1988 1396 1879 1123 3985 1903 1122 1396 1988 1987 131 2002 3071 2872 2204 1936 2063 1185 1187 133 1988 131 1987 5564 2000 3060 1593 1083 1990 1880 1988 4473 5209 839 5150 1988 3095 1083 1396 1991 1882 1082 1990 5564 131 1990 1991 1087 1991 131 1984 1883 1991 1984 1884 1083 1990 1879 1082 1593 5617 2536 1592 1396 1988 131 1879 1995 2875 1987 1881 5255 2000 3057 3060 1991 3088 2018 1089 2018 1880 1990 1881 1593 5617 2062 5564 1882 3088 1991 1883 1991 1087 1883 1984 1879 1990 1988 131 1984 2536 131 1410 3953 1883 1590 1884 1089 2536 1991 1591 1921 2035 2029 1992 1991 2482 1082 1087 1085 5617 1593 5564 1922 2024 2971 4011 1921 2197 1624 1992 1626 3010 1275 1992 3102 332 1155 2051 1888 2019 1889 1895 1994 3950 1993 2873 3071 3950 2002 2872 2000 2872 2001 1085 1993 2873 1092 1994 3763 3639 3435 2874 1083 1995 1987 1881 1995 4077 1878 1987 2887 4307 4093 1996 1986 1996 1590 1985 3230 5648 3422 5647 2889 4093 443 3965 4039 4095 4093 1885 1985 1996 1590 1885 1883 1996 1590 1884 1591 4095 1997 3321 1963 3063 1964 1998 2950 3608 1563 1971 1560 4296 3344 230 1998 1909 1964 1963 1909 3063 1964 1914 1088 2887 140 1997 1909 1998 1910 1963 3032 4043 1978 3452 3130 2152 1704 2126 3011 3959 2883 2872 139 2000 141 1085 2875 1881 1990 1988 2872 5255 4868 2875 2875 2018 1250 1589 3011 1093 2000 2001 2879 1587 1585 1999 141 2001 1085 2000 1085 2872 2001 2481 138 2001 1085 141 439 2873 1994 1084 1587 3950 1086 2883 2001 3950 2872 2883 2001 3950 2883 2481 4657 5005 3306 2820 3355 4718 3753 925 2409 4615 2407 4474 1227 2920 2003 1555 1091 2100 438 2004 1585 2100 1587 438 1555 3070 1556 1121 3950 2481 2872 3071 1950 2003 1902 1949 1946 2003 1227 1554 1227 2003 1556 1555 2920 5013 1117 4285 3979 4059 3070 1950 1091 2004 438 1090 1253 2911 2006 1599 1252 445 446 2006 2912 2006 1109 2908 1253 2006 1252 446 2006 2908 1110 1109 1599 2006 1253 446 2020 2539 2021 1113 1890 5001 2249 2007 1890 3096 2007 1100 1111 4890 3974 3975 1594 3096 1100 2538 1105 4243 2911 3597 3975 4923 4573 3096 3965 2889 2022 443 1110 3091 2008 1597 3091 1110 2537 1597 2897 3084 1098 2892 2673 3762 3363 2290 1919 4000 2540 475 322 2009 1150 1158 4093 1885 443 3965 1158 2009 1150 1918 1915 4171 1916 2039 1410 1096 441 2011 3766 2253 936 3765 2889 2022 1097 1886 443 4307 2010 1097 1097 2889 441 2010 1596 1410 441 2011 134 2011 1410 1596 1886 3376 441 2889 1401 2011 1409 1096 131 2011 1410 134 2011 4994 4291 441 1886 3376 2022 1887 1098 3964 1409 2011 1401 2011 134 1409 2064 3005 1187 1941 1986 3088 1590 1882 2015 4843 2012 4841 2015 4843 4841 1102 1106 2077 2013 444 1106 1108 444 2013 1107 4843 2013 1106 3768 2912 2813 2908 2005 3970 1103 445 446 3970 2006 445 1102 444 1603 2015 4843 1107 2013 2012 4890 2486 3094 4690 1915 4171 4010 4092 2813 3080 136 1102 2539 3094 3080 3003 1104 4841 2016 3969 1895 2019 1108 1113 1102 3003 2911 2912 1880 3088 1991 1882 1411 3003 1895 2486 3732 4702 2096 4036 1888 2017 1411 1104 1589 1089 1085 2018 1250 2875 1589 2872 1187 2063 1940 1936 1108 3080 1106 1113 1987 2875 1988 1881 1991 2875 2018 1990 1588 2018 1880 1250 1842 4928 71 4695 3094 3003 1895 2019 2537 1099 1890 1597 1888 2019 2016 1889 3317 4291 2022 3965 1595 2539 1113 136 2022 4994 2894 1100 2539 2020 1595 1113 1414 2020 1113 1595 1646 4074 2374 4891 2527 3144 2064 2996 1891 4890 1111 2007 3457 4026 1173 4454 3003 3080 1102 2019 2358 4924 2662 1767 942 3769 938 2686 1600 2895 2022 2894 4690 3768 3003 2539 2539 4890 2020 2021 2030 1148 1920 1923 1890 3085 3083 1099 2010 2022 443 1097 2679 5693 5397 5237 2410 4741 961 2099 1003 5294 1001 1000 2051 4892 1162 4463 1148 2030 1920 2029 2032 4011 2033 1922 4101 1174 2045 3131 332 3102 331 2051 1148 2024 1153 1922 4870 5727 5078 3707 2086 4116 1927 1167 1917 2030 2029 323 475 3125 476 3132 2024 2971 1153 1922 2223 4185 3558 1813 3175 2984 2075 2076 2026 2024 324 323 323 2981 2524 2026 2027 3740 1928 1931 2027 1170 1177 1175 1176 2027 1175 1932 1925 3128 1165 1926 1791 3801 958 3544 4867 3127 4034 3126 2074 4023 2988 3239 1174 3604 3181 2992 2030 1148 1922 2024 3008 323 2029 2030 4101 4117 2045 2044 2080 2092 2081 1182 1645 5561 2187 2552 1923 4011 2030 1922 1159 2972 1157 2037 3058 4346 1992 3008 1920 2029 1921 1149 1148 2029 1149 1917 1920 3058 1992 2030 1917 2036 2035 1149 3805 2714 1800 2097 323 2523 2030 2024 1148 2030 2029 1917 2031 5005 4866 3305 3058 1920 2197 1923 4742 4810 2821 3910 4744 1867 1362 2300 4435 4626 4568 3912 2032 1922 1148 1153 2033 4011 1923 1922 1626 4107 2197 479 4443 4162 3592 3593 4152 2675 3654 3854 4470 5226 1035 4570 2950 1910 1228 1998 1051 2034 1868 1859 1284 3923 5 2 1868 3908 2838 2034 2244 4171 3982 325 3111 2035 1499 2036 3062 4037 2039 1916 323 4037 2244 3007 1149 2035 2029 1921 2038 2972 2037 1158 2244 4171 3007 1916 2029 3111 323 3008 1917 2036 1499 2035 1921 2036 1149 2035 2065 4037 3062 2036 2577 5439 5066 2231 4588 4437 3633 3296 2065 2969 2036 1921 3111 2029 1992 3008 1150 1919 475 2038 1159 2972 2037 1924 2037 2993 475 1621 1158 2038 1919 1150 1621 2052 1623 1159 1621 2052 1159 2037 1560 4329 3344 1911 1924 2038 1919 1158 1924 3120 2972 1918 5216 5145 3811 5193 2030 4011 3105 2024 2969 4109 4037 3111 2065 2969 1915 2039 2969 2966 1624 1921 4010 4092 1918 3290 75 2043 1849 77 3817 1848 2447 2043 1855 2818 1358 2450 77 2818 2450 75 1355 2041 1848 1356 1857 2046 2040 1358 1851 2447 2046 1852 1852 2041 1356 1848 2812 3576 1355 3294 1851 2041 1356 1852 1848 2812 2041 1355 1846 2041 1356 1851 4899 1926 1165 2979 1626 2971 2042 1154 2986 4116 2982 1927 1926 4899 3053 2979 1626 4021 2042 2971 2032 2971 1922 1153 2040 2447 1852 2046 4740 2458 4322 4593 2810 3817 2447 2043 3128 1176 331 2044 1926 3128 1165 2979 4502 2979 2042 1154 1176 2045 331 2044 1793 3802 2410 3182 915 3741 2392 3461 1176 2045 2044 1932 2046 2818 75 2450 4315 2543 3780 1635 1848 3454 3176 1357 971 4999 4418 4417 2043 2306 75 1849 1356 2447 1852 1848 3906 3571 2048 2785 1844 2785 1843 2047 1844 2799 2785 2047 1040 2182 1653 76 2305 3571 2785 72 1042 2048 1853 1847 5227 3385 3575 2801 2173 4635 3453 4385 2560 1653 76 1654 324 3373 323 1499 2153 5319 1840 1034 2787 3806 3426 3574 4011 1154 1626 3058 1093 3011 2879 2001 3058 3010 1626 1992 3058 4105 3105 4038 2051 4105 3010 4038 1919 4000 475 3125 1924 2053 1152 1919 1185 2994 1937 2088 1924 2993 1919 2037 2053 3132 1919 2993 1924 2052 1159 1152 1924 2993 2037 2052 1152 2053 2049 1919 2993 2037 2052 1623 4458 4786 4751 2778 3613 2603 803 5368 4181 4336 4114 1294 4965 3300 4564 3199 1020 2777 2773 2767 2057 3052 1930 1929 5253 5463 4993 4522 1627 2068 1276 482 5321 5401 5315 2412 3129 1936 1982 1937 1178 2092 2082 1182 3739 4502 1164 2028 3699 4686 1939 3698 3156 3175 2091 2984 2995 4026 1173 3457 4657 4437 1054 4568 4207 3143 87 2463 2074 3239 2988 3156 2059 4032 328 1509 5807 5634 1006 3360 2061 4124 328 1189 1938 3698 1168 1513 4235 1939 3045 3610 3052 5488 4028 326 5744 4175 5275 5721 326 2059 328 2058 4158 5072 4088 3871 1943 4136 3180 3606 2064 2996 1940 2063 143 4573 142 1100 1512 3165 2084 3159 1186 4036 1628 3732 326 4566 4028 3698 3978 4741 961 3800 1178 2092 480 2082 1191 2060 326 1514 2995 3140 1930 2057 1191 3699 1169 1939 1189 1178 328 2061 2061 2090 1189 1178 1182 2083 1183 1178 1933 2084 2083 1942 1512 3159 2084 1942 1940 2996 1941 1977 3060 1095 1408 2062 2818 2046 75 2997 2872 5564 1085 5255 3060 5564 1408 5255 3010 3102 2051 3058 1185 2527 1187 2063 2537 4923 2813 4097 1977 2063 1982 1940 2996 2064 1940 1941 1179 3177 3040 2056 1940 2064 2063 1187 2966 2969 2065 1921 1149 2065 2036 1921 2966 2969 1915 2065 2966 2969 1624 1915 2431 4226 58 3650 2428 1822 59 1342 3853 1340 2066 2428 3562 3439 1000 3222 1002 3357 3151 1341 5187 2426 4827 4581 3431 4985 3355 3682 4686 3699 1939 1169 482 2068 481 2056 1818 3557 2748 3148 482 2068 1277 481 4027 1187 1940 1936 1276 2068 1277 482 1276 3040 2068 1627 3040 4900 1977 1277 1977 4900 1982 1277 3239 4128 3156 3172 2757 5161 3854 3022 2221 4879 4422 4421 1276 4046 4044 3020 3345 983 55 2222 3707 5078 4148 5188 2743 3847 3560 997 1814 2937 2071 1813 1695 2807 2596 2390 34 5674 3761 2580 1939 3610 3001 3045 2363 3130 858 1707 1512 3165 3006 2084 2988 4034 2989 3740 2982 3127 1925 3126 3172 4024 2986 3175 1925 3172 2982 1927 2633 4009 2144 3705 2984 3052 2988 2076 2074 4115 3463 3150 2988 2984 2076 2075 4117 4101 2045 4102 1986 3054 1882 2087 1170 4025 1928 2985 3457 2984 2091 2995 5735 5850 5787 5832 1164 4899 4103 4502 1106 2077 444 1102 3101 4117 3102 4102 4907 1510 327 326 326 5333 4907 1510 57 2748 59 2987 2998 4022 3053 2073 4566 3175 2057 3168 2057 4028 3052 2076 1169 5330 4024 2086 5330 5488 5333 4907 1102 2077 444 2015 2078 2427 2220 1813 4422 4421 991 2221 2078 2220 995 2071 2426 4185 1813 2427 2078 2937 2071 995 2223 3558 1665 2576 2201 3642 1806 988 982 4268 2727 2222 3554 4694 2724 3752 51 3551 2291 53 1178 2080 1183 1182 1180 2080 1183 1178 3159 1942 2090 2083 2081 3160 1184 1182 2080 2092 1182 2082 1183 2081 1182 2080 50 5032 2093 48 1182 1184 480 3160 1178 2092 1182 480 3163 1178 2080 1180 1933 2084 1180 2083 1934 2083 1942 1933 2888 4045 3019 3518 1178 3159 2083 2084 1933 2084 1942 1512 2083 2090 1934 1942 4140 2854 2170 3033 2084 1933 1180 1512 5332 2086 1629 5330 1178 3159 2061 2083 1512 3006 1181 2084 2090 3159 2061 1190 1180 2084 1181 1178 1371 5598 1370 2864 4024 4566 3175 2076 3823 4694 2565 52 1169 2086 1927 1167 2715 2862 1803 977 3101 4021 2028 2026 5736 5383 3778 4604 1166 5606 1510 5333 1250 2087 1880 1588 2527 4032 2994 2526 131 2482 132 1879 76 2178 1041 2171 1882 2087 1082 1880 4028 4566 2057 3140 2994 4135 2526 4032 3578 76 3293 2560 2090 2061 1189 1190 2090 2083 1934 1183 1935 2090 1942 1934 1942 3159 2090 1190 1189 2090 1182 1178 1935 2090 1934 1184 334 1173 1172 2091 3119 4891 4501 4074 2530 3175 3168 334 1171 4454 3457 1172 2985 1928 1170 2027 1172 4500 3127 3152 3545 3546 2712 1327 3546 2711 3545 2712 1797 2093 1798 1327 4468 4916 2414 4612 3672 3673 1203 2893 46 3669 964 3268 2075 5488 3463 5333 2711 3546 48 2712 1328 2095 972 1796 5051 974 49 4299 1942 3605 2528 3159 3173 4136 3606 3180 3173 5170 2096 4702 1944 4124 1191 3180 3733 4703 1694 2650 2529 3173 2096 1188 2707 3812 3620 969 3322 4419 2422 4249 3801 5943 958 4319 5943 5849 958 5928 4727 5381 4533 5088 4862 5636 1164 3463 4350 2096 3180 2098 2530 1169 1191 1514 2027 3747 1931 1932 2098 4124 1939 3180 963 4741 961 2921 2710 4457 3349 4295 2410 1326 44 42 1091 2100 2004 1999 3929 4514 3930 2843 4514 3184 3929 3930 1869 4735 85 1073 1075 2101 1873 1872 3186 2462 2105 3100 1072 3868 1070 2840 4502 3102 2971 3101 2463 3143 2839 2023 3494 1871 2834 3267 1874 4607 1372 1079 1871 3494 2834 2463 1068 4819 1870 1071 2843 4019 3100 2103 1873 3937 2104 1872 5183 4478 2844 3253 4737 2542 3611 3288 4906 5215 4122 2870 2106 2323 1637 493 2123 4208 4164 1 88 3113 1069 2976 3987 616 3539 3394 1677 2352 2255 1321 2107 3388 1321 3134 3987 2257 3784 3190 2696 3356 2697 2406 1320 2402 1783 1780 2111 4826 4825 804 5138 5754 4949 5165 2699 2109 1322 2110 3939 4729 4308 3782 1303 3524 4787 4401 2699 1322 39 2110 952 3790 3538 3191 1778 2402 1783 1320 2851 3304 2547 602 5624 4150 2626 3709 601 3304 2851 602 3304 4208 2851 1 867 5624 877 10 4257 4922 4018 4259 4008 4950 4330 4859 3200 4977 2626 2629 4880 2208 4733 4430 2636 2116 886 2380 1313 5161 3056 3202 868 2619 599 2551 3441 4340 1297 2641 3958 4677 4601 4397 1992 4010 3010 1275 13 3238 874 2375 2115 5563 878 2374 888 2546 1294 1727 2544 3503 801 802 2377 1728 884 2376 2626 4150 2629 3709 3077 3615 881 2774 1690 5953 3954 5863 5713 5288 5582 5793 3207 2888 886 2275 2137 1294 886 2116 913 2117 1766 1756 3255 929 28 2285 2998 4034 2028 2989 875 2118 13 1725 1725 3704 3240 2639 1300 2119 1747 1301 1750 2119 1301 1747 1744 2119 1301 1749 1749 2119 1301 1750 3528 3745 1755 912 3992 2783 2213 3135 5374 3718 1751 4161 5567 909 2654 5416 4649 5378 3147 5098 70 1648 3934 2189 4014 2397 33 3056 1638 3304 1 2123 34 2680 931 3023 20 4013 18 3727 4163 4315 3780 1635 802 5693 801 5114 805 3503 2544 1636 3752 5669 3554 2566 2363 3503 2362 2884 861 1 1081 2124 857 2124 1 861 198 2495 208 200 2299 2389 1694 2293 2129 2293 2125 1745 2130 3223 3214 4 2125 3442 1746 1302 2877 2974 19 3520 856 3130 1704 858 1704 3257 2126 2152 4698 5893 5605 3738 5708 5727 5609 5756 4040 1564 3009 3719 3442 1745 2125 1746 1298 3497 1736 1735 3724 4699 1743 4696 2129 2293 903 2125 4703 3733 1693 4701 2129 2389 2293 1745 903 2295 2129 2125 4 3503 1636 2369 852 2607 4 2130 3599 859 853 852 3316 1329 980 978 5395 5795 5410 5657 1736 2361 1740 2131 4289 2149 2369 2881 3618 3503 2369 2881 1286 4190 2368 4179 2132 2369 4 1711 2369 4012 2881 2149 2133 2980 1636 4 332 4117 1154 1165 4684 864 4179 4190 2135 7 863 1643 2149 4289 2880 2881 666 2355 662 663 2115 4180 4016 2374 2618 868 599 2372 2283 1741 894 1733 4904 4177 3713 1732 599 2138 7 600 5176 896 892 4508 2137 4336 2636 3207 4555 896 1736 1735 895 5010 2382 3904 3703 1699 2380 3207 4205 2605 1685 1699 15 3715 3237 1295 599 2138 2135 7 5819 5910 2839 5960 599 2138 600 2135 2140 3693 2880 3234 1162 4549 2051 2025 2139 4082 2384 2877 1749 2649 21 1750 622 5128 844 2877 2139 2974 844 2877 1285 3626 1712 2366 2880 2368 2370 2140 2141 1292 9 1720 3204 13 887 882 2617 1712 1285 1714 4207 2023 3143 2463 2142 4860 12 4691 4606 5424 5252 5039 2592 5625 3519 1684 1292 2631 1290 2142 2142 1290 1721 1723 3010 1151 1625 4010 2315 3465 2391 2393 1699 3520 2877 19 892 2143 844 2136 2753 5584 1006 5635 5342 11 9 5037 4009 5249 3712 11 4752 3303 4564 3300 3705 5067 4009 2144 1921 2969 2035 1992 806 4183 4170 3226 962 3408 3179 965 3528 5550 1697 4332 1282 2148 1706 1283 871 5213 2960 3513 1708 2148 1283 1709 1703 2148 1283 1708 2958 1357 2089 2983 4012 2369 2881 3302 5725 3890 5707 2582 4507 1737 17 2385 4012 2369 2132 1711 2138 3778 7 600 1712 2617 1285 2366 3943 5313 5300 3397 4392 5373 5038 5075 2546 888 2116 2379 4289 2368 3234 4179 2679 5397 5351 1675 2554 2189 2949 3934 5100 5382 4456 4958 2606 1703 1708 1285 3502 1709 1703 1283 2617 2606 3 2151 859 3221 2611 4 859 3501 2607 852 2184 5177 4149 3938 2172 3884 2792 1028 856 3130 3049 1704 3075 3214 3049 2152 1030 2153 1840 1034 5632 5761 5698 5656 5441 5694 5058 2445 2153 2445 1034 1838 2153 5441 1034 2445 1030 2153 1839 1840 3544 5895 3193 2749 2801 3887 3260 3385 5530 5642 5553 5408 3885 5254 5059 1033 5620 5520 4742 2815 1647 2441 2189 2156 500 2355 690 499 2023 4207 3143 1368 28 4332 3528 2285 1837 4998 2442 3188 2441 3253 2156 2443 1359 3189 1854 1048 5982 1845 2781 2804 1022 4521 1647 70 1648 2554 2158 70 3188 1027 1647 1837 4478 5538 4716 2949 3934 5355 5223 3574 3359 1745 2293 2389 2157 5183 2964 2844 2176 5064 2160 1067 4865 2781 2055 4802 4386 4318 2206 4258 2420 5123 3664 4830 2831 3918 3264 3793 3915 4106 3922 2827 3929 5482 3266 2843 3264 3799 3627 2825 5546 5658 5493 5343 5322 4603 4814 3269 81 3922 2827 3915 3304 4545 3788 1638 3921 4958 4455 4814 1067 5445 1051 1056 5092 4079 4425 61 2324 4842 616 4204 4007 4464 3027 2961 5315 3539 2324 4919 1677 2352 1321 2330 2166 85 1059 2164 4047 4650 4457 4415 2829 3914 3412 3587 1066 3273 2461 2828 5350 4441 2162 5307 2459 3588 2826 3274 1060 4440 1062 2824 3914 5390 3587 84 623 3968 3413 2541 2166 2460 1864 85 1367 4339 1369 2847 85 2166 1059 1058 4108 3931 3679 2164 3868 5229 2977 2840 4010 4346 2969 1992 2167 4735 1073 2466 3444 4820 2298 1369 771 3074 589 590 4057 2255 3784 3064 950 2168 1784 1779 1676 3432 3064 2163 943 3278 37 2581 1003 5053 1823 2577 4825 1076 804 4826 2943 1344 64 2207 1344 4003 2210 2943 2066 2430 2233 2428 2234 362 1524 1528 1038 2448 76 2178 4748 5915 5894 5766 4022 3053 3172 2982 5060 5923 73 5915 2241 3774 941 1771 2449 3578 76 2806 1847 4513 1042 3285 1041 2983 1357 2958 808 4845 809 4574 2452 3189 2454 3123 2594 4622 1699 2389 2803 1664 2427 2568 996 5004 4421 1661 2854 4140 2432 4134 3456 3566 3318 1825 2870 3961 2357 2356 1971 1911 1563 2950 2160 5589 2176 1657 5788 5845 5822 5756 3794 2845 2055 2442 832 3670 833 836 5712 4512 5177 5680 2455 3208 2031 3107 3031 5189 3823 3315 4867 1177 2985 4500 1000 5092 2232 4679 3253 2441 2189 2845 5091 3580 2186 3702 1355 3454 2447 1848 4513 2181 3299 1651 2182 2453 76 1854 1048 2453 2183 1649 5451 4200 4173 3263 1655 2562 76 2561 1649 2453 76 2185 3635 4232 2557 79 1939 4235 2194 3610 1656 3796 3586 1858 1855 2452 2188 2450 812 2185 815 811 3410 4513 3415 3285 2306 3906 72 1849 1649 2185 815 812 2508 3583 1480 78 2452 3189 1854 3044 4230 1652 3578 2185 2189 5183 3934 4521 1645 5677 2112 5561 5729 3705 3200 3614 4512 5321 605 5177 2452 3044 1854 1359 4033 5005 3305 4866 2816 4742 80 4156 1855 2452 2450 1358 3228 4949 3778 3508 2441 3253 2189 2156 3512 4668 3246 4112 4008 4859 4330 4564 932 3435 1312 934 574 3473 791 2901 4150 5624 2626 877 3695 870 883 867 880 4598 4364 3661 3114 4144 1360 2455 1146 4066 2963 1983 2454 4149 3938 2184 857 3309 1 2124 4415 5168 4047 4654 972 5050 4415 4654 2245 3378 46 3193 4832 2411 2270 3978 5294 61 1003 1001 3149 5330 2947 3153 4116 2086 4024 3169 2947 3694 478 3149 1629 5340 1939 5332 2072 2194 1276 1277 3628 4476 3265 3590 3361 5364 2759 2991 3153 3694 2947 3149 623 3413 3205 1203 1365 4562 1368 4207 2049 4000 1919 3125 4000 2196 1919 2540 2196 4010 1625 1918 479 1274 478 2197 1275 2197 1274 479 1769 1768 3952 4152 1624 2197 1274 1275 2719 5283 3823 2203 1920 3058 2197 1992 1921 2197 1920 1624 1921 2197 1992 1920 5149 824 2722 4850 4974 5326 4758 5325 1805 3322 2198 2735 2763 3643 2672 3437 2422 2722 2423 984 4143 5492 4878 5069 5234 4248 2422 4809 2719 5283 5125 3823 3323 4527 3841 3835 1377 2904 2317 2416 1803 3829 977 987 2415 1802 976 2200 984 2201 1805 1806 5045 5450 5365 5407 2955 4253 2716 3823 2719 976 1802 2200 2851 4854 4732 3304 1805 3322 2735 2201 984 2201 1806 988 2862 2868 2417 2085 3316 4934 1329 4304 3032 4066 1146 1983 5739 979 5283 2203 2873 3997 2204 439 1250 3609 1251 1588 932 3435 3201 1312 1250 2205 1251 443 1834 2440 65 1348 520 2355 680 519 2435 4880 64 4430 3167 4134 3183 3989 3647 4638 2356 2572 5034 823 635 2175 4044 4132 3446 4496 3146 4172 1828 3565 5818 5740 3554 5770 1344 2943 64 2435 43 2267 5391 5035 2307 65 1348 1834 1671 3456 1670 3277 608 4430 609 827 2439 4538 2438 3647 1012 4431 67 3137 2206 4386 4258 1201 1344 4003 3456 2210 800 4571 3879 1700 651 2355 848 500 1670 3564 2931 1004 3416 2169 2309 2237 2944 1965 409 1135 2701 961 43 5048 3328 4386 1201 3330 2923 4722 1556 3979 2211 3137 1012 67 1672 4487 3395 4054 2356 3647 2870 2573 1287 3570 3512 2371 1774 2401 1318 2334 519 2355 678 518 5215 3568 3340 4996 2216 4432 3751 2942 2213 3992 1350 2574 4809 5537 5377 4660 4433 5223 5058 3574 2574 2783 2444 2213 1562 2214 230 1560 4266 2940 1560 2214 2940 1560 1562 2939 2940 3039 2938 2214 2223 5187 4581 2426 230 4310 1460 1454 2278 3465 2315 2393 4381 4932 3598 1754 802 5693 5114 2603 3744 917 3460 3527 1853 5743 2785 5627 1564 3009 1144 1143 2936 3038 2218 406 3046 2938 3038 2218 4874 5019 4338 4266 1971 2217 1911 1229 3037 1971 1229 2217 998 2425 3560 992 406 3046 2218 407 4053 4338 1906 3757 406 4053 407 4052 232 3344 230 3028 1566 4853 4078 4452 131 5617 2536 1991 3607 2535 1458 2219 3608 2535 1462 3607 1458 2535 232 2219 3607 4450 1458 1462 2220 2071 1813 1814 3556 995 3352 2425 5449 5347 4679 5396 982 4755 2222 3827 612 4042 3649 611 1335 2730 983 990 2732 5287 4268 4828 2937 1814 1339 2223 1335 2730 990 2721 4356 2576 1815 1339 3658 4992 3831 4581 1814 2937 1339 2071 1226 406 1227 2224 407 3013 1556 2224 407 2224 1227 406 1556 2224 1946 1227 2224 1554 1227 1226 3352 2743 995 997 992 3560 58 2743 4055 2226 1226 1227 3977 4055 2226 2917 2534 1227 1554 1226 2917 1116 1124 1953 4055 2917 1226 2226 2227 2431 58 1820 2227 4226 2431 3989 3351 3539 2257 2692 2228 58 999 998 2745 4768 3345 3845 3145 4126 1338 1818 1003 2429 1000 1001 3992 4779 4121 1350 3574 2158 70 5254 943 3850 3777 37 3434 4425 3652 4294 3656 5054 4425 4775 4559 5800 4557 844 5464 4618 4577 5220 363 2234 364 355 5323 2236 61 2229 4425 3646 61 2577 3142 4028 2060 1514 66 5296 1348 68 5013 4285 3018 1970 4042 5287 4828 2222 898 3717 19 891 4148 3585 3586 3999 1820 3357 2854 1341 3289 4679 2570 3280 62 4423 60 1342 2428 57 60 1342 1340 3853 2066 1824 1532 2533 1533 365 356 2533 362 2234 356 2234 355 364 3360 5616 1006 2759 1830 2762 1829 2433 405 2932 1130 1905 5055 3360 1008 1011 4264 4428 1012 4426 3859 2762 1830 2433 3856 4776 3429 4554 2762 4423 1821 2753 4846 3973 3676 4064 2309 3983 3416 2237 2681 2765 2254 2755 1009 4425 1007 3656 1972 3758 2938 2214 2200 4167 2719 2418 4168 3456 1825 2435 3456 4168 1825 3318 2931 1004 1344 1670 938 2679 2238 1771 616 4204 2679 2324 1777 2691 2671 2333 4473 5209 4571 839 3768 4890 1892 4097 5397 2672 2243 3761 934 2757 932 2672 229 4090 1967 3404 2241 3770 3320 3367 2675 5572 5472 3761 2761 3375 2683 3771 2763 3437 932 3201 2675 4048 3761 3854 3433 5114 843 646 3435 3763 2672 2763 2672 5397 3893 3761 3655 4389 3228 1713 1079 2851 1075 1872 580 2784 579 709 617 5595 1675 5351 1497 2244 323 1499 2244 1497 323 325 1033 5254 2158 3573 2246 3812 2245 3620 975 4999 1800 959 5650 5437 5638 5559 2675 4152 4048 3854 49 2252 967 2247 4462 5228 5138 4621 3663 4111 2708 3379 5402 970 5050 5238 3539 5315 5110 2582 837 2746 2707 2741 981 2747 2737 967 3819 4426 3340 4264 2707 4457 2746 3548 3033 4140 2431 2170 4494 5271 4532 2929 1795 5238 970 973 3096 4923 142 2538 3085 3981 3083 3317 2889 3965 2022 3376 3085 3981 2249 3083 2008 2249 1253 1252 71 4695 69 3891 3090 3969 3003 2911 1100 441 1887 4286 963 3946 836 2978 1330 3551 1377 2291 4140 5355 1662 2354 2508 2251 1479 283 282 2251 1479 83 2251 284 285 283 1361 2251 81 83 4826 5082 2111 4825 49 2252 2247 2929 4301 936 1316 3377 617 4056 2679 3665 5674 34 945 2580 2682 4014 33 3781 2896 3781 1318 2685 3750 4715 2669 4707 3056 4646 3368 3202 3898 4253 2955 3823 3945 1 1081 4545 3388 2692 2404 3351 3278 37 950 2256 944 37 943 2256 950 2256 37 944 1775 2687 1784 2677 40 3666 3539 2408 734 3074 591 731 2257 3783 3394 3539 3258 4517 4343 2793 1781 4081 39 41 2402 1780 1320 1319 267 2259 268 259 443 4291 1096 3317 5469 3771 2686 2678 2404 3539 2692 3064 2259 266 1471 1473 1475 2507 1476 269 260 2507 266 2259 260 2259 259 268 952 3538 2403 946 3666 3783 3394 2260 4875 817 4544 3799 1676 4947 835 3540 955 5737 5637 4771 4741 2921 963 2978 4313 5044 3427 3844 614 2262 43 615 2405 2699 41 1786 615 2269 2262 2261 953 2266 40 952 5046 5930 3112 5943 3543 3621 3270 3401 2108 3192 3124 1322 2264 3792 2867 2698 4154 5045 1789 5365 2265 4212 1678 3666 1320 4728 4374 3191 2265 2408 40 1785 1785 2407 1323 2265 1782 3192 1322 2693 3543 4614 3848 3671 2108 2407 2268 2405 2323 4212 3666 616 2683 5469 2761 3771 85 3931 3797 4735 5377 4828 4042 3559 5578 5793 3380 5582 2262 2269 614 43 961 2700 2269 2412 3539 4212 2323 3980 615 2269 614 2262 1859 3312 1050 3109 1902 3979 3070 1950 2193 3311 2412 2590 3846 5050 3549 4415 2338 3093 838 2327 3968 1683 2898 3205 885 3735 16 3722 1700 2541 798 624 1431 2490 1432 173 164 2490 170 2272 164 2272 163 172 4970 5631 2682 4369 5114 803 802 2603 1206 625 1205 2347 2277 5648 5176 2143 16 3735 2922 3015 1699 2280 627 1690 2233 4178 2428 2430 2274 3720 1732 1731 3229 888 3019 3518 4790 4905 2941 1836 5093 3734 626 4889 2280 2888 1699 2275 2116 4114 2636 2137 2380 2116 888 2379 2772 4255 3245 3870 4095 2536 1591 3953 4479 5380 4482 5336 2644 892 896 1735 5643 6021 2973 5994 2383 5789 5765 5601 3875 2655 26 4705 2039 4010 2969 1915 2382 4080 2591 2383 892 2644 896 2277 892 2277 896 2143 2315 917 2278 2393 25 3883 2392 3681 2661 4620 3525 3746 2660 915 917 2315 915 2660 917 2120 915 2393 2392 917 3688 2285 28 3528 1686 4365 1209 1685 2776 5425 10 5624 1209 2282 1687 2281 2282 4376 3262 4375 2389 2596 1699 2594 4196 2364 2365 4076 1734 3441 890 2640 3218 894 1741 2284 3219 5836 3730 1742 1733 3219 1741 2384 1733 4082 2643 3219 3354 4332 2876 28 1761 3532 925 3431 1983 4966 1978 1134 1759 2286 31 920 921 2290 31 1767 1760 3371 2286 1759 1760 2286 31 1759 927 3962 920 921 847 4160 618 3209 2663 5646 2287 5571 3857 2663 3355 847 4407 5412 5241 1308 4155 2395 926 2665 5372 3531 5233 4522 2673 3866 2674 3363 2146 5555 4926 1763 927 2288 1762 1763 1767 2674 2289 2673 3270 4614 3543 4474 4408 30 2343 3966 2806 4685 2173 4635 3098 4552 4099 2672 1767 3866 31 935 3866 2289 2674 2400 4795 3574 70 5254 2289 4833 4585 2674 5299 619 2392 4366 1188 4496 4302 3446 90 2291 1375 53 93 2291 92 91 93 2291 51 92 1377 2291 53 1375 2839 2869 1877 2023 4019 3403 3100 3710 3521 5024 900 906 1749 4937 907 1303 903 2650 2387 2293 19 3283 898 2294 1733 3881 2139 2384 3283 904 19 1688 2388 2295 1745 2129 1745 2295 2125 2129 1745 3442 2125 2295 2295 903 1302 2125 2389 3442 1745 2388 1302 2295 1692 905 4510 4896 4511 4575 1330 2471 1376 1375 2469 1875 1370 2296 1875 2469 1370 1080 3200 4894 3108 3705 2300 81 83 2297 1059 3587 2829 1058 1072 2465 1369 1365 1483 2298 84 86 1070 2847 1367 1072 621 2299 1694 2293 4172 4643 1670 1828 1364 2300 1867 2297 2300 2509 1867 83 1866 2300 1364 1362 2300 4893 83 1867 952 3540 2403 3391 1694 2302 22 1693 5478 5085 5327 5342 5183 2189 3934 2949 1638 3593 3592 1074 902 2302 22 1304 621 2302 1694 620 1849 75 72 2306 621 2302 22 1694 4862 2028 2998 3739 909 5567 25 5416 5430 27 29 1306 2654 1752 911 908 2654 5567 5416 914 909 2304 25 2303 908 4348 25 2304 4705 2661 2654 2655 911 2654 908 909 2656 4787 22 1689 63 1348 1346 2307 3285 2048 1042 1847 4635 5181 4818 2806 73 5743 5442 1029 4565 643 638 4303 3454 1357 1848 1355 2173 3453 2089 1357 1841 2797 1354 1035 1347 2307 1346 1834 2307 1346 1834 1348 3395 5724 2870 3961 3333 1018 2775 2772 3133 1832 2307 2770 65 2770 2307 63 2153 4536 1839 1840 1841 2796 1842 2791 2797 3381 2310 2800 3065 5536 736 5531 2309 3636 2434 2758 2943 4935 4386 2360 3894 2797 2310 1842 638 4912 4565 4472 78 4434 3910 4810 2223 5187 2426 1813 2169 3416 2309 2579 4833 2289 2358 2400 1007 4824 3861 2433 2308 3089 1842 3086 2306 3906 2305 72 5945 5982 5902 5973 4695 71 69 4928 2659 3742 3525 2661 3972 2311 2392 25 1009 4492 3362 3973 3461 4366 3862 3526 2692 3388 2404 2255 54 2424 1379 96 54 4446 2421 2473 988 2729 1807 989 1806 2726 1807 1808 53 2472 93 51 3973 1009 1007 3362 1726 3425 3229 2878 2446 4670 1035 1031 3551 1330 51 2291 2737 1801 981 2316 617 4056 616 2679 3642 2726 1806 1808 978 3382 3325 3166 3466 1331 3166 3382 1377 2416 1330 1375 50 2471 48 2416 5006 4822 0 1371 3382 3466 1331 2861 981 2737 974 967 2685 3781 1318 2682 3321 1591 139 1997 4581 5187 4992 3831 3828 2721 3157 2751 3558 2937 1813 2078 1661 3559 2567 2858 1951 2915 1969 1115 617 4842 616 747 745 2323 746 615 1870 4819 2843 2103 3280 4140 3289 3183 2584 3539 2408 40 4847 4816 2192 4640 3726 5154 1743 4700 1199 4239 3495 3329 744 2323 745 614 741 4842 595 739 797 5080 2355 2901 743 4842 746 742 602 4842 557 493 726 5683 5321 3078 5098 5815 5764 3147 587 4842 586 2323 2604 698 549 848 5110 2851 2324 2332 4842 2324 602 4204 2899 709 579 2784 2733 2567 2736 3834 585 4842 759 761 709 3066 712 2899 745 4842 742 746 595 4842 594 739 4953 5508 2582 5110 3797 5172 2840 4665 837 3549 2248 613 4913 4279 4628 4133 614 5321 744 2323 834 4990 2679 4283 3078 780 566 778 4842 719 2355 584 2573 3961 3395 2870 594 2355 784 593 1853 3906 3571 2048 848 3473 573 2901 781 3078 2355 779 2355 766 765 530 596 3078 778 779 2355 529 530 665 2355 665 666 662 630 5114 629 799 661 2355 505 659 650 2355 648 504 707 2604 703 551 790 5080 793 2901 2271 2338 624 2327 3093 2338 2271 2327 557 5080 717 556 803 5114 802 800 554 2901 767 763 714 2604 598 582 4018 5425 3199 5368 842 3262 2605 2594 599 5299 3778 7 923 5646 5571 2287 2837 4144 3924 3310 31 5357 3363 1760 2630 5423 874 3514 5214 5548 4600 5483 617 4954 572 4885 2603 4604 3613 802 5191 5088 4189 4533 3527 3883 846 2392 3447 3504 3249 3214 623 3338 2541 798 3209 5299 2876 2603 1683 3338 643 838 4609 1699 2888 2380 5299 599 714 598 550 2604 551 703 801 5487 630 5114 622 2604 621 707 620 2604 705 706 3267 4485 3710 3186 4725 4284 3320 3770 5705 1349 5781 5817 1709 3502 1703 2606 2105 4819 2843 1870 4133 5203 4251 4276 633 4565 808 4472 705 2784 701 2604 827 3865 1015 4636 3991 3831 3319 4992 580 2784 751 579 2899 576 575 789 5483 5842 5459 5779 698 2784 848 2604 711 2784 709 712 576 3066 2899 788 4397 5299 2380 1646 2899 5299 577 4839 620 2604 706 621 2799 3571 1353 2785 620 5299 705 2604 702 2604 700 703 2095 5032 4840 2337 708 3473 579 2901 617 4954 747 572 3064 5023 3539 4057 2372 5604 5342 5478 801 5114 630 799 2851 2324 602 1637 2947 3694 2195 478 3623 2241 1773 3367 2085 3155 2868 2417 3858 5400 2914 5184 2896 1318 1774 2685 1773 2682 1774 1318 1774 2401 1317 942 2335 2401 1318 38 4656 2679 1675 4216 1782 2402 1783 1778 36 2688 2335 38 5555 3530 3436 1763 3251 3806 2787 2788 2710 4457 4295 3548 2095 5032 47 4840 2012 4843 1107 4841 5401 3549 5321 5168 624 5130 2341 5107 4614 4615 3621 4263 3085 2895 2249 1600 2271 2341 624 2338 2271 3093 2341 2338 1204 4323 624 3773 3082 2911 1109 3079 3093 3413 2271 2893 4552 3363 3900 4099 1253 3083 442 1252 3083 2008 2249 1890 1755 5484 5429 912 4406 4708 3755 30 4554 4672 3209 3429 3840 5089 4765 2726 3966 30 32 4408 3429 928 3533 3754 4387 5088 4208 3780 925 4407 2340 1308 5273 3773 4661 5107 2271 3773 2341 1204 1204 4661 4323 3773 625 2891 2347 2345 3773 5519 4661 4323 3755 4406 2668 2975 3433 5114 646 2603 1307 2668 1765 2343 1761 3532 3203 2340 2340 5422 29 5356 2426 5187 2427 1813 5266 5269 29 5018 3879 839 3678 842 2891 625 2347 1205 625 2349 1207 2273 839 2347 1206 1205 2150 3502 3 2494 3490 4624 625 3653 4583 4908 4584 4480 1206 3068 2347 839 3672 2341 1204 2893 5556 5235 625 5467 2347 5106 3068 625 4205 5093 4848 1699 1317 4989 3536 2761 1207 3492 2273 2349 2273 3476 2605 625 841 2351 2281 1208 2281 3262 841 2282 903 2650 2293 2389 1908 4851 2959 2946 2281 1209 1208 2351 3476 4375 841 3486 1207 3492 841 2351 4379 3488 2273 3490 1207 2351 841 1208 1686 2351 1208 1209 2273 2351 1208 1686 5526 4505 4169 4166 2360 5615 4935 4386 2255 4057 2163 3064 2168 3027 950 2961 5139 5310 5069 5182 4382 4341 3863 3493 4207 2023 5206 1368 3522 1747 1301 1300 2390 2389 22 2650 21 4384 1748 1747 2652 4161 1751 3718 2223 4185 1665 3558 3328 4386 3815 3496 5021 3563 3014 3826 635 5311 809 811 3496 2206 1200 1201 5173 4518 4121 3878 1820 4134 2854 2430 4130 3843 2715 2726 615 5321 614 2323 3472 5223 811 636 736 3074 735 732 667 2355 663 511 491 2355 542 522 841 4678 3262 4365 684 2355 681 685 2355 681 515 849 2355 696 693 692 544 2901 796 2355 797 2355 543 544 595 2355 2323 781 4692 5253 3363 1698 4429 1019 3647 3873 2662 3962 2394 1764 1767 2358 935 1770 1065 4603 3629 3269 5831 3808 2172 4537 2444 5355 4651 4586 3536 5199 1317 3485 5060 5915 5683 606 3078 727 561 723 736 5532 610 735 3864 827 2769 2768 4267 3991 3831 3319 2212 4781 1016 2870 3989 5536 610 4226 1353 4353 3571 2555 3289 4140 2354 3961 1814 5187 3991 4992 1016 4781 827 4780 2943 2207 64 2208 2662 3962 1764 921 1767 2358 2289 935 2358 4924 3920 2662 822 5034 2354 3472 4882 5244 4674 4339 4364 4894 1720 4259 64 2435 609 1825 69 3888 71 3891 3676 5208 4846 4884 1752 2654 4401 908 2357 4679 3961 4079 4244 5375 5148 5363 2273 4848 625 3879 1014 827 2571 2769 787 3078 849 786 4400 3720 16 4080 827 3864 2769 1014 4400 2276 16 889 1966 2944 1913 1965 2768 3864 827 2439 2204 3950 2872 2002 2871 4077 2875 3785 2381 1742 894 2283 3216 1299 20 2131 2361 3216 1740 2131 856 3214 4 2130 2362 3737 3504 3249 1707 2884 2122 2363 2901 791 794 795 3214 3075 2362 2152 858 2363 1707 2122 2152 3130 3075 2126 2550 3503 2980 4 2608 4196 2612 2849 1710 3505 2612 2608 4196 2608 2612 3505 4665 5498 5404 5172 1710 2612 1876 2608 5299 2899 577 2784 857 2608 855 1705 3957 5228 3655 3506 1710 861 857 2608 1635 3780 1 2543 2037 4015 2972 1157 2366 8 5 6 1709 4188 2606 1708 2786 5971 814 5961 2825 3627 1061 817 2545 4389 3228 3778 1285 4188 2617 1714 5397 5595 2332 5351 4 2369 864 1711 1675 5595 496 647 2133 2369 4 1636 2369 4 864 2133 2368 2880 2370 2149 1683 3968 2898 3338 1712 2970 2140 2616 1153 4021 2971 2026 3462 4389 3508 3655 3462 4389 862 3121 4008 2968 3509 3511 327 3698 1513 1168 4829 4600 1079 3612 869 2621 2551 7 8 2371 1289 6 2364 5259 4076 4943 4687 866 3511 4652 2126 2884 2363 2362 5249 5247 4009 3712 5946 5826 5751 5722 4564 4801 3700 4008 1719 878 2115 2373 881 2373 878 1719 4659 4255 3333 2775 5473 2618 2619 5394 599 5425 3696 10 802 5114 799 800 5425 4922 2374 5171 5035 5321 5315 2412 2275 4849 2280 4782 3715 14 1295 17 1086 2879 1093 1999 884 2378 2376 2279 4182 4247 1732 2274 2638 3423 889 895 5895 5929 5911 958 885 2634 889 2377 2639 3716 2779 3704 4397 4677 4601 2380 3256 3502 3047 2150 1725 3714 13 2882 2116 2380 888 886 5078 3999 3707 4148 3231 3716 3240 3704 1733 2645 844 894 1565 4040 1229 3063 2116 2636 2379 2380 2118 4397 13 3714 4507 3960 1299 18 844 1730 893 3723 5128 5836 4491 4082 1733 2643 2139 844 3326 3822 978 2716 5380 4482 5336 5335 5489 1939 2058 4897 4080 1732 895 2642 4881 5177 605 4688 5428 5648 3954 5176 5836 2877 3520 3881 2591 4400 4080 895 4726 4849 2383 16 1725 3231 2882 3122 2619 5213 3613 7 3283 19 898 2593 3875 2654 4401 1752 1741 3219 2283 1742 1691 2600 2595 2389 1733 3219 2283 1741 1733 4082 2139 2643 1748 3963 2353 2386 1436 2491 187 186 23 2491 1436 186 2388 2389 2129 1745 5024 5025 4937 901 3521 903 3448 2387 903 3521 3448 1300 4886 1692 3442 2388 2295 2388 905 2129 2601 845 2390 905 905 2389 2129 2388 2295 2388 1692 905 2389 905 845 1691 904 3072 19 1688 2389 621 22 1694 238 4337 2963 1132 905 2389 2388 1691 1694 2650 2389 2299 621 2389 2293 1694 1692 4886 2159 1691 891 3072 904 2651 905 2650 2389 2390 2650 900 2387 2299 915 3461 2392 2657 1695 2807 845 2596 2299 3733 1694 2650 2660 915 2315 2391 3640 4925 2395 1307 1696 3745 3528 3688 25 3883 3527 2392 4366 5299 3972 2392 2278 3465 2660 2315 915 3461 2657 2391 3729 3430 19 3225 2215 2393 917 2392 4608 5504 2374 4606 1764 2662 1767 1770 2662 1764 2146 1770 3051 5048 3946 836 922 5570 5412 1308 5339 5463 4160 4927 923 2665 926 2395 4553 4876 2243 3761 3506 4462 3655 3462 403 3977 3026 3024 4072 4646 4073 3059 2916 1967 1124 4049 5666 5218 1786 5496 1777 2680 1769 945 3760 4553 4073 2239 2671 4369 2333 2691 2760 3825 3209 847 2949 3794 2845 2055 35 4014 3781 33 619 2764 28 2876 2874 1312 934 1314 2616 3364 1712 2970 5610 5092 5323 61 556 5080 555 760 5898 38 36 5852 4038 3058 3010 2051 942 2688 2401 1317 1782 2402 1778 2110 2402 3187 1783 1780 3343 4518 2444 4432 2694 2402 1783 2109 1783 2402 2110 2109 3391 3538 949 2403 3391 3783 949 3540 1677 2255 2163 2404 3540 3790 952 3392 5002 5361 4413 4750 1676 3064 2404 2163 849 3074 589 771 949 3388 951 3351 835 3540 951 1676 5496 3671 5136 4769 2867 4210 1785 2408 4411 3356 44 3798 4411 3356 2696 2406 4147 954 1787 957 2409 4615 2268 2407 1785 2926 2867 1323 2108 2407 2405 1322 2265 4212 2408 3980 1819 2751 2721 2070 4919 5315 2323 2324 40 2408 956 1785 2409 4919 2867 2264 1077 3400 2301 3198 2409 2867 2698 2264 2794 5663 832 2585 4919 2264 3671 2794 957 4312 43 1787 2099 2702 961 2410 3427 5452 4412 5035 5895 5927 5849 5903 2094 3178 2413 2193 2269 2700 614 2412 2413 3409 2270 2411 1284 3923 2 5036 614 2749 958 46 2413 3311 2193 3178 3978 4741 2921 961 2906 3546 48 2711 3818 5277 4154 4738 1377 2416 1375 50 4275 5686 4799 5240 5145 5216 3811 3550 970 4915 2414 973 970 2414 1795 973 4004 2203 3823 2565 2085 2862 2415 1803 1375 2471 2470 48 2223 3468 1814 1339 2415 3174 2868 1802 2392 4366 5480 5886 2775 5282 5276 2848 2200 3174 1802 2719 1330 2471 1375 2416 2318 2906 2720 2705 2200 3389 2415 3174 2221 4421 55 3291 2715 2085 3843 2738 2200 4167 3389 2719 3390 4145 2851 3612 51 3467 1329 1330 2868 1332 1329 2417 1801 2718 2250 2717 2419 980 1329 1333 1331 2419 2317 1329 1331 2419 1333 2317 1330 2419 1329 2317 2316 2250 981 2420 2718 1801 49 2717 1378 2472 2421 94 1333 3466 2318 2720 54 4446 2473 56 2905 4445 53 2421 2314 3099 2905 1808 819 5311 3472 821 3147 2721 2070 2745 2424 97 59 1379 59 3148 2424 1816 97 2424 96 1379 1670 3564 4169 3277 4126 3847 998 3556 995 2743 2425 2220 992 2743 2225 2425 4217 1411 3597 2485 2427 3675 1662 825 2223 4992 3468 4581 2319 3468 1816 2312 996 4422 4271 1819 3286 4185 2426 1664 2233 4178 3014 2428 2743 3352 995 2425 4660 5537 3942 4515 4553 4646 3854 3760 2066 3853 2428 1822 1664 2803 2427 2426 1793 5358 2099 5292 1830 4773 3859 4423 2076 3463 2988 2075 2066 2430 2428 1340 951 3539 3351 2404 5397 5595 2603 2329 3536 5199 2688 4547 61 1006 4775 5439 3826 2428 2754 3014 4424 3280 3183 3563 4140 3289 3183 3961 3650 2427 58 2431 2431 5355 3650 2427 1820 4134 2430 3989 2431 58 1662 2427 2431 58 1002 1668 2860 3945 1 2543 3290 4000 2196 1274 2464 4514 1068 3184 2839 3143 87 2855 328 4135 1509 4032 2170 3851 2432 2754 5610 5830 4988 610 1829 3859 2433 62 934 1312 2874 3435 3652 4294 826 3434 2066 2754 2428 2233 4059 4722 1950 3979 1905 4083 4052 3757 3407 4316 4173 3926 2437 4906 1831 4610 2943 1344 2207 2210 2933 405 235 1956 3566 4505 3564 2931 1345 1827 62 2436 1016 2437 2212 1831 1835 4611 4458 4292 2437 1019 1016 1346 2775 5276 3993 2848 3995 2956 1134 3994 2626 5425 10 2776 4260 4781 1016 4780 2571 1014 1018 1832 4301 5003 1316 3766 2870 1016 2212 1831 2360 4430 4087 2439 64 4753 827 4430 3261 3897 2801 3625 2209 4254 2357 3332 2768 3864 2439 2438 4255 2775 2772 3333 1672 5536 3751 5531 3647 2439 2357 2870 2206 4318 3496 3331 2189 3188 1837 2845 2055 2845 1837 2442 3751 5355 3343 637 2442 4865 3794 1349 2189 3188 2845 2441 5352 5799 5160 5148 2444 3343 1024 2783 2441 3253 2443 2845 4031 4998 1033 2788 3888 4865 69 4802 4521 2844 2157 2443 5188 5546 5493 5078 3879 839 842 840 5355 2444 4651 3961 3343 5724 3751 2444 4790 3878 2216 4432 1943 4350 2530 3606 5781 5855 5835 5811 2789 5776 2801 3897 2445 1030 1034 1838 4536 5694 4060 4539 1030 2446 1035 1031 3385 5240 3260 4225 1848 3817 2447 1852 1851 2447 1852 1846 1356 2447 1848 1355 3576 1041 3294 2448 3820 2173 3577 2806 1044 3576 2812 3294 76 2448 1041 2178 1343 3983 2237 3416 1167 334 3127 3172 3415 4635 3933 4385 3295 2182 2453 76 3301 3702 1046 3580 2817 4314 4149 2184 2046 2450 75 1358 2818 77 2450 2816 1359 3030 1854 2452 1049 5386 4743 1047 1652 4230 2449 1850 3297 5060 3299 3578 3719 4493 4043 4497 2453 3578 2560 76 2453 5321 3938 3295 2557 5061 4512 79 3578 76 2171 3293 5321 3938 5311 3578 4293 3578 2185 4230 2183 2453 76 1649 1854 3123 2452 3030 79 4856 4512 4065 2407 3124 2108 2926 3928 78 80 3910 1858 3582 2948 1050 3909 4816 2819 2457 2177 4322 2457 2564 5589 1858 1050 3109 83 4682 81 1860 5407 5731 5619 5640 1052 4437 3306 2820 2952 4435 2837 816 4505 5526 4630 4166 2199 5281 5125 976 4001 4503 1564 4040 1062 2824 817 1060 4960 4201 3684 2881 1941 3005 1187 3177 2554 5491 3934 5222 4543 5118 4475 4603 3793 2832 3264 2831 2826 1062 2165 2459 2460 4211 2166 1864 2459 3588 3272 2826 3027 4498 3275 1779 5589 3312 1051 5445 3273 3797 85 2460 2832 3793 2161 2831 2819 4816 2458 2457 1059 2829 1066 1058 85 3273 1066 1073 2461 1058 85 1066 823 1200 1199 3495 5523 4299 2739 5211 70 2189 1647 1648 1877 2852 1871 1078 3184 3930 3224 3929 3930 5178 88 4737 3397 2839 2292 2852 1639 3788 2853 3787 87 3445 1365 1366 288 2512 1366 1483 2840 5421 3288 5110 5132 4958 4455 4456 1365 3591 1366 3445 1483 2511 2298 86 3540 3539 40 3783 1061 3915 3627 3106 5104 5505 2840 3932 3273 85 1066 2461 1869 4735 1073 2167 2461 3273 85 2460 3450 5803 3947 3279 5381 2860 2543 4145 3787 3945 1077 2857 1373 3594 2468 0 5227 5552 5226 5458 1370 2864 2469 1371 2937 1339 2576 2223 1373 4959 2468 4444 4922 5425 2374 4393 2296 2469 1372 2468 2613 5398 2367 4388 50 2471 2416 1375 50 2471 1375 48 2472 95 93 92 95 2472 1378 94 93 2472 92 51 2421 2473 94 54 1834 1018 1833 1347 56 2473 54 1379 93 2474 1380 92 100 2474 99 1380 102 2475 112 104 110 2475 103 111 104 2475 105 103 112 2475 113 104 5175 5352 3636 5009 2477 116 115 1389 119 2476 116 1390 124 3596 2476 125 125 2477 2476 123 116 2477 1390 2476 3596 2477 116 2476 124 2478 123 2476 2478 123 1390 126 2477 2478 2476 123 1393 1390 126 2479 118 2479 119 1390 123 2479 127 126 118 2479 1393 119 124 2479 123 2478 124 2479 127 123 1398 122 1395 2480 125 2480 1398 1399 1086 2883 2001 2879 3950 2204 2872 3949 131 2890 2483 1984 1087 2890 1984 2483 1984 2890 1885 1096 131 2483 132 1984 3019 4609 2888 888 2485 4091 2486 1411 3095 1987 1878 1396 1597 2008 1890 3091 4217 1411 2486 3003 144 2485 142 143 142 4923 4306 1414 1411 4217 3597 3090 2486 3428 2485 144 142 2485 144 2486 3643 4777 4692 4591 3040 3177 3005 1941 4860 2142 12 1292 1112 4706 4217 4690 1888 3003 1895 1411 2019 3003 1895 2016 1416 139 147 2487 139 1415 147 2487 140 2487 1415 139 148 2487 147 1415 2488 2489 150 1420 1418 151 150 2488 1419 2488 153 152 2488 1417 152 1418 1419 2488 152 1420 150 2489 158 1420 1421 2489 161 1420 2489 158 1421 159 1426 2489 1421 159 2489 2488 1419 1420 1419 2489 161 153 150 2489 151 158 164 2490 2272 172 2490 1431 172 170 171 2490 172 2272 171 2490 1432 172 1436 2493 2491 23 2491 3963 2386 18 2491 3963 2493 2386 1436 2491 2386 187 2386 2493 23 1748 186 2493 2491 2492 1436 2493 2386 2491 186 2493 23 2491 1706 3502 2150 2494 4076 5259 4704 4324 1284 4815 2494 2150 2151 3502 2606 3 208 2495 209 200 206 2495 199 207 1444 3600 210 218 3600 212 1444 210 1111 4453 2007 3975 211 2496 212 1444 215 2496 212 211 215 2497 2496 214 219 2497 222 2496 2497 222 220 219 223 2497 1447 222 2498 220 221 218 1457 222 230 2499 1452 218 1449 2498 221 2498 1452 1453 219 2499 222 220 1454 2499 230 1451 1453 2499 230 222 2499 222 220 223 231 2499 230 1454 1949 2500 1897 1114 227 2500 228 1897 1950 2500 1119 227 227 1454 228 2501 2501 4041 1454 1129 3039 2938 1972 2935 2500 3012 228 1119 2505 2506 246 1468 3978 4741 2978 2921 240 2503 241 3398 2319 4581 4378 3468 4398 4176 2276 4045 4043 1907 1978 1979 4063 1461 4043 1979 2007 5001 2249 4453 1907 4043 1978 2959 3602 3917 84 3158 4001 4452 1143 1564 4043 1983 3032 1978 1467 2505 249 248 2505 1465 248 1466 1467 2505 248 1468 246 2506 254 1468 1469 2506 257 1468 2506 254 1469 255 1472 2506 1469 255 2506 2505 1467 1468 1467 2506 257 249 246 2506 247 254 2507 1475 268 266 267 2507 268 2259 267 2507 1476 268 2825 3627 3264 1061 1861 3583 3449 1361 2300 2509 83 1363 1481 2509 1363 83 1071 2834 1069 1871 1481 2509 1482 1363 1362 5179 2830 4129 1363 2510 286 84 84 3386 1483 2510 286 3386 84 2510 1365 3591 2465 1366 87 3591 89 3445 1483 2512 1366 2511 3591 87 89 2512 284 1484 291 2513 1485 284 291 2513 285 2513 284 1485 292 2513 291 1484 294 2514 304 296 302 2514 295 303 296 2514 297 295 304 2514 305 296 2515 303 1488 300 308 2515 300 303 1488 2515 300 299 2515 308 311 303 1489 2515 299 300 1492 3603 308 306 2517 308 307 1492 311 2516 308 1493 2517 2518 315 1493 4030 2992 2028 3604 308 3603 2517 2516 317 2517 2516 315 308 2517 1493 2516 2518 315 1493 318 316 2519 315 2518 2517 2518 2516 315 4020 1789 1325 2094 1496 1493 318 2519 310 2519 311 1493 315 2519 319 318 310 2519 1496 311 316 2520 1502 1500 2520 1497 1501 1502 316 2520 314 1502 1501 2520 314 1498 316 315 319 2521 1502 2521 1503 315 318 2521 319 315 320 2522 318 1508 1505 2522 1508 318 2522 321 320 319 320 2522 319 318 2523 323 2030 1917 2523 1148 2024 1153 323 2523 2024 324 2981 4862 2524 1164 323 2524 324 2026 4489 1513 1938 4351 2526 4123 1185 3002 1707 858 1704 3130 2526 2994 1185 2088 4489 2058 2999 3139 3180 4350 2098 1943 3566 4505 3456 4166 328 4811 2527 329 3177 1179 3040 3005 3180 4350 1943 3606 336 2528 334 335 2096 3606 3180 2529 1188 2529 1186 2096 3605 4136 3236 3159 335 3175 1169 334 4824 5316 5208 4774 3175 1169 1927 1167 3168 334 1173 2530 2530 3142 1514 1173 2219 1910 1142 3607 331 1515 339 2531 1516 331 339 2531 332 2531 331 1516 340 2531 339 1515 342 2532 350 1521 1522 2532 353 1521 342 2532 343 350 2532 350 1522 351 1527 2532 1522 351 1520 2532 353 345 344 2532 1517 1521 362 365 2234 2533 356 2533 2234 364 2533 1532 364 362 363 2533 364 2234 363 2533 1533 364 1227 2534 2226 1226 4623 5321 3629 4206 230 3028 1561 232 2920 1554 2003 1900 2535 3608 1563 2950 4572 2412 2193 4068 2219 4966 2950 4296 2535 3608 1462 1563 1884 2536 1991 1984 2535 1131 1462 1560 5346 1963 3063 1964 140 4039 1997 2887 5377 3559 3674 2567 5430 5266 27 5566 1089 2536 1591 139 3094 4890 4690 2539 1407 2813 1110 2537 1407 2813 2537 136 134 2539 1595 136 2912 3768 1253 2908 134 2538 1594 1410 441 2538 1594 1100 1111 4890 3975 2007 1150 1918 2009 2540 4890 4923 2539 2020 3080 3094 1113 2019 2813 4890 3768 4097 3114 3911 3310 3208 3003 4841 2019 1102 2009 4092 1918 3120 2196 2540 1918 1919 2423 5579 989 985 1275 4010 2196 3290 2634 4326 889 3423 2327 2541 1700 624 3094 1113 2539 3080 1077 3400 2865 2866 3503 4960 802 1636 1080 3936 1076 1075 5178 3595 2542 1078 3403 4019 2977 3710 2843 4819 4514 3930 1870 3100 2105 2462 3503 2122 3212 2884 3945 4920 1081 3400 1081 3309 1 2543 2881 3503 2369 1636 3310 4144 3208 1053 802 2544 805 801 3934 1648 70 2554 582 2604 552 748 2544 3503 802 1636 1636 2544 805 802 2998 4862 3739 3463 7 3227 873 872 2617 5 2366 2615 2374 4016 2115 1646 2379 4114 2116 2546 1875 2910 2296 1372 2852 3185 1078 2292 4575 4896 4511 4729 2104 3937 3880 3691 3400 3638 2866 2301 1080 4826 1370 1076 3783 2403 949 2260 2851 2111 804 2548 3939 4575 3782 4146 859 3501 3221 2607 4 2808 858 2611 1642 2611 2549 4 1642 2611 859 2549 3503 858 3075 4 2363 2550 805 858 2135 2551 7 1643 4951 4112 2147 1287 2135 2551 599 7 2968 4008 3700 3511 3241 4186 872 873 4040 4982 1564 3719 2623 4687 1644 2552 5561 870 2187 2552 5736 5243 5688 5608 2274 4849 2383 4247 5250 5497 5091 4881 3108 3200 877 2627 1151 1918 1625 4010 2566 4694 3554 3752 1032 3897 2801 3261 2652 5166 3072 5070 3261 5225 4952 3897 3784 5077 3539 3987 3282 3810 2789 3808 73 5442 2559 2558 4797 3385 4748 4275 1037 5627 5442 5443 2454 5248 3123 4149 1052 4812 5063 2820 2558 1036 73 1037 79 3635 2457 2557 5442 5511 73 2556 2559 1036 73 2558 76 3293 2560 2178 1655 2812 2561 76 2450 3821 3706 2816 3295 76 2453 2560 76 3295 2182 2560 1854 3030 2182 2453 1653 2560 76 2182 2562 3577 2954 76 2562 2812 2561 2802 2563 5589 1056 3109 2852 1877 1871 2839 1055 4435 816 2837 3114 3449 1360 3107 4816 79 3635 2457 3909 4816 2456 2819 1811 2738 2085 2715 3977 403 3026 2917 5770 5866 5862 5818 3677 5167 3645 5235 4934 4004 3326 2955 3645 625 2349 1207 4694 2566 2565 987 5669 3752 3554 2724 4419 2201 988 3642 4581 3489 2319 4378 822 4809 821 2354 3048 4493 3344 4067 2913 56 2424 1816 3157 5246 3552 3828 4767 54 56 4446 736 5536 2885 3078 5367 4527 4764 3838 2202 5189 3031 4167 4092 2009 1918 3290 1662 2568 825 822 2223 2576 1665 1339 2427 2568 825 1662 4540 4425 2357 4294 2356 3815 3329 2569 5134 3434 4580 5017 1018 1834 1832 1347 5868 5916 5301 5881 3234 4684 4179 4190 2231 5053 1003 2577 3720 4400 2642 4080 4178 2432 2233 3014 2357 2570 2569 2356 4795 4944 70 4192 2356 3807 3647 2572 3845 5004 2745 4768 3900 2874 3763 2805 2858 3674 3559 2567 1815 2576 997 1339 1665 3558 1664 2576 1753 5748 1305 4278 2231 5053 2577 61 2400 4833 2674 4803 4312 5044 1787 3396 5066 4642 3892 3651 961 2701 43 2269 4386 3328 3815 3330 2682 4014 2671 33 235 3756 2933 1956 1828 4282 1005 4172 4929 5075 4392 4887 5469 3374 5119 2752 2679 4990 3769 938 2679 5693 4953 5110 4309 3540 3392 3790 4474 4919 4614 3197 1784 3275 2695 2677 40 2584 1674 2408 2849 4933 4920 2608 3540 3772 2266 2925 2962 3493 1748 6125 2706 1795 5050 970 4832 5048 43 961 4344 5482 3418 3266 3539 3890 2795 2582 5049 2589 3667 2588 5437 5559 5436 960 1781 5614 39 4081 960 5049 3408 2701 3886 5401 2412 2590 3667 5049 2588 2587 3159 4124 2061 1189 5050 4612 1795 4157 2696 5292 2697 2702 2703 5049 3406 962 5048 3667 836 2587 4111 4295 2742 3379 5407 5731 5640 5047 2270 4832 2094 2413 2380 3207 886 2636 4326 885 2634 889 3904 895 2591 2382 5210 3420 3869 4726 5625 5176 3954 1699 5176 5581 2277 5428 4326 4400 889 3423 1712 4942 1285 1714 5176 5644 1699 5625 4717 2735 3322 2945 4678 2605 3262 2594 3410 4385 3415 3933 5750 5940 5795 5791 4886 1691 2388 2389 841 4678 2605 3262 1691 2807 2389 2595 2596 3879 2605 842 2595 3287 2389 2600 4402 4348 620 3972 2596 3879 2603 1699 2609 4789 2364 3215 22 2596 1699 2389 2654 2661 2659 2655 4924 2289 2358 4585 3451 3883 25 3681 2603 3681 2598 842 5566 5270 4715 5260 2882 4397 3958 3714 2215 3883 846 2602 3364 2370 2616 2134 2390 2653 2601 905 29 5270 5266 5263 4670 5456 1354 5302 1312 4151 3498 3201 3056 2121 5161 1313 621 6109 6093 6112 906 2601 1695 2390 4680 5602 5459 5596 2215 3883 2392 846 1758 3746 2659 1757 2602 3342 2392 3341 3883 2392 3341 2602 2596 2605 2594 842 2392 4402 3681 2603 2606 2617 3 2366 2273 4964 2605 3879 1689 2603 1699 2596 1151 1918 1152 2049 4713 4714 924 3749 628 5114 629 4565 5171 5504 803 5370 803 5114 3879 2603 799 5114 798 800 2782 4727 3212 2884 2622 4857 2190 2619 5299 2603 2380 1699 492 2604 622 552 714 2784 581 711 4960 3503 802 2603 5368 3696 3199 5111 2604 622 621 1699 492 2604 552 582 3876 5088 4727 4704 2287 4160 2665 2914 5842 5909 2851 5821 2784 705 701 704 705 2604 701 702 3882 871 3246 3117 3760 3761 2239 2672 580 2604 581 749 4839 5595 601 5299 3503 2544 801 2811 627 2604 1699 492 1192 3689 3478 638 4393 5710 5557 5539 5130 4473 624 4571 142 4573 3096 1100 3621 4614 4263 3543 3256 3502 2151 2610 3221 3501 856 2607 2607 852 4 859 3221 858 1282 2611 4 2607 856 2130 859 3501 2611 3221 1705 3780 857 3215 1635 3780 857 1 4163 857 3780 2609 4077 4868 2875 2872 3 2610 5 2151 4188 1709 3502 3256 3 3047 1284 5 859 3221 4 2607 4 2808 2550 858 1642 2611 4 859 5171 5504 4922 2374 3782 4145 3947 2543 2863 4196 2849 2612 2612 4822 4196 4681 4822 5006 0 4831 326 4124 1191 1189 2367 4980 2613 4788 4788 2614 865 3957 1717 2620 1351 2371 3616 3903 2882 3958 5383 5754 5243 5736 2620 2624 1718 2614 4683 5398 2613 4388 4511 5086 4732 4896 5477 5721 5701 5706 4605 3228 4389 4174 2366 5689 5398 4388 5 2615 8 2366 3713 5926 4696 5919 2880 2881 2370 2149 4038 4011 3102 2971 5026 1712 2368 3626 2370 2880 2140 2616 3206 4180 1719 3077 3915 2162 3106 1061 5 2617 2366 3 4343 4730 4464 4410 5299 2619 3778 7 2613 4980 2614 2620 2551 2619 599 7 2370 3364 2616 2970 2603 3613 803 802 2619 868 599 2618 2147 4857 2622 4792 3700 4564 3696 4262 2372 4792 2618 4668 5425 2603 2374 5299 1644 5561 2552 4687 2960 3513 7 871 868 4980 1351 3244 4003 3456 2210 3259 2614 5398 2620 2624 2780 1015 1017 3245 2950 4966 1963 1998 1351 4980 4352 3244 868 3244 1351 871 906 4675 2119 4383 4112 3882 3117 4006 2613 5398 2614 2367 5561 870 867 5426 870 5561 3248 2623 3570 5057 1287 4951 1718 3701 2620 1717 5283 5739 2203 1802 8 4388 3697 6 5505 5104 2840 4664 2626 5659 2776 3516 2626 5425 807 10 2626 5659 4977 3339 2626 3339 807 2776 2629 879 2627 2113 2626 4977 3516 2629 4598 5039 3661 880 882 3204 2375 2628 5040 2112 4395 4394 1999 2883 2879 1587 874 2628 882 2375 2374 3615 881 3077 3875 21 23 1749 2848 3333 1018 2775 4394 2629 4150 3709 2357 5092 4679 4079 4978 2627 2113 4977 4019 4819 3930 2542 4257 5031 4393 4364 1292 2631 12 1290 3268 4417 2245 975 5863 3954 5920 5953 1290 2631 1723 2142 3734 5093 1699 4889 3206 3871 3077 2774 5879 5429 1755 5484 879 3108 877 2627 2633 4009 3705 3712 877 3705 3200 3108 3938 5248 3123 3030 599 5299 2619 3696 879 3705 2633 3695 2634 4120 3220 3713 4849 2280 4726 1690 2635 3518 3425 2888 14 3715 1295 2637 2391 4278 3526 2660 2888 886 2275 2635 884 5427 2279 1728 5076 4891 2374 4887 1646 5205 3119 3703 5190 4458 3340 3819 1293 3715 1295 3237 3680 1684 1699 1685 3514 3813 2779 2631 2637 888 1293 1727 1294 2637 1293 1727 4120 2634 3220 895 4837 4398 4460 4637 5919 1743 3724 2128 70 5059 1648 1027 4398 4837 3869 2378 888 2888 3019 3518 2779 3704 2630 2639 2630 5423 2779 2628 887 2639 2630 1725 2630 3704 1725 2639 2407 3124 2926 1322 3232 2640 1734 890 3729 4340 3717 898 5542 5605 3718 4698 1301 3522 1750 1747 865 3226 873 7 890 2641 844 2640 1739 4340 898 1297 3717 3441 2640 2641 890 3441 1297 2641 2638 3423 2634 889 3722 4400 4326 3423 1731 4080 1732 2382 897 5014 1298 3725 1733 2645 894 2283 3720 2274 1732 3015 2277 5560 896 5428 5544 5797 844 5543 1690 3954 1699 2383 3233 2139 844 2877 2646 20 1299 2131 4439 5717 5673 4211 4347 4557 2283 4328 2645 1733 844 2643 1737 3960 2646 1299 6003 6030 2819 6005 1033 4031 3728 3895 1739 3718 2647 1297 1297 4345 2647 4331 5836 3881 2384 2877 2139 3233 844 2643 3430 3729 19 3520 869 4980 4941 4788 894 2648 2284 1734 3232 2139 844 1733 3441 1734 3225 2640 894 3218 1742 1296 894 2648 1741 2284 1744 3522 2649 1750 4384 1300 1747 3522 3733 900 2390 2650 3809 5982 5540 2050 2650 1694 2389 22 905 3448 1300 903 2387 2650 2299 2293 2299 3733 900 1694 891 2651 621 19 3611 5693 3612 5110 891 2652 621 2651 1876 4933 4920 1081 5070 5374 4161 2652 904 3718 891 2652 915 3741 3527 2392 2390 3448 905 2650 3448 2390 905 2653 1049 5061 1856 4232 1664 2427 3558 4185 4041 5414 4062 3039 2661 4705 26 2655 4402 4787 3875 1689 4405 5432 914 5417 4482 5380 4946 5141 4787 2656 22 3524 3462 4389 3655 1713 2393 2657 2391 915 2311 3972 2392 3461 2215 3342 2393 2392 4983 990 1335 983 3525 2658 3460 915 3460 3741 2658 3527 3624 3862 2657 2392 1758 2659 2655 2654 5686 5240 4275 4225 3460 4648 3527 2658 915 3460 2120 917 4465 4382 4341 2766 4278 3525 2660 1305 913 2764 619 912 4923 3975 4573 3974 3525 4903 2120 3460 2315 3465 2660 2391 2659 3746 2661 3525 2120 3525 1757 2659 1305 4932 4381 1754 4401 4787 21 3875 1758 2661 2655 2659 3525 2120 1757 3210 4776 5043 4333 4409 5218 3356 4411 2406 4290 2681 940 2254 2664 4554 2760 2666 4332 3354 3209 3429 3533 4334 928 3534 3754 4332 3354 2285 3203 4671 3750 4333 3061 4715 2669 3750 2664 5043 2667 924 2665 5267 4160 923 4285 1960 1117 1555 5043 4333 4409 3061 4160 5595 5299 2603 2667 3754 928 3429 5372 1759 1760 1762 2761 5120 3375 4548 5363 5375 609 4087 3857 4160 3209 3753 847 4160 2287 618 3856 4776 4554 4409 3354 3429 2666 3209 2666 4776 2664 4554 2664 5043 924 4333 3534 4332 3429 3533 2314 3099 1808 2313 2998 3172 2073 3053 4552 3639 3763 3951 2883 4075 1585 1993 5018 2340 2344 3203 928 5258 2669 3750 1766 4707 2117 913 3205 623 1202 2898 5260 5270 4715 2670 2139 3232 844 2974 2117 4707 2670 2973 1769 2680 931 945 3760 2239 932 2672 3498 3920 2662 2676 2239 4553 2243 3761 617 5595 5351 496 2673 3866 3363 3762 913 2764 28 619 3866 1767 31 3762 1770 2146 2662 2676 932 3760 2757 3059 1768 5572 2675 2240 5572 34 930 5472 2580 5572 3761 34 930 5572 2242 1768 2677 937 1784 1779 1959 1970 1958 1127 3415 4513 3171 3285 2763 3860 2672 3643 4803 2674 2400 2599 2695 5833 3767 5767 1776 2677 1316 1775 2677 2695 1784 1775 3781 4369 2671 2691 4729 3939 4308 4511 945 5399 3537 2333 2679 5351 2332 617 2686 4288 2679 3660 2265 4210 2407 3980 3775 4953 4410 2679 2679 4204 617 2332 617 4056 3665 616 938 2679 1771 941 2679 4056 2755 3665 2896 3781 2685 33 940 2765 2254 2681 1316 2687 937 943 2689 4273 2581 2690 1302 4465 2159 3442 3337 4431 67 1020 943 3777 2581 37 5199 3485 3536 4373 1318 2896 1774 2334 2691 4014 2671 3781 2685 1318 1774 2682 3155 4934 2868 1332 3849 2689 2581 2690 2683 942 939 1317 932 3760 2672 2757 2254 2765 2684 2253 1316 5003 943 937 2233 3851 2854 3357 940 2684 936 2254 2894 3317 1600 3085 1054 4657 4568 4033 942 3769 939 938 2678 3852 3375 2679 938 2686 941 942 2678 3769 939 2686 2678 3769 2686 2679 3771 2686 939 2683 1316 2687 2677 937 937 2687 944 943 2265 4919 2408 4210 2335 2688 2401 38 3777 4997 943 4273 4282 5440 1010 1005 2688 36 2335 3485 2401 3485 2335 1317 1315 4373 2690 3536 2681 3777 2765 3775 5540 5982 2781 5798 2581 4550 4288 3775 2765 3775 37 2755 3560 4274 997 3847 2681 2690 940 2689 942 3374 1317 2683 4281 4547 2690 3849 5120 5185 4989 4281 940 3777 2689 3377 34 3025 3023 931 1777 2691 2121 2671 3351 2107 2257 3134 949 3351 2257 3134 3930 4344 4017 3224 770 3074 769 768 1778 3191 1782 2693 588 3074 728 589 2402 2694 39 2109 1778 4728 2693 1322 947 2693 953 952 1676 4947 2795 835 2845 3188 1837 2442 3187 2402 1783 2694 2402 3187 1780 2330 41 3187 39 1781 4735 3273 1073 3630 1315 4373 3535 2690 1794 5292 1793 2702 3178 4320 1325 3409 957 4771 2697 4147 2704 3798 3356 2410 4411 44 42 3798 2696 4734 3356 4411 2702 3802 2704 2410 1323 3124 2926 956 2409 2867 2268 2698 2110 2699 2109 39 2405 2699 1786 2108 2413 4068 2193 2412 614 5293 2411 5047 2094 3178 2270 2413 961 3978 3946 2921 2269 2700 2411 614 3829 977 2715 1803 3961 5829 2870 4079 5049 5437 5048 2701 2589 5049 962 2588 5366 2701 5358 5292 1793 2702 2099 2410 4124 2058 1939 2059 4775 5066 5439 5807 2702 3356 2697 2696 43 5737 955 2261 3180 2096 2529 3173 5049 2703 3406 5048 5292 5637 5559 960 3406 5358 2701 4280 4414 5135 4416 4486 3798 3802 2704 44 1820 3357 2430 2854 5192 2705 2720 2711 2712 3811 5192 3545 3833 4579 3379 3663 2716 4576 3824 980 3206 4158 3871 3235 4413 5361 3545 4750 969 2710 971 2709 1820 3989 2227 2431 4651 5355 3961 2354 974 2747 966 967 2709 3349 2246 2742 4999 2713 1800 3805 4111 3116 3805 2713 972 4111 1796 2095 2707 4295 969 2741 3812 2246 2710 3620 230 4296 232 2535 2710 3620 2246 3548 613 4157 2248 1682 2710 3620 3548 2707 3349 4295 2742 2709 1811 2738 2715 2079 3018 4285 1967 2927 1331 3466 2318 1333 50 2906 2711 2720 1799 4915 1327 1797 3818 2713 3805 2714 2338 5509 5130 624 3545 1327 2712 1799 2712 1327 48 2093 2720 3546 2906 2711 5145 4612 4468 4535 1800 3805 2713 2714 4295 4111 2742 3116 2906 3546 2705 48 47 5435 45 1326 2726 2945 1806 2735 2717 5123 2250 4975 2862 2715 1803 2417 495 5683 1663 612 2717 4975 2250 4913 978 3824 2716 3325 2091 3175 334 3168 983 4421 55 991 4973 5089 4908 4765 2739 4721 4532 2716 2716 4420 3898 3823 5713 5288 4653 4764 1077 3945 3198 2857 1350 4751 66 68 1801 2718 981 2250 2415 4167 2200 2418 1802 5283 2719 2203 3822 5189 2716 4253 3430 3729 1734 3225 1333 2317 50 2720 3611 5937 5875 4600 2672 4692 3363 2603 50 2906 2720 2904 1377 2904 50 2317 1810 3552 1335 2721 2070 4649 4193 3147 2858 3347 2174 996 2778 2773 4427 3819 980 3824 978 2861 1760 5357 4099 4927 70 4877 2554 2158 4878 5492 4305 4410 4226 2227 3650 1666 979 5283 2203 52 1811 3829 987 2079 2735 4249 3786 3840 1335 3834 2736 1810 4420 5321 2716 5311 4552 4777 3363 3860 3322 4717 2945 4419 1809 4422 2721 2730 4911 998 4126 1817 4268 4828 3346 2732 986 3839 2725 2733 4579 4650 4529 3379 3099 1807 1808 2313 5334 2086 4024 5330 982 4755 4270 1335 4269 2727 2222 3827 1808 4445 2905 3836 2726 3843 2728 1808 1807 2729 1808 2313 3323 4760 3553 4250 2313 3836 2729 1808 2421 5513 4761 4445 4272 2314 54 2421 1842 4928 3894 71 3837 5291 3552 4763 2223 5187 4992 4581 3464 5291 2731 4272 2721 4271 983 2730 56 5246 54 4763 5291 4767 54 4763 2729 3464 2314 1336 2727 4268 986 2734 4357 2736 1334 3553 989 2731 2729 1336 2314 5291 4272 54 4248 5234 2422 3644 990 3839 2567 55 3835 3323 2733 2736 31 5357 1760 2288 2910 3948 87 3594 2725 5052 3839 2734 2422 5582 2722 3649 2222 4042 55 3345 2733 3835 2736 2567 2733 3323 986 2736 986 3839 2727 2734 2725 5287 4268 2732 4983 4270 4269 4756 4270 2727 982 3327 2198 3322 1804 2422 3450 5006 2864 1371 2423 5632 5579 5578 2422 3322 2201 2945 4791 5602 5596 4895 1143 4853 4452 4078 3322 1805 2198 1804 986 3834 2733 2736 2318 4766 2705 2720 2739 5051 4532 49 974 2747 967 2737 2726 3642 1806 2945 2715 5876 4130 5866 2726 4130 3843 1808 2323 2957 632 2840 5828 5969 5934 5947 4532 5321 2716 4721 4414 5051 5002 966 2718 2739 2717 49 5271 2929 2739 49 1754 5430 29 1306 995 3352 997 1337 3853 2740 2069 1824 4305 4410 37 4730 949 3539 2257 3351 906 2387 2390 900 1796 4111 3379 2708 837 4526 3833 3846 2707 3620 2746 46 2746 4526 837 3549 2710 4295 3349 2709 3379 3833 3663 2741 1337 4355 4126 1338 972 3379 1796 2742 2709 3349 2710 2246 4295 3349 2742 3379 3816 4747 2708 2095 2225 2743 2220 2425 2743 3350 2427 58 995 2743 2220 2427 2743 3847 3352 3560 2743 3350 2225 2220 1667 2743 992 58 993 3560 992 998 3942 5187 3831 2427 2745 4768 2744 3345 3574 4633 1650 2445 3950 3162 439 3069 983 4421 991 4271 3367 4284 2682 3623 3559 5377 3674 4509 1819 2745 996 2070 3845 2745 1819 2721 3942 4515 4378 2803 2745 3845 1819 996 4253 4530 2719 4167 837 2746 46 2707 4300 5528 4139 4157 837 3549 46 2746 2746 4526 4457 2741 1942 4136 3159 1943 2868 1802 2085 2415 1801 2747 2316 2737 2747 4766 3466 3842 4535 5193 4612 4297 5708 5822 5756 5788 2717 4975 2252 2739 2424 4356 3148 57 2194 5340 2072 1939 2987 3557 2740 57 2856 2467 1077 3194 46 3801 964 3669 2686 5469 3374 3771 2467 2866 1077 3194 3544 5895 958 5849 5110 4410 2324 3539 3548 3620 3549 2746 3385 5240 4225 4275 4919 5315 2582 2584 2585 5315 2412 5035 2684 3850 2253 2765 4919 5321 3197 2323 2752 4288 942 3779 4919 2409 2867 4210 4076 5036 3421 1284 4210 2867 1785 2407 3828 3837 3552 3157 1317 3779 3374 942 3360 5616 2759 5362 4428 4431 1012 3137 3014 2754 2233 2428 1830 4773 2762 3859 2293 4622 621 4277 2689 3777 3775 2581 2254 4056 2755 2253 3771 3852 3375 2678 139 3321 441 2536 5464 3537 5447 5220 4874 405 4338 4062 1772 3320 1773 2241 3321 4093 4039 441 3761 2757 3022 2672 2085 4934 3174 2868 4307 139 441 1097 4278 5027 5011 1305 1990 5564 1991 2875 4426 4458 3819 3340 5535 3259 4630 4003 235 2933 236 1130 2759 5807 4775 1006 3361 4863 2759 3656 5807 2759 5066 3360 2640 3430 844 3232 2762 3656 1007 2759 2067 2762 1007 2433 1829 3859 1830 2433 3651 4863 3361 4642 2760 3825 3354 3209 2660 3525 2120 915 3536 940 2690 1315 4246 5200 4991 4284 4989 5120 4548 5119 2681 4281 940 2690 3656 4863 2762 2067 3438 94 54 96 3360 4914 3361 3170 5055 5634 3360 1011 3763 3435 934 2874 934 3202 2757 3022 4151 3920 3498 3639 3862 3624 2657 3526 940 3777 2681 2689 3850 2684 3777 2765 2765 4056 37 2253 2254 2765 2253 2755 4281 5120 4550 3383 4341 4886 4465 4086 2765 940 2254 2684 3777 940 2765 2684 4234 2412 3311 3886 2293 3359 1746 1745 5828 5872 5723 5735 2600 4086 2159 2962 3206 3077 881 2774 1013 2767 1025 1020 2213 3992 3135 1350 4458 4426 3819 4427 2438 2848 2439 2768 2360 4880 4430 3334 31 3762 3363 3866 3516 5624 2626 3709 4257 4785 3661 4393 2848 3333 2768 2769 2943 5297 2208 64 3206 4158 3235 3515 2760 4554 3209 2666 1828 3855 3146 3565 1346 4786 1348 66 1346 2771 1834 1348 3420 4837 2378 3869 2208 4520 3334 3870 2767 4779 1025 2777 2307 3133 2770 65 1018 3333 1832 2772 1020 2777 2767 1025 3993 2209 2357 2360 3333 2848 2768 2775 2773 4427 2767 2777 770 3078 560 773 2769 2848 2438 2768 3333 4659 2571 4636 4386 4258 1201 4256 2360 4254 2357 3993 3994 4043 1978 1979 10 5425 807 599 5425 4785 807 2374 2113 5425 3199 4018 1012 4427 2773 4426 5511 5775 5766 73 807 5425 2374 598 3961 4638 2356 2573 2949 3794 2055 4716 1025 4779 1836 2941 1012 4426 2773 4264 1348 2778 1346 2054 4779 1025 3250 2941 2788 2050 3809 4031 1346 4786 2778 1348 1346 2778 1835 2054 3820 1041 2958 2983 4626 4435 4568 3634 5319 1842 2791 1034 2779 4697 3704 3716 4009 5247 3705 3712 3425 4837 4637 4835 3855 3874 3867 2780 1021 3855 1005 1015 3466 4279 3382 4133 2122 3503 3212 2544 2212 4906 4054 2870 805 3503 1636 2980 857 3215 2364 1705 1707 2884 2782 2122 794 3473 573 574 2901 527 578 488 3251 3574 2787 3426 2784 699 701 2604 3809 3728 2050 3035 2019 2902 1895 1108 2784 580 751 2604 698 2784 574 573 710 2901 708 554 701 2784 576 575 577 2899 576 2784 2785 1029 1844 1843 789 2901 790 792 754 2901 848 527 2901 754 579 578 751 3066 579 2899 704 5299 2784 705 4402 5299 2392 3972 4088 3077 3615 2374 3788 2851 4854 2860 3574 4633 3806 1650 5225 1353 1844 2799 4661 5509 4571 5130 2555 5227 2556 3385 2801 3260 1032 2555 3422 5647 4556 3230 834 4656 2679 3665 2922 5210 884 16 5766 5823 5776 3575 2796 2797 1842 2308 5541 5574 5082 5143 2791 1034 1841 1840 1028 3282 2792 2172 2792 5837 4222 4321 4222 4962 4793 4794 5454 5675 5620 5671 2793 4464 2586 1673 3432 3539 1676 3064 2793 4517 4410 2581 4532 5528 5164 5135 2107 3784 2255 2692 4343 4517 4410 2793 1864 5673 4211 4439 5315 5663 832 3197 3539 3890 2583 2795 3343 4432 2444 3751 4118 5533 5319 2791 5401 5895 3378 5731 5060 5227 2556 1651 1035 2800 2797 1354 2799 4225 3571 3803 2310 2797 2308 1842 2310 2797 1354 2308 3896 72 3803 3571 4159 916 3459 919 3035 4433 3728 2798 3885 5254 4795 5059 5441 2153 1034 5319 2050 5798 5540 5716 2799 1844 2785 1353 2797 3458 2310 1354 1352 3261 1353 1028 3571 2799 1353 2555 3895 4433 2158 2798 2799 4225 2555 3571 5759 4799 5699 4797 1032 3897 3261 2792 2954 3577 1652 76 1032 3625 2801 2555 3887 2801 3260 2789 3385 4748 4275 3575 3897 1032 2789 3808 76 2802 2562 1043 815 2802 1043 2562 134 2813 136 2537 2562 2812 76 2561 5720 4509 5098 5537 996 2858 1661 2575 4648 4903 3460 3744 1845 5982 2781 2050 1845 2804 2055 2781 4586 2444 2574 4191 2201 3642 2945 1806 3363 4552 3860 2672 2805 934 2672 646 2676 4551 2662 3498 3921 4641 3269 3916 3435 3498 3201 1312 1691 2807 845 2389 2390 2807 2596 2389 1715 3510 2623 1716 2550 2808 2611 2549 805 2808 858 2550 4 2808 2611 2550 2048 3285 3171 1847 5766 5683 5311 5060 1172 3172 334 2091 2027 4867 3747 1932 5177 5641 4227 3411 75 2043 77 2810 2040 2997 2447 2046 2447 2997 2810 75 3253 4478 2845 2949 1878 4077 3785 133 5099 3655 4949 3228 2562 2812 2802 76 1043 3294 1355 1041 1044 3294 2812 76 2802 2812 1043 76 3080 2813 3003 1102 1655 2812 76 1044 1594 2813 2539 134 4890 3768 1892 4690 134 2813 2539 136 3768 5001 1892 1598 4097 4923 2813 4890 4690 2486 3003 4217 2912 3090 1894 3003 4923 2007 3975 4890 3079 1413 1110 1109 4501 4891 1646 4016 78 3928 80 3449 4665 2840 3797 5007 2509 4744 2300 1867 2126 3737 2782 2884 5388 1052 4437 3306 1863 5005 4901 4910 1862 2821 2031 2455 2814 4742 2815 2451 2821 3913 2823 2455 87 4207 3445 3143 77 2816 80 2450 2188 5248 3706 2452 2818 1857 2046 2040 2818 1855 1358 1857 2188 3821 2816 3706 3907 2188 3189 2817 1186 3045 2098 3001 2450 2817 2188 1855 77 2997 2818 75 2997 3817 2447 2810 4173 5008 3796 3292 4144 2837 1053 3310 2458 4593 2456 2819 3181 2992 2028 4034 1053 5005 2031 3305 1656 4436 3586 1657 4437 4657 1054 3306 4792 5317 4599 4857 1053 2821 2455 2031 3264 2832 1061 2831 5222 5592 5355 3934 1656 3796 3292 3586 3792 2108 2268 2698 4322 2177 2457 2458 475 1275 476 4000 1863 4743 4901 5005 2837 4144 1053 3909 4742 4810 2814 2821 1863 3913 2823 2821 1062 4440 1064 1065 87 3591 1366 2512 1062 4603 2826 2165 817 4603 2824 2165 4144 3924 3310 3393 2832 1063 2831 2161 2162 5307 4813 1061 1062 2826 1065 2459 5814 5353 5324 5753 817 4739 2824 3590 2161 4476 2832 3589 2166 4211 1058 1864 3265 4440 3628 1064 3640 5101 3858 4632 4165 2832 2825 3589 4382 4465 4341 2159 3627 4666 4106 4595 2832 3264 1061 2825 1869 2846 1073 2829 1339 995 2576 997 2832 4165 2825 3919 2835 3916 3269 1065 3264 4106 3106 3915 2698 4263 2405 2268 1869 3440 2167 1073 1363 3917 84 1362 1065 3274 2830 1362 1362 4129 1866 1867 5105 5475 5095 1865 4955 3590 3263 3926 3920 2662 1770 2358 3401 4459 3543 2750 5431 5550 3528 5480 1060 5470 2824 817 5064 5350 1051 5307 2832 4441 2161 3919 4129 1362 1866 2830 4649 5098 3147 4245 1363 3158 2833 84 2509 3602 1363 2833 3100 2834 1870 1871 1870 2834 2462 1068 27 5430 29 5266 3272 3804 2826 3588 4641 4958 4456 4215 2835 2459 1065 2826 2104 4607 1874 1079 1063 3106 1061 2831 5453 5620 5142 5520 1871 3267 3100 2834 3539 4057 3784 3064 4437 4588 3633 3634 2455 3208 1053 2031 2061 4872 4871 5344 5776 5823 2789 3575 3159 4871 2061 4044 2034 3582 1858 1050 3106 4106 2836 3915 3264 4544 3627 3799 3908 2034 3164 2838 4735 4108 2841 2842 2608 2863 2612 1876 3877 5538 2964 3934 4735 2167 4108 2842 3403 5206 3710 2977 2106 2840 2323 632 2845 4736 3794 4478 3010 3102 1155 2051 4735 2167 2842 2466 2840 5084 3930 3403 1870 3100 2843 2105 2464 4819 2843 2105 3999 4148 3582 3707 2844 4521 3253 2443 1921 2966 1149 2065 4795 4796 70 4944 4796 4795 5059 3885 1363 5179 1362 4129 2268 3792 2867 2926 4346 4463 4105 3010 4277 4341 3863 2766 1065 3274 1362 2459 3274 3804 3588 2826 3072 5836 3523 1688 2846 4108 3914 3440 4603 1062 1065 4440 3444 4820 84 2298 4385 1850 3453 2173 4784 5297 1005 5056 3630 5593 2842 4592 2969 4346 3111 1992 4485 5206 3710 3403 4456 4641 4215 2830 5157 2870 2573 3395 2848 3333 2769 2571 1018 2848 2438 2571 4822 2849 2863 4196 2852 88 1069 1078 4146 5706 5477 5701 2608 2863 2849 2612 5425 5171 2374 2603 1071 2852 1871 1069 3181 4117 2044 2028 2850 3936 804 1076 2978 4832 3051 4020 1325 3182 2410 1790 3497 4209 1737 3726 602 3307 2851 1637 5009 5352 4202 5158 1077 3787 1639 2853 1894 4243 1112 4447 629 5508 630 810 2853 4896 2865 2860 2408 2867 956 1785 3143 5819 2023 3948 3771 4548 3375 3852 4140 2854 2432 2170 3851 2170 2854 3033 2431 2854 1002 1820 1875 2859 1372 2855 2457 3308 604 2819 2859 3948 87 2910 1875 5020 1874 2855 4732 2547 2851 3304 3947 4729 2543 2866 5574 2111 4825 2850 1077 3195 2853 1639 1077 3945 2865 3198 2857 4545 3945 3789 3789 2857 1638 3592 2853 3945 2865 1077 1639 2857 1074 1638 2956 4063 4043 3994 5377 4809 3942 2427 2309 5109 2579 3567 4760 3323 3830 4250 3942 4660 3284 2427 2996 3004 329 2527 3450 5490 3279 1370 3297 4513 2809 2181 2750 4769 4467 4459 2855 3948 2859 1372 2101 4141 2851 1075 896 4508 3067 892 1331 3466 1333 2861 1 4387 3780 1705 1329 3551 1332 2419 3782 4729 4308 2543 4575 3782 4146 3947 3700 3247 1715 3303 2861 3944 3824 3382 1370 2864 1080 2469 3467 51 1329 3155 978 2861 1331 980 4468 4915 4535 973 2085 2862 1803 2417 1802 2862 2415 976 1046 3940 1047 1049 2857 3198 1077 1074 2468 4959 2469 4444 2409 2867 2407 2268 3390 5197 5143 4145 0 4444 1373 2 5452 4313 3427 4412 3451 3681 25 2597 2324 4737 1637 2851 2468 4444 2469 1373 2853 3194 2856 1077 1077 2866 2467 2301 5574 2111 2850 2851 1077 3198 2301 1074 2853 3945 2860 2865 3692 5021 3826 4534 1323 2867 1785 956 2301 3638 2866 2467 3390 5143 4825 2850 1876 3400 1081 4920 2865 4729 2543 2860 4196 1705 2365 2364 2023 5819 2839 2869 2871 4077 1995 2875 5315 5663 5035 832 2439 5830 2870 827 3873 1019 1833 1016 1513 3698 326 3139 2357 4079 2439 2360 2173 3820 2958 2089 1083 3095 1995 2871 5502 5714 5517 5689 1085 2875 1589 2018 1084 4077 3785 3949 3730 2381 1742 3500 2873 1251 439 2204 1093 3011 1091 2879 2501 4041 3012 227 30 4708 32 4723 2481 3950 1086 2002 2290 5253 3363 4591 4804 1040 3118 1358 1881 2875 1990 2018 2875 5255 1988 1990 1298 5709 1740 2361 2018 2875 1250 1881 1990 5564 2875 5255 3060 5564 1593 2062 1588 2875 1881 1250 2000 5564 1085 1593 1881 3609 1588 2871 496 5299 618 1698 5299 2876 2603 2392 2285 3688 1697 3528 5906 5958 5940 5957 2666 3354 3209 2760 1699 621 19 2877 621 5128 2877 1699 5837 4794 73 1036 2877 621 844 622 1905 4083 2932 4052 3573 5254 2158 3574 3722 3720 4400 2642 3720 3722 16 3735 1091 2879 1999 1093 2886 3518 2635 888 3959 4075 3956 2883 3956 4075 3955 2879 1999 4075 1585 2879 3011 3956 2879 2883 2370 2880 2616 2134 4160 5595 2603 1698 4289 2149 1711 2369 1725 3240 887 2639 3503 5595 2881 3618 3206 4088 3515 3077 5317 4792 2619 4857 4960 2881 2134 1636 1725 2882 13 887 3204 4074 13 2375 3616 2882 887 3204 5906 1305 1753 5839 4088 5087 5076 3615 2380 5205 3958 4397 1587 3950 1585 3069 858 3503 2550 4 1999 2883 1086 2879 1092 3959 2873 1993 2883 4075 2879 1585 2874 3639 3498 3951 2883 1086 2001 2481 2980 3503 1636 4 2860 5381 4208 2851 3618 4 1641 3302 3505 5036 3421 4076 3078 768 770 561 735 3074 734 731 2152 3737 2362 3249 2122 3212 2884 2782 2884 1707 2126 2363 5355 4140 1662 2431 3074 735 732 731 849 3078 728 2885 735 609 734 5532 562 3065 592 2885 3078 787 563 564 728 3078 563 564 1413 3079 2813 136 5532 494 637 608 769 3074 771 590 3425 1726 888 2886 3078 787 783 786 2591 5427 4726 16 560 3078 720 559 5536 736 610 611 4093 4095 1996 1885 441 4039 3321 139 4447 3597 4217 4096 1984 4095 4039 1885 2486 4690 3003 3094 3420 5210 2378 884 3207 2888 1699 2380 16 4726 2591 2383 4726 4398 4045 4460 3207 2275 1699 2888 4798 5920 1684 5900 3019 4460 4045 2888 3243 4183 3226 4170 886 2888 2380 888 2061 4046 3020 4044 441 4093 2889 3965 1315 4273 1316 3377 1097 2889 1886 441 131 2890 1984 1096 625 2891 624 1205 2341 5130 4661 5107 2347 2891 1205 839 2327 5509 624 1700 3270 4474 3197 3980 30 3966 32 3755 1098 2894 2011 1596 2894 3317 2022 1600 4093 441 2889 2010 1596 2895 1099 2894 3093 2271 2341 2893 3085 2895 1600 2894 2341 3672 1204 838 3003 3094 1895 2486 2011 2894 1100 1596 2249 2895 1890 1600 1100 2895 1600 1890 1596 2895 1100 1594 1098 2897 2011 2894 2895 1100 1600 2022 1318 2907 2335 38 2907 3781 1318 2896 3376 4994 441 4291 1098 2897 2892 2011 2022 4286 1100 1887 2332 4410 2679 2324 2897 3085 2894 3084 623 497 1202 2898 623 4303 628 497 1202 3205 2898 1683 1202 2898 643 1683 1209 4376 2281 4375 4224 4565 633 4472 2898 3968 623 3338 1192 3689 638 4466 2901 792 795 796 710 2901 554 555 797 2901 796 793 2901 767 528 553 848 2901 2355 657 2077 4843 1102 1106 788 5080 571 790 577 4885 572 788 794 2901 795 546 2901 528 507 488 795 2901 796 545 791 2901 792 795 4842 741 595 2323 2016 4843 4841 1107 708 3473 2901 709 496 5595 4839 5299 2901 527 488 507 578 2901 488 553 1685 4667 2605 4205 3066 4839 2899 577 615 5321 5035 614 2906 2317 2720 2904 1193 3480 634 1194 1195 2903 818 1194 636 3472 2354 635 820 2903 818 1195 3971 5311 819 4845 636 3472 635 811 634 3971 635 2903 818 4224 3480 638 635 3971 3472 2903 50 2904 2416 48 53 2421 51 2905 4840 47 2095 4747 51 3843 3155 53 2719 4530 2418 4167 2422 4639 4223 612 2906 50 2711 48 35 36 33 2907 38 2907 36 35 2334 2907 2335 1318 2335 2907 36 38 3079 1893 1413 1109 3004 3144 3005 2064 2912 4243 2911 1599 2908 3079 2912 2813 2665 3858 3640 2914 4890 2813 3768 2539 1252 2912 1253 2908 1110 3079 1109 2908 4711 3072 3748 4569 1252 2908 2008 1110 4923 142 4306 4573 2007 1100 3096 3975 2912 3768 3003 1894 1894 5001 1598 4243 1373 3594 0 87 3970 1599 2006 2911 3594 1372 2296 2910 1372 3594 2296 2468 1599 3970 1105 2911 3970 1603 1105 3969 446 3970 445 2014 4841 3003 2019 2016 1102 3970 3969 1603 2006 2912 1109 2911 1109 2911 1103 2005 3082 3970 1103 2911 1110 3079 2908 2813 2908 3079 1109 2912 1253 2912 2911 1599 2006 2912 2911 1253 1252 2912 2908 2006 3157 4772 3828 2751 2721 3157 2751 1809 1379 2913 54 56 1335 3837 3552 1810 4409 4985 3431 4333 2916 3076 1116 2534 4903 4931 4648 2658 2927 1124 1967 1123 1898 4049 2920 3076 1124 2930 2927 2916 1116 2917 403 1953 2534 2917 1226 403 1004 3566 1825 609 1896 2918 1969 2915 2739 2929 2252 49 2917 4055 1226 403 1124 2917 1953 1952 2226 2917 2534 2916 2876 5550 2392 5480 1948 2920 2003 1900 1951 2920 1954 1967 1117 2920 1555 2003 1900 2920 1898 1954 3034 1951 227 1967 1227 4285 2920 1555 1790 3800 1789 1325 1950 4722 2923 3979 5048 4832 3051 3946 16 2922 885 884 1946 2923 1901 1945 1901 3012 2923 1950 1946 3979 1901 2923 3012 228 2501 227 3772 2925 3540 40 3778 4488 3508 4949 3540 4947 3539 2795 2863 3400 2849 2866 2263 2925 1674 40 2407 3124 1322 2108 2832 3799 3793 3264 1785 2926 1323 2407 2268 2926 2867 2407 1125 4285 2928 2927 1323 2926 1322 2407 956 3792 2867 2924 1962 2928 2927 1957 1124 2927 1952 1123 3978 961 2412 2700 1957 2930 1553 1118 1961 2928 1123 1962 4994 3376 441 4286 1123 2928 2927 1962 1961 2928 1903 1123 4414 4909 966 4494 3183 4140 3989 4134 4907 5340 1168 5332 3166 4528 3382 3325 2916 3977 2226 2917 4876 2239 4553 2243 2930 4285 2916 3977 1124 2930 2916 2917 2928 4285 1959 2927 1957 2930 2927 1553 2411 4832 2270 2413 3951 4833 4585 3920 3024 3977 3026 1960 4774 5363 4824 4987 1352 3625 2555 1353 3566 1004 2931 3564 2091 4454 3457 1173 4062 4627 4041 405 4240 5390 4456 5179 3988 3036 1129 2934 3988 1119 3012 2923 2501 4041 1129 3012 4052 5268 1129 4053 2938 3046 2935 1980 1972 3758 2214 1562 1972 4310 3039 3990 407 3037 1229 2936 1972 3758 1128 2938 4627 2933 405 2932 407 3037 406 1229 1980 4338 1132 1906 1972 4310 1460 3039 1813 2937 2071 2078 998 2425 992 3556 2937 3558 995 2078 1132 2940 1566 2939 4826 5143 5082 4825 1560 2940 1562 2214 2214 3758 2938 2940 405 4874 4338 4266 1128 3758 1562 1131 2938 3039 1972 2214 2939 3758 1562 2940 1560 2939 1132 1911 2936 3038 406 3037 2217 2939 1911 1566 3752 3829 2079 987 2940 1132 1566 1980 1560 2940 1132 2939 4665 2840 3402 3271 2940 4266 1560 1132 1682 5321 3759 495 1566 3758 2939 2940 3758 1566 2939 2217 1566 2940 1980 2218 2211 4613 4487 2942 4431 1020 3337 2773 2944 1966 409 1965 4026 3743 1171 3457 3567 4504 4386 2953 2435 3334 2360 2943 2944 409 1134 1135 1141 3029 1913 1964 5615 5670 5526 4630 3074 730 728 729 2201 2945 2735 1806 3326 4589 3822 4304 2201 3322 2735 2945 2725 3835 3555 3830 2959 1140 1983 2946 1140 2959 1983 1146 240 2959 238 2503 479 3149 2947 478 1276 3149 478 1277 2194 3149 1276 1277 5332 1169 4686 1939 3407 4436 3585 4261 4302 4496 4044 3446 1276 5344 4871 4872 3585 4261 604 3407 817 4603 2165 603 1228 2950 1229 1971 2535 2950 1563 1911 1910 2950 1963 1998 2217 2950 1911 1229 1228 2950 1998 1229 2950 1910 1963 2219 5147 4503 4078 4001 5147 3601 4329 4067 2963 3050 3048 1147 28 3209 619 2876 3355 4985 4523 847 4919 5321 5315 3197 2952 4002 3924 3635 3678 2349 1207 3677 3332 4538 2357 3807 2562 3577 76 1043 2954 2183 76 1649 2185 2954 1652 76 2185 2954 815 1652 1043 3577 76 1041 980 2955 2716 641 3326 4934 2955 3213 2079 5740 5866 2715 3994 5079 1137 2956 4742 5620 2815 2451 4800 2565 3823 4420 3641 5311 5234 2422 3552 5291 3464 54 2715 3155 2085 2417 5346 2944 2956 3995 3861 5208 3676 4884 2944 5346 3029 1134 3063 1966 1913 1914 1966 3995 2956 2944 2089 3820 2958 2983 4674 5007 3402 4665 493 2957 2323 1658 3356 5218 4411 1786 493 2957 632 2323 5471 5534 1658 2460 3793 4666 3918 3264 3110 4339 1367 3042 2089 2958 2173 1357 3577 815 2562 2954 2173 3820 2089 2806 3400 1876 2863 2849 4966 4296 4493 4040 1851 4804 3118 1358 1983 2959 2946 1908 5213 3882 4792 4006 3882 871 868 3246 4792 5317 2619 3613 3710 5482 4485 3403 4425 5363 4987 4988 5528 1682 4494 4050 1132 2963 238 1147 4572 43 3670 2585 856 3130 3075 3049 3048 1147 2965 2963 408 2965 1145 1147 2963 4066 2959 1983 4184 3101 3102 4102 1560 4329 1132 3050 4207 3710 2463 3494 4737 3930 2542 4019 4521 2155 1022 2157 2039 3062 1916 1915 1921 2966 1624 1149 2039 3062 1915 2065 5128 5844 4508 5809 1645 3700 1644 3303 3290 2009 1918 2540 325 3982 1497 322 322 3120 2967 2009 2967 4171 1916 4092 3982 4171 1916 2967 1739 4340 1297 4331 3511 4652 866 599 3509 3247 1715 2968 1924 4010 1918 1151 4113 2149 4012 3626 4687 3336 3696 4652 4101 4117 3181 2028 1712 5026 2368 2970 3388 1677 2255 1321 1712 2970 2368 2140 2140 2970 2370 2616 2368 5026 3626 4477 4011 2030 3105 3058 3058 1923 2197 2033 2026 4038 2971 2024 1161 3007 1159 1151 4389 4604 3778 2545 2037 4015 1158 2972 2038 2972 1158 1924 1499 4037 323 3111 4403 5096 4366 4658 2664 4671 924 847 1305 4403 5027 5042 3203 4715 3061 3750 29 5266 5018 27 1756 5484 913 2117 3430 3881 2974 3232 4985 4409 4776 4333 3717 2640 3430 844 2840 4737 3288 3930 88 2976 1069 1068 3710 5482 3403 3100 3731 5189 4242 2716 2843 4019 2103 3930 836 3946 3051 2978 2977 3930 2840 3288 3266 2105 2843 3186 5389 5763 5619 5731 631 5421 5104 5097 2921 3946 963 2978 4136 4499 3020 4124 1970 1959 1958 4285 2410 4741 2099 3182 2971 4502 3101 4021 2979 4899 4502 2042 2074 4115 4022 2075 2042 2979 1165 1154 3102 4038 3101 2051 5601 2383 1690 5336 2188 3821 2817 2816 2363 3503 805 2980 2133 2980 4 2550 858 3503 2363 2550 2550 3503 2363 2980 3503 2363 805 2122 1626 4021 2971 2033 4500 1177 1172 3127 2981 1153 2524 2026 2981 4862 323 2524 2971 4502 2042 1154 4862 2524 1164 1504 2089 3820 2983 2171 1177 4500 1172 2985 2999 1937 2994 2088 4026 3156 2984 1929 2027 4867 3740 3747 2998 4022 3739 3053 3172 4500 3152 3127 3168 2995 1173 2091 1172 3152 1171 2985 3052 2984 2988 1929 2527 2996 2064 2063 2995 4026 1929 1173 3128 1925 1167 3126 2312 3976 2913 1816 2985 1177 1170 1172 4026 2995 2984 3457 4034 3126 2998 3128 1170 2985 1172 1171 4025 4500 2985 3152 5179 1362 2830 4456 1172 3743 3172 3457 2075 4024 3175 2076 4024 5488 1169 4566 3175 1169 2986 1927 4024 2982 3172 2986 2074 4115 3150 4022 2740 3853 2069 2987 57 3853 59 2428 2069 3557 2987 2748 4032 4811 328 4135 1170 4025 2985 1171 2074 4023 2073 2988 3747 4034 2992 3181 323 4549 4105 4892 2984 4128 2091 3156 3460 3741 915 2658 2988 3463 2073 2074 2527 4029 328 2996 1919 3132 3125 475 4862 2026 2028 2981 3181 1932 2044 2045 3740 2027 1928 2985 3747 2027 1931 3740 3239 4500 4025 3152 1185 2990 2527 2063 2063 4029 2990 2527 2412 4234 3311 3637 1937 2990 2063 1982 3040 4029 1977 2996 3170 3360 3136 1011 5066 3360 2759 3361 4428 4431 4264 1012 4428 4458 4426 3340 2026 4602 4030 3101 5143 2850 3390 2851 1174 4101 3181 3604 2028 4502 4021 3101 2993 1924 1919 2053 1919 2993 475 2037 2993 475 1620 476 1620 2993 1623 1621 2995 2057 1929 2984 4032 2527 2994 4029 2058 4135 2999 4032 4029 4811 4032 2527 1185 2994 2990 1937 2994 2527 1185 2990 2995 3168 1173 3140 2995 3457 1173 2091 2057 2995 1929 1930 1929 2995 1173 1930 2040 2997 2046 2818 1940 2996 1977 2063 2996 3040 2061 1178 3809 4031 3728 2788 3144 3004 329 2996 2527 3144 3004 2064 6031 6026 6014 6042 2447 2997 75 2046 3130 856 3075 858 326 5636 1510 1504 3165 5998 5963 3006 2998 3128 3126 3053 2982 4899 4116 3053 2988 3156 2075 2074 3461 3741 2392 2311 2988 4128 4025 4026 4022 3172 2073 2074 1185 4123 1937 3002 3075 3130 858 2363 2058 4489 2999 4135 5612 5758 5692 1276 1982 4029 2061 2999 1134 3021 1138 408 4029 1982 2990 2999 2990 4029 2999 2994 1944 4124 3180 1189 1186 3610 3045 3001 1943 4350 2098 2530 1790 3800 1325 3182 3607 3608 2950 1910 3143 5819 3948 2839 3000 3001 1186 2098 1939 3610 1169 3001 1938 4900 2999 4351 3003 1888 2016 2017 3002 4489 2999 4351 2058 4124 326 2059 1938 4900 2072 2999 1894 4690 1112 1892 942 3769 2686 939 1102 3003 2912 2813 2911 3597 1894 3090 2672 5595 4692 2603 2016 3969 3003 2017 4096 3090 1894 3597 2813 3080 3003 2539 3313 4871 3006 4044 4046 4897 2061 4499 2009 4092 3120 2967 4037 1916 1499 2244 3007 1161 1159 1157 1924 3007 1151 2972 4037 1499 323 2244 2244 3007 325 323 4109 4037 323 3007 1158 4015 3120 2972 1159 3007 2972 1151 2969 4010 1275 1624 2030 4011 2024 1922 4593 5071 4322 4740 4010 4109 1161 3007 3010 1626 1275 1625 1850 3453 2173 1357 4493 4296 3344 4067 1145 4066 1146 3028 1144 4883 4451 4497 4485 5482 3418 3403 1564 4503 1229 4040 1918 4171 4010 3120 1163 4463 1155 1162 1161 4010 1151 3010 133 5255 3057 1408 1626 4011 3058 2033 1092 3955 133 3011 1626 3058 1155 3010 4463 4346 323 4109 2039 4171 3007 4010 3057 1095 2000 3011 2883 3959 1993 3950 3050 4337 4329 1132 3011 2001 2883 2879 1119 3988 3012 2934 2224 1556 1946 3013 4722 2923 1556 3988 228 3012 2934 1119 1956 4041 405 3012 4041 4722 1956 4627 2500 3012 227 228 1820 4140 3989 2431 1955 3013 407 1981 3013 3979 2923 1556 406 3013 1981 407 1955 3013 1556 407 4518 5525 4432 5173 2995 3175 3168 2057 3289 3961 2354 2356 2432 4178 2233 2430 3561 1823 1000 3439 4140 4134 3563 2432 1558 4059 1559 1557 1127 4448 1970 3016 2935 4061 1129 4053 5237 2679 4953 4995 1986 3055 443 3017 4035 3101 4184 4101 1885 3017 1985 443 1123 3984 1122 229 443 3055 2205 442 3018 3984 1127 3985 1123 3985 3018 1903 1726 3425 888 3229 2597 3875 4402 1752 1699 4609 2888 3734 4837 2279 2376 2378 1974 3998 1973 3021 3005 3144 1179 3040 1276 6041 1939 2072 3002 4811 4489 4351 2061 5783 5692 5758 4499 4235 1276 2194 4124 4499 2059 1939 2061 5345 4872 5344 2762 3656 2067 1007 2671 2333 2680 1777 2672 3893 646 3022 5117 3854 3761 4553 4934 3155 2868 2085 3977 1551 403 1952 1118 4285 2930 3977 1953 3977 1952 2917 3977 1553 1118 3024 2917 4055 403 3026 3024 403 1551 404 1553 3977 1551 3024 4055 3977 1960 3026 3024 3026 403 404 403 4055 404 3026 1226 4055 1227 404 4343 4464 2793 4410 2961 4464 3027 950 1561 3048 1145 3028 3032 4066 1983 4043 232 3028 1561 1145 1145 3048 2965 1146 1983 4966 1134 3452 3028 4066 1146 3032 1134 3032 232 1138 233 3029 1912 232 1998 5346 3063 4966 3029 1141 1463 1964 2944 5346 1913 3029 232 3029 1134 1135 2944 5346 1134 3995 1141 3029 1135 1913 233 3029 1135 1912 2816 3706 2450 2452 2184 3938 2453 1649 2719 4004 2203 3823 5283 5281 52 979 2948 3585 1050 3582 5321 3295 3578 606 3030 1359 1854 2182 5818 5876 5805 5866 3823 2202 3031 3315 4253 4934 4004 3326 4304 1329 3316 3217 4530 5189 3823 2202 2202 3823 2199 3315 4004 4253 2719 3174 2152 3130 1704 3049 4966 2219 232 4296 232 3032 1145 1138 1146 3032 1145 3028 3539 3432 1676 2583 3033 2431 1002 1668 2431 3033 1662 1668 1002 3851 3151 3357 3141 1817 1341 1340 3851 2170 2432 2854 5131 5803 3279 5701 3034 1948 2003 1949 1949 3443 227 1950 1949 3443 2003 3034 1951 3034 1948 2920 4059 227 405 1459 4539 1838 2154 2445 406 4052 3036 1129 3988 1119 1945 1947 4061 1128 2935 3990 495 1682 642 3759 407 3037 2936 406 3758 3037 2936 2217 4052 4061 4053 1129 227 4062 4041 405 1277 3040 2068 1276 2938 5414 1980 5268 2716 5683 3823 1663 2935 4041 1129 3039 1627 1179 1181 3040 2056 3040 1179 1627 3313 5757 3006 5611 1178 3040 1181 1179 1941 4027 1187 1940 1138 1140 408 3041 5757 3159 3165 5611 3021 1138 408 3041 1974 3041 1138 3021 5114 843 842 2603 4340 3441 3717 2641 1367 3042 2847 1070 3042 4339 1367 2847 5421 5097 631 4957 2851 3390 1075 3936 1359 3115 2452 3044 3043 3996 1136 3994 3996 1976 3043 1973 3995 1137 1565 2956 1569 3994 3043 1137 2218 4061 3046 406 2096 3045 2098 1186 1359 3189 1048 3044 3115 1359 2452 1358 2452 3115 1855 3044 2188 3907 3044 1855 1130 4052 2932 2933 4052 1904 1133 1130 1904 4052 1905 1130 3 3047 5 2610 3048 1561 1145 2965 3344 4066 3028 3452 1145 4066 3028 3048 2094 4832 4068 2413 3009 4902 1144 1143 2963 4329 4067 3050 2965 3048 2963 1146 2061 5758 5612 5757 1132 3050 2963 1147 3183 5829 5347 610 1561 3050 1147 3048 2963 4337 3050 1132 3757 5019 4053 4338 4319 5943 958 959 1707 2126 3130 1704 960 2701 43 5437 4312 5048 3670 836 4572 4832 3670 43 3670 5048 3051 836 3019 4798 4460 2790 4020 4741 3978 3800 3463 2076 2988 3052 2074 3463 2073 3150 4115 5607 5333 1164 3361 5364 2991 4914 1977 4029 1982 2996 2032 4021 3103 3161 4021 4103 3103 3161 2986 4116 4024 2982 2073 4022 2074 3150 3053 3127 2982 3126 4022 3172 2074 2075 1986 3054 1985 1882 1883 3054 1985 1087 3056 3368 3059 932 443 3055 442 3017 1095 3060 1408 3057 2286 4522 1760 3092 4868 2875 1988 1987 2374 4887 4608 5076 3952 4152 1768 4072 5161 3654 3854 4152 1988 4868 1987 133 5066 826 2577 2231 1095 3057 1408 3011 4077 1084 130 1092 1155 3102 3058 1154 2000 3057 3011 2872 139 4307 441 4039 1154 4011 1626 2971 3105 3058 2030 3008 3008 3058 2030 1992 1920 3058 2030 1923 1095 3060 1593 2062 4645 5117 3366 3761 1713 3462 3506 3655 2374 5299 4074 1646 5851 3954 2383 1699 5255 3011 2872 4868 5255 2000 1085 2872 1085 5564 2875 2018 5709 1298 1740 5256 4328 5827 4347 4557 2065 2966 1149 3062 2340 3203 1761 2344 4332 3528 2285 1697 3062 2036 1917 1149 3063 5079 1565 3719 1229 3063 2956 1565 1966 3063 2956 1229 2255 3064 2404 2692 2584 3539 2795 2582 1966 3063 1913 2956 2745 4267 3345 2744 3452 3028 232 3032 79 4816 3924 3909 2255 3064 2163 2404 5814 5023 5162 5077 4114 4560 2636 4336 3666 3783 40 3394 2266 3540 3392 3399 772 3074 771 769 733 3065 730 2885 849 3074 772 3065 733 3074 732 730 567 5683 3078 495 3074 592 768 3065 770 3065 768 2885 849 3074 588 589 564 3065 2885 730 5720 4759 4267 4245 789 3473 788 2901 617 4842 747 4204 579 3473 709 3066 577 3066 788 2899 4596 4816 4002 3924 617 5595 496 1675 576 3066 789 2899 4839 572 496 577 576 3066 788 789 3066 574 575 2899 575 3066 789 791 754 3473 579 3066 709 3473 712 3066 573 3066 2899 574 848 3066 2899 573 751 3066 2899 754 5645 5747 1699 5644 2643 4082 2139 3233 892 3067 896 897 5553 5836 1699 3523 893 3067 1730 892 839 5106 2347 2345 5092 3646 4425 2357 1206 3068 839 3417 3068 5556 3417 625 2577 5092 61 5053 1585 3069 439 1587 1587 3069 439 440 1901 3979 1950 2923 1121 4342 3070 4059 3070 1556 1121 1120 3979 1902 1946 1901 1120 4722 1557 3979 1555 3070 2003 1556 1902 3979 1950 1901 1556 4722 1120 3979 1117 3070 2003 1555 2872 1589 2204 3071 1085 3071 1589 2872 3072 5836 1688 3414 891 3072 2651 19 1688 5836 19 2593 19 5836 1699 3520 6044 6062 6055 6057 5325 5284 4298 5285 4057 2255 2163 2352 41 4081 39 36 4464 2961 2586 950 731 590 729 3074 591 3074 590 731 730 3074 732 729 589 3074 729 590 5532 592 3074 5531 769 3074 590 591 733 3074 730 3065 3074 849 772 771 728 3074 729 589 3720 2383 16 4080 592 3074 591 734 770 3074 768 3065 728 3074 849 3065 592 5532 3074 734 3075 3214 856 3049 2363 3503 3075 2362 2045 4117 4102 331 2126 3075 2362 2363 4285 1125 1959 1117 1896 4090 4049 3076 3076 2916 1116 1124 1116 4090 1124 226 2920 3076 2534 1898 3518 4460 2888 4045 3206 4180 3077 3515 3077 3206 881 2373 2374 5504 4922 4606 780 3078 782 779 3082 3970 1102 1103 558 3078 718 2355 781 3078 782 2355 596 3078 2323 778 566 3078 778 567 494 5532 637 5531 561 3078 723 560 1080 5314 4918 5197 786 3078 2355 782 781 3078 779 782 3078 778 567 597 719 3078 718 720 773 3078 559 777 559 3078 718 558 849 3078 2355 786 567 5683 737 3078 772 3078 773 776 1649 5311 3938 3578 4828 5683 2422 5355 812 5321 5177 5311 1108 3080 2019 1106 1102 3080 1106 2019 1113 3094 2539 2021 136 3080 1113 1106 1108 3080 1113 2019 2813 3080 2539 136 3084 3964 2892 1096 1253 3083 1252 2249 5422 1310 29 4408 2008 3083 1099 1890 2327 3968 838 1700 1109 3082 3079 1893 1096 3317 3084 443 3084 1096 443 442 1098 3085 2894 1099 3138 3965 443 1885 1098 3085 3084 2894 2897 3085 2022 2894 2895 3085 1099 2894 442 3981 443 3317 442 3317 3085 3083 2894 3317 3085 2022 2892 3085 2897 3084 2897 3317 2892 2022 2005 3970 2911 1103 4113 4201 5974 2881 2017 3090 3003 1411 4845 830 639 4574 4841 3087 1104 2012 1105 3969 3087 1104 2018 1590 1089 3088 1250 3088 1882 1590 1591 3088 1991 1089 1590 3953 1089 3088 1880 3088 1250 2018 3953 2536 1591 3088 2536 3088 1991 1591 1088 4095 1996 2887 2308 3089 2310 1842 72 3894 2310 3089 3597 1105 1411 3090 2912 3090 2911 1894 2017 3090 1411 1105 3090 4217 3597 4096 1411 3597 2485 2484 2677 4219 2695 3767 2091 4454 1172 3457 1253 3091 2249 2008 1110 3091 2908 2008 4890 3094 1414 2021 2249 3091 1890 2008 336 2528 337 3372 1252 3091 2908 1253 2007 4923 1890 4097 4243 2912 2911 1894 4423 62 60 3859 3090 3969 1105 2017 5368 5425 3696 2603 1720 4894 2141 4259 3968 838 3093 2327 2338 3672 2341 838 2327 3968 1700 2541 904 3685 3072 3414 1113 3094 1895 2019 2486 4690 4306 4217 1414 3094 1113 2021 4690 4217 1112 2909 1414 3094 1895 1113 1995 3095 1878 2871 1988 3095 1396 1987 4938 4175 4732 4806 3094 4890 2539 2021 4552 4924 4777 4151 2007 4923 4097 4890 2736 3841 2567 3835 3866 5357 31 2288 2975 4712 4708 4406 3670 4832 3051 43 4099 2672 3363 2603 2672 3098 2805 646 4713 28 3354 3825 2715 3155 3843 2085 3099 3843 51 2905 3895 3728 2050 4031 3102 4502 2971 1154 2028 4502 4117 3053 3607 2219 2950 2535 2074 4023 3172 2073 4117 4101 3101 2028 4101 4184 3131 4102 3102 4117 331 4102 1154 4011 3102 3058 332 3102 1154 331 3010 3102 3058 1155 4101 4184 4035 3131 4107 4899 3161 479 4101 2028 3604 3101 2981 4502 4103 4021 478 4103 479 3161 2032 4021 1153 3103 4021 2032 1153 2971 2706 1795 970 2248 2681 4281 2690 3849 3058 4038 3105 4011 1162 4549 2025 323 3102 4038 3058 4011 4038 2026 323 2024 4544 4666 4595 4546 2162 3106 1061 1063 4344 5084 3930 4017 3799 2832 3589 2825 2162 3106 1063 2836 2823 3928 2455 3913 3208 4144 3114 1053 3208 3114 2455 1053 1861 3114 1360 3107 1862 3107 2455 2031 2177 4596 2564 2457 3924 4597 3911 3393 3114 3208 2455 3107 3924 4597 4002 2952 3437 932 2672 2763 4895 3880 4823 4791 880 4259 1720 2141 1347 3873 1016 4260 3108 4150 3705 879 1859 3312 1051 1050 1656 5589 1657 2563 5305 5444 3296 5591 1056 3312 1859 3109 2969 4037 2036 3111 1072 3932 1070 2847 1366 3591 2465 2511 4463 3010 1161 1163 2035 3111 1499 323 1298 5256 5014 897 1499 4037 3111 2036 5128 5836 2877 1699 4037 4109 323 3111 3809 4433 3806 3728 3568 5157 4428 4487 2413 3311 2412 2193 4632 5339 5101 4155 2713 3818 3805 3816 2097 4738 2714 3112 5389 5448 5231 5365 5946 2881 600 4113 3186 5482 2843 3266 1055 3310 1053 2837 3844 5433 3541 5403 2211 3395 67 2942 3921 4958 4641 4215 3390 4145 3612 1080 1359 3118 1358 3115 2742 4295 3116 2709 3116 969 971 2709 4458 4786 66 4751 4477 2368 2970 2370 3336 4687 3696 3700 5754 5517 5529 5165 871 3512 868 3246 2622 4857 2619 4792 3118 1359 1040 1048 2746 3549 46 3620 3512 4668 1287 3246 1855 3118 1358 1857 1040 3118 1048 1045 13 3119 2118 2114 12 4181 1294 3704 3703 4397 2380 1646 3238 13 874 2114 1725 3714 2882 3231 3519 5920 1684 3954 3704 1725 3240 3231 1725 3714 3231 2118 1918 1158 2009 3120 2972 3120 1158 1918 322 3120 2009 1158 3120 322 325 1158 1924 3120 3007 2972 3655 4389 3508 3228 3914 5312 5202 4339 3604 4602 1511 2025 3943 5594 3397 5178 862 3507 3121 2138 3189 2817 2188 2454 2025 1511 323 4602 3204 4397 13 4074 4114 4836 3958 4807 4512 2557 79 2457 1854 3938 3030 2453 3189 2452 1854 3123 953 3192 2693 948 1323 3124 1322 2926 2192 4816 2822 2458 2995 3175 2057 2984 3290 4000 2540 2196 1177 3127 331 334 1925 3172 1167 3127 3175 3156 3172 2075 1176 3128 1932 2044 3172 4022 2073 3053 1176 3128 331 3126 1171 4128 1172 3743 3172 1925 1167 1927 331 3127 1167 334 3239 4128 3172 3152 2028 4117 2044 3128 331 3127 3126 1167 1177 3127 334 1172 3172 3156 2074 2075 2988 4128 3156 4025 3126 3172 3053 3127 2982 3128 1926 3053 1167 3128 331 1165 2073 4023 3127 2998 1926 3128 2979 3053 1167 3128 3126 331 3126 3172 3127 2998 2998 3128 3053 2028 1937 3129 3002 2999 3127 4034 2998 4023 4867 3126 4034 3128 1938 4489 2999 3139 2056 4027 3040 2068 1936 3129 1185 1937 1936 4027 1185 3129 1185 3129 3002 1937 4029 4811 328 4032 4980 3244 868 2621 2152 3130 3049 3075 1942 3606 1943 2528 331 4035 3131 1174 331 4184 4102 3131 3101 4030 2028 3604 4184 3102 331 4102 2993 475 476 3132 1919 3132 475 2993 2053 3132 3125 1919 2772 4659 4520 2775 2692 3388 2107 3351 3245 4255 1015 3870 2371 3246 1287 868 1018 3133 2772 1832 2692 3388 2255 2107 2107 3388 2255 1321 1321 3388 949 3134 1564 4040 3009 4001 2848 3993 2775 1018 5214 5483 4600 5081 4121 5173 3878 4905 2493 4213 3963 20 5742 5362 5634 3136 2759 5616 5364 5362 2450 4314 3821 2816 5616 1006 2759 2762 2759 5616 2762 5364 3170 3361 1008 2991 2673 5116 2674 4924 2211 3395 3137 67 67 4431 3395 3137 3017 1885 1989 3138 443 3138 1885 3017 442 3138 1096 443 1509 3139 1513 326 1092 4868 133 4077 3139 3699 326 2058 3693 4898 2134 2880 1938 3698 1513 3139 2994 4135 2999 2088 1514 1930 1173 3142 2995 3140 1173 1930 1173 3168 3142 3140 1341 3151 1002 3141 1514 3168 2060 3142 1817 3141 1341 1002 1824 3145 1340 2069 2855 3948 87 2859 328 3144 2996 1178 630 3611 801 631 87 3948 89 3594 3143 2463 2839 87 329 3144 328 1179 1941 3144 2996 2064 3144 3004 3005 1179 2527 3144 2996 3004 329 3144 2996 328 1817 3145 1340 3141 2740 3145 1340 1812 1812 3145 1340 1817 1338 3145 1818 1812 4172 1670 1004 3564 65 4483 3146 3565 3874 3245 3867 2780 65 3874 3867 3146 1813 3558 2078 2427 59 3148 2748 57 479 3149 1276 2947 3698 5340 5332 1939 2072 3149 2194 1277 1169 5332 1629 1939 5330 5340 5332 1168 479 3149 478 1276 3694 3153 2947 2195 1172 4128 3172 3743 1329 3155 2417 1332 4022 2073 3739 3150 4433 5854 5798 3806 2073 3739 3150 3463 3101 4862 4030 2026 4862 5636 1504 1164 3151 1340 2430 2066 2066 3357 2233 2430 1340 3151 2430 1341 1341 3151 3141 1340 3172 3457 2091 1172 1171 4128 4025 3152 3172 3152 1172 3127 2311 2392 25 3741 2995 4026 2984 1929 1929 3156 2984 2988 3694 5334 2195 3169 3153 5607 3694 3154 5607 1166 5333 5606 2113 5539 4018 5331 1166 5334 5333 5330 5380 4479 2383 5336 2726 3843 51 2728 2044 4034 3181 2028 51 3551 53 3467 2715 3155 2417 51 1330 3551 51 3467 4034 3127 2998 3126 3172 4023 3239 3127 3555 5367 4828 3838 2721 3157 1809 1810 2840 5321 5315 2323 3158 4744 1363 2833 3602 3917 86 84 4512 2186 4881 4229 1363 3917 3158 84 1189 3159 1190 2061 2061 4136 3159 4044 2092 1182 480 3160 1512 3159 1942 2528 1942 3159 2084 2083 4499 2061 4046 3020 1932 3181 2992 1174 1189 4136 3159 4124 2090 3159 2083 2061 1251 3997 2204 1250 2042 4103 4021 3161 2873 3997 439 3162 3997 3950 2002 3162 3162 439 3069 440 1863 4743 2815 4901 2540 4000 1274 475 3146 4169 3277 1670 2838 3915 3908 2836 5009 4483 1826 3416 4216 5397 2679 1675 3159 4132 3605 3165 1512 3165 3159 2528 3384 978 2716 3325 1331 3382 978 3166 3325 4276 4133 4251 980 3326 3213 3316 3326 4589 4304 3217 3691 4823 3880 4791 4425 4079 2357 2360 3563 4178 2430 3167 2105 3266 2462 3186 3826 4534 4424 3280 2105 3266 2464 2462 2356 3289 2570 2569 4679 3289 2356 3183 4534 1823 3561 3439 2995 3168 3140 2057 4127 4899 1164 4116 3168 4686 3140 4566 3295 3578 2560 2453 1514 3168 2530 1169 2984 3175 2057 2076 1514 3168 3142 2530 815 3577 1652 2954 331 1165 3128 4117 4116 2986 2086 1927 4022 4899 3053 4116 2759 5364 2762 4863 3156 3175 3172 2091 3171 2048 1847 2305 1172 3172 3127 334 73 5915 2172 5766 2048 3415 2305 3171 2173 4685 3453 4635 3405 3940 1856 2815 4136 2061 3020 4044 2028 4101 3604 3181 3173 3606 3605 2529 1190 3180 1189 1944 4132 3159 3605 3236 4036 1186 1628 3045 2096 4350 3180 3606 3181 3604 2028 2992 4702 4136 4044 4496 5942 71 1349 4865 3390 5197 4145 1080 3382 3824 978 3325 2851 5110 2324 4737 1167 334 3172 3175 980 3326 2955 3213 2415 3389 2868 3174 2415 3174 1802 2200 2530 3175 1169 3168 2986 3175 1927 3172 2091 3175 3172 334 335 3175 1167 1169 3175 4566 2057 2076 1848 3176 1043 1357 3176 3453 1850 1357 5134 3973 4774 4846 2173 3577 2806 2449 4900 4027 1982 3129 3409 3637 2413 3178 4154 5575 5446 5277 1941 4027 1940 1977 4027 1941 1187 3177 3409 2413 2270 3178 2270 3409 1325 2411 2395 4632 3640 4155 2270 3409 3178 1325 1943 4136 1190 3180 1793 5292 2099 2702 5407 5731 5047 5231 2096 3606 2529 3000 3127 4867 4500 1177 1932 3181 1174 2045 3173 3606 2529 3180 2556 5837 1036 5225 1793 3182 2410 2099 4741 3800 2410 961 2094 4832 3978 4020 3962 927 1763 1764 1875 5020 1372 1874 3167 4134 3563 3183 3550 5145 4300 3811 4079 2357 2870 3961 2569 5092 2570 2357 3002 4489 2526 4123 3691 4829 4607 2104 2146 3962 1764 2394 3929 3184 3266 3224 2464 3929 3184 3266 4112 3882 4006 4792 1870 3267 2834 3100 2105 3266 2843 2464 4345 4331 2648 3729 2402 3187 39 2694 41 3187 2694 39 2189 3188 2441 1647 3938 4058 3189 2184 1647 3188 2441 1022 3907 1048 3044 3115 2454 3938 3189 2184 1854 3189 2453 1048 1048 3907 3044 3189 2188 3189 2452 3044 2817 3189 2184 2454 1359 3189 3044 1854 4143 5527 4305 5492 3784 2107 2255 3190 3987 2257 3539 3784 592 5536 562 2885 2962 3493 4382 1748 614 2749 46 3193 2865 2543 2866 3400 952 4728 3191 4374 1782 3191 1320 1783 1780 3790 1319 951 3540 952 2266 3392 1778 3191 1320 1782 1782 3192 1788 1322 1323 3192 3124 956 614 3549 2412 3193 2804 4802 2781 4118 5368 5504 803 5171 1791 5849 3544 958 3397 5300 4110 5313 2865 3194 1077 2866 4896 2853 2865 3194 2853 3194 1077 2865 3783 2260 949 2257 4175 4938 4732 4511 3195 1077 2853 2856 2677 3776 1776 3535 3196 3767 2677 2695 36 5852 3767 3535 2677 3196 1775 1776 36 5833 38 3073 3767 3776 3196 2677 5499 5915 5802 4748 2267 5035 43 615 5555 2394 2146 4617 2851 3788 1 2860 3881 1733 2648 2384 3980 4616 3270 3621 3707 1858 3164 3584 2857 4162 3945 3198 2849 3198 1074 2301 3400 1077 2865 3198 855 4933 2608 1081 3696 5368 2619 5111 2629 4977 3516 2113 2629 3200 877 2626 4455 3588 3921 3804 3639 4585 4552 4151 932 3435 2763 3201 97 96 95 3438 2674 4924 2289 2673 3201 3763 3639 3435 3654 5161 4072 4152 934 3368 1311 932 3368 934 1311 3202 1311 3202 1313 3056 2669 4707 2670 3750 929 4714 1766 913 1766 4707 3750 2117 3235 2373 878 881 3616 4397 3204 3958 887 3903 3240 3122 3350 5683 611 2427 4206 4603 3629 3590 13 3204 2375 882 3077 4088 3615 3871 3204 4677 4397 4074 3093 3672 3205 2893 1202 3205 1683 1203 3205 3968 3413 623 3515 3235 2373 1290 4180 2373 2115 3515 1017 3872 2208 3870 1055 3911 3208 3310 4393 5729 5031 5557 3714 5205 3231 2118 4114 4836 2379 4560 1699 3703 627 3207 2275 3207 627 886 816 3911 1055 2837 3209 847 619 618 4409 3431 3856 3532 5542 5621 4698 5374 5426 5677 2112 5040 3460 3525 915 2120 4698 5726 4399 5605 3287 2595 2389 2807 904 3211 1751 2652 3048 4067 3344 3050 2150 4815 2494 3 3035 3728 2050 2798 2277 5176 896 2143 4253 2955 2716 3326 4727 2884 3737 3503 2544 3503 3212 2811 1329 3316 980 3213 3326 978 3217 3316 2724 2079 2715 5740 2332 5595 2329 5381 3737 2884 2362 3504 2365 4196 4076 3505 3214 856 4 3075 2653 3521 1300 3448 4717 5089 2726 4583 1209 5773 5747 1699 5977 5524 5456 5545 5726 2647 3718 1297 3500 5726 4956 4399 1299 3216 2361 2131 898 3718 1297 891 3731 4589 3822 3217 3823 4242 2716 1663 1186 3732 1188 2096 978 3822 3731 2716 3389 4934 2868 3174 2284 4331 1297 3441 1296 3218 1742 1297 3729 4340 898 4331 2648 5836 3218 2593 3718 5726 1297 4399 2284 4345 1297 4331 3638 4575 4220 2866 2611 3501 1282 3221 902 5257 4701 1693 3219 1733 2283 2643 4509 5720 4759 5537 2139 4082 2877 3233 2384 5836 3219 1741 2383 5769 4479 4971 2607 4 856 3221 3641 5073 4800 4420 858 3221 856 4 859 3599 2148 3501 5294 1000 5092 2230 2387 2650 903 3448 1000 4679 3222 4424 4679 1000 3222 2232 3562 4939 3439 4936 601 3618 3503 3223 5174 5615 5352 5375 2640 3717 3430 3225 1710 3505 2608 2365 5161 2757 3854 4646 906 3448 2653 2390 7 3243 3227 872 1995 4077 1987 2875 1898 4049 3076 1896 3232 3430 844 2974 2648 4345 2593 3218 1734 3729 2648 3441 19 3729 898 2593 19 3729 3717 898 4352 871 3244 3513 3227 4170 3243 3226 5771 2842 5733 5703 3655 4949 3228 3508 7 3227 3226 873 4941 869 865 873 4186 3241 872 3455 3869 5427 4726 4398 1305 1753 6021 5957 5781 5679 1349 5705 3229 4460 4045 4176 2772 4520 4255 3870 3425 3518 888 3229 4016 4481 4461 4392 5038 2375 874 3238 1731 4080 3720 1732 5647 3422 4556 5581 4336 5205 3207 3231 4557 4347 4082 4491 5469 2679 3852 2678 2277 5647 2644 5581 1733 3232 890 844 894 3232 2648 1734 1646 5205 4397 3119 3881 3430 2648 3232 3714 1725 13 2118 894 3232 1733 2648 2640 3232 844 890 2571 4659 2769 827 2304 4348 25 4100 2368 1712 2140 3234 2880 2368 2140 3234 2368 4179 1711 1286 2140 3693 3234 1712 4190 3234 3693 1712 2368 4289 3234 2880 3234 4684 2880 4289 4785 5425 4393 2374 1290 4689 1291 1721 1723 3235 1290 1721 2373 3235 3206 881 1722 4689 1291 2141 5252 1291 3235 4689 4136 1943 1190 3159 1188 4496 3173 3732 2878 3237 1726 1293 2026 4602 3101 4038 5075 5373 5354 4929 1999 4075 2100 1585 2375 5373 874 2628 4397 2882 13 3714 4726 2276 4045 4398 3181 4867 2044 1932 4500 4025 2985 3740 2392 3527 25 3741 4023 2073 2988 2989 4115 2074 3463 2075 1725 3240 3122 887 7 873 869 3241 2621 7 869 3241 872 4669 7 4390 5000 4758 4298 4760 4929 5087 4391 4783 3455 4352 3244 3513 3244 7 868 2621 4364 880 4257 4259 3563 4178 3167 3014 1731 4247 4182 2274 871 5213 806 2960 4980 1717 1351 4352 4390 3513 3455 3244 4980 868 1351 2620 873 4980 869 3241 7 3513 3244 871 2848 5282 2439 2768 1015 4520 3865 3872 3494 5206 5163 4207 3246 4668 1287 868 4668 2145 1287 2372 4792 5213 4006 4599 3512 871 868 1351 4498 5466 3275 4143 3882 4112 3117 3246 2113 5624 3199 5425 1715 3700 3303 1644 1639 4854 3902 2853 3336 4687 3511 4652 2112 3700 1645 3300 3248 3510 866 867 9 5342 1287 1288 807 5563 2374 2625 4478 4716 3794 2949 2782 4727 2884 3737 4680 5596 5081 4823 3949 4077 3785 2872 2941 4432 3250 3878 3503 3214 2362 3504 2362 3249 3214 2152 3504 3737 2884 3503 5141 5360 5304 4904 1672 5830 5532 608 797 5080 2901 569 3943 5320 5313 4737 2713 4999 4418 971 2155 4795 3574 70 4999 4417 975 4418 3809 4031 2050 3728 3251 3574 3426 3252 2155 3574 3251 3252 959 3805 969 4999 4521 3253 2443 2156 2845 3253 2949 2189 3253 2443 2845 2844 4173 5546 5008 5451 4603 2824 1062 4440 2152 3737 3257 2126 3249 4533 3504 3447 3257 1704 1707 2494 2824 4603 1062 2165 2189 4521 3934 70 3275 1779 1784 2168 3258 4464 2961 2586 4219 2677 4143 3767 3637 2700 2413 2412 2961 3275 2168 3027 4760 5325 4758 4298 3456 4630 3259 4003 2677 4219 4143 3275 3575 5823 3887 4748 4202 2579 3636 3416 1171 3743 1172 3457 839 4571 840 3879 1033 3895 3728 3573 1032 3625 1352 3261 3625 1032 2801 3261 3106 3627 1061 3264 5172 5321 2323 1658 2722 5149 2422 4639 5709 5882 4834 5820 1656 3586 3292 1657 4165 2161 3263 2160 79 4229 4512 4856 4603 1065 3629 4440 4548 5120 3375 4524 1081 4443 1 855 2464 3929 3266 2843 2462 3267 3100 3186 1870 3267 2462 2834 823 5034 3495 2175 5482 3929 3224 3930 1871 3494 3100 3267 46 3669 3268 3544 1681 3544 46 3268 3631 4624 3653 625 3274 3921 2835 3916 3027 3275 2168 1779 5686 5892 4225 4275 2459 4456 3274 1362 2264 3848 2698 2409 2413 4832 4068 2412 3590 4603 3629 4440 2460 4664 3797 4603 4893 1364 1866 1867 2840 2957 632 3271 1070 2840 632 3271 1070 3402 3271 3110 1867 4744 1362 4129 1065 3274 2459 2835 4893 1865 2297 2827 4021 4107 2042 3161 1207 3492 2349 841 603 4603 2165 1658 3630 4592 2842 3273 2826 3274 2835 2459 2584 5508 5315 2582 4603 5322 4814 5118 5182 5707 5310 5069 5527 5767 3767 3073 2961 4007 3275 3027 3348 3560 3353 2228 1668 3276 58 2228 3676 4778 4492 3362 998 3560 3348 2228 5607 4022 3169 4116 2742 4047 3349 2246 3456 3566 1344 2931 3564 4505 4166 4169 3983 1343 2237 2434 2202 5189 3823 3031 2931 3456 3277 1670 5147 3601 4337 4329 2210 3456 1671 3259 3278 943 37 2256 37 3278 1673 2581 79 1052 2191 4812 1080 4918 1370 4826 3939 4732 4308 4511 3632 4625 3678 3677 3782 5803 4146 3947 4134 4140 3563 3183 2354 3289 2569 822 3289 4679 3280 3183 3289 4679 2356 2570 3280 4679 1669 4424 3578 5923 3901 5060 4513 3410 3415 3933 5853 6017 5887 5949 954 5403 1787 5391 4799 5686 5230 5240 1032 3897 2789 2801 19 3283 1688 2593 3415 4513 3933 3901 3832 3553 986 3323 4697 12 4181 1294 4660 3942 3284 4515 2568 4809 2427 3284 4515 2803 3942 3284 2048 3410 3285 2809 3751 5683 637 5536 2426 3286 1664 2803 2223 4185 3286 1665 2659 3746 3525 1757 2807 4622 2389 3287 3072 3748 3685 904 5982 5902 5973 2781 5166 5530 5295 5329 5226 5545 4570 5524 4324 2782 3737 3876 5533 5691 5195 5694 3090 4096 1894 3003 2977 3930 3288 3403 125 3596 1389 122 2542 4737 4019 3288 1638 2857 1074 3592 1849 3454 1850 1848 3289 2354 1662 822 1821 4423 3692 2429 2356 3289 2569 2354 1275 4010 3010 1625 2969 4010 1624 1915 1624 4010 1275 3290 2196 3290 1918 2540 3291 55 990 2567 4963 5004 1661 4421 4436 1050 3585 4261 1858 3584 3582 2034 4415 4526 2741 4457 3582 3999 3707 3796 4682 3908 2838 3925 76 3293 2178 2171 76 3578 2171 2806 5468 5684 5623 5672 1041 2448 76 3294 1041 3576 3294 1355 1044 3294 76 2448 1043 3294 2812 1355 3295 3578 606 2560 5311 3472 5223 811 3295 2182 2560 1653 4132 3605 1188 3236 4232 5063 4435 3296 1055 4435 3305 3912 5005 5386 4743 5305 1049 4743 2815 3940 1362 4744 2300 1363 4232 5061 1856 3298 2817 4149 2454 2184 3297 5060 3578 4513 2619 5317 2553 3613 1045 1851 2041 4804 5920 5859 5851 5863 1649 5227 2185 812 3297 4293 4230 3578 2557 5061 3298 4512 1856 3579 3405 3301 3897 2556 3625 5225 716 4885 601 4839 2047 3906 3571 1853 1652 3578 76 2449 3796 5727 3164 4870 3578 3938 1649 2453 5061 1049 1046 79 5520 5620 4742 4156 1652 4818 3578 2449 6022 1360 1860 6038 3696 4564 3300 3199 4010 4092 3290 1915 5689 5935 2366 5891 3700 4801 4262 3336 3405 5061 3298 1856 4009 5342 4950 5037 3700 4801 3511 4008 3405 3940 3579 1856 4012 1711 2368 2149 2116 4114 2137 1294 3618 4012 3302 600 3618 4012 600 2881 4 3618 2369 3302 2130 3618 3223 4 12 4860 14 4691 3107 3449 1861 3913 2968 3700 3247 1715 4861 2146 2662 2394 3247 4752 3303 4564 3821 5248 3706 2188 1644 4687 3700 1645 3503 4960 1636 2881 5206 3868 3403 5163 2851 5275 4732 4308 4657 4812 3305 2820 1177 4867 2027 1176 3263 4436 2160 3926 5063 5388 1052 4437 4437 5063 4435 4812 5036 4196 0 4681 2851 3617 602 2547 3936 4917 1076 1075 2456 4144 3909 3308 2819 3308 604 2456 3958 2882 3231 3122 2457 4065 3308 79 857 3309 1635 1 1055 3310 3208 1053 4816 4847 2177 4002 4640 3114 4144 1360 1070 4817 3868 4252 3313 4871 4044 1276 1051 5589 5445 82 2248 5576 2706 837 3178 4138 3637 3311 5748 5839 5795 5750 2697 5618 1794 5292 5618 4771 5559 5292 3544 5873 5629 5777 3178 4320 3409 3637 4302 4702 4496 4235 3020 4302 3313 4235 3159 3605 2528 3165 1628 4496 4235 4302 3314 4757 3315 2199 3201 3860 2763 3643 977 4241 2199 52 2422 5274 1663 4731 2565 5816 2566 3554 2723 4757 4420 3314 3315 4420 1663 3823 3315 4242 3823 1663 4167 4304 2868 3389 5691 2791 4060 5533 1329 3316 3217 978 978 3326 980 3316 1334 3834 2736 1335 3083 3981 1253 443 3317 3085 2892 3084 3317 442 3084 443 2897 3317 3085 2892 3317 4291 1096 2892 1671 3456 3277 3259 3780 4943 1705 4387 227 5013 3034 1967 1344 3566 1004 2931 2943 4168 2360 2435 3395 4054 2870 1672 2220 3991 2427 3350 5377 3831 611 2427 5447 2333 3537 5399 1772 3770 2238 3320 2858 4509 3674 3899 5481 5070 5374 5265 1771 3774 2679 3770 2682 3623 1773 3367 4712 4861 2975 4551 1997 4039 139 3321 2857 4545 1638 3787 5866 5392 5274 5862 4357 3553 3841 2736 5089 4249 4480 4717 4207 3710 2023 2463 3322 2422 2201 1804 3786 4223 2422 2198 985 5579 3380 5578 2905 3836 2421 2314 4279 3466 3382 3944 5657 5011 5027 5418 4276 2716 3384 3759 4628 5204 4913 2316 1032 3889 3572 3260 619 3825 847 3209 1044 4349 2041 3576 3384 3731 642 2716 3466 4628 2747 3842 3822 4934 3326 4304 986 3327 1334 982 3326 980 2955 2716 3731 5189 3031 4242 1118 3977 3024 1960 2727 4270 982 3827 1334 3834 1335 3327 1334 3327 1335 982 3329 3496 2356 3495 3327 4976 3834 1335 1334 3834 986 2736 4386 3332 4318 4258 3328 3495 3329 1200 2572 3496 2356 3331 3973 5134 4425 3652 5775 5776 2556 5766 2679 5351 617 1675 2569 3329 2354 822 3260 4797 3887 3889 2708 4111 3816 2095 3330 4540 2357 4294 3363 4160 1698 1760 2572 3495 3331 823 3807 4318 2357 3332 2356 4318 3331 3496 3994 4063 1979 1137 2438 4538 1018 3647 3647 2356 2870 2357 3133 4636 3867 4255 2775 3993 2772 1018 2360 4254 3993 2439 2438 3993 2848 1018 3337 4432 67 3395 4636 3133 3867 2770 2848 3333 2571 1018 2209 4386 3334 4256 1832 3333 3133 2772 1290 3871 3235 1723 2770 3333 1832 2571 1018 3333 2571 1832 2770 3333 3133 1832 1344 4311 2207 2210 5157 4264 4431 2773 2435 4430 64 2360 3872 4520 2208 3870 2435 3334 2943 64 4311 64 3335 4218 2207 5440 64 5297 3401 4263 3848 3543 4311 5440 2207 3335 5561 4687 866 3248 4687 5561 2552 2623 3300 4965 4564 4752 4687 1715 2623 1644 3888 4802 69 71 628 5114 3338 798 643 4565 638 828 2112 3696 3300 3199 4566 4028 2057 2076 3961 4638 2354 2356 633 4565 628 808 3337 4651 3395 4638 1020 3337 1025 67 4431 3337 67 3395 1026 4586 2444 2574 1192 3689 633 3478 843 5114 840 645 842 5114 2603 3879 3286 4581 2426 2223 876 3661 2625 807 3614 3200 2626 877 2744 4759 4267 3559 3342 3624 2393 2392 2620 3701 2624 2371 3543 4459 3671 2750 4919 4474 3980 3197 1346 4611 4292 4458 2291 3551 1377 53 3741 914 2311 2658 2215 3342 2278 2393 5592 637 4194 4710 1024 3343 3135 2783 3289 3961 2356 3183 3028 230 1561 3344 5212 2891 839 4590 1560 4296 230 2535 3344 1561 3048 3050 2219 4296 2535 232 2219 4296 2950 2535 3344 4503 4067 4296 4040 4966 1998 3063 2228 3675 3276 3560 4527 5367 2567 3835 3320 4284 2682 3367 2725 3830 3346 3324 996 2174 2070 3347 2391 3624 3526 2657 3324 4268 3346 2725 2722 3380 985 824 2745 996 2070 3347 2858 3347 996 2745 3899 2858 2575 3674 1349 4751 68 71 3360 5362 4914 3136 4457 2710 2246 3548 4126 3556 1337 3847 4281 4550 3849 2681 5002 5137 5135 4414 3620 4999 959 969 2741 4457 2707 4295 3991 2220 2427 1813 3650 2225 2743 3350 3350 2743 2427 2220 2427 3991 611 3350 2743 3650 3350 58 4582 5467 625 5167 3560 3675 3276 58 3675 2427 1662 58 3560 4274 3348 3353 2666 3754 3429 3354 3825 5016 4713 2760 3754 4332 3429 3354 38 5898 36 2688 2974 844 19 3430 3761 5472 34 5572 2664 4671 4333 924 4343 4498 4464 4143 922 3355 2663 847 3682 3753 925 3355 3356 4734 2702 3798 2704 3798 44 3356 3356 2702 2697 2704 2233 3357 2854 2430 1002 3357 1341 2854 1820 3357 1341 2430 2066 3851 2233 3357 1002 3851 3357 2854 2759 5807 1006 3360 4863 1829 2762 2067 2578 5055 1008 2235 4622 3359 4086 4277 5508 4953 831 5487 5634 5807 1006 5760 4914 3360 3361 2759 2633 5067 3695 3705 1008 3360 3170 1011 2208 5056 1017 2207 3361 3170 1008 3360 5438 5760 2231 5584 932 3435 2672 2763 3651 2991 1008 3361 4146 5477 3939 3941 2672 3893 3022 3761 716 4954 4885 713 4824 3676 3362 4778 1343 4125 2433 1827 1826 4125 1343 1827 1009 4778 1007 3362 2835 3921 3269 3916 916 4648 4159 3459 4766 2705 2747 3466 634 3478 1193 633 3757 4053 1904 1906 3452 4066 3032 4043 2392 4265 3342 3624 2241 3367 3320 1773 2241 3770 1772 3320 3624 3342 2278 3424 1311 3368 3056 932 934 3368 932 2757 1311 3368 3202 3056 1626 4107 479 2042 1504 3370 323 3369 1317 2761 2683 3374 1503 3370 1500 323 2528 2525 337 3372 1760 5328 4522 2286 2201 4419 2945 3642 2528 4069 1942 3372 1933 4069 1942 1934 323 1497 1499 3373 324 3373 3370 323 1500 3373 323 3370 2686 3374 2752 942 1317 3779 942 2688 2686 3374 942 2683 5121 4546 5105 5095 2022 4994 1100 4286 2404 951 1677 3388 3375 4524 3387 3852 1 3945 1081 2543 5200 5397 4577 2679 1679 3666 40 1678 2678 3375 834 2679 1886 3376 2889 2022 4531 5215 5190 4996 4287 2392 3341 3883 3376 1886 441 1887 4291 441 3376 3965 4473 5130 4661 4571 940 3377 1315 936 1315 4273 2690 1316 1315 4273 940 2690 4655 5238 5050 973 2447 2040 1852 3817 3378 3620 2246 2245 4657 4910 4033 4131 3833 4650 2741 3379 3193 3620 3378 46 51 3467 53 3155 4759 5711 4267 5377 3803 4644 72 4542 3323 3835 2725 3830 2185 5227 3578 4293 4140 1820 3989 4134 2729 3464 1336 2731 3946 963 961 2921 4975 5204 5123 4913 4279 5204 4628 4830 2868 1802 3174 2085 4373 5199 3485 2688 940 4281 3383 3536 2681 5120 4290 3383 2860 4208 1 2851 3375 4524 3852 4548 2681 4290 940 3383 2689 4550 2681 3849 2884 4727 3212 3503 2716 3759 642 3384 3563 4134 2430 2432 2543 3400 2865 3945 3260 2555 2801 3385 3386 286 84 288 3385 4797 3887 3260 4962 5837 4952 1036 3385 4748 3575 3887 1355 4349 2041 1356 289 288 287 3386 3387 2679 834 3375 286 3386 287 288 84 3386 288 1483 3388 2107 3351 3134 3389 4934 4304 2868 2415 4167 2868 3389 3316 4934 3213 1329 4530 5189 4253 3823 1825 4168 609 3318 1079 3612 1080 3390 1075 3390 1079 1080 1737 4507 17 4209 2850 3936 1076 3390 5197 5541 5490 5143 2850 3936 3390 2851 5706 3782 5477 4308 3540 3790 951 3391 952 3783 2403 3540 1780 3790 3191 1319 4195 5538 3877 4716 952 3538 3391 2403 949 3540 951 3391 3418 5163 4817 4252 1319 4374 3191 1320 2192 4816 2456 4640 3310 3924 3911 3393 3351 3540 3539 951 4264 5157 3819 2773 2573 3961 2870 2356 2352 5353 5324 5169 3351 3539 2692 2404 4313 5549 5521 5452 241 2503 2502 3398 3167 5021 4939 4936 4668 1287 2147 4112 2927 1967 3018 1123 2329 5693 2851 5381 2852 3397 3185 2292 1461 3398 2502 2503 2959 4085 3398 240 949 3783 3539 3540 4947 835 3540 3772 3540 1676 2795 3539 3540 4214 3772 40 3945 2853 2860 3787 2849 4920 3400 1876 3400 3638 2301 2849 1077 3400 2866 2301 3401 4616 4459 4467 5108 5818 5816 4800 4176 4045 4398 4460 4263 5218 3848 2405 3932 4821 4561 3042 5593 5348 5312 5202 1070 3402 2840 3271 44 4411 42 1324 3225 4340 3717 3729 229 4090 3404 226 3100 5482 3403 2843 4737 2840 2106 3930 4876 5573 34 4051 88 5594 4017 4737 3051 4832 4068 4020 4485 5482 3186 3418 5482 3710 4485 3186 3267 3710 3494 3100 2703 3104 962 3406 3579 1856 1046 3301 2815 3940 1856 1049 963 5048 4280 4984 3406 5366 3408 5292 4832 5048 961 3946 2792 4537 2172 3808 3179 3406 962 3104 5049 962 2588 965 4661 5273 2891 1205 1858 3796 3586 2948 3408 4137 3179 965 3696 4979 599 4262 3273 5309 4664 2460 3586 4200 4173 3292 1657 4436 3586 2160 4436 82 1050 4261 3406 5049 3408 962 5078 5727 5493 5188 3406 5292 3408 2701 1628 5170 4235 4702 2411 3637 2700 3409 2700 4320 3637 2411 2413 3409 2411 2700 5293 614 2411 2700 4635 3415 3933 3901 4921 5582 2422 5288 5532 3074 736 5531 3780 5088 4315 4541 4232 1049 79 3296 2866 4220 3947 4575 2557 5680 812 4512 3415 2048 2305 3410 3901 4513 3933 3578 3405 3702 3301 3581 5347 5449 4679 2232 5453 5671 5497 5454 5521 5666 3541 3844 3412 5848 3587 5133 1369 3444 1367 2298 2188 3706 2816 2452 3691 4829 4680 4607 3274 4215 3588 3921 2828 3587 2829 3412 2800 1354 1035 4570 2877 5836 3520 1699 2647 5726 3218 1297 3718 5374 4698 5295 5915 5060 5683 5766 4818 4635 2173 4385 3973 5134 3652 4846 3410 4513 2809 3297 4513 3415 3171 3901 3224 4514 3930 3184 2048 3415 3171 3285 2305 4635 3415 4385 1201 4719 4386 4256 625 3417 3068 1206 4202 2579 3567 3636 2102 5084 4344 2106 4142 5163 3868 4562 3186 3418 3266 3267 1871 3494 2463 2023 3230 5648 3419 3242 896 4556 1737 5560 2722 5582 3662 3649 5428 5648 3519 3954 5141 5468 5335 5380 2638 3713 2634 3220 5427 884 2378 5210 3223 3503 3214 4 3503 5405 5122 2811 3421 4324 1284 3923 4199 2148 1703 1708 2277 5581 5560 5428 5124 5761 5290 5704 3422 3954 3519 3242 4183 3243 3226 7 1732 4080 3720 2642 885 4326 2634 3722 2642 4400 895 4080 2634 3423 895 2642 885 4326 3722 16 2638 3423 895 2634 983 4756 4755 4983 5298 3877 5090 4945 3424 4619 4327 4359 5266 5269 5018 4715 3342 3624 2278 2393 1726 3425 2878 2886 2619 5473 5111 5368 1353 5225 3625 2799 2278 3624 3424 3465 2635 3518 2888 888 3229 4637 3425 4460 4398 4837 4460 3869 5004 2744 3559 2858 2791 5691 4060 4536 3251 3806 3426 2787 5058 5223 4877 4754 2556 5766 5227 5060 5434 3427 5403 5391 5135 5361 4750 3811 3427 5403 5044 4313 3545 5193 3811 5145 3671 5239 3197 2794 2485 2484 145 3428 144 2485 145 3428 4091 2486 1411 1895 1734 3430 2640 3232 1888 4091 1895 1889 2664 4714 847 924 891 3430 19 844 2585 5044 3396 5035 3203 3532 3061 2340 1734 3430 3225 2640 3441 4331 2648 2284 3064 5324 3432 5023 3857 4718 3355 2663 3354 5016 2666 3754 925 3856 3431 3532 4985 2760 847 2664 3856 4985 3431 4554 4858 5139 5069 4335 951 3539 2404 1676 4564 5111 3199 3696 3351 3540 951 949 4723 2975 4712 4708 3682 4718 925 922 4846 5316 4580 4884 4968 5242 843 5094 2300 4893 2297 83 3201 3763 3435 2763 3933 5181 3901 3578 2943 4935 2360 4168 2360 4294 3330 2357 4386 5413 2953 3330 1314 4712 1312 30 4527 4764 3838 4758 3973 4846 3652 4064 3646 4425 826 2577 4992 3658 3831 3319 920 3436 1763 1762 1759 4522 3371 3531 2668 4406 1307 3622 3201 3643 2763 3437 2289 4924 1767 2673 94 3438 95 96 54 3438 96 1379 1000 3439 1823 3222 1823 4534 1669 4424 3222 4534 4424 3439 2754 3826 3563 3280 1003 3561 1823 1000 1834 1018 1832 3133 4108 5202 2846 3914 4108 1869 3914 3440 1869 3914 3440 2846 3440 4108 1869 2167 4345 2284 2648 4331 1302 3442 2159 1692 2125 3442 1302 2295 890 3441 2284 1297 3441 3717 2640 3225 1297 4345 3218 2647 1746 4465 3359 2766 3359 3442 1746 1745 4059 3070 1950 3443 4052 4061 406 4053 1126 4869 1122 3986 1152 1918 1919 2049 1949 3443 3034 227 2003 3443 1950 3070 1121 4059 1557 1559 1365 3591 1368 2465 3602 3917 3158 86 3627 4106 3264 3915 87 3445 89 3143 2512 3591 2511 89 3445 4207 1365 1368 3006 3605 3165 2528 4356 1665 1816 1815 4378 2319 3468 1816 3503 2122 805 2544 5474 5506 4130 5089 1665 3468 2576 4356 905 3448 903 2650 906 4383 2119 3521 2455 3913 3449 3107 4682 81 1860 1360 80 3583 78 3449 1360 3449 1361 1861 3393 3911 3310 3114 80 3583 1479 78 3114 3449 3107 2455 3195 5086 4896 3902 3279 4631 3947 3450 4567 3529 3686 3451 4404 5432 4405 5264 3459 4931 4159 4930 3741 915 2311 3461 3451 3883 3527 25 3601 4493 2963 4067 3994 5079 2956 4063 4493 4966 4043 3452 1983 3452 1134 3032 1963 5346 232 1964 4966 1978 1134 3996 1848 3454 2447 2043 2564 4955 2457 4596 5520 4156 4742 4314 4742 4314 4156 2816 3415 4685 2305 3171 75 3454 2043 2447 4230 3933 3410 3297 1849 3454 2043 2306 75 3454 2306 2043 4669 3244 7 4390 872 4669 3455 3241 4010 3007 3120 4171 4352 2621 3455 3244 5189 4304 4589 4167 1825 3456 1344 2435 4935 4003 3456 4168 1344 3456 2943 2435 4244 5352 3636 5175 4630 4166 3318 3456 3456 1671 1670 1344 3456 2931 1344 1670 4128 1171 4025 4026 3156 4025 3239 2988 2310 3803 3458 3381 2310 3458 2800 3381 2797 3458 2800 2310 5432 4405 3451 3529 2797 3458 1354 2800 3451 4404 25 4405 2658 4931 2659 4903 917 3744 846 3527 2285 3688 3255 1697 2661 5261 5103 26 4648 3529 2658 3459 3525 4903 2659 2120 4425 826 1009 3973 2657 3862 3461 2392 2674 4924 4585 2289 2311 4100 25 3972 3524 22 4402 620 2486 4890 1414 4306 3656 4775 1007 2759 5138 4949 4462 4488 3506 1713 862 3462 862 3957 1713 3506 3464 4272 2729 2314 323 4862 326 1504 2989 4862 2998 3463 3463 2989 2073 2998 5607 3169 3694 4127 3553 986 2736 1334 5311 3641 641 3898 4616 5338 3980 5012 5794 5855 5781 5811 3526 4619 3862 3624 3342 4265 3424 3624 2660 3526 2391 3465 2657 3526 2391 3461 2391 3624 2393 3465 3465 2278 2660 3424 5797 5844 5820 5800 2318 4766 3466 2705 28 4713 3754 3749 3286 3468 2223 1665 1329 3467 3155 1332 1198 822 1197 3471 5116 5357 4803 4099 1197 3483 1196 3471 3297 5060 4513 3299 713 3473 710 2901 4845 810 809 812 2584 5315 832 3197 1198 5384 5034 1659 819 4845 639 3971 5385 5420 1659 635 821 5311 641 640 2891 4662 4590 4661 5311 5177 812 3938 3940 5620 3405 3579 5299 2380 4074 4397 5034 635 2354 3472 2450 4314 2816 4156 4841 2019 1102 4843 789 3473 3066 788 791 3473 3066 789 3473 713 710 712 709 3473 2901 710 573 3473 3066 574 794 3473 2901 573 848 3473 3066 573 754 3473 2901 579 708 3473 709 579 2401 3485 2688 2335 3486 3678 3476 3677 2345 3632 839 3631 625 5150 3632 4221 2273 3486 3476 625 3631 4625 3677 4624 1209 4380 1686 3492 3262 4375 841 4365 3486 4376 4375 841 4375 3476 841 4365 3489 4581 3658 3942 3480 4224 633 808 818 4224 3478 3480 3478 638 1193 1192 1193 3478 1192 633 633 3480 808 634 633 4472 808 4224 3480 818 638 639 634 3971 2903 3480 639 4574 4472 4231 634 4231 808 809 818 3971 3480 2903 4303 5217 4565 628 1352 4353 2555 3572 628 4912 808 4565 1193 3480 3478 634 633 3480 634 3478 819 3480 639 818 5384 1198 5034 4967 3444 5390 3914 84 1197 3483 820 1196 1195 3483 1196 820 635 3483 3471 1196 1197 3483 3471 820 2401 3485 1317 2688 839 4582 3631 3677 2273 3488 3486 625 841 3492 2281 2351 3678 3879 842 2605 3476 4678 841 4365 3347 4649 2070 2745 841 4379 3491 3490 3491 4084 625 2349 2273 3490 3488 625 3488 4379 2273 4376 4389 3462 862 1713 2427 2743 58 3560 825 3675 3560 2427 3491 3677 3490 3653 4515 3942 4378 3489 5098 5764 5537 5378 3658 4992 2319 3319 3491 3653 3490 625 2349 4380 3492 2273 2273 3491 3490 625 3488 4961 4625 3677 621 4986 2651 2652 2273 4376 3486 3488 2273 3491 625 2349 4961 3632 3678 4221 3262 4678 2594 1687 4084 3491 625 3653 1686 2351 1209 3492 2273 4678 1686 2605 4678 3476 841 2605 2281 3492 1209 2351 1686 4375 4365 2273 3491 4379 2273 3490 4429 2438 3647 2439 3524 2656 22 1304 2446 4670 4470 1035 4937 2119 1744 1749 2788 2050 2781 3809 4817 5084 3418 2102 2127 5726 3718 5605 2647 4345 1739 4331 1290 5087 1723 5072 3418 5482 5084 3403 3418 4485 3267 3186 2978 4832 3978 3946 3331 3495 2206 823 5034 5385 1659 5384 3329 3495 1199 1200 1199 5034 1660 3495 2175 3495 823 1660 1200 3496 3328 3495 2206 3496 1200 3495 2572 3496 3331 3495 1200 3496 1201 3328 5435 4154 1789 47 3331 3496 2206 3495 3329 3496 3495 3328 3332 4386 2209 4258 3334 4386 2943 4256 3332 4386 4318 2357 1737 4507 3960 1299 3960 2361 1299 18 2128 4555 3726 3724 1737 3960 1736 2646 2646 3960 2131 1299 3435 3639 3201 3498 1312 3498 1314 2874 3860 4692 2672 3643 3951 4585 4552 3639 4834 3730 2283 4328 5726 5755 4399 3727 2381 3730 1742 2283 3599 1282 2148 3501 3501 3221 856 1282 2611 3501 2148 1282 3047 3502 3 2150 3502 1709 1283 1706 2610 3502 3 3047 1709 3502 2150 1706 3075 3503 3214 2362 5132 4456 5133 5382 3612 5693 2851 5110 2884 3737 2362 2126 3503 3223 3214 3447 3421 5036 0 3923 5851 5780 5765 5789 3908 4682 3584 3915 1729 1726 2878 3237 4462 4621 3507 3506 3513 4390 7 3244 5201 5342 4950 4009 4462 3121 3462 3507 3677 4964 3678 3476 3374 3779 2752 942 3613 3778 2603 2619 3508 4389 3778 3228 1938 4489 4351 2999 2368 4477 3626 2149 4183 4390 7 3513 3778 3613 7 2619 3121 4462 3462 3508 4389 862 865 1713 3511 866 2968 3509 2623 3510 866 3248 5335 5360 3713 5684 11 5342 9 1288 3695 1716 2144 1724 3248 3695 1716 3510 3695 1724 2144 2633 4177 5360 4904 3713 1042 4513 2809 3285 2968 4008 3509 3247 4605 5213 7 4604 3512 3246 871 3117 3246 3512 2371 1287 2620 3701 2371 1717 5073 3641 2422 4420 3620 3378 2246 3549 871 4352 3244 1351 871 5213 3513 806 806 4183 3226 3513 3712 5249 3705 4693 2631 4391 1290 1723 5354 5038 3238 2375 2631 3514 12 1290 4088 4158 3206 3515 5659 2626 4977 3516 2631 4391 2779 3514 5851 3954 5863 2383 2373 4180 2115 1719 4461 5076 4088 5072 3716 4697 3704 4181 4461 1290 4391 1723 4180 2115 1719 2374 2629 4977 2113 2627 883 5426 870 2187 5926 4696 1729 4396 3724 5919 3713 4696 3220 5926 3713 5919 1743 5926 4696 1729 2886 3518 3425 2635 2356 4638 2354 2572 4120 4904 4177 4325 3430 3881 3520 2974 5953 5859 5920 5863 3519 5625 5560 5428 2879 3011 1091 3955 5453 5680 5520 5369 2382 4198 2383 2591 2644 5581 5560 2277 3729 19 3717 3225 3430 3520 19 2974 3523 1688 19 3072 3881 3430 3729 2648 3729 5836 3520 3881 19 5836 3520 2593 4383 1300 2119 3521 2653 3521 2119 1300 1750 3522 21 1747 5276 2439 2360 2848 5375 5158 4202 5352 5836 19 1699 3523 4987 1007 4425 2236 5947 6004 5874 5969 5442 5586 2559 5554 619 5299 620 3972 4402 25 1752 908 2391 3525 1305 2660 4458 4751 4427 2778 4467 5136 4459 4769 2215 3527 917 846 917 4903 3460 2120 2801 2556 2555 3625 2658 3741 915 2311 915 3527 917 2392 2215 3527 846 2392 915 3527 3460 917 3741 4648 3529 2658 1696 3745 1755 3528 5623 4798 2383 5380 4266 4338 405 1906 4933 855 4443 1081 3529 4567 3686 3687 920 3531 3530 3436 3451 4404 911 25 914 3529 3459 2658 1100 441 4286 4994 2146 3962 2394 1763 3531 5555 3530 3436 3962 5555 1763 3530 2682 4618 4284 4369 4154 5435 1789 5045 5218 5666 1786 3356 4524 3665 3387 2679 1759 5372 3531 1762 4617 5555 5232 4926 1761 3532 2340 925 1737 4556 4555 2128 4718 3857 4160 2663 3532 1761 3203 3431 3750 4409 3203 4333 3534 4332 3533 2285 2285 3534 929 3533 28 3533 2285 929 4334 5016 3754 928 3429 3534 3533 928 3485 2688 36 3535 3122 5205 3231 3958 3767 3776 2677 3535 2255 4057 3190 2352 604 5778 5639 5853 3536 4547 2688 4373 1316 3776 2690 3535 2677 3776 3196 1776 3623 2682 1773 1318 5768 2756 5573 4051 4266 2214 230 4874 3822 4934 4253 3326 3770 4873 2238 3320 5464 5674 5447 3537 3538 3391 949 1319 5666 5218 2697 3356 3538 3790 3391 1319 1053 4144 3308 3909 3539 2323 616 2324 3064 3784 3539 2692 5238 4655 5050 4654 2583 3539 2795 1676 949 3783 2257 3539 1676 4947 3540 2795 2925 3540 40 2266 3783 952 2403 946 3541 5434 3542 5403 5218 4467 4769 5144 5044 5403 5391 1787 3542 5403 4313 3541 2750 4769 4459 3671 4313 5452 3427 3542 4459 4616 3621 3270 3401 4616 3621 4459 2354 5491 5222 5355 2467 4575 4510 4220 1858 3707 3164 3796 2245 3544 46 1681 2409 4919 2264 4614 2407 4474 3980 4210 3543 4459 3270 3197 2712 48 1327 3546 1699 6105 5836 6095 3884 4794 4222 4793 3544 46 2749 3193 977 5630 5577 2862 2720 3546 2705 2906 4534 3692 1821 3826 2246 4457 4047 3349 3547 5145 4139 4673 3551 1329 1332 3467 4158 4088 3206 3871 5946 5736 2881 5974 3549 837 614 613 2706 4157 2248 3549 2246 3812 2710 971 3549 614 46 3193 2412 5321 3549 614 2211 4487 3395 2942 2268 4615 4263 2405 981 4299 49 974 2113 5659 3516 5425 4139 5216 4916 5145 3828 3837 2721 3552 2421 4446 1378 2473 4223 4731 2422 1663 641 4576 2716 980 2721 3837 3157 1810 4763 3552 3837 3157 2566 4694 2565 3554 3147 3976 2751 3828 2736 4357 1334 1335 5672 5782 5780 5765 5321 5558 4469 5311 2725 3835 2733 3555 2725 5052 2732 3555 3767 5898 3535 5852 986 3832 2725 3324 5377 3831 4267 611 2576 4356 3468 1339 906 3448 2387 3521 4355 1337 4126 3556 3556 3847 998 3352 2748 3557 57 3148 1815 4356 3557 3148 57 4356 3148 3557 1818 3557 3148 1815 1664 3558 2427 825 3557 1818 1338 1815 2987 3557 57 2748 3557 2069 2987 2740 5592 5585 637 4710 2426 4185 2427 1664 4493 4503 4040 4296 995 3558 2427 2078 906 2387 900 3521 4528 5211 5123 4830 997 3560 2743 2427 2803 3942 3284 2427 4809 5355 2422 5311 4415 4526 3549 3846 2228 3675 3560 3353 993 3560 58 992 2425 3560 2743 3352 4936 3183 3563 4424 4161 5022 3211 3748 1003 3561 2429 1823 1821 3561 1823 2429 3167 5021 4178 4939 2357 4679 2570 2356 3439 4936 3222 3562 2754 3826 3014 3563 3167 5021 3563 3014 3563 2432 3014 2754 5134 3652 4846 4580 2432 3563 3280 2754 4409 4985 4776 4554 4172 3855 1828 3565 3564 3277 1670 2931 1740 5755 3216 2361 3565 3867 3146 63 2163 2330 1677 1780 1780 2330 1677 1321 5363 2758 2434 4484 1828 3855 1021 2780 3887 5499 4797 4748 5363 5375 5148 609 4719 2943 4386 4256 1007 4775 2236 2759 3658 4992 4581 2319 5316 2237 2169 5208 2309 3636 2579 3416 2309 3636 2758 3567 3247 3510 4950 3509 1008 5066 3361 5055 4139 5216 3550 4157 2437 4906 2212 1831 2870 5157 2573 3569 3395 4613 3137 4487 4486 4909 4494 4532 3377 4997 1316 4301 4292 4906 2437 4610 2047 3571 2799 2785 3458 3803 72 3571 3512 4951 3570 1287 3458 3803 2800 3381 2310 3803 72 3458 2555 3572 1032 1352 3282 4663 4203 2789 2310 3803 3381 72 5240 4797 3889 4799 2555 4353 4225 3572 4712 3498 4151 2662 4198 4946 2383 4798 5254 2788 1033 3885 3573 4433 3574 2158 1033 3895 3573 2158 5254 2787 3574 3573 1027 4998 4197 1837 3282 5823 5766 2172 3416 1343 1826 2169 3574 3426 3252 1650 2599 5357 4803 3363 2128 5954 5917 2592 1650 3806 3574 3426 4742 3910 80 4434 2787 5254 2788 3573 4433 2787 3728 3573 2555 5227 3385 5226 5311 812 811 5227 5766 5355 5227 5311 5303 5923 5060 3281 1044 3576 2448 1038 1652 3577 2449 76 1850 3577 3176 2173 4513 3297 3933 3578 3577 1043 815 3176 4688 5248 4149 5177 1850 3577 2173 2449 2171 3578 3293 606 606 5923 3578 5915 3901 5923 606 3171 4514 3184 4017 2976 3171 4805 4513 3901 3297 4513 2181 3299 3580 3579 1046 3301 2817 5248 3821 2188 5490 5131 5143 5082 5250 3580 2186 5091 3581 5280 3405 5142 2457 5321 604 4065 3296 1049 79 5062 5061 3581 3298 4512 3301 5091 3702 3580 1050 3584 2034 3582 3146 4172 4169 1670 1479 3583 2508 78 1479 3583 1361 1480 4441 5350 4442 5064 2835 3916 1065 3274 3908 5350 5307 1868 4169 5409 3146 3277 1050 3584 1051 2034 3628 4594 3629 4206 5388 5591 5444 5305 4200 3926 2160 3586 82 3926 3263 3590 3336 4801 599 3511 3585 4148 3586 3407 4603 2826 2165 3272 84 4456 3917 4240 4545 4920 3789 1081 2829 4438 3587 2828 4010 4109 3010 1161 3627 4666 4544 3264 3914 2829 3412 2846 3272 4603 4475 1658 4215 4456 3588 4455 3274 4456 2830 1362 4603 5321 603 3590 3628 4440 3590 3629 3590 4206 3628 3629 2832 4441 2162 1063 604 5196 3590 82 3590 817 604 603 4005 5673 5471 5152 5306 5308 4165 5196 3263 4436 3926 82 3274 3921 3588 2835 3591 1365 1368 3445 1366 3591 2511 2512 2161 3590 3263 3265 2849 4933 4162 4920 4764 5288 4828 3649 1372 3594 2468 1373 4162 1074 2857 3592 4162 1074 3592 3593 3593 4933 2849 2608 89 3594 1373 87 4829 3691 4823 3937 3595 5178 2542 3943 3185 5245 2292 3397 3903 4807 4114 3958 3185 5178 2852 1078 3596 116 1389 114 1389 3596 114 122 2911 4243 1894 3597 2477 3596 1389 125 1112 4243 1894 1598 3597 3969 2911 1105 1306 3598 29 1754 3926 4200 2160 3263 859 3599 3501 852 221 3600 1444 218 221 3600 2496 1444 220 3600 2496 221 238 3601 239 2503 2963 4067 3048 3050 1297 891 2641 4340 2963 3601 238 2959 2833 3602 86 2509 3158 3602 2833 84 317 3603 1492 314 316 3603 2516 317 2517 3603 1492 317 2025 4035 1511 3604 4101 4117 3101 4102 2992 4030 2028 2989 3605 4132 1188 3446 3605 4132 3446 3165 3006 3605 3446 3165 1942 4136 3606 3159 2528 1943 335 3606 1942 3606 2528 3605 2530 3606 335 1943 1942 4136 1943 3606 2219 3607 2950 1910 2096 4350 3606 3000 1509 4811 4135 328 1910 3608 1971 1142 2950 3608 1971 1910 2535 3608 2950 3607 2422 3786 2198 3322 1251 3949 1084 3609 3609 2875 1250 2872 1881 3609 2871 2875 1939 3610 2194 1629 3610 1186 3045 1628 3471 820 3483 4362 3610 1939 1169 1629 5510 5731 5231 5401 2557 5321 2457 4512 3611 5875 4737 4600 3397 5178 3185 3943 2851 4145 801 3612 2851 5381 2332 2329 5730 5245 3943 5687 2469 4444 1372 1373 3903 4181 3240 4114 4174 5213 7 4605 4305 2258 37 4056 3200 3614 2626 3339 2603 5425 3696 5299 3974 4923 4890 4573 5039 4257 3661 880 2631 4783 4391 1723 3903 4114 3122 3958 887 3903 2882 3616 2851 3617 3307 602 3617 2851 804 2547 2369 3618 2881 3302 3618 4012 2881 3302 647 5595 5299 3711 4792 4857 4006 4112 3513 5213 7 806 4006 5213 3619 4599 2707 3812 969 2710 3620 3548 2707 2746 3378 3620 2245 46 969 3620 2707 46 2246 3620 3549 3548 3514 3813 3704 2779 3193 3620 3549 3378 3683 5267 5241 4718 2414 4916 4673 2248 3401 4263 3543 3621 2394 5555 2146 1763 229 5013 1967 4448 2668 3622 1307 1765 4512 1046 2186 79 2394 4861 4617 3622 3433 4927 4160 4099 3774 1771 2679 941 3770 4284 3367 3774 4618 5464 4991 5220 2241 3774 3623 941 2686 4288 942 2752 1675 5573 5397 34 2278 3624 3465 2393 2657 3624 2392 2393 4265 2392 3342 3341 3624 2391 3526 3465 1353 3625 2555 2799 1032 3625 2555 1352 5935 5974 5102 4201 3626 1285 1712 2368 2686 5469 4288 2752 2149 4012 3626 2368 2368 4477 2149 2370 3919 2825 2832 2162 1064 5095 3918 4546 2297 4893 2827 3922 4215 4456 4455 4958 3628 4476 3590 4440 4893 5095 1064 1865 4354 5236 5155 5068 4846 3973 4824 3676 3915 5105 5095 2827 3590 4955 3263 4206 3811 5135 4297 4750 3791 5538 2964 3877 3630 3797 3273 2842 2841 4735 3797 3931 2457 5071 4322 4593 3632 4961 625 4221 4583 5506 2726 1808 839 5106 3631 4582 5092 2577 1669 5053 1155 4463 2051 1162 4221 5150 839 4228 3634 4437 1054 3633 4493 4451 4043 4497 4131 4657 1054 4033 4532 5321 4157 2716 3296 5063 5062 79 2557 3635 812 816 2579 4202 3567 2953 4203 5499 5153 3887 2382 5010 1732 4198 4505 4630 3277 3456 2309 3636 3567 2579 2360 4935 4087 4168 2309 3983 2434 3636 2413 3637 3311 3178 2723 5770 3314 4420 4235 1628 3045 4036 2413 3637 2412 3311 5777 2245 3544 3193 3860 3763 3201 2763 3941 4575 4510 4511 2673 5116 3363 2674 2673 4591 2290 3363 5253 3092 3363 31 3435 3639 3498 2874 4151 4552 3639 3860 4712 4861 4551 2662 2665 4160 926 4155 5618 4771 5292 2697 926 4632 4155 4153 5613 2466 3440 5593 2395 3640 2914 2665 4228 4964 625 3879 4973 3840 4731 4249 5311 4420 3641 3898 4216 5397 1675 4873 5005 5388 4901 3306 3553 3841 2736 3323 3898 4800 4420 3641 5854 5982 2781 5902 4709 916 3529 4648 3201 3860 3643 4151 2423 4248 2422 3644 2422 4584 4480 4419 3490 4624 3677 3488 2905 4445 2421 3836 3631 5106 2345 625 4429 3647 1018 3873 3043 1136 1137 3994 2438 4254 2439 3993 4479 5380 2383 4946 4042 4639 612 3649 639 4472 638 4231 5118 5471 5152 4475 824 3662 2722 3380 2722 4639 2422 3649 612 4223 2422 1663 638 4231 3480 639 4642 5066 3892 5054 2134 2881 5155 4477 5054 3892 826 3358 4111 4295 3805 3116 4778 3861 2433 1007 5143 3390 4825 4918 2349 3678 3491 3677 4526 2746 837 2741 4492 3973 3676 3362 3631 3678 839 3677 3068 5556 839 3417 4961 3486 625 3476 1207 3677 2349 3645 2396 4073 4072 3654 3760 3854 3761 2757 2396 4073 2242 2398 1769 4072 3952 2397 2242 4152 2396 1768 3540 952 40 2266 3656 5066 3361 5054 4775 3656 1007 4425 3358 5066 2231 5054 5000 3830 3832 3324 5765 5623 5672 5745 3286 4581 3468 4378 2732 4828 3838 3555 4488 5165 5138 4949 4827 4581 3286 4378 1046 2186 79 2180 2580 5397 3893 3659 2972 3007 1157 4015 4403 5221 5042 5096 5397 5693 2329 2603 4288 5237 2679 3660 4548 5119 4524 3852 2368 4289 2880 2149 4288 2686 942 3660 4259 5331 5031 4978 880 4598 876 1720 5331 5659 5557 4977 1327 5193 5145 4915 5731 5911 3193 5895 5401 5558 833 5168 4829 3612 1079 2851 5713 3649 5582 5288 1335 4357 3837 2736 3380 5582 3662 2722 824 3662 3649 2722 969 3663 837 2741 3379 4295 2741 3663 3833 4579 837 4529 1796 3663 2708 3379 2372 4792 2145 2622 3945 3787 2860 3788 2747 5279 974 966 2705 5192 4766 4237 2861 3944 3382 3466 4250 5325 4758 4760 5528 4300 3811 3550 2456 4640 1360 2192 4212 615 2323 3980 3387 4770 4524 4290 3668 5049 2589 3667 5049 2701 3406 3408 3104 4984 3406 2703 3856 4985 4523 3431 2701 5048 4280 961 3801 5943 1791 958 3672 3673 2893 1204 1680 3801 3544 3669 3182 2410 1790 3802 4319 46 964 959 2585 3670 832 836 2700 4832 2412 3978 4712 4723 30 1314 3671 5136 4769 4459 4778 3676 4064 3861 2750 3848 3671 3543 3205 3968 3672 3093 3205 3672 1203 2893 2338 3672 3093 2341 3968 1683 838 3338 3205 3672 1683 1203 838 3968 3338 1700 2893 2271 1204 3673 1203 3673 3413 2893 2575 3674 2858 1661 2796 4516 1842 2791 1661 3674 2858 2567 3252 5298 2964 3934 4118 4516 2791 1842 3828 4772 3976 2751 2174 4193 2070 3347 3675 825 3560 3353 3560 3675 58 2427 1006 4775 2759 2236 5208 2237 1343 2434 1370 5598 3450 5490 3488 3678 3486 3677 4885 716 601 717 5208 3861 3676 4824 3490 3678 3488 3677 4625 625 3488 4624 3476 3678 841 2605 3631 4624 3677 3653 2349 3678 1207 841 3631 3678 3632 839 2605 3678 841 842 4961 625 3488 4625 3631 3678 3677 3632 3486 3678 841 3476 3488 3678 841 3486 3490 3678 841 3488 3491 3678 841 3490 2349 3678 841 3491 5534 3679 3797 4005 3931 4005 85 3797 2829 3914 1869 2846 1365 4562 4207 1072 3402 5007 2840 4665 2790 3734 1699 3019 4933 4162 4443 3593 3681 2603 2596 842 2603 3681 2392 2598 3451 3681 2597 846 1766 4334 3534 3750 922 3682 1761 925 929 4334 3534 1766 1761 3682 3203 3431 3682 4718 3355 925 2881 4960 2134 3684 5824 5974 5888 5784 3685 4569 3072 3414 5898 3776 3535 2690 4893 5095 2827 4106 5007 5498 5244 5404 3529 3686 919 916 916 4709 3529 3687 3529 3687 3686 916 3529 4567 3527 3451 3529 4648 916 3459 3686 5432 3529 919 4648 4931 4119 4159 4522 5328 3531 5233 916 4709 4119 4648 1697 3688 1696 3528 918 4358 28 913 28 3688 918 3255 3478 4224 638 3689 623 4303 2898 628 4565 633 628 3689 4565 4466 638 3689 628 4565 4303 3338 1874 3880 2855 3691 3937 4829 2851 4823 2877 2974 3520 3881 2104 3880 1874 3691 1873 3937 3880 2104 5819 3948 2855 5020 3693 2616 2880 2134 4481 3515 4088 4180 1286 4289 1711 864 2140 3693 1712 2616 479 3694 478 2195 4885 712 716 713 4150 867 877 3695 4262 5085 4979 599 4687 2112 10 3199 870 3695 1716 3248 3199 5425 10 3696 618 5299 619 3209 1760 5328 3371 4522 5425 4018 5171 5368 2638 2377 3517 1728 3700 4564 3247 3303 5398 4683 2613 2620 5398 3697 8 4388 3697 3701 2371 2624 3699 1191 1169 2060 3139 3699 1939 3698 3336 4687 3700 3511 2061 4029 2996 328 5488 5332 3698 4907 2096 5170 3180 2098 327 3698 326 1513 4124 326 1191 3699 2098 4124 1191 1939 2060 3699 1191 326 3699 3139 326 3698 4686 3168 3142 2060 3300 3700 1645 3303 3700 4564 4008 3247 4687 10 866 4652 3778 4604 3613 2603 2112 3700 3300 3696 3701 2371 1717 3570 1288 5057 4951 1287 3570 5057 3701 2371 5744 3304 4732 4806 1718 3701 2624 2620 2186 5091 4512 4881 5155 2881 3684 4201 3301 5061 3405 1856 3301 5061 1046 3702 3405 5061 3702 3581 22 5299 620 1699 5299 1646 627 3703 5205 3714 3231 3958 3397 5300 5245 2292 4074 5299 4397 1646 3704 2779 2630 3514 2116 4181 2546 4114 3704 1725 875 2630 4009 5067 5037 4950 2633 5067 2144 3695 2633 3712 3705 2632 605 5248 4688 5177 12 5251 4860 1292 5248 2454 2817 4149 3706 5248 605 3030 2192 4852 1360 2456 2948 3999 3586 3585 2327 4662 1700 838 4322 2177 2458 2822 5546 5078 4173 4870 2541 1700 3338 3968 3725 5337 3723 5014 2113 4394 2112 3709 5624 2113 3516 5425 3018 1967 5013 3984 2626 5624 2776 10 883 5426 2112 5040 5659 5495 5557 3339 2626 3709 2629 3516 5624 2113 3199 2112 4019 2843 3100 3403 6009 5300 5960 2839 5163 4252 3868 4817 3267 3710 3100 3186 5595 5381 601 3503 4555 896 1735 2644 5249 3712 3705 5247 5249 5037 9 11 2622 5604 5473 2147 2638 3713 3517 2634 5918 5298 5198 5884 1729 4696 1743 4396 3959 4075 1993 3956 4397 3119 4074 1646 4022 5607 4115 1164 3425 4835 3229 2878 4397 2118 13 3119 3498 4712 4151 1312 15 3715 17 3237 19 3717 3225 3430 4181 1294 2546 1727 3240 3716 2639 3704 3903 4807 3958 4601 844 2641 891 3717 2640 3717 2641 844 19 3717 3430 891 898 4340 3717 891 4086 2159 2962 4341 2127 5726 2647 3718 18 3727 3216 20 3275 4498 4143 1779 18 4698 4399 4213 1738 3718 891 1751 5158 5615 5352 5174 3573 3728 1033 2788 761 5080 762 2355 1199 5034 3495 4239 1749 4787 1303 2656 2274 3720 2922 3015 2922 3720 16 3015 4080 1731 2383 2382 3720 4849 2274 2922 3723 5543 3725 844 5420 635 1195 4362 5155 5102 3626 4113 4400 2642 895 3423 2645 4557 2643 844 2643 4557 3233 844 3067 3723 893 1730 3067 3725 897 893 3725 844 893 3723 3804 4603 4543 3272 17 4696 4396 1743 1743 4699 17 4696 4559 5820 5800 5797 5882 4834 4328 3730 893 3725 897 1298 5337 5543 3723 5376 1742 4956 3730 3500 3730 4834 2283 2381 5014 5337 3723 5140 1743 4209 3726 1737 1743 4700 17 4699 2128 3726 1737 3724 3153 5607 3154 1166 2493 4213 20 1748 3963 2491 2493 20 3430 3881 3729 3520 4559 5820 5797 4834 1734 3729 3441 3225 3225 4331 3729 3441 4759 5711 5377 5537 2283 4834 4328 4559 638 4466 497 4629 1742 3730 3219 2283 2276 4400 2591 889 2643 4347 2283 3219 3384 3731 2716 978 5111 5473 5201 5318 3315 5125 2199 52 3173 4702 4496 4136 3876 4324 4076 4704 3007 1916 2039 4037 2096 3732 1188 3173 4703 3733 3736 2650 3732 1628 1186 1188 4302 3020 3313 4044 1628 4496 1188 3732 2782 4727 3737 3876 1693 3733 1694 901 900 3733 901 1694 1628 5170 4036 4235 2299 3733 2650 900 1693 4701 902 22 2379 4889 2546 4609 3720 3735 16 3015 2650 3736 2390 3733 1695 2390 22 3736 906 3736 2390 1695 907 4703 22 4701 2650 3736 22 2390 3733 5025 901 4701 3504 4704 3249 3737 2782 4324 3737 3257 4704 3249 4324 4189 3739 4022 1164 3053 5022 4161 4711 3748 5542 3718 1751 5374 4161 2652 1751 3211 1748 4213 20 3738 5166 5836 5408 5553 2028 4862 2981 1164 3739 4502 2028 3053 2028 4862 2989 4030 4031 4998 2781 1845 2985 4025 1928 3740 4023 4025 3740 2988 3740 4500 4023 4034 1941 4027 3040 3177 2998 4034 2989 4023 3741 4648 2658 3527 4551 4712 3498 1312 2659 4705 2661 2654 4705 2655 2654 3875 3172 3743 2091 3457 2988 4128 4026 3156 3239 4128 4025 3156 4128 2984 2091 3743 2091 4128 3743 3172 4023 4025 2988 3239 4317 5093 626 4205 3529 4709 3527 3687 3527 4567 846 3451 4903 917 3460 3744 4358 5484 912 913 3528 3745 28 3688 918 4358 1756 3745 3528 4358 3745 912 3746 3525 1757 3210 5837 2792 4222 3897 4620 5103 4381 26 3789 4933 4443 1081 1169 3175 2986 4024 1176 4867 2027 1932 3181 4867 3747 4034 4023 4500 3127 4034 1813 4185 3558 2427 3127 4867 1177 3126 3211 5022 2652 904 5517 5754 5502 5138 3754 4334 928 3533 3825 5016 2760 3354 2760 5016 4713 2664 4713 4714 3749 847 3750 5411 5258 924 28 4713 847 3825 3825 5016 3354 4713 928 4334 3750 3534 5016 4334 3754 3749 3534 3750 2669 1766 3750 4409 4333 3061 3250 4790 2941 1025 2444 5724 3751 1672 3878 5525 4432 3250 2566 2079 987 3752 3752 4694 3829 987 3363 4160 1760 4099 4672 4160 3753 3209 926 5267 923 5241 3856 925 3431 3753 2665 4160 3858 2914 3857 4718 3753 3355 3431 3857 3753 3355 5733 4108 3914 5202 847 4160 2663 2287 923 4160 2665 2287 3682 3753 3355 3431 3533 4332 3754 2285 2666 3754 2667 3429 3754 4334 3533 3749 28 3754 2285 3533 28 3754 3354 2285 2664 5016 4713 924 2343 5422 4408 1310 4406 3966 2343 30 3756 236 1120 1956 4627 2932 405 4083 2933 4627 3756 1955 4083 5186 4627 4052 235 3756 236 2933 1950 4722 1557 3012 2933 4627 405 1956 3979 1120 1556 3070 4041 5186 3988 4627 3757 5019 4062 4720 2870 2212 1672 4054 3757 4720 4062 4083 1904 4052 3757 1905 4720 5414 4062 5268 4052 5268 4053 5186 2939 3758 1131 1562 2214 3758 2940 1562 3037 3758 2936 3038 2936 3758 2218 3038 1911 3758 1131 2939 2218 3758 2938 3038 1980 3758 2938 2218 4532 4721 1682 4157 952 3540 40 3783 4051 5655 5631 5074 2239 3760 932 3059 2757 3761 3760 2672 3368 4646 2757 3202 3025 5472 930 34 2672 5397 2243 2603 2243 5397 3761 1675 4073 5117 2675 2398 5464 5655 5447 5397 5472 3366 5117 3761 2673 3762 2290 1767 2239 3761 2243 2672 3893 5397 2603 3659 2242 4152 1768 2675 3092 3762 2290 3363 3092 3762 31 2290 2674 3866 1767 2289 2599 3866 2288 3363 65 3867 63 3146 3866 1767 2673 2674 934 3763 2805 2672 3860 3763 2763 2672 934 3763 2874 2805 3764 4723 4712 1314 3369 4862 323 1504 2343 4406 30 1307 3765 4724 4301 3766 4246 5272 5074 4970 2684 4301 936 3765 2684 3850 3765 2253 2253 4724 3765 3766 936 4301 3766 3765 1781 5833 3073 38 2677 4219 3275 2695 2258 4730 1779 4305 2849 4822 2863 4631 3768 4890 2539 4690 2679 2686 938 3769 4991 5447 4369 5220 2908 3768 3091 2813 3091 4097 2813 3768 4243 1253 2912 3768 3003 3768 2813 2539 1253 4097 2249 3091 3367 3774 2241 3770 3504 4727 4704 3737 4725 3770 3774 4284 1771 3770 2679 2238 3770 4725 3774 2679 3367 3774 3623 2241 3770 2241 1772 1771 834 3771 3375 2678 834 3771 2683 3375 3771 3374 2686 2683 5469 2686 3374 2752 939 3771 2683 834 4474 4919 3980 4210 3772 4947 835 4214 2271 3773 624 2341 3537 5464 2580 5220 2341 4661 1204 3773 2271 3773 1204 624 4618 2682 1318 4369 4619 4265 3424 4327 4577 941 2679 3660 2383 5925 5336 5769 5400 3640 3858 2914 3774 2241 3770 1771 2581 4410 37 3775 2581 4550 3849 4288 3849 2690 2681 2689 3775 2765 2681 2755 3535 5898 2690 4373 5887 5822 5727 5860 1316 3776 1776 2690 2581 3775 37 3777 2684 4301 3777 3377 3775 2765 37 3777 600 3778 7 599 4301 2684 936 3377 940 3777 3377 2684 2681 3777 3775 2689 5595 3503 601 3618 600 5299 3778 599 600 5595 3618 2881 3507 4621 4488 2138 3197 2267 5682 615 3655 4949 3508 4462 857 4163 3780 1635 2765 2253 37 3850 1317 5199 3779 2688 3374 4989 1317 2761 4789 4163 3780 2609 3781 2907 1318 35 3780 1705 857 1 857 3780 2609 3215 5122 3212 3503 2811 2860 5381 2851 4145 2543 4315 3780 4208 1 4164 2123 3304 3056 4372 33 4014 2671 4014 2397 33 1028 4793 4222 1353 2866 4631 3947 4220 2323 3980 3197 4919 4826 5131 4918 1370 3941 4575 4220 4510 3783 2260 946 2403 3394 3783 40 3539 1679 3783 2260 946 952 3783 40 946 3783 1679 3666 40 2107 3784 2257 3190 3539 2257 2692 3784 2257 3987 3539 3394 2255 3784 3064 2692 2107 3784 2692 2257 3064 5324 4057 2163 2255 4057 3784 3190 2853 3945 1077 3787 2871 4077 1878 1995 130 4077 1092 133 3609 3785 2875 2872 3785 3609 2875 2871 1251 3949 2204 2873 1638 5086 4854 3304 2853 3788 2860 3787 4545 3787 3945 3788 1081 4545 1 3789 1081 3945 3400 2543 1639 3788 3787 1638 3945 4920 4162 3789 3787 1077 1639 2857 1639 4854 3788 1638 2860 3945 2543 2865 2857 4545 3787 3945 3540 4309 3392 3399 4933 4162 3789 4443 4443 1081 1 3789 3790 952 3538 3391 1 4443 1638 855 3787 4545 1638 3788 4920 3945 3198 3400 4041 4310 1129 3039 5005 3305 1053 2820 3790 3540 952 3391 3538 3790 1319 3191 4309 3540 835 3399 1979 3994 1137 1136 4823 3691 3880 3937 4583 3642 2726 4717 2832 3799 3264 2825 4736 2845 2844 4478 3792 2926 2108 3124 4927 4160 1760 5463 2161 3918 2831 3793 4441 5350 2162 4442 817 4875 3795 3799 4476 2161 2832 3793 5095 5475 1064 1865 2161 4476 3589 3590 3791 5538 3877 4195 4195 5198 4945 3877 1690 5789 2383 5601 3799 2825 3589 3795 4165 3589 2825 3795 3586 4173 3796 3292 1858 3796 2948 3582 3407 4316 3926 604 3999 5078 4173 4148 2948 3999 3796 3586 3999 3582 3585 2948 4674 5498 5244 5007 3797 4603 1658 2460 5321 5172 2840 3797 1324 5218 2405 1786 2323 5172 1658 2957 2840 5315 2324 2323 2825 3799 817 3795 2824 4603 3590 4440 5312 5505 4821 5113 2841 4735 2842 3797 5105 4106 4666 4595 3679 3931 2841 3797 2825 3799 3627 817 2923 4722 3012 3988 1325 3978 2094 2270 2701 960 43 2269 3800 4741 2410 3182 21 3875 4787 1749 4020 4741 2978 3978 2410 3800 1325 961 46 4319 964 3801 3544 4319 3801 958 2702 3802 2410 1793 3798 3802 44 2410 1794 3802 2702 1793 44 3802 1790 2410 1794 3802 2704 2702 2799 3896 3803 3571 3803 4542 72 3896 5226 2446 1035 5224 2160 4441 1063 4442 1064 4440 3628 1065 2838 4442 3908 1868 3274 3804 2826 2835 2758 5316 5134 5208 3805 4295 3663 969 4111 4746 3816 3805 3809 4433 3728 3035 3805 971 3116 969 3590 4739 4440 4476 3663 4111 3805 2708 2787 4433 3574 3573 2788 3806 2787 3728 2787 4433 3806 3574 46 4319 958 959 3807 2356 3331 2572 2439 3993 2848 2438 2357 3807 3647 2356 1032 3808 3282 2789 4222 4962 1353 4793 3282 3810 3808 2172 2792 4222 3897 3261 2788 3809 3806 3728 3897 1032 3808 2792 3809 3251 3806 3426 3100 2023 3494 1871 3426 5902 3806 5854 4143 5767 5527 4219 3282 5766 3810 2172 5776 5823 3810 2789 3810 5823 3282 2789 5776 2789 2801 3575 5680 5641 4314 5520 4749 1327 2337 1328 813 5321 5315 4955 5759 5868 5834 5699 5192 3842 4237 3814 3042 4674 3110 4339 5027 5657 5042 5221 2710 3812 969 971 4999 971 3805 969 3812 4999 971 4417 2245 3812 46 3620 2246 3812 971 2245 2707 3812 2710 3620 4697 12 14 3813 2116 4181 4114 1294 5842 5483 2851 5804 4697 1295 1294 1727 4181 4697 1294 1727 12 5251 1292 14 3815 2356 3329 3496 4673 5216 4916 4612 3814 5192 4750 4237 4125 1826 1343 3861 3329 3815 3496 3328 3815 3496 2357 2356 3818 5277 4738 4746 2870 5157 4487 3395 4264 4427 3819 4426 4369 5220 4618 4991 1789 5435 1326 5045 5407 5678 5047 5045 4738 2097 2714 3805 2714 4738 3818 4154 3805 4746 3816 4738 5293 5929 614 5911 4487 1672 2942 4613 76 2806 2171 3820 3577 3820 2806 76 1041 3820 2171 2983 2089 3820 2171 2806 2450 4314 4156 3821 5248 2454 3123 2452 2817 4314 2816 3821 80 4434 3910 78 3411 5177 3938 4227 2629 4394 4150 879 2454 5248 2817 2188 3301 5280 3581 5091 3898 4253 4004 2955 978 3822 3217 3731 4253 4167 2719 3389 3316 4934 3326 3213 3822 3326 978 3217 1658 5321 4603 3797 4047 5401 5168 3549 3031 5189 3315 4242 5641 5680 5369 5520 2719 5125 4530 3823 4713 28 847 913 5492 4143 4878 4305 2202 5125 976 2199 3382 3824 2861 978 980 3824 2716 978 2739 4576 4528 4469 2760 4713 3825 847 3354 3825 28 3209 619 3825 28 847 28 4713 3354 3754 3826 4424 3563 3280 4178 5021 3692 4939 2222 2727 982 3827 1744 4937 1749 1303 5021 3439 3561 4939 4043 4451 2503 4063 870 5561 2187 5426 996 3845 1819 4271 5287 2725 4268 2734 2721 4245 3147 3828 4245 2721 3147 2745 2963 4329 3601 4067 3828 2721 2751 3147 52 987 977 3829 4764 5000 4653 3838 2724 4757 4694 2723 3089 4928 72 3894 3642 988 1808 1806 3829 1803 1811 987 3346 4828 4653 3838 4943 3215 3780 1705 4976 3839 3327 3834 3835 3323 2725 2733 4187 5325 4250 4760 2732 3838 3830 3555 2745 4509 4245 2858 3991 2427 611 3831 4267 4768 3559 55 5007 5244 4674 5113 2223 5187 1814 4992 972 4111 2742 1796 2282 4379 4376 2281 2725 3832 3830 3324 3323 4527 3830 4250 986 3832 3323 2725 3663 837 2741 3833 4579 5050 4529 972 3939 5477 4175 3941 3833 4650 3379 4415 2202 4167 2418 4530 4415 4529 3833 3846 986 3834 3327 2733 3327 3839 2733 3834 990 3839 3834 2567 4269 4270 2727 3827 4272 5151 2421 54 37 2679 2755 3775 2733 3835 2567 3555 3323 3841 2736 3835 4527 4760 4250 4758 4653 5326 5284 4298 2472 4445 1378 2421 3552 5246 54 3976 2905 3836 2314 1808 2635 4782 4762 2888 4273 2689 2581 3777 913 28 912 4358 2721 3837 1810 3552 1335 3837 1810 2736 3830 5367 3555 3838 2739 5523 4469 4532 5052 3555 2567 4828 4828 3346 4653 4042 3641 5073 2422 4908 4639 4828 3649 4042 3323 4527 3835 3830 2732 3838 3346 3830 2733 5052 2725 3555 3346 4828 3838 2732 2727 4270 3839 3327 5052 2733 2567 3555 2079 5866 5740 5805 3839 3327 986 2727 2735 4717 2726 2945 4694 3554 2724 2723 2735 4249 3322 3786 2423 4248 3644 989 4249 3322 3786 2422 4187 5516 3841 5159 2567 4527 3835 3841 3553 4357 3841 4187 3768 5001 1253 4097 3830 5367 4527 3835 4759 2744 4509 3559 4760 3553 4250 4187 3814 2747 2737 3842 2747 4628 2737 3842 4470 5524 5301 2446 3843 4130 2715 2738 3843 2726 51 3155 3843 4445 53 2905 3099 3843 2905 1808 51 3843 53 2905 3794 4716 5090 2055 4314 5248 4149 3821 2681 4770 2755 2254 3844 4147 3541 1787 4494 5528 5137 5164 3844 5044 3427 4412 3845 5004 4421 996 1015 4880 4784 3865 3845 55 3345 983 2721 4422 1819 4271 4421 983 3845 4271 837 3846 2706 3549 5528 4532 4494 1682 1337 3847 3352 997 2743 3847 997 3352 998 3847 3348 3560 4274 3560 3348 3847 4127 4116 479 478 3556 3847 3352 1337 4116 5607 1164 4127 2761 5469 4989 4548 3401 3848 2750 3543 3659 5464 5397 4577 4614 4615 2409 4474 3539 4212 3666 2323 4263 2698 2409 2268 5185 5120 3849 4281 2253 4724 3766 937 2253 4724 37 3850 3850 5003 4301 4724 5120 4548 5119 4524 2432 3851 2854 2233 2432 3851 2233 2754 2066 3851 3357 3151 4548 5469 3852 3771 4989 5469 3374 5119 57 3853 2987 59 3853 59 2428 1822 3761 3022 2757 3854 2740 3853 2987 57 1340 3853 1824 2740 4048 5572 2240 3761 5935 5974 5891 5946 4796 4998 4197 5156 3761 4048 3022 3854 3760 4553 3761 3854 2671 2756 2680 2333 4553 4876 3761 4645 1017 3855 2780 1021 3133 4636 4255 3333 1017 3855 1021 1015 2780 3867 1015 3245 4333 4985 3431 4671 3245 3874 3867 3133 3855 4172 1828 1005 2760 4554 4523 3209 4672 4718 3753 3683 925 4672 3856 3532 4523 3431 3355 3857 3431 4554 4409 3856 4160 847 2663 3857 3665 4524 2755 2679 3857 3431 3753 3856 4160 847 3857 3209 3098 4160 2603 4099 4569 5507 5166 5408 5973 3426 3806 4633 5384 1660 5034 2175 4160 4155 2665 3858 2585 5315 5035 832 2235 5066 2578 5055 4423 1821 3692 1822 4423 1821 2753 2429 3763 4552 2672 3860 2672 4099 3098 2603 4924 5116 4585 4777 3098 4552 2805 3900 606 3901 2171 3578 4151 4591 3860 3643 4552 4924 4151 4585 4552 3098 4099 3900 3432 5753 5707 5023 2067 4125 1829 2433 3361 5055 3360 1008 1018 4429 4260 2438 2433 4778 2067 4125 3676 4778 4064 4492 2392 4366 3461 3972 2657 3862 3526 3461 3287 4622 2389 2600 2807 4622 2594 2389 1127 4448 3016 1459 5947 5984 5934 5897 3359 4341 4277 2766 4265 4619 3424 3624 4781 1014 4260 3864 2769 3864 2768 2438 1051 4261 604 1050 4431 1012 67 1020 1005 3865 64 1015 1015 3872 1017 3870 2360 4880 2435 4430 1005 3865 827 64 2848 5282 5276 2439 3877 5298 5198 4945 3866 5357 2288 3363 2674 3866 2599 3363 935 3866 2288 2599 1767 3866 935 2289 2400 3866 2599 2674 3565 3867 63 3855 3867 3133 65 2770 65 3867 2770 63 3245 4636 1015 4255 3133 4255 3867 3245 3867 2780 1015 3855 5210 3420 2378 3869 4814 5479 5382 5322 5084 5163 3403 4817 1072 4142 1070 3868 4460 4837 4637 4782 4255 4659 3333 4636 5427 16 884 5210 2279 4398 4176 1728 3212 5122 4727 3876 3425 4782 4460 4637 4431 5157 3337 3395 3235 4158 1290 3515 3137 4487 4428 4431 3872 4784 1015 1017 3334 5276 4430 2209 4659 3333 2571 2769 2438 4260 1014 3864 2659 4705 3742 2661 1019 4429 1016 3873 3647 4429 2439 2870 1018 4429 3873 4260 1347 3873 1018 1833 1019 4429 3647 2870 3855 3874 3146 3867 3249 4704 4533 4189 4402 1752 25 2597 2655 3875 1752 2654 1689 4402 2597 3875 5141 5380 4946 5304 1816 1815 3148 4356 3877 5298 2964 5198 4478 3253 2845 2844 3936 2850 804 2851 2942 4790 2216 4432 3250 4790 4432 2941 4191 4518 2574 3992 3343 4518 3878 4121 3751 4432 2444 1672 2941 4790 1836 1025 2596 3879 1699 2605 3476 4964 3678 2605 2104 3880 1873 1874 2603 5093 3879 4608 3691 4791 2855 4680 3879 5114 800 1700 803 3879 625 626 3359 2389 4622 4886 4680 2855 3691 4607 1873 3937 2101 3880 3729 5836 2593 3520 2648 5836 3881 2384 5836 5874 5553 1699 3881 3232 2139 2974 2139 3881 2877 2384 2648 5836 3729 3881 4792 2372 2145 4668 2619 5213 7 4792 3882 4006 2960 3117 3246 4792 3882 4112 2147 4792 4668 4112 871 3882 7 2960 2392 3883 2598 3681 2215 3883 2602 2392 3883 3451 3527 846 3451 3883 3681 846 5686 6010 5892 6000 1028 4793 2172 3884 2792 4222 1028 3884 4031 4998 1845 1033 5778 5860 5853 604 2788 5254 4795 3885 4191 4779 4751 5525 4036 5170 4702 2096 3637 4234 3311 4138 3889 3260 2789 3887 2801 3887 3575 2789 5728 3803 5518 4225 3887 5823 4663 4748 2801 3887 3385 3575 3260 3889 2789 1032 2324 4842 602 2323 3525 4903 3460 2659 4470 5524 2446 5226 4461 4391 4392 4929 1032 4203 2789 3282 3888 4865 2781 69 5678 5877 5806 5460 1035 4670 4470 4570 758 5080 759 4842 5301 2446 1031 4670 3810 5823 5766 3282 4546 5121 4440 5095 4074 3204 4887 5354 3890 3539 2583 3432 5360 4904 3713 3220 2636 4560 2380 3207 1842 3891 71 3888 5054 3361 3656 4642 3894 72 2310 3381 2577 5066 61 4425 3893 2672 646 2603 646 3893 2603 3659 4048 3761 3022 3893 1842 4928 3089 3894 3894 4928 74 71 3086 4928 1842 4695 2239 4645 4553 4073 2799 4104 3896 3571 2798 4433 3728 3895 2050 3895 2798 3728 4222 2792 1028 3261 4680 5459 5214 5081 2555 5226 3385 4225 5776 5775 3808 3810 2801 5776 2556 3897 4513 5511 5060 5303 2792 5837 3808 3897 4422 4421 996 4271 4529 4650 4415 3379 4882 5348 4339 5312 3898 641 2716 2955 2716 3898 2955 3823 4649 3347 2858 2745 4393 5557 5031 5539 5098 4649 4509 4245 3489 5815 3942 3658 2858 3899 2575 2174 2744 4759 4509 4245 1555 4285 2920 1117 2858 4193 2174 3347 4193 2858 2174 3899 3698 4686 4566 4028 2288 5372 1762 1763 3098 4552 2672 2805 4805 5303 3281 1847 3285 4805 4513 3171 3410 4513 3285 2809 2028 4862 1164 3739 3195 2853 1639 3902 2866 4631 2849 2863 4897 1276 1939 4499 887 3903 3122 2882 3903 4601 3958 3616 2432 4178 2430 3563 4199 4942 854 860 4278 5410 1305 5011 2634 4326 3423 3722 4437 4626 4435 4588 72 74 1849 3906 2048 3906 2305 1849 2306 3906 1849 2305 2785 3906 2305 2048 3571 3906 2305 2785 2184 4058 3189 3907 2817 3907 2184 3189 1855 3907 3044 3115 4058 2184 2453 1649 2162 3915 2836 3908 3924 4812 2837 4435 2830 3274 1065 3916 2837 4812 3909 1053 4144 4816 2456 3909 4832 4572 3670 4068 3310 4144 3393 3114 2455 4742 2823 2821 3164 5727 4682 4870 4435 1055 1053 2837 4812 3924 2837 3909 1055 4866 3305 2031 2823 3928 3913 80 4437 4588 4435 3296 3446 4044 3165 4132 4626 816 4435 4588 1862 3913 2455 3107 80 3913 1861 3449 3930 4017 2106 1637 1863 3913 2821 1862 2962 4382 3493 4341 3914 3935 2846 3412 5244 5703 5113 5404 3914 5202 2846 3935 2842 4592 3797 3273 2836 3925 2838 3915 4108 4735 2841 3931 1080 3936 3390 1076 325 4109 323 3007 2836 3925 3915 3922 3584 3915 81 3908 3106 3915 3627 3264 3908 4682 2838 3164 2826 4603 2835 3804 3919 5308 2160 4165 84 4240 3917 86 2840 5505 4561 3932 3935 5083 3914 4339 4632 5184 5101 3858 977 4241 52 3829 817 2824 5121 5470 3917 4129 1363 3158 4893 5095 3918 1064 2358 4833 3920 4585 3360 5364 4914 5362 1064 4546 3265 4440 2831 3918 3106 3264 5878 1305 5749 5042 4441 2832 2162 3919 2832 4165 2161 3589 2161 4441 2160 3919 2832 4165 3919 2161 5064 5350 4442 1067 4833 5116 4803 4552 2396 4152 4072 1768 5116 2673 3363 4777 3916 4215 2830 3274 3925 2838 3915 3908 0 5036 4681 2 79 4816 3635 3924 5 3923 3 2 1286 4942 1285 4190 3923 3 1284 5 2952 3924 2837 3635 4435 3924 3635 2837 3924 4435 3635 79 2177 4596 2457 4002 3286 3468 1816 4378 3911 3924 2837 2952 3310 3924 2837 3911 3915 4682 3584 81 3915 4682 81 3925 3908 4682 3915 3925 83 3925 3922 81 5172 5321 1658 3797 82 3926 3590 604 3586 4200 1657 2160 4436 3407 3926 4261 3590 4206 3265 3628 80 3928 3913 3449 3913 3928 2455 3449 2823 3928 80 3910 2464 4514 3184 3929 5110 4737 2840 2324 3929 5482 3224 3266 4344 5482 3930 5084 2840 5084 2102 3930 4514 2464 2843 3929 2977 3930 3403 2840 2106 4737 3930 1637 1869 2164 85 3931 2167 5613 3440 4108 2840 4737 2106 2324 2102 3930 2106 2840 3679 3931 2166 2164 2843 4019 3930 3403 2166 3931 85 2164 4735 1073 2466 3630 3931 4005 3679 2166 2167 4735 4108 1869 3630 4735 3273 3797 3042 3932 1070 3402 2840 4561 3402 3932 4559 5820 4834 4328 1652 4818 4230 3578 1070 3932 2840 3402 3797 5315 4664 2840 3042 3932 2847 1070 1072 3932 2840 1070 4845 4231 639 3971 4636 4520 1015 4255 4385 3415 2305 3410 3252 4194 3934 1650 3468 1816 1665 3286 3252 3934 3574 1650 4521 2157 1022 2443 4814 5479 3269 5100 5233 5463 4522 5328 70 3934 3574 3252 3359 4341 4086 4277 5479 4814 5382 5100 1080 3936 1075 3390 2101 4745 3307 2851 4425 5323 61 4988 4314 5671 5520 4156 3691 4791 3880 2855 2190 5317 2619 4857 3945 2860 1 3788 3691 4823 4791 4680 1872 3937 2851 2101 3295 3938 2453 3030 3629 5321 4603 4206 1854 3938 3189 3123 2866 4896 4729 2865 4623 5321 4955 5315 4592 5505 5113 4664 2184 4227 3938 1649 3938 4058 2453 3189 4729 4896 4511 4732 2815 5620 3940 2451 1370 5490 5131 4918 3632 4961 3678 4625 5701 3941 4146 3279 5150 4221 625 4228 4743 1049 1047 3940 2866 4631 3638 2849 2814 5005 2815 2821 2377 4176 3517 1728 3678 4221 3632 839 2439 5282 5276 4430 3489 4581 3942 4378 2426 5187 4827 2427 626 5504 803 3879 1670 4172 4169 3564 5812 5180 5537 5764 1686 4380 4379 2273 3611 4600 2851 3612 4737 5110 2840 3288 2106 4737 1637 2324 2852 5594 3397 3113 3943 5178 2542 4737 4110 5594 4017 3113 4576 4528 2716 3824 4565 5217 3689 628 3382 4528 3944 3824 3945 4545 3788 1 2864 5006 4822 4831 3277 4630 3259 3456 4059 4722 3979 1557 963 5048 836 3946 3450 2864 2863 3947 2860 4145 2851 4308 3939 4575 4146 3941 4918 3390 4826 1080 4664 5315 4603 4957 5608 5790 5718 5714 3594 3948 1373 1372 1373 3948 89 1372 3956 4868 1092 3949 3948 89 3594 1373 87 3948 3143 89 2839 3948 3143 2855 3950 3997 2002 2204 2204 3949 3609 2872 1084 3949 2873 1092 1251 3949 3609 2204 3763 3951 3639 2874 3920 3951 3498 3639 3959 1092 3949 3956 3162 3950 2002 3069 4833 4803 3951 4552 439 3950 3069 1993 1585 3950 2883 1993 3950 3959 2872 2883 1994 3950 2873 439 1587 3950 2883 1585 2481 3950 2002 3071 2204 3950 2873 3949 3639 4552 3763 3860 1089 4095 1590 1088 933 3952 931 1769 2671 3952 2397 1769 2675 4152 1768 2240 1768 3952 2396 930 1591 4095 1088 1997 1883 3953 3088 1991 1089 3953 1591 3088 1996 4095 3953 1884 1089 4095 3953 1590 2536 4095 1884 3953 3953 1884 1590 1996 3419 5176 1690 3954 5176 3419 1690 844 5587 2591 5380 5304 3019 4798 4045 4460 1878 4868 1987 4077 5176 5625 3954 5428 3794 5942 1349 4865 1993 3955 1092 3956 4075 3956 2883 2879 133 3955 1091 3011 3956 4075 1993 3955 3956 1092 3011 3955 3956 4868 3959 3011 4868 3956 3959 3949 3011 3959 3956 2883 1092 3959 3949 2873 4130 5089 2726 4765 862 3957 863 865 2614 5228 3957 2367 4788 2367 2614 3957 4076 5259 4324 4943 2638 2377 1728 889 2118 5205 3207 3703 4397 3204 13 2882 3122 3958 2882 3903 2882 3958 3231 3714 4624 3490 3677 3653 3616 4397 2882 3204 1993 2873 3950 3959 3959 4075 2883 1993 1092 3959 1993 3956 3949 3959 3950 2873 3959 4868 2872 3011 4507 1737 3497 4209 2343 5422 1310 1307 1759 5372 4522 3531 5829 5531 1672 5532 3632 5150 839 4221 1736 3960 2361 2131 3960 1737 1736 3497 3343 5724 2444 5355 3961 5724 2444 4432 3751 5536 637 5531 1662 5355 2427 2354 637 5683 494 5536 5355 3934 4194 1650 5347 5830 610 5829 1763 3962 3530 920 2353 4213 1748 3493 2493 4213 1748 3963 1674 4947 40 4214 2011 1409 1096 3964 2892 2011 1096 3964 1098 3964 2011 2892 1885 4093 443 1996 1885 1984 1096 3965 1984 4093 1885 4039 443 4291 3317 3965 1984 4291 1096 3965 3138 3965 1096 443 4403 4619 3465 4359 1096 4291 441 2011 2889 3965 3376 441 4095 1984 4039 3321 5116 5357 4099 3363 4876 3366 3761 4645 5512 4507 1299 18 3968 3413 2271 3093 2271 3968 2327 2541 2006 3970 2911 2005 3968 3205 3413 3093 1683 3968 3672 3205 3087 4841 2015 2012 1603 3969 3087 1105 3969 3090 3003 2017 1104 4841 2012 1107 1603 3970 1105 2014 2015 3969 3087 1603 3597 3969 1105 3090 3082 3970 2911 1102 2014 3970 445 1603 2006 3970 2005 445 5311 3971 819 3472 4231 3480 808 4224 830 4845 639 640 4816 4847 4002 4597 819 3971 2903 3472 634 4231 3971 3480 4231 634 808 3480 2360 5363 5134 4087 2392 4402 3972 25 2392 4366 619 2876 2311 4100 2303 25 4146 4575 3947 4220 4922 5539 5425 4393 3465 4403 4359 4278 4366 2392 3461 3862 1154 4117 2979 1165 4890 4306 3974 4573 2909 4890 4306 3974 441 4307 1097 2010 2333 5447 3537 4369 3552 3976 54 3828 2744 4759 4245 4267 2126 1707 3130 2363 2920 4285 2534 3076 5246 3552 54 4763 2917 3977 1952 2930 1551 3977 2930 1952 1953 3977 403 1952 1118 4285 2927 2930 2894 4994 2011 1100 961 4832 3946 3978 2700 4832 2413 2412 3013 3979 1556 1946 2323 3980 615 3197 615 4212 2323 616 442 3981 3317 3083 4212 2408 3539 3666 2409 4614 4474 4210 442 3981 3083 443 1600 3981 3085 3317 1600 3981 2249 3085 3982 2244 325 1497 325 3982 322 2967 3494 5163 3418 4252 3456 4166 3318 3566 2309 3983 2237 2434 5615 5670 4630 5409 3318 4935 609 4471 3983 2309 3416 3636 3416 4483 1343 3983 4485 3418 3267 3494 3985 4869 1127 3986 1121 5013 3070 4342 3443 4342 227 4059 1123 4448 3984 229 3070 5013 1117 2003 4101 4035 3101 3604 3986 3018 1127 3985 3165 4871 3159 4044 3018 3986 1903 3985 3796 4870 3999 3707 1127 4449 1959 3986 4449 1126 1959 3986 1122 3986 3985 1903 3018 3986 1959 1903 1556 3988 2923 3013 4143 5767 4219 3767 4225 5892 5226 4275 2671 5768 2333 4369 1119 3988 2934 1947 1946 3988 2923 1945 3612 4829 4600 2851 4052 3988 1981 3036 3013 3988 2923 1981 1947 3988 2934 3036 4722 1955 4627 3988 4140 5355 3989 2431 3183 5347 3989 610 2431 5355 4226 3650 5724 5536 610 3989 5173 2941 3878 4905 4310 4041 230 3039 3039 3990 2935 1972 1128 3990 1972 2935 3039 3990 1129 2935 1137 3995 1569 3994 3991 2220 1813 1814 4356 1339 1815 1337 3992 5525 5173 4779 640 5311 819 821 2573 5157 3395 4638 2941 5173 3878 3250 2360 3993 2848 2439 2772 4520 3993 2775 1976 3996 3043 3994 1136 3996 1973 1139 1569 3996 1976 3994 1978 4966 4043 3996 3995 409 1134 2944 3950 3997 2873 3162 3995 1137 1569 1975 1136 3996 1978 3994 3994 4966 3996 4043 5346 2944 1913 2956 3995 1966 409 2944 1983 3998 1138 1134 1276 5692 5612 5489 1569 3996 1134 1976 439 3997 440 3162 1251 3997 1250 439 1139 3998 3996 1973 1978 3998 1139 1983 3998 1139 1974 1973 3021 3998 1134 1138 1983 3998 1134 3996 3125 475 476 4000 4148 3999 3582 3585 3407 4173 3586 3926 4982 3719 1565 5079 5079 1461 1137 2502 3705 4150 3695 879 3407 4173 4148 3586 2196 4000 1275 1274 1564 3009 1143 4001 4001 4452 1564 4078 4452 4503 4078 2217 1911 4078 1566 1132 4040 4982 1229 1564 3924 4596 3635 4002 4596 2457 3635 2557 3921 4641 3916 4215 5409 5813 4169 4483 5465 5670 5615 5409 5363 4774 5134 4987 1344 4003 2943 3456 1303 907 902 4937 4008 4801 3511 3509 5073 5876 5108 5818 4253 4800 3898 4004 2719 4004 3174 2203 85 4005 2460 3797 5202 3440 4108 2846 3931 4005 3797 3679 4005 3931 85 2166 85 4005 2166 2460 5503 5529 5517 5165 4825 5574 5143 5082 5387 4965 5111 3199 2581 4464 37 4410 3882 5213 4792 7 4859 5327 5111 5085 1151 4010 3007 1924 4564 4801 4262 3700 4008 4564 4330 3247 1914 5346 3063 1964 5473 2147 2190 2622 4262 3700 3336 3696 4979 5478 5394 599 4093 441 1984 3965 1924 4010 3120 1918 4010 1275 2196 1625 2196 4010 1918 3290 4010 1924 3120 3007 4011 2033 1923 3058 1626 4011 2033 2971 323 4602 2026 4038 1923 4011 3058 2030 4307 4093 441 4039 4038 3102 3058 2051 1154 4011 2971 3102 4213 18 3738 4013 2369 4012 2149 1711 4 4012 3302 2369 2149 4113 4012 2881 1286 4012 2132 1711 4013 5605 4399 3727 4013 4698 4213 4399 4014 2121 2671 2397 3056 4372 1313 1311 4372 3056 33 1311 35 4014 33 4372 2023 3100 3494 3710 2682 4014 3781 2671 3007 325 1157 4015 3120 4015 325 3007 1158 4015 325 3120 4022 4899 1164 3053 5563 807 878 5562 5359 874 3238 5038 4387 5191 4164 4208 2102 5084 2106 3930 3224 4514 3184 4017 3224 4514 4017 3930 4737 4017 3930 1637 3695 4395 879 4150 2976 5594 3113 4017 4019 3403 2977 3288 4689 5371 880 5252 2113 5331 4978 4977 3019 4609 3734 2888 5039 4922 2374 4393 4216 5397 4873 2679 2542 5178 1078 88 3829 4757 52 4694 5959 5875 5939 5909 3930 4019 3288 3403 2839 2292 2852 1877 4832 2094 4068 4020 1325 4020 3978 3800 2585 5401 832 4572 4832 2978 3051 3946 2413 4068 2094 2193 4021 1153 3103 2981 4503 1564 1229 2217 4103 4899 3161 2042 3101 4021 2026 2971 1153 4021 2026 2981 5334 2086 2195 3169 4116 4127 479 3169 2086 4024 1169 2986 5607 4024 3169 4022 5332 1169 1629 2086 4022 5607 2075 4115 2075 4024 3172 3175 3739 4022 3150 1164 4116 4022 2982 3053 4024 4116 4022 2982 2988 4034 4023 2989 3172 4500 3239 3152 2988 4034 3740 4023 2086 4116 4024 2986 4034 3128 2998 2028 5488 4024 1169 5330 2947 5332 5330 3149 1840 5319 4060 2791 1929 4026 3156 2988 5334 3694 2195 3153 1171 4025 2985 3152 1171 4454 4026 3457 2984 4026 3457 3743 3040 4900 4027 1977 1514 2060 326 4028 4027 1936 1982 3129 1982 4027 1977 1940 2056 4027 3177 3040 1941 4027 1977 3040 2057 4028 3140 1930 2994 4029 2527 2990 4029 2061 2999 2059 4038 2024 323 3105 3159 4132 3165 4044 2063 4029 2527 2996 2994 4032 4029 2999 3739 4115 1164 3150 3101 4862 2028 4030 4862 2028 2989 2998 2051 4549 4105 4038 3101 4862 2026 2028 2524 4862 3369 1504 2788 4031 3728 1033 2088 4135 4123 2526 1513 4489 1938 3139 4032 2059 328 4029 4811 4135 2526 4489 1937 4123 2999 3002 3236 4136 4044 3159 2526 4811 4032 4135 4568 4866 4033 3305 3526 4658 4366 3862 3159 4132 4044 3236 4034 2989 3740 2992 3740 4867 4500 4034 3128 4034 2044 2028 2989 4034 2028 2992 1176 4867 1932 3128 3740 4034 2992 3747 1177 4867 2985 2027 3896 72 3571 4104 4102 2045 331 3131 331 4035 1174 1511 1186 4036 2096 3045 4235 5170 3045 1939 4602 3101 2025 3604 1628 4235 3045 3610 5170 4036 4235 3045 4010 4037 2039 2969 1186 4036 3732 2096 4036 5170 2096 3045 2244 4037 1916 3007 4346 4010 2969 4109 4037 2065 2969 2036 2065 4037 2039 3062 2026 4038 3101 2971 3321 4093 441 1984 3101 4602 2025 4549 2024 4038 4011 3105 3775 4288 2679 4550 4038 2024 4011 2971 4307 4093 443 2010 2383 2591 16 4080 4041 2501 1454 227 3012 4722 4627 3988 227 3012 405 4041 4296 4493 3344 3452 4503 4966 2950 1998 4001 4503 4078 1564 1565 4040 3063 3719 3039 4062 4041 230 4041 4310 1454 1129 2959 4451 2503 4043 55 4267 3345 4042 4828 3346 4042 2222 4042 5377 4267 611 3048 4493 4067 2963 1461 5079 2503 2502 5325 4187 4250 4974 1907 4043 2959 1461 2725 5287 2732 5052 4268 4828 2222 3346 5683 611 4226 3650 4040 4966 3063 3719 3159 5611 2061 5344 2061 4872 4046 4871 4966 5346 2956 1134 3236 4496 4132 4044 3518 4782 2888 4460 4496 1188 3173 3236 3446 4044 3006 3165 4044 3313 1276 3020 5611 3313 1276 5344 1728 4835 2377 4176 1732 4198 4177 4182 3720 2642 3735 3015 2061 5861 5783 5847 1729 2878 3229 5926 4872 5345 4897 1276 1276 5783 5758 5692 4655 5168 4415 4654 5050 3846 3549 2706 3854 5161 4048 3022 2671 5768 2756 2333 229 4049 1124 1967 1954 4049 1967 2920 2226 4285 3977 2916 4090 229 1967 4049 1116 4090 3076 1124 4140 5355 2354 3961 4468 4916 4612 4673 4139 4300 3550 3547 3235 4158 3871 1290 2680 5573 3023 34 2238 4873 2679 4216 4061 3046 406 4053 4053 3757 1904 4052 1981 4052 407 1955 4062 4627 405 4083 406 4052 407 3036 3036 4052 3988 1129 1906 4053 1133 1980 3137 4613 4428 4487 4052 4061 1129 406 227 4062 230 4041 1904 4053 1133 1906 2058 4135 4032 1509 4487 4054 3568 4122 2376 4837 4835 4637 403 4055 1226 404 3977 4055 2917 3026 2765 4056 2755 37 7 862 2138 2135 3064 5324 5023 4057 2679 4410 616 2324 616 5664 3539 4410 4056 4410 2679 37 2254 4770 2755 4056 2765 4056 2253 2755 2453 4058 1048 3189 3938 4058 2184 2453 3189 4058 1048 3907 4059 405 1558 1459 2003 5013 3034 4342 1968 4448 4059 1459 3012 4059 1950 227 3443 4342 3070 2003 4059 4448 227 1459 2153 4536 1840 4060 3046 4061 3038 2935 405 4338 4062 3757 405 4338 3757 1906 227 4062 405 230 3757 4083 405 1905 3677 2349 3645 4084 1133 4266 1906 1132 4083 3757 405 4062 4276 2716 3759 4721 2901 5080 2355 763 4966 4503 2950 4296 4063 4043 3994 1979 4043 4883 3719 4497 2951 5349 3601 5147 1461 5079 1137 4063 3676 4884 4846 4064 5349 4493 4040 4902 4774 5316 5134 4846 2236 4425 61 4775 2223 4992 1814 3468 1145 4066 3048 1146 2457 4065 604 3308 4493 5349 4040 4067 3028 4066 3032 3452 3344 4503 1911 4329 3027 4498 4464 4007 4040 4902 3719 3009 5141 4904 4325 4482 3719 4902 4493 4497 2667 5043 928 5411 2590 5401 2412 4572 832 4572 833 3670 4572 5035 2585 2412 1942 4069 336 4070 1934 4070 4069 1942 2528 4069 336 1942 1935 1942 336 4070 4095 4039 4093 2887 2242 4073 2675 2398 2242 4073 3654 2675 1768 4072 2396 3952 2121 4072 1769 2397 5619 5045 4154 5365 3854 5117 3761 2675 3366 5117 4073 2398 4073 4646 3760 3059 4073 2396 2242 3654 3119 4891 4074 1646 3119 4397 4074 13 5960 5869 5909 5939 2114 4074 13 3119 4783 5354 4887 3204 4678 1685 1209 4365 4075 1999 1091 2879 5088 5122 4789 3876 2875 4077 2872 3785 2612 5036 4196 3505 4316 3407 4173 4148 2458 4852 2456 4593 3011 5255 2872 3057 1871 1870 1071 2834 4077 2871 1878 3785 4442 1868 1067 5350 2870 4087 2439 4079 1143 5349 4001 3009 2851 4854 2860 4732 5829 4079 3183 5347 2439 4087 2360 4079 3515 4481 4016 4180 5422 2340 29 1310 2642 4400 3722 3423 895 4080 2591 2382 4400 2591 16 2276 38 4081 41 36 1781 4081 38 3073 1781 4081 41 38 5622 5337 4508 3067 2643 4347 3219 4082 5544 5337 3725 5014 2938 5414 3039 2940 4329 1560 3344 3050 4557 4347 2283 2643 1733 4082 3219 2384 2933 4627 1956 3756 4041 4722 3012 1956 4627 5186 4062 4041 2427 3831 3991 5187 3653 4582 3677 3631 4052 4720 4053 4083 4083 405 1905 2932 3491 4084 2349 3677 4084 5167 625 3645 625 4084 3645 2349 2503 4085 3398 2959 5507 4711 5166 5265 2959 4851 4085 240 2503 4085 2959 1461 4466 4565 638 4303 3176 1041 3577 1043 2807 4622 3287 2594 4086 4886 3359 4622 5481 5621 5569 5374 494 5532 592 608 5830 4430 609 608 4461 3515 1290 4158 5830 2870 827 2212 3751 5531 637 1672 2435 4087 2360 64 4016 4891 1646 2374 610 5830 4988 609 5532 5830 609 608 2360 4168 4087 2435 5830 4079 5396 4087 4816 4847 4597 4640 4988 4425 2236 4987 4425 5323 2236 61 4079 5830 5829 2870 4765 5474 5392 5289 3077 4180 4088 3515 3734 4889 1699 4609 3206 4088 3077 3871 1124 4090 4049 229 139 4307 4039 140 2485 4091 3428 2486 1889 4844 4091 1895 2486 4091 144 1895 4845 819 639 640 4093 4095 2887 1996 2889 4093 2010 443 4093 4307 441 2010 4093 4307 443 1996 4160 5299 3209 2603 844 892 1730 4508 1590 4095 3953 1996 4039 4095 1997 2887 1088 4095 2887 1997 1885 4095 1996 1884 4095 1997 3321 4039 1591 4095 1089 1088 3768 4690 3003 1894 1411 4217 3090 3003 4217 4306 2486 2485 4924 2358 3920 4585 1890 5001 2007 4097 1892 5001 4097 1891 1253 4097 3091 3768 4097 2537 1890 3091 1890 4097 3091 2249 5014 5820 5140 5256 2759 4863 2762 3656 4634 5184 4993 5101 963 5358 4984 4280 3139 5340 1938 3698 3972 4348 620 4100 3098 4160 3433 2603 3639 4585 4151 3920 4096 1894 3003 4706 4100 4402 25 3972 2045 4101 2044 3181 3131 4101 1174 4035 1174 4101 3604 4035 5058 5533 4495 5195 3101 4184 3102 2051 2044 4117 331 3128 4117 2044 4101 3181 2051 4184 1511 2025 1911 2217 4078 4503 4103 2981 4021 3103 4346 3058 3010 4105 72 3906 3571 4104 74 4104 3906 72 2047 4104 3571 3906 2799 4104 3571 2047 3105 4105 323 4038 5602 5842 5596 5821 950 1779 37 4464 5595 647 2672 3711 323 4346 3105 3008 3010 4105 3058 4038 4893 5095 4106 3918 2392 5480 4366 2876 1064 5095 4546 4440 4893 2297 83 3922 2836 4106 3922 3915 479 2197 478 4107 3264 4106 3918 3106 3161 479 478 4107 1626 4107 2042 2033 4021 4107 2033 2042 1739 4340 4331 898 4561 5113 3797 5007 3736 5025 5024 901 4882 5244 5113 4674 325 4109 1161 323 2466 5613 2167 2842 4463 1163 1161 1162 3010 4463 1161 4109 4346 4463 3010 4109 3943 5300 5245 3397 5620 5280 5142 3579 88 5594 4737 5178 1796 4111 2708 2095 4111 4746 3805 2708 4111 1796 3379 2742 2710 4295 2709 969 4105 4549 323 4038 2970 4477 2370 3364 4112 3246 3512 3117 4012 4113 600 2881 5503 5661 5529 2138 2149 4477 2881 2370 4736 5183 4478 2844 4113 5102 4012 600 5529 5754 5165 5736 2137 4336 4114 2636 2584 4947 3539 40 3463 4115 3739 3150 3067 5337 5140 3723 4351 2999 3129 4900 332 4117 331 1154 2982 4899 1925 4116 4502 4899 4021 2042 4021 4899 4103 2042 3102 4117 1154 331 3169 5607 3694 5334 2979 4117 3128 1165 4802 1842 3888 4118 5152 5717 4211 5673 3053 4117 3128 2979 2045 4117 331 2044 2028 4117 3128 3053 4118 4516 1842 3888 2445 5551 5058 5441 4433 5890 5825 5854 3744 4648 3527 3460 2382 5010 4198 3904 4971 4182 4177 4479 2634 4120 1732 895 4946 4177 4182 4479 2634 4120 3713 1732 2430 4178 3989 3167 5450 5806 5460 5678 3343 4518 3135 2783 2870 5157 3569 4487 4518 3343 3135 4121 3135 4518 4121 3992 1350 4121 3992 3135 2870 4487 3569 4122 2086 5332 1169 5330 4611 1346 4292 2437 3568 5157 3569 3340 4123 2526 1185 2088 2088 4135 2999 4123 1937 4123 2088 2999 2994 4135 2088 2526 1185 4123 2088 1937 1190 4136 1189 3180 4124 1191 1939 3699 3020 5170 4235 4499 328 4124 326 1189 328 4124 2059 326 2061 4124 2059 328 2058 4124 3699 326 5170 4235 4499 1939 62 4125 2433 1829 1343 4125 3861 2433 2709 3116 969 4295 3652 5134 3434 4580 62 4125 1827 2433 998 4355 4126 3556 2352 5353 2163 5324 3861 4778 2433 4125 4425 4540 2569 3646 998 4911 4126 4355 1815 4126 1818 1338 479 4127 3694 3169 4911 4126 1812 3145 2091 4128 3172 3156 1172 4128 3152 3172 4128 3239 4025 3152 2984 4128 3156 4026 2806 3578 2171 5181 1171 4128 3152 1172 4249 5089 3840 4717 1362 4744 1363 4129 4276 2716 3325 3384 4074 4887 4891 5075 2929 4909 4532 2247 3601 4902 4451 4493 3642 4583 2726 1808 3740 4867 4034 3747 1054 4131 1057 3306 5386 1049 4743 5305 3236 4496 1188 4132 4251 4721 2739 2716 4722 1120 1557 1956 4722 1556 1120 1955 4397 5205 2118 3119 2862 1802 2415 1803 3382 4528 4133 4279 3868 5163 4817 3403 3167 4134 3989 2430 2170 4140 2431 1662 3606 4136 3605 3159 4489 3002 2999 4123 4352 4980 4186 2621 2061 4136 3020 4124 4136 3605 3236 3173 4136 4496 3236 4044 4124 4136 3159 2061 1190 4136 3159 1189 4702 3732 2096 3173 4237 4750 3814 4413 5638 960 5049 3408 5559 5618 5292 4137 5040 5774 2112 5734 4771 957 955 4147 3408 5366 3179 4137 5618 4771 2697 5559 3178 4320 3637 4138 5851 5900 4798 5838 5724 4140 3961 5355 4139 4916 4050 4673 5051 49 966 4909 3459 4930 4159 919 2851 4745 804 4141 4139 4673 4050 3547 2432 4140 2170 3280 2170 4140 1662 3289 5592 5679 5379 5585 3563 4140 3280 3183 804 4917 2851 4141 2851 4917 1075 4141 5381 5595 601 5351 1072 4562 4142 3868 4157 5135 4297 3550 1072 4562 4207 4142 4253 4004 2719 3823 1324 4411 42 2405 5381 2543 801 4145 1959 1970 1127 3018 3898 5311 4420 2716 4465 4886 2389 3359 4144 4816 3924 4640 2582 4919 2584 3539 5478 2618 599 2372 3947 4220 3279 4146 4212 4919 3980 3539 3632 5212 2345 839 5755 3727 1740 3216 4576 3824 980 2861 3638 4575 2467 4220 954 4147 955 957 3541 4147 2697 2406 4771 2406 2697 4147 961 2412 43 4832 2697 5292 1794 2702 2819 4852 4593 2456 3585 4148 3407 604 3734 2790 1699 4317 3763 4151 3860 3201 3821 4688 3706 4149 2184 5177 3411 4149 5321 5680 5177 4512 3123 4149 3938 2454 2850 5574 2851 5143 5521 4313 4412 3844 2112 5040 4395 883 2629 4150 877 879 3705 4150 877 3695 4150 5040 867 883 1724 4150 3695 883 2626 4150 877 2629 3108 4150 877 3705 4925 5486 3622 4153 2121 4152 2397 3056 3763 4151 3639 3860 3920 4151 3498 2662 3498 4151 3639 3201 1307 4925 4407 1309 3648 4651 4432 3337 4646 4072 4073 3654 5258 924 3061 3750 3854 5161 4152 4048 4553 4646 3654 3854 5232 5486 4617 4926 2397 4152 4072 3056 4925 3640 3622 1307 4155 3640 2665 3858 2288 5372 1760 1762 3209 847 3857 4523 4238 926 4160 4155 4409 4985 4554 3431 3622 4925 1307 1765 926 4632 2395 4155 3429 4554 2666 3209 2664 4671 847 4985 2395 4925 926 1307 4685 2806 2173 2089 5947 6004 5969 5983 4738 2714 3818 3805 4160 5400 2914 1698 3816 4738 3818 3805 4160 4672 3753 3683 1074 4162 2849 3593 926 4238 4160 3683 4156 80 2816 2450 5813 4483 5160 5799 3821 4156 2450 3706 4742 2815 2821 2814 1858 3164 3584 2034 4931 2659 1758 4930 4157 613 2248 3549 4297 5558 4157 4655 2248 4157 4050 1682 3515 4481 4088 4461 4574 5508 4845 830 2414 4612 1795 973 5160 5352 5148 5175 3098 4160 4099 3433 4903 2658 4648 3460 4160 4238 3433 3683 3168 4686 1169 2060 2287 4160 2914 1698 4160 5595 1698 5299 1754 5430 1753 29 2760 4713 847 2664 4162 3789 2857 3945 1074 4162 3198 2849 3789 4162 2857 3592 2161 4165 3919 2160 5259 3780 5088 4943 1 4387 2123 4208 2825 5196 3795 3590 1785 4210 2265 2408 4387 1 3780 4208 4076 4943 3421 4196 3589 4165 3590 3795 4441 4813 3919 2162 3263 4165 82 3590 3263 5308 2160 82 5064 2160 4442 4441 3564 4505 3277 2931 4224 4565 3689 633 4505 3566 3456 2931 4530 2418 976 2719 4087 609 2435 4168 2943 4168 2435 3456 3238 5354 2375 4074 1825 4168 2435 609 4003 4168 2943 3456 5114 643 4565 3338 4935 3318 609 4168 3565 5409 4169 4483 4284 3367 3774 3623 2209 4386 2357 2360 3194 4575 2467 2866 4675 4937 907 2119 2330 2163 1677 2352 3226 4183 7 3513 2614 4980 1718 2620 2967 4171 3120 325 1918 4171 4092 4010 2244 4171 1916 3982 325 4171 3120 3007 1918 4171 3120 4092 1915 4171 4092 1916 626 4317 4205 3680 4200 3586 4173 3926 4173 4148 3586 3999 4172 3146 4169 3565 4316 5188 604 4148 4173 3999 3586 3796 2458 4593 2457 4322 1290 5087 3871 1723 3228 4605 4389 2545 2788 2050 4031 2781 865 4389 1713 4174 5213 7 806 4174 5663 5682 3197 5035 5389 5731 5702 5652 4410 4464 37 4730 4520 3865 3872 4733 1732 4182 2274 1731 3713 4904 1732 4120 3423 889 895 4400 1728 4176 2279 2376 3229 4460 3518 4045 3869 4837 4782 4762 4177 4971 4479 4482 1717 4980 1351 2620 5160 5813 5799 5352 4684 3234 2880 3693 1286 4289 864 4179 2681 4770 4290 2755 2368 4289 1711 4179 2880 4898 2881 4289 2115 4180 3515 4016 3317 4291 2892 2022 1719 4180 2374 3077 2373 4180 1719 3206 3231 4181 3716 3704 3240 4336 4181 3231 4336 4181 3231 3704 1658 5321 603 4603 4697 2779 3704 3813 4181 3240 3231 3716 3101 4602 4030 3604 1731 4198 1732 4182 3904 4808 4198 2591 4183 4390 3243 7 3199 5624 10 5425 4808 3904 4198 4325 2382 4198 2591 3904 1731 4198 2383 2382 2789 5776 3808 3810 4247 4182 1732 4177 2025 1511 4035 4184 2051 4184 331 1511 4184 4035 331 1511 2426 4185 2223 1813 1665 1664 3558 4185 4035 4184 331 3131 1045 2041 1044 4804 4980 1717 4352 4186 5042 5657 5096 5221 5159 5516 3841 5290 5191 5088 4387 4943 5393 5326 5325 5284 4186 4669 3455 2621 3841 4250 3553 4187 2703 5048 3668 4984 1285 4188 2606 2617 2151 4188 2617 2606 1285 4188 1714 2606 3502 4188 3256 2151 1709 4188 3502 2606 4704 3504 3249 4533 3737 4704 4324 3876 3249 4704 4324 3737 4942 1712 1285 4190 4942 1286 854 864 4684 4289 3234 4179 1714 4942 1285 1708 3234 4190 4179 2368 4043 4966 3063 2956 3992 1350 2574 4191 4191 4779 3992 1350 2574 4518 2783 3992 4432 4586 4191 2444 4795 3251 2788 4192 975 4999 4418 1800 2788 4795 4192 3885 3147 5720 4245 5098 4245 2745 2858 2744 3147 5815 3976 5720 5119 2679 4524 3852 637 5592 4194 5355 5592 1026 1024 5379 5090 4195 3877 4716 1024 5592 3343 2444 5835 5918 1349 5883 4716 5538 3877 3934 5538 3791 2964 4736 4716 4478 3794 4195 1705 4196 2365 2608 4196 5036 0 3421 4076 4196 3421 3505 1837 4998 1033 1845 4681 4822 4196 0 4822 4831 0 4681 2787 5254 4795 2788 1033 4998 4197 3885 5802 4797 5499 4748 5156 70 1023 1027 4158 5072 1290 4461 1731 4198 2382 1732 4198 4798 2383 2591 4180 4481 2374 4088 2457 5341 4955 4948 3515 4481 4461 4016 5304 4808 2591 4946 4325 5010 4198 4177 5643 6021 5879 2973 4177 4946 4182 4198 1703 4199 1708 1285 21 3875 23 5565 2619 7 868 4792 5677 5426 867 5040 4682 3164 3908 3584 4200 3586 1657 3292 3926 4200 3263 4173 5697 5707 5069 5599 2661 5103 4620 26 5068 5102 4354 1712 4462 4949 3508 4488 3073 5814 5353 5527 5084 5163 4817 3418 2360 5615 5375 4935 5158 5375 5174 5352 3574 5683 2445 1650 4955 5321 3590 3926 4203 1032 2789 3889 2789 4203 3889 3887 4670 5302 1031 5301 1712 5102 4354 2366 713 5080 717 4954 717 5351 601 4885 712 4954 3473 713 3635 812 813 4955 4885 577 3066 788 4954 788 572 4885 577 4885 3066 4839 496 4885 572 4839 741 4842 739 742 868 4792 3246 4668 3635 4955 2557 812 3494 5206 4485 5163 1072 4207 1070 4142 1368 5206 4207 4562 1072 4207 1365 1070 4142 5163 4207 4252 1 4208 4164 3304 5132 5660 5152 5118 4164 5381 4208 5191 4145 5381 2851 801 2543 4208 1 2860 3724 4700 1743 4699 1674 4919 2408 2584 4614 4919 2794 3197 2681 5120 3383 4550 4919 1674 2794 2584 2794 4919 2584 3197 3270 4614 4474 3621 2265 4919 4210 3980 2867 4210 2409 2407 4919 2924 2264 1674 2264 4919 1674 2794 1785 4210 2407 2265 4212 2265 2408 40 3738 5605 4698 4013 20 4213 3963 18 2353 4213 3963 1748 1674 4214 40 2925 3833 4526 4415 3846 40 4214 3772 2925 2161 4546 3265 3918 3921 4814 4455 4543 3588 4455 3921 4215 3274 4456 4215 2830 2238 5207 2679 4283 4643 64 1010 4282 3090 4217 4096 3003 4217 4447 4096 1112 4218 1671 1344 1670 64 4643 1010 4218 3196 5852 3767 5833 1748 2159 4384 4382 2856 4575 4510 2467 4631 2866 3638 4220 3486 4961 3677 3476 2792 4321 4222 3884 5225 1353 3261 4952 1028 4222 3261 1353 5837 73 2556 1036 3261 4952 1353 4222 1353 5225 3261 3625 3897 4952 3261 4222 5149 2198 2422 4223 4828 4639 612 4042 4224 3480 633 3478 1329 4589 4304 2868 4912 5508 629 810 4797 5240 3385 4275 1354 5545 5456 4570 3572 4225 2555 3260 4826 5131 2111 5082 4226 2227 2431 58 3632 5212 625 2345 3298 5369 3581 5142 4227 2184 3938 3411 3938 4227 812 1649 3678 4228 839 3879 3631 4625 4624 625 3678 4228 4221 839 4003 4935 2943 4168 2557 5680 5641 4227 5194 5973 4118 5981 3411 5680 4149 5177 2557 5369 4512 3298 4743 2451 2815 3940 2180 4856 79 2179 5227 2185 812 811 819 4231 3480 3971 639 4912 4472 4574 3539 5315 2582 4919 3652 5134 4425 3434 5508 4912 830 4574 4231 638 3480 4224 3635 4435 4232 79 4227 5680 5641 5177 3313 4235 1276 3020 2412 4519 3886 4234 4133 3466 2705 2318 5731 5407 5619 5231 3466 2318 4133 1331 3180 5170 4499 4124 3781 4369 1318 2682 5000 3830 3324 3346 5279 2747 974 3814 2747 5279 4237 3814 3842 5192 4237 4766 2705 5192 4237 3546 4654 4650 2742 4047 4925 1307 4407 926 4685 2806 2089 2171 3139 5340 3698 1939 4238 926 4155 4153 5102 4113 4012 3626 4632 4925 4153 926 823 5034 2354 3495 3329 4239 2354 822 4239 3329 2354 3495 3042 4821 4339 2847 5083 3935 3914 3412 4820 5083 3444 4240 5007 4882 3402 4561 84 4820 86 2298 4543 5132 4455 4475 3914 5390 3412 3587 4929 5373 4783 4391 4757 3829 52 4241 2721 2751 4422 1809 495 642 1663 4242 2887 4307 4039 4093 2716 4242 3731 642 3567 3636 2758 4244 1105 4243 1599 2911 1894 5001 3768 1598 3597 4447 4243 1894 5002 5279 4413 966 1253 4243 2912 1599 3418 5163 4485 3403 5411 3750 928 5016 2758 4484 3636 2434 4484 2758 3636 4244 2427 5683 5377 5355 2744 4267 3345 3559 55 4267 4042 3559 3976 5815 2319 5720 2745 4267 2744 4245 4284 3320 2682 4246 3320 4284 3367 3770 1731 4247 2383 4182 1731 4247 2274 2383 5124 5393 4974 5290 4653 4828 4764 3838 4250 5290 5124 4974 2354 5311 821 3472 4761 2729 2314 3836 2567 5124 4248 4921 4423 3859 60 4773 2567 4828 4248 4809 3831 5815 5720 3319 4251 5204 4975 4913 2724 5770 3554 5740 2735 4717 3322 4249 2208 5276 4733 4430 3939 5477 3782 4308 2422 4731 3786 4249 4250 3841 3553 3323 1336 5583 989 2731 4527 3323 3841 4250 4527 4760 3830 4250 3323 4760 3830 3832 4133 4528 4251 4279 3166 4276 3325 3384 2293 4277 2766 3359 2716 4276 3325 4251 5735 5850 5621 5787 3382 4528 3824 3325 3325 4528 2716 4251 961 5292 2099 4280 4913 2747 2316 1801 3056 4646 3202 5161 5163 3494 3418 4485 1070 4252 3868 4142 4817 1070 2102 4252 4207 4252 1070 4142 2719 4253 3389 3174 2716 4253 3326 3822 2955 4253 4004 3326 4304 5189 3822 4253 4589 5189 3031 3822 3822 5189 3031 3731 3822 5189 3731 2716 4538 2439 2438 4254 3332 4538 4254 2357 2438 4254 3993 1018 2360 4254 2439 2357 2571 4659 827 4636 3284 4809 2427 4660 3333 4636 2571 2770 3133 4255 2772 3333 2206 4386 1201 3496 4863 2762 1829 5364 4052 5268 5186 1129 2093 5032 1798 1327 5557 3200 4977 3339 1347 4780 1014 4260 4395 5040 4150 883 4393 5710 5425 4785 4364 4393 4257 3661 4318 4386 2206 3496 4386 2209 3334 2360 4393 4922 4018 4257 5729 4364 4894 4598 4894 1720 4598 4364 5031 4257 4259 4364 2627 4978 3200 4977 880 4364 4257 3661 4259 5331 4257 5031 2438 4781 2439 4260 2438 4429 4260 2439 1014 4781 827 3864 1014 4781 4260 4780 2160 5589 1657 4436 3926 604 82 4261 3407 4261 604 3926 4436 2948 1050 1858 1051 4261 82 604 4261 3585 604 1050 5362 5634 3360 1006 5589 1056 2176 2563 1050 4436 3585 2948 2698 4263 3848 2405 3336 4262 3696 599 4263 4614 2409 3848 621 5329 4986 5295 4801 3700 3511 3336 5111 4330 4564 4752 4008 4859 4564 4801 3397 5594 5313 4110 5486 4099 4927 5339 5327 5473 5111 5394 4979 3696 599 2619 2407 4615 3980 4474 2409 4474 2407 4210 4781 4260 1016 4429 1012 4431 4264 2773 1012 4427 2767 2773 2438 4781 3864 2439 230 4266 405 1147 4264 4427 2773 3819 2391 4278 1305 3526 1133 4266 405 1906 2732 4268 2725 3346 2734 4268 986 2725 3324 4268 2725 986 983 4271 991 2730 2727 4268 2734 2222 990 5580 3839 55 3827 4756 2222 4269 55 4756 990 4269 2727 5580 3839 4269 3839 4976 4270 4269 3839 4976 990 3834 2222 4755 983 4756 983 4421 3845 55 982 4270 3327 1335 4270 4983 4269 4976 4976 5580 4269 3839 4270 4269 2727 3839 2778 3819 4458 1835 2689 4273 3377 3777 4421 4422 991 4271 991 4422 2730 4271 4271 2721 983 3845 2744 5004 3559 4768 4963 996 4421 1661 2729 4761 2314 4272 2422 5234 3641 3644 943 4273 2581 3777 1776 4997 4273 943 3377 4997 4273 1316 4997 3777 3377 4273 5721 2111 5706 2548 5226 5766 5227 3575 1299 5512 18 15 5355 5552 5311 5223 3385 5227 3575 5226 4797 5240 3889 3260 3889 5153 3887 4203 4797 5240 4275 4799 4251 4721 2716 4276 2293 4277 621 3863 4751 4191 2574 1350 3166 4276 4133 3325 1803 1802 2415 2085 4277 2293 2766 3863 3525 4932 1305 4278 4327 5221 4981 5011 3465 4278 3424 2660 1305 4932 1753 4278 5185 4550 5120 5119 3525 4932 3746 4620 3526 4619 3465 4403 1876 4933 2608 4920 4279 5123 4830 4528 3858 4632 4155 3640 3166 4528 4133 3382 4133 4528 3325 4251 4534 3561 1821 3692 3406 5358 4280 4984 961 4280 2099 963 2701 5049 3406 5048 3383 4989 2761 3536 3406 5366 3104 3179 1320 4728 3191 1778 3849 5199 5185 4281 4281 2681 940 3383 940 4281 3536 2690 1813 5187 2427 3991 4172 1005 1004 4282 1344 4643 1670 4282 1828 4643 4282 4172 64 4282 1004 1005 4282 1670 1344 1004 1010 4282 1005 1828 834 5207 2679 4656 2679 4990 938 4283 2238 4283 2679 938 4812 4657 3305 4435 4990 834 2679 3769 3769 4990 939 938 4284 4725 3320 4246 4246 4369 2682 4284 1227 4285 1555 2226 827 5282 4659 2768 2682 4618 3623 4284 4284 5200 4991 4618 4369 3781 2671 2682 4284 5200 3774 4725 4049 4285 1967 2920 5013 2003 3034 2920 1125 4285 2927 1118 2003 5013 1117 2920 4285 1967 2916 4049 1960 4285 3977 2226 2534 4285 2916 3076 3018 4285 2927 1959 1984 4291 441 1096 2392 5146 4287 4981 2392 5750 5590 5395 2392 4287 2598 3883 2881 4898 2134 2369 5852 36 3767 5833 3779 5199 5185 4288 5050 5402 972 968 4547 3536 2690 4373 1286 4289 4179 1711 5047 5966 5640 5045 2881 4898 2369 4289 864 4684 4179 4289 1711 4289 2369 864 4898 2880 4684 4289 4289 2368 1711 2149 3693 4898 2880 4684 443 4291 3965 1096 5120 5185 5119 4989 4544 5121 5105 817 3376 4291 3965 2022 4292 1346 1019 2437 4291 2011 2892 2897 2892 4291 2897 2022 2897 4994 4291 2011 5145 3547 3545 4673 2437 4610 1019 4292 5104 5262 631 5229 4156 4742 2451 5620 2815 5620 5142 3405 826 4425 3652 3973 4540 4425 826 3646 2569 4425 3646 2357 4111 4295 3663 3805 3349 4295 2741 3379 3805 4295 969 3116 2741 4295 969 3663 4295 2710 2707 969 3452 232 3344 4296 2219 4966 232 1963 4503 2950 4296 2535 230 4296 3344 232 4503 4966 4040 4296 4493 4503 4067 4040 4296 4966 4493 3452 4966 4040 4493 3719 4329 4503 1911 4078 4503 4966 1998 4040 4469 2739 4532 2716 5751 5946 5722 600 4612 5050 4655 4157 5135 5361 5002 4750 4758 5000 4298 4653 49 5051 966 974 3405 3940 2815 5620 981 4299 2718 49 2718 4299 2739 49 4628 3466 4279 3944 4300 5528 3811 5361 3325 4528 3824 2716 3882 5213 7 2960 5689 5891 5888 5826 4157 4300 3550 4139 3850 4301 2684 3765 4301 3850 2684 3777 3777 4997 4301 3850 3006 4302 3313 4044 5003 1316 943 4997 3777 4997 3850 943 3006 4302 4044 3446 4496 1628 1188 4302 628 4912 4565 629 3389 5189 4253 4167 638 4912 639 828 638 4303 643 497 2898 4303 643 3338 4303 5217 497 4466 623 4303 497 2898 1329 4934 3213 1332 4304 3326 3217 3316 4304 5189 4589 3822 4934 3316 3326 4304 4253 4934 3174 4004 2485 142 143 4306 3572 5240 5230 4225 2486 4306 142 2485 1892 5001 1891 1598 4307 140 2887 4039 1414 4306 142 2486 4453 1100 2007 3975 4481 4891 4016 2374 2543 4308 3782 4145 3540 4309 951 3790 3939 4575 3941 4511 2851 5275 2548 2547 4729 3947 2543 3782 4854 1639 3788 2853 4732 5275 4175 3939 3939 4729 4575 4511 2548 5574 5275 2851 230 4310 3039 1460 3039 4310 1129 3990 64 4311 1344 4218 1972 4310 3990 1460 2352 5614 2163 5353 1671 4311 1344 2210 64 4311 2207 1344 1671 4311 4218 1344 5048 4312 3670 43 3670 4312 2585 43 5044 4312 1787 43 957 4312 2587 43 3670 4312 836 2585 4467 5338 5012 5136 3545 5193 1799 3811 1787 5391 5044 954 1052 79 2191 2179 4149 3411 2184 4314 4412 5521 3844 5515 5404 5534 5172 5498 3504 4727 4533 4704 4315 5381 4208 2543 5088 5405 5381 4315 3231 5205 3207 2118 3780 5259 3215 4943 4541 3780 4163 4315 2941 4790 4432 3878 4163 4789 3780 4541 3215 4943 2364 1705 4727 5405 5381 5122 3926 5406 604 4316 3407 4316 604 4148 2790 3680 1699 4317 4205 4317 1699 3680 3734 5093 626 4317 4318 3807 2356 3331 2356 4318 3496 2357 964 4319 959 1792 3544 4319 46 3801 3544 4319 958 46 4999 5943 959 3805 5407 5460 5450 5231 4320 3409 3637 2411 5281 5739 5283 5630 2172 4537 4321 73 4870 5546 5485 5008 4320 3178 1325 4138 5092 5610 5449 5396 3808 5831 2172 3810 1036 4962 4794 1029 2172 4794 73 4321 3251 4795 3574 2155 5451 3292 4173 4200 4666 3627 4106 3264 4870 4173 3796 3999 2891 5273 624 1205 2458 4740 4322 2822 5788 5860 5853 5778 1700 4662 4571 840 4356 1665 1815 2576 1284 4815 3 3923 4378 2319 1816 3489 3212 5122 3503 4727 4325 5010 4120 3904 5919 3724 3713 5917 2591 5380 4946 4798 844 4559 2645 4557 4040 4902 4493 3719 3889 5240 4799 5230 3465 4403 4278 3526 3424 4359 4278 3465 4359 5221 4403 4619 3862 4619 2392 3624 3344 4329 3050 4067 4503 5147 4078 4329 238 4337 3601 2963 3009 5349 4040 4902 4503 3344 1911 4296 4669 4980 4186 3241 3225 4340 3729 4331 898 4345 3729 4331 2647 4331 1739 1297 2648 4345 3729 2593 2284 4345 2648 3218 4715 5269 3203 2340 5842 5843 5459 5779 4968 4160 3209 2603 4332 3354 2285 28 924 5411 5043 2667 4332 28 3528 2876 5689 5891 2366 5888 3431 4523 3856 3857 3061 4671 4333 3750 4382 4465 1302 2766 4878 4343 4730 4143 4582 5467 3677 5106 4498 3027 3275 4007 2379 4560 2636 4114 1294 4336 4114 2137 5205 4560 4114 4336 5349 1143 2504 4902 1132 4266 1906 4338 3601 5147 4337 2951 4329 4337 2963 3601 4896 3902 2853 3195 4337 4329 2963 3050 239 4337 3601 238 3441 4340 4331 1297 1980 5019 1132 4338 4053 4338 1980 1906 2446 5226 1035 4470 2940 5414 4266 1132 898 4340 891 1297 1367 4339 3444 1369 3494 5163 4252 4207 842 5114 3879 840 2962 4382 4341 2159 3984 5013 4448 1967 1122 4869 3985 3986 5013 227 4448 229 3070 5013 2003 4342 3101 4035 2025 3604 3016 5013 1559 4342 3443 4342 3034 227 227 5013 4448 4342 2581 5707 4410 4953 633 4466 3689 1192 3258 4464 2586 2793 3258 4343 4335 4007 3432 5707 5600 3890 2061 5914 5913 5963 4734 2696 3356 2702 4341 4465 2766 3359 1673 4464 950 37 3539 5110 4953 2582 5247 4009 5067 5037 4344 5482 3224 3930 5069 4517 4343 4335 3105 4346 4105 3058 3111 4346 3008 1992 4346 323 3105 4105 3105 4346 3058 3008 4010 4346 3010 4109 4346 3111 323 4109 4346 4463 323 4105 4010 4346 1992 3010 2969 4346 4109 3111 4082 5836 4347 3219 3723 5140 897 5014 5391 5035 3427 5044 4347 4557 4082 2643 2283 4347 3730 3219 4082 4940 4557 4491 1044 4349 3576 1038 3524 4402 4787 4401 1040 4804 3118 1045 1355 4349 3576 2041 4349 1044 1039 1038 4804 1045 1851 3118 2041 4804 1356 4349 1045 4804 1039 1040 2096 4350 3000 2098 3305 4812 1053 2820 4489 2526 4123 4135 4123 4489 4135 2999 4265 4981 4327 4619 3572 5240 4225 3260 2555 5719 3571 4225 1353 4353 2555 1352 2858 4649 4509 4193 4710 5585 5462 5690 5503 5689 5517 5661 998 4911 4355 993 4354 5155 5102 5068 5398 5689 2367 4388 998 4355 3556 992 1816 4356 2312 3468 1337 4356 3557 1815 3146 4172 1670 1828 4356 2424 3148 2312 4483 3146 1826 65 5284 5713 5522 5288 5290 4187 4250 3841 5466 5697 4143 5069 3528 4358 28 3745 4758 5000 3830 4760 918 4358 3745 28 4357 1335 3837 3552 3837 4357 3841 2736 6038 1360 1860 4740 3528 4358 912 28 924 5258 3061 5043 4327 5221 4619 4981 5418 5657 5011 5410 4658 4619 3526 4403 3424 4359 4327 4278 2667 3429 928 5043 2445 5552 5223 5224 1195 4362 3483 820 1196 4362 3483 1195 5729 4598 4894 1720 5085 4801 4564 4859 880 4364 1720 4259 4259 5031 4894 4978 1209 4375 2281 4365 1685 4678 1209 1699 3476 4678 2273 2605 4678 2281 1209 1687 1685 4678 1699 2605 2281 4678 1209 4365 4278 4403 1305 3526 2282 4678 3262 1687 3476 4375 2273 4365 3476 4375 3486 2273 2682 4618 1318 3623 4894 5729 1720 3705 4588 816 4435 3296 5850 5933 5792 5921 35 33 2399 4372 1311 4372 2399 33 1313 4372 2399 1311 3767 5898 3776 3535 3536 4547 2690 4281 2281 4380 1209 3492 952 4374 3538 946 1209 4375 4365 1686 3262 4376 841 4375 1686 4376 4375 2273 4376 2273 3486 4375 3486 4376 841 3488 2282 4379 3262 4376 2282 4375 4365 2281 4379 3491 2273 4380 192 4381 24 1437 3262 4380 2281 841 1686 4379 4376 2273 2282 4376 4375 2281 2282 4379 2281 3262 1209 4376 4375 1686 4379 2281 1209 4376 4581 4827 3286 2426 3262 4379 841 4376 3286 4827 4378 2803 3489 4581 2319 3658 4581 3286 3468 2223 3488 4379 841 3490 3488 4379 4376 841 1209 4379 4376 1686 4380 2281 1209 4379 3262 4380 841 4379 1209 4380 4379 1686 4380 841 2349 3492 1686 4380 2273 3492 2349 4380 2273 3491 2281 4380 3492 841 3262 4380 4379 2281 1754 4381 1306 3598 192 4381 1437 1306 4932 4381 3598 26 4932 1305 1753 1754 4932 4381 26 3746 4932 3525 3746 3210 5798 5982 2781 5854 4341 4382 3863 2766 4072 2121 4152 2397 21 4384 1747 3522 4384 21 1748 2353 1313 2121 4014 3056 1692 4384 4382 1302 2357 4386 3330 2360 88 4819 2103 2542 4635 5181 2806 4685 3567 4504 2953 4202 4818 1850 2173 2449 4230 4818 3933 3578 3815 4386 2357 3496 3334 4386 2360 2943 2953 4504 4386 3330 3328 4386 3496 1201 5010 4120 895 1732 5413 4386 2360 3330 2123 4387 1705 4164 1 4387 1705 2123 8 4388 6 2366 4330 4950 2144 4009 4174 4389 1713 3228 5213 4174 806 4605 3244 4669 7 2621 4389 4605 4604 2545 865 4389 4174 7 2693 3191 952 4728 7 3243 872 4390 3121 4389 3778 3508 878 5563 5424 2374 5072 4158 4088 4461 4391 5072 4461 1723 4074 5359 2114 3238 1595 4923 1414 2020 3119 5075 4074 4501 5495 2776 807 3339 883 5426 867 870 4598 5039 876 3661 5039 4785 2374 2625 3695 4395 4150 1724 2113 4394 879 2112 2629 4394 879 2113 2112 4394 879 4395 1295 4396 15 1293 4150 4395 879 4394 2633 4395 879 3695 17 4396 15 3237 1699 5920 3954 1684 17 4396 3237 1729 5299 2374 4074 2603 3237 4396 2878 1729 1293 4396 2878 3237 5920 4798 1699 5851 3714 5205 4397 3958 3616 4397 3958 2882 2784 5299 2604 705 3207 5205 2380 3703 2790 4726 2888 1699 2273 4678 4365 1686 5123 5523 2739 5211 4726 4798 2591 2383 4045 5427 2276 4726 4698 5726 3718 4399 2361 3727 18 4399 4956 3730 2381 4834 4013 4399 18 3727 4213 4399 18 4013 1742 4399 3500 1297 1740 5755 5726 3727 1740 5755 2361 5709 4326 4400 16 889 2591 4400 895 889 4400 16 3722 4326 2591 4400 16 4080 1699 4402 2603 1689 25 908 4402 4348 4401 4402 620 3524 26 5565 3875 4705 5565 4401 3875 4705 1752 3875 4402 4401 2597 4402 3681 25 4100 4402 4348 25 4616 5338 5012 4467 4348 4401 908 4402 4100 4402 3972 4348 2392 4402 25 3681 4359 5027 4278 4403 4402 1689 2597 3681 5014 5820 5709 5797 3465 4619 3624 3424 4658 3862 4619 2392 4405 3529 914 2658 3526 4658 4403 4366 911 5416 4404 5264 2658 4405 3529 3741 3686 5568 3451 5432 2658 4405 3741 914 25 5416 911 909 4405 5264 3451 4404 3741 4405 3527 25 3527 3451 25 4405 4405 3529 3741 3527 5806 1325 1789 4138 5416 25 4404 4405 2668 4406 3622 2975 2662 4861 2394 4406 3966 4406 2668 3755 2343 4406 1307 2668 3764 4712 1312 1314 3966 4406 3755 30 1314 4551 1312 3764 5242 4160 4968 2603 1308 5241 4407 923 4925 3622 4632 4153 4407 1307 2344 1308 30 29 32 4408 27 4408 29 30 29 5422 27 5356 3856 4409 3532 3429 3203 4409 3061 3532 4523 3856 3857 3753 3431 4409 4333 3203 3750 4409 3061 3203 2664 4985 4333 4671 44 4411 1324 1786 1779 4730 4143 4305 4953 2581 3775 4410 4730 4878 4305 4410 37 4410 4305 4056 2581 4953 3775 4288 3775 4410 37 2679 4305 4410 616 4056 2585 5315 832 2412 4263 5218 3621 3401 4412 5044 5035 3396 5403 3427 5044 5391 621 5967 5933 5968 4313 4412 3844 3427 4606 5087 4608 3615 2295 1692 3442 1302 3395 4613 4487 2211 43 5391 954 5044 5528 5361 4300 5137 5002 5137 4414 4413 4414 5051 966 4909 2741 4650 3349 3379 4494 4909 2247 4532 4494 4532 2247 2929 4462 5228 4621 3506 2246 4457 3549 4047 1748 4382 2353 3493 5793 5632 5761 5704 4704 5088 4727 4533 4299 5279 4416 5051 3197 5136 4459 5012 4486 5135 4416 4532 4139 5528 4050 4157 5528 4532 4050 4157 810 4912 808 629 971 2245 3812 4417 2245 4418 4417 971 2422 4584 988 3644 2245 4417 46 3812 3620 4999 3812 959 4417 2245 46 3268 2713 4999 971 3805 4999 3812 971 969 2422 4908 4584 3641 4908 2422 4584 4480 2725 5287 5052 2734 4584 2422 988 4419 2289 4833 2358 4585 2945 4419 2422 3322 4419 4717 2945 3642 3314 4420 1663 3315 2567 4421 3291 55 5816 5669 3554 5805 4421 3845 996 4271 4421 4768 3845 55 2723 4757 4694 4420 5004 3845 2745 996 3943 5594 4737 5313 2422 4480 4249 4419 2565 4800 3823 4004 996 4879 4421 4422 991 4421 55 2221 4422 2721 2730 4271 2221 4879 4421 3291 61 5449 2230 5092 2428 4423 1342 60 1830 4423 3859 62 4423 62 1821 1822 2428 4423 3692 1342 2119 4937 907 1749 4774 5363 2758 4824 2357 4679 2356 3961 5245 5730 2292 5687 3183 4936 3563 3167 4936 3439 3222 4424 4679 2570 3280 1669 1012 4613 4428 3137 1000 4424 3222 1823 4079 4425 4087 2360 4824 3973 1007 3362 2357 5134 4425 2360 4425 1009 1007 3973 2235 5651 2231 5055 4428 4458 3340 3568 4614 3543 4474 3197 4947 2584 3539 2795 4264 4427 4426 2773 2212 4781 2870 827 4779 2777 2767 4427 3568 4613 4487 4428 1816 3468 1665 4356 5157 4428 4431 4264 1016 4429 4260 3873 4087 827 2439 4430 4636 5276 4520 4659 1016 4781 4429 2870 1019 4429 2870 1016 1759 4522 1760 3371 4430 64 2360 4087 2439 5276 2360 4430 64 5830 609 4087 64 5830 4430 609 4753 64 827 3865 5276 3334 3993 2209 4430 3334 2209 2360 2209 5276 2360 3993 3137 4487 4431 3395 1012 4431 2773 1020 4518 5525 4191 4432 5724 4432 3961 3395 4386 5535 2943 4719 4432 4651 3961 3395 4790 4905 2216 3878 2216 4432 3343 3751 1335 4983 983 4755 4270 4756 3827 4269 3728 4433 3573 3895 4434 4742 4156 80 80 4434 78 4156 5626 5848 4438 2828 3910 4742 80 2823 2814 4742 2451 4434 1055 4435 1053 3305 4232 5063 79 4435 3926 4261 82 4436 4232 4435 816 3296 2952 4435 816 3635 3305 4812 4435 1053 3924 4812 4435 79 4568 4866 3305 3912 1053 4812 3909 3308 4657 4812 2820 4437 3586 4436 3926 2160 3263 4436 82 2160 5589 1656 3109 2563 1858 4436 3586 1656 2160 5589 82 5445 2948 4436 3586 1858 1054 4437 3306 1057 3633 5444 3296 4437 1052 5063 4437 2820 4437 4568 3634 1054 4456 3274 4215 3588 5219 4467 5218 5144 2829 4438 1058 3587 2829 4438 2828 1058 4439 1058 1864 2461 817 2824 4739 5121 4603 3921 3804 4543 3588 4455 3272 3804 1058 5626 2461 4439 5904 5746 5696 5848 1864 5746 2460 5673 5746 4439 5717 5673 1065 4603 3269 2835 2165 4603 3272 1658 1060 4440 1064 1062 1062 4603 1065 2826 4441 5064 2160 3919 2160 5064 4442 1067 5165 3778 2138 5736 3921 4814 4603 3269 2838 4442 2836 3908 1698 5595 3711 5299 4442 2836 2162 1063 2162 4442 1063 4441 1638 3593 855 4443 1 4443 3789 1638 3592 4443 1638 3789 855 4933 4443 3593 1373 4959 4444 0 4162 4933 3789 4920 1152 1918 1924 1919 1372 4444 89 1373 4959 2468 2864 1371 4682 5727 81 1360 3843 4445 2905 1808 2472 4445 2421 53 1968 4448 3016 4059 4096 1894 1112 4447 3597 4447 1894 4096 4342 4448 227 4059 4059 4448 3016 4342 1123 4448 1967 3984 4448 1127 1970 3984 5013 3016 1559 1970 1968 4448 1459 3016 1557 5065 1559 1558 2219 4450 1458 3607 1958 4449 1959 1127 1958 5065 1117 4449 1117 4449 1959 1958 2219 4450 3607 1142 3607 4450 1462 3608 4414 4413 966 5002 4337 5147 1132 4853 4452 2217 4078 1566 4001 4452 4078 1143 1600 4453 2007 2249 1111 4453 1598 2007 2007 5001 1891 4097 2249 5001 4097 1253 3269 5100 3921 4814 4454 1171 477 1172 2091 4454 1173 1172 831 5693 5237 5114 4457 2741 2707 2746 4456 84 3917 1362 4455 5132 4814 4958 2161 4546 4476 3265 3272 4543 4455 4475 1065 4603 2835 2826 3804 4543 3921 4455 4047 3549 4415 4457 3548 4457 3549 2246 2746 4457 3549 3548 4295 4457 3349 2741 2707 4457 3548 4295 4292 4458 1835 1346 66 4458 1346 2778 4459 3543 3270 3401 1835 4458 2778 1346 3621 4459 3270 3401 5101 5455 4632 3622 3543 4459 3197 3671 5849 5943 1791 3112 4300 5145 3545 3811 3401 5218 4616 4467 3507 4488 3121 2138 3019 4726 2790 4460 3019 4726 2888 2790 54 4767 56 4763 3420 4849 4762 4726 3420 4837 3869 4762 4637 2376 2279 4176 2279 4837 4637 4398 4180 4481 4016 2374 4088 5076 2374 3615 4462 3506 3507 3462 1161 4463 323 4109 5385 5034 2175 5384 1155 4892 4463 3010 1161 4463 1162 323 3027 4464 1779 950 2581 4464 1673 37 4973 5474 4908 5392 1746 4465 1302 3442 2586 4464 950 1673 2793 4464 2581 4410 2258 4730 4305 37 2793 4464 1673 2581 4382 4465 2159 1302 1746 4465 2766 1302 5217 4303 4565 4466 3689 5217 633 628 4303 4466 497 638 4056 2755 3665 4770 4459 2750 3401 4467 3270 5012 4459 4616 4615 5218 4263 2405 3401 5218 3621 4616 5521 5682 5515 5452 4882 5007 3402 4674 995 2576 997 3558 3166 4528 3325 4133 1327 5193 4915 1799 4528 4576 3944 3824 4120 5010 4177 1732 4343 5466 4143 5069 3267 4485 3494 3710 3983 5009 3416 4483 2931 3277 3456 4505 831 5114 645 829 3589 4875 4476 3799 830 4912 639 4574 808 4574 4231 4472 4224 4565 638 3689 2891 5212 839 2345 4272 5286 2421 5151 800 4571 624 625 3975 4573 1100 3096 4661 5273 4590 2891 4767 4446 56 5151 3270 4614 3621 3543 3543 4474 3197 3270 2794 4614 3197 3671 4666 5105 4595 4546 5152 5534 5471 4005 2357 5134 2360 4294 3627 817 3799 4544 3272 4603 4543 4475 4544 4875 3799 4476 2832 4476 3799 3589 3589 4875 3590 4476 2161 4476 3590 3265 3628 4546 4476 4440 70 5156 5059 1027 2881 4477 2134 2370 3687 4709 3527 4676 2149 4477 4113 2881 5026 2970 1712 3364 4161 5070 5022 4711 2591 4946 4808 4198 3791 5538 4195 4736 3794 4478 2949 2845 5369 5453 5280 5142 4182 4971 4177 4247 4182 4946 4479 2383 4250 5124 4527 4921 4419 4717 3642 4583 4288 2679 5119 5469 1743 5919 3724 4696 4314 5680 5520 5671 4904 4120 3713 3220 5153 5802 4797 5499 4973 4249 4731 2422 5088 5381 5191 4208 5862 5876 5818 5866 4177 4946 4198 4325 5062 3296 1049 5305 621 5329 5295 5603 1343 4484 3983 4483 3983 5175 3636 5009 3983 5175 4483 4484 4484 1343 3983 2434 1345 4483 1343 1826 3636 4484 3983 2434 4483 65 63 3565 63 4483 1343 1345 3692 3826 1822 1821 2252 5271 2929 2739 3447 4533 4164 4189 2870 4487 4054 3395 4414 5164 4494 5137 3547 5528 4300 5137 4881 4512 5177 5712 3547 5528 4050 4139 2942 4487 3395 1672 3568 5157 3340 4428 3568 4487 4122 3569 2870 4487 4122 4054 3121 4488 3778 2138 5157 3568 3569 4487 3508 4488 3121 4462 3340 5157 3819 4264 4811 2526 4032 2527 3507 4488 4462 3121 3508 4488 3778 3121 3932 5229 2840 5104 3139 4489 1509 1513 2058 4489 4135 1509 4489 4811 1513 4351 4811 1509 4135 4489 5337 5544 3725 5543 826 4492 3973 3652 5844 5140 5415 5337 4560 5205 3958 2380 5128 3233 844 2877 1730 5622 844 4508 4585 5116 2674 4833 3362 4824 4778 1007 4493 2959 4451 3601 1009 4492 3973 826 2959 4043 4066 4493 2959 4493 4451 4043 3048 4493 2963 4066 3452 4493 4066 4043 4503 5349 4001 5147 3344 4493 4066 3452 5147 1143 4001 4078 1144 4902 4451 2504 3215 5259 2364 4943 3173 4702 3732 4496 4269 4983 990 4976 2445 5058 3574 5195 5895 5966 5927 5930 5129 5738 2798 2050 3888 5194 4118 2791 5058 5551 4754 5441 1628 4702 4235 4496 2650 1694 22 4703 1188 4496 3446 4132 4136 4702 4044 3020 4883 5079 4855 4451 1144 4883 3719 4855 4043 4883 4451 4063 4143 4464 1779 4498 1144 4902 3719 4497 5002 5135 4750 4416 1144 4902 2504 1143 4858 4007 4343 4498 4007 4858 3275 4498 3027 4498 1779 4464 4136 4499 4124 3180 4007 4858 4343 4335 2864 5803 5598 3947 2059 4499 2058 1939 1276 4499 4046 3020 2061 4499 4124 3020 2194 4499 1939 1276 4046 4897 1276 4872 4872 5345 1276 5344 3173 5170 3180 2096 2061 4499 2059 4124 4235 4499 1939 2194 3127 4867 4034 4500 3128 4867 1932 2044 4500 3239 4025 4023 1172 4500 3152 2985 2985 4867 3740 2027 3239 4500 3127 4023 3172 4500 3127 3239 4392 5075 4501 4891 4481 4501 4392 4016 4257 5039 4393 4922 1164 4502 2981 2028 2979 4502 4117 1154 1998 4503 1229 2950 4502 2028 4117 3101 3102 4502 4117 3101 2971 4502 4021 2042 3344 4503 4329 4067 2981 4502 4021 2028 3102 4502 1154 4117 4899 1164 3053 4502 4452 4503 1564 4078 1229 4503 2217 2950 2535 4503 1911 4296 4493 4503 4296 4067 4452 4503 2217 1564 1998 4503 4040 1229 1780 5614 3187 1781 4386 4719 3330 4504 5375 5700 5352 5148 4526 4415 3549 4457 3564 4505 4169 3277 4166 4630 4505 3456 2746 4526 3549 4457 17 5512 15 5154 1743 5154 17 4700 17 5512 4209 4507 1737 4507 1299 2385 892 5176 844 2143 2858 4509 3899 4193 3067 4508 1730 892 3233 5128 4082 2877 1730 5622 4508 3067 3233 5128 4940 4082 5683 2427 3650 5355 2744 4509 2858 4245 4509 2858 3674 3559 2744 4509 3559 2858 4509 4649 2745 4245 4828 5004 55 3559 4660 5377 4809 3942 5321 4065 4512 605 3941 4938 4511 4510 2866 4896 4575 4729 4729 4896 4732 2860 4730 37 1779 4464 3941 4938 4175 4511 3941 4511 4175 3939 4575 3941 4220 4146 4896 4575 2856 3194 4856 5177 4512 605 5680 2557 812 4227 3567 5109 5134 5316 3405 5061 3581 3298 5093 4848 1699 3879 5369 5641 3298 2557 5511 5627 1042 5442 1042 4513 1651 2181 1651 5511 2556 5060 4805 5303 4513 5060 2464 4819 1068 4514 4017 4514 2976 88 3184 4514 1068 2976 2843 4819 3930 2103 4819 1071 2103 1870 2464 4819 2105 1068 5815 5098 5537 5720 4809 5537 4660 5500 3891 4516 3888 1842 5180 5812 5537 5500 5502 5754 5243 5099 5378 4509 4649 4193 4118 4516 3888 2791 5166 5295 4986 5329 5599 5707 5310 5600 4517 5069 4343 4410 4518 4191 2574 2444 3258 4517 4335 4343 3135 4518 3992 2783 4518 5173 4121 3992 4191 4518 4432 2444 4518 3343 3878 4432 4518 5173 4432 3878 2574 4518 2444 2783 1328 5238 970 5402 5169 3784 3539 4057 5731 5401 5702 3378 2208 5276 4430 3334 4520 4636 1015 3865 3334 4520 3993 3870 3865 5276 4733 4520 1015 4520 3870 4255 2208 5276 3334 4520 5276 2208 4733 4520 3334 5276 3993 4520 4520 2772 3993 3870 2208 4733 4520 3872 3253 4521 2189 2156 1022 4521 2443 2156 2155 4521 3252 2157 3252 5183 4521 3934 4099 5339 3433 4927 1647 4521 2156 2189 2964 4521 2157 3252 4577 5397 5200 5464 3375 4524 4290 3387 1759 5372 1760 4522 3943 5594 5313 3397 3856 4776 4409 3429 2689 4550 3775 2681 3387 4524 2679 3852 4290 5120 2755 4524 3154 5607 4127 5606 4526 837 3833 2741 4250 5290 3841 5124 4653 5326 4764 5288 2421 4761 3836 4445 5124 3841 4250 4527 3555 5367 2567 4828 4250 4974 4921 4758 2716 4469 2739 4528 4528 4576 2716 4469 4528 4279 3382 3944 4279 4913 4251 4133 3944 4830 4279 4628 3846 4529 837 2706 3833 4579 4529 3379 976 5283 2719 1802 3846 4529 3833 837 3846 5050 4415 4529 4253 4530 3823 2719 3454 1850 1848 3176 3647 2573 1019 4531 4610 3647 1019 4531 4611 5215 4122 4906 4996 4610 4292 4531 4292 4996 4531 1835 4050 4532 1682 4157 2747 5279 966 4237 4532 5528 5135 4157 3737 4727 4704 3876 4189 5191 4164 4943 4305 5664 5527 3987 2929 4909 2247 49 4486 5051 4909 4532 4297 4532 4157 4469 4416 5523 4532 5135 3504 4533 3503 3447 3222 4534 3439 1823 3439 5021 4424 4936 3222 4534 1823 4424 4050 4916 2248 4673 4673 5216 5145 4916 4916 2414 4612 1795 4468 4612 973 4535 61 5610 4087 4988 3402 4674 4665 3110 1839 4539 2154 4536 1840 4536 2791 4060 5381 4315 4208 5088 4794 5837 4962 1036 73 5837 2556 5775 73 5831 5766 2172 3808 5837 5775 3897 4537 5837 73 5775 4537 2792 2172 4321 2357 4538 3647 3807 4779 4191 4751 1350 2439 4538 2357 4254 4539 2153 2445 4060 2439 4538 3647 2357 2438 4538 4254 1018 1349 1026 4751 71 2162 5306 1061 4813 3915 5307 3908 2162 1839 4539 2153 1838 1839 4539 4536 2153 2357 4540 3815 2569 3330 4540 3815 2357 74 3896 72 4542 5259 4704 5088 4789 3780 5259 5088 4789 2609 4789 3215 3780 4790 4905 3878 2941 2826 4603 3804 3272 5134 5109 5017 4580 5321 1658 603 2323 4543 3272 4455 3804 1814 5187 1813 3991 2835 4603 3269 3921 4106 4666 3264 3918 817 4875 4544 4739 3793 4544 3799 4476 3627 4666 4595 4544 817 4595 4544 3627 5405 5088 4541 4315 1638 3789 1 4545 3628 4546 3265 4476 3304 4545 1 3788 2267 43 5391 954 4545 2857 1638 3789 2267 43 954 2262 1064 4546 3918 3265 4546 4544 3793 4476 3793 4546 2161 3918 3628 4546 4440 3265 5470 5095 1064 4440 4546 4739 4544 4476 3793 4546 4476 2161 4544 4666 4546 3793 2679 5119 4524 4550 2690 4547 2581 3849 4288 4547 3849 2581 3849 5120 4550 4281 3771 4548 2761 3375 5185 3374 3779 2752 2761 5120 3383 3375 2975 4712 4551 3764 3010 4892 4463 4105 2761 5120 4989 3383 4989 5469 5119 4548 5469 5119 4548 3852 4549 4602 2025 323 1162 4892 4549 323 1162 4892 323 4463 4550 5185 4288 5119 4602 323 2026 4030 4602 4038 323 4549 4038 4602 3101 4549 2755 5120 2681 4550 2676 4861 2146 2662 2686 5469 2679 4288 4550 5185 5120 3849 4550 2679 2755 4524 4550 3775 2681 2755 4550 2689 2581 3849 5120 5119 4550 4524 4281 4550 2681 3383 2676 4861 2662 4551 4632 5486 5339 4153 1314 4551 3498 1312 2026 4862 323 2981 2975 4861 3622 2668 3363 4552 2672 4099 3763 4552 2805 2672 3951 4552 3900 3763 4645 5117 4073 3366 2398 5572 5472 2675 4645 5117 3761 4553 3854 5117 4073 4553 2666 4776 3429 2667 3654 4553 3854 4073 3209 4523 3753 4554 4672 4554 3753 3429 4523 4554 3856 3753 4672 3209 3753 4554 2664 4985 4554 4776 4776 2666 3429 4554 4555 1737 3726 3497 5882 5709 5256 5820 2305 3410 2048 1849 4439 5746 1864 5673 2128 4556 3230 3422 5550 1755 5643 5649 5581 3519 5560 5428 3723 5543 844 5376 5820 4559 5800 4328 5800 4328 4559 4557 4082 4557 3233 2643 4557 4559 2283 4328 2283 4557 2643 2645 3229 4835 4176 2878 5116 4803 4552 3900 4559 5800 844 5797 4559 4557 2283 2645 2379 4560 2380 2636 4336 5205 4560 3207 4560 5205 4114 3958 2636 4560 3207 4336 3402 4882 4674 3042 5129 5738 2050 5716 3733 5024 901 3736 3042 4561 3932 3402 3932 4821 3042 2847 4544 5105 4595 817 5172 5321 2840 2323 3793 4666 4546 3918 3631 4625 625 3632 3700 4564 3300 3696 4564 3303 3700 3300 3247 4752 4564 4330 628 5114 798 629 643 3338 4303 4565 643 5114 4565 828 5114 629 799 798 638 4912 828 4565 4472 4912 808 4574 4249 5089 4480 4973 5114 628 3338 4565 2057 4566 3168 3140 3153 5332 3149 5330 4686 5332 1939 3698 4028 5488 2076 4566 3175 4566 1169 3168 5488 2076 3463 3052 3529 4676 4567 3687 4959 1371 2864 5006 4568 3912 3305 4435 4718 5571 4160 5267 4569 5408 5166 3414 5304 5587 5468 5380 4569 5166 3072 3414 3748 4569 3072 3685 4711 5507 5166 4569 1035 4670 4570 1354 4670 5456 4570 1354 4571 625 4473 624 4228 5209 3879 625 840 4571 1700 3879 4571 800 3879 625 5130 624 2341 2338 4473 4662 4571 4661 838 4662 1700 840 2585 4572 832 3670 5693 802 801 3503 4572 4832 43 2412 143 4573 4306 142 3975 4923 4890 3974 3638 4575 2866 2467 4912 830 639 828 624 5130 4571 5509 4510 4896 4575 2856 808 4845 810 809 3361 4914 2991 3170 4575 4729 3782 3947 4231 4845 639 4574 4896 4510 3195 2856 2856 4575 2467 3194 3824 4576 3944 2861 4576 641 2716 4469 1046 4512 2186 3702 5237 5397 3660 3659 4577 3774 941 3623 5200 5272 4246 4991 4529 837 968 4579 2237 5316 2434 5208 972 4579 968 1796 4579 4650 3379 972 5614 2163 1780 2330 5316 4846 5208 4884 5413 3567 5134 2360 2579 5413 2953 3567 2169 5316 5109 2309 5106 839 3631 2345 3653 5167 3677 4582 2383 5863 1690 3954 3653 5167 625 4084 4584 4419 988 3642 4717 2735 2726 3840 4419 4584 4583 3642 4480 4584 4583 4419 4584 2422 3641 3644 2289 4924 2358 1767 4921 2423 5704 4248 2777 4751 2778 4427 816 4626 4435 3912 3181 4867 1932 3747 625 4590 624 2891 4167 4589 2868 4304 3326 4589 3217 3822 4589 3731 3822 3031 5519 3773 624 4323 4590 4662 4473 4661 5212 3632 625 5150 3773 5519 624 5273 1205 4662 2891 4661 625 4590 4473 624 3778 5165 4488 4949 5253 2290 3363 3092 3643 4777 4591 3860 4522 5253 3092 4993 2673 4777 4591 3363 4777 5253 3363 4692 31 5253 3092 1760 2458 4593 2819 2457 4561 5505 4821 3932 4957 4603 3629 4623 5348 4882 5113 5312 5299 5736 2603 5595 2360 5615 4386 5375 4664 3273 3797 4592 4425 5363 4087 5134 5695 5778 5639 604 2466 5613 3440 2167 3999 5078 3707 4870 3292 5451 4173 5008 4852 2822 2458 2192 4957 5315 4603 4623 813 4957 630 631 73 5511 5303 5060 4106 5105 4666 5095 4666 5095 4546 3918 5658 5810 3263 5788 2457 4955 2557 4596 3911 4597 3114 3393 3114 4640 4144 3393 4597 3924 3911 2952 3393 4640 3924 4597 3661 5557 807 4598 876 4598 3661 807 4259 5331 4018 4257 880 4598 1720 4364 4343 5069 4335 4858 5022 2652 3072 5070 56 5246 4772 54 4600 4829 1079 4607 3828 5246 3976 4772 4783 4391 2628 2779 3958 4601 2380 4397 3797 5505 2840 4664 4603 2835 3804 3921 2840 5321 3797 5315 5790 5608 5718 5722 3778 4604 7 3613 7 4605 4389 4174 4604 3778 7 4389 2619 5213 4792 3613 4829 3691 4680 4823 7 4605 4604 4389 5213 806 2960 3619 880 4922 4257 4259 0 5006 1371 4959 1291 5252 878 5371 4158 5072 3871 1290 4690 4306 4217 2909 880 5252 5039 4606 4306 4923 4573 4890 3932 4821 2847 5505 4922 5039 2374 4606 2104 4607 3691 1874 5093 5504 626 3879 3780 5088 4541 4789 5114 5242 2603 3433 5087 4929 4887 4783 4889 2379 2546 4601 4292 4906 4611 2437 2379 4609 888 2380 3647 4610 2573 4531 4611 5215 3568 4122 1776 4997 1316 4273 4458 5190 1835 3819 1831 4610 2870 1019 3647 4610 2870 2573 2573 5215 4531 4610 4292 4906 4610 4611 3568 5215 3340 3569 2414 4612 973 4468 3568 4996 4458 3340 4611 4054 4122 3568 5216 4612 5145 5193 1012 4613 3137 2211 4054 4613 1672 4487 3395 4613 2211 3137 2409 4614 2264 3848 2264 4614 3671 3848 3543 4614 3671 3197 2409 4919 4614 4210 4615 2409 2268 4263 3270 5012 3980 3197 3980 4615 3621 4474 2268 4615 2405 2407 4614 4615 4263 2409 2146 5555 4617 4926 5012 3270 4459 3197 5144 5663 5136 5496 5486 3622 4632 5455 2394 4861 2146 4617 3427 5452 5035 2267 1760 4927 4099 4160 5372 5463 5233 4927 2011 4994 441 1100 4617 4926 3622 4861 3751 5724 5355 5536 1652 4818 2449 4230 3623 4618 3774 4284 5410 5657 4981 5395 5519 4661 1205 5273 5200 3774 4725 2679 4619 4658 3526 3862 1132 5147 4329 4078 4981 2392 4265 4287 2392 4981 4265 4619 26 4620 3746 4381 4932 3525 1305 4620 2661 4620 3746 26 4932 4620 1305 4381 4621 4462 3507 4488 4564 5085 4979 4262 5668 5787 5621 5603 2293 4622 2389 621 4711 5166 3072 4569 3698 5488 326 4566 3359 4622 2293 4277 4886 2600 4086 2159 3359 4622 2389 2293 2600 4886 4086 4622 5321 5663 5315 3197 4623 4206 3629 4594 3488 4625 4624 3677 5315 3797 4664 4603 4657 5005 4033 4910 3488 4961 3677 3486 4625 3631 3677 3632 4221 4964 625 4228 4221 4964 4228 3678 625 4961 3488 3486 4437 4626 3634 4435 1955 4722 4627 3756 4627 4052 2932 4083 2933 4627 4052 2932 4627 4722 1956 3756 1955 5186 4627 3988 3012 4627 4041 3988 3456 4935 3318 4630 3944 5211 4528 4830 4386 5375 3567 2360 2420 5204 2316 2250 4913 5123 4975 2250 5211 3664 5123 4830 4631 2866 3947 2863 3947 4631 2863 3450 4631 4822 2863 3450 4632 5339 4155 4153 896 4556 2644 4555 3622 5486 4632 4153 3640 4925 3622 4632 2395 4925 4632 926 5694 5441 4060 4539 4754 5533 5058 5441 3426 4633 1650 3806 3806 5195 4633 3574 2194 5340 5332 3149 326 4686 4028 2060 4635 4818 2173 2806 4634 5463 5339 4927 5339 4155 4160 5184 4927 5486 5339 5455 3866 5357 3363 31 5463 5328 4634 4993 3415 4685 3901 4635 3425 4837 4782 4637 3865 4659 4636 827 3245 4636 3867 1015 4520 5282 4659 5276 3245 4636 4255 3867 4659 3333 2769 2768 4520 5282 2775 4659 3518 4782 4460 3425 4255 4659 4636 4520 2635 4762 2886 2275 4835 3425 3229 4637 3229 4637 4460 4176 2354 4638 636 2572 5157 2773 4431 3337 636 4651 2354 4586 2444 4651 4432 4586 4639 4828 612 2422 2722 4639 3649 824 2192 4847 4640 1360 3393 4640 4144 3924 2830 4215 3916 4641 4901 4743 2815 5305 4597 4816 4640 3924 79 4816 3909 2457 4816 2192 2456 2458 3114 4640 4597 4847 3921 4814 4543 4603 1015 5056 4784 1005 4864 1348 2778 4786 1009 5054 3656 4642 4282 1670 4172 4643 4863 1009 3656 4642 1009 4863 3656 2067 1009 5054 826 4425 1344 4643 4218 1670 64 4643 4218 1344 1010 4643 4282 1828 72 4644 74 4542 4644 3381 72 3894 72 4644 3894 74 2239 4876 4553 4645 4072 5161 4646 3056 2757 5161 3022 3202 26 4381 24 5103 4646 4073 4553 3654 2970 5026 4477 3364 2366 4647 4354 1712 3654 5161 4646 4072 4072 4646 3059 3056 2757 4646 3760 3854 4477 5236 5026 5068 3741 4648 3527 3529 4648 916 4159 4119 3459 4931 4648 4159 2745 3147 4245 4649 2070 4649 3147 2745 4509 5378 4649 5098 3347 4649 4193 2070 2858 4649 2745 4509 4579 4650 972 4529 3379 2742 972 4650 3349 4650 2742 3379 4529 4650 972 4415 4650 4654 2742 972 4457 4650 2741 4415 3833 4650 4415 2741 4457 4650 3349 2741 3395 3961 4638 4651 636 4651 4638 2354 4651 4432 3337 3395 2354 4651 4638 3961 2444 4651 3961 4432 4651 5525 4586 3648 3511 4652 599 3336 599 866 10 4652 3696 599 10 4652 3336 4652 599 3696 4687 2968 866 1715 4687 5677 5561 10 4687 866 3248 2623 866 4687 3511 2968 4653 5326 4298 4764 4276 5203 4975 4721 3378 5401 3549 3193 4764 5000 4758 4653 5516 4357 3837 3552 3838 5000 3346 3830 4249 5089 4973 3840 4612 5050 973 4655 4650 4654 4415 4047 5050 5402 968 2706 5168 4655 4415 3549 4415 5168 3549 4047 4650 4654 972 4415 4532 4909 49 5051 4612 4655 4297 4157 5401 5558 5168 5321 973 4655 4297 4612 5743 1042 1853 1847 2679 4656 617 3665 3305 4657 4033 4568 4437 4657 3306 2820 4657 4131 1054 3306 5096 4403 4366 5042 4435 4657 4568 4437 3862 4658 4366 2392 5221 4359 4403 5027 5856 5940 2392 5931 5689 5888 5824 5826 5282 4753 827 4659 2769 4659 2768 827 3333 5282 2775 2768 3333 5282 2768 4659 2772 4659 2775 4255 4809 2568 2427 2354 4810 4742 2814 4434 4065 4812 2191 3308 4509 5500 5377 3674 3193 5911 614 2749 5160 5813 5352 5175 2327 4662 838 4661 3197 2267 5035 5682 4590 5130 5107 4661 2341 4661 2338 838 1205 4662 839 2891 2327 4661 838 2338 4571 4662 839 840 4473 4662 839 4571 4590 4662 839 4473 5509 4661 4571 4662 2891 4662 839 4590 5903 5943 5849 3112 2789 4663 4203 3887 5088 5405 5122 5381 3271 5172 2840 2957 5153 3889 3887 4797 5152 5534 1658 5471 5327 5473 5201 5111 4957 3269 4603 4664 4664 5113 4592 3797 3269 5309 4603 4664 3402 4665 3271 3110 4317 5093 4205 1699 4674 3402 3042 3110 4668 4951 3512 1287 2605 4848 4205 4667 2618 868 2372 4668 2619 4668 868 2618 1287 4668 2372 868 2145 4792 2147 2622 2631 4783 2779 4391 3244 4669 3455 4390 4186 4669 3241 3455 1031 5302 814 5301 4669 872 7 3241 3244 4669 2621 3455 4669 4980 3241 2621 3061 4671 3750 924 2446 5301 1031 2786 5230 5686 5685 5457 1042 5743 5627 5511 1035 4670 1354 1031 3429 4968 4672 3209 3431 4985 3682 4671 3061 4671 924 4333 3431 4671 3203 4333 4777 5253 4591 3363 5242 4968 4672 5094 4332 5015 3209 2876 3547 5145 4300 3550 4160 4968 3209 4672 3753 4672 3429 3856 3856 4672 3429 3532 3547 5145 3545 4300 4592 5505 5312 5113 4673 4915 2414 1327 4612 4916 1795 4157 4882 5348 5113 5244 1695 3736 907 4675 5404 5244 5007 5113 3733 5025 3736 901 5257 4937 902 5025 3529 4676 3527 4567 846 4676 4567 3527 3529 4676 3687 3527 4397 4677 2380 4074 4608 4074 2603 4677 4677 1699 2380 2603 2380 4677 2603 4074 2375 5354 3204 4074 4601 5093 2380 4677 3616 4677 4601 3958 2594 4678 1699 1687 2919 4678 1687 1699 1686 4678 1685 2605 2594 4678 2605 1699 4678 1687 1209 2919 2282 4678 4365 3262 2281 4678 4365 2282 3222 4936 2232 3562 4308 5574 2851 5275 4138 5871 3637 4234 4079 5347 4679 3183 4424 5092 1000 4679 3961 4679 3183 4079 3222 4936 4424 4679 2356 4679 3183 3961 4178 5021 3014 3692 4019 4737 3930 3288 5706 2548 5574 5275 2061 4046 4044 4871 2863 4831 2864 4822 3697 6 4388 4683 3901 5181 4685 2171 4899 2982 1925 1926 3234 4684 4190 3693 864 4684 4289 4898 3415 4685 4635 2305 2173 4685 2089 3453 3901 4685 3171 2171 4685 4635 2305 3453 3901 5181 4635 4685 4685 3415 3901 3171 5181 3933 4818 3578 3140 4686 4028 4566 1169 4686 3699 2060 4686 326 3698 3699 1645 4687 3700 2112 3142 4686 4028 3140 3168 4686 4566 1169 10 4687 3199 3696 1715 4687 3700 1644 2187 5677 5561 2112 2968 4687 3700 1715 4881 4688 605 3706 605 5248 5177 3030 3938 5248 4149 3123 5142 5641 5369 5520 4856 5177 605 4229 1290 4689 3235 1291 1291 5252 3235 878 1290 4689 1721 3235 5371 5039 880 5252 880 5371 1291 876 2909 4890 1111 4690 2672 4692 3711 3643 12 4691 14 3813 4690 1892 1111 1112 1111 4690 1112 2909 2486 4890 4306 4690 1112 4706 1894 4096 1112 4706 4690 1894 2486 4890 3094 1414 2631 4691 2142 12 2565 987 52 4694 3712 3705 2632 4693 3712 5249 4693 11 5037 5249 9 5247 3823 4694 4420 2565 3554 4694 2565 4420 3829 4694 52 987 3823 4694 52 4420 2724 4757 2723 3314 2566 4694 3752 987 3752 4757 4694 2724 4695 1842 4516 3891 1842 4695 71 3891 2379 4889 2380 4601 2637 1295 14 4697 4013 4698 3738 4213 1295 4697 1294 12 3704 4697 12 4181 4696 17 15 4699 4862 5636 3463 1504 5624 3516 2626 2776 3718 5542 1751 2127 5070 5481 5374 2652 5512 17 4209 5154 3724 4700 3726 1743 1743 5154 4209 17 5382 5762 5133 5660 17 4700 15 4699 3726 5154 4209 1743 17 5154 15 4700 2385 5512 4507 1299 3733 5025 4701 3736 3733 4703 3736 4701 5025 3736 5024 4675 1693 4703 4701 22 3736 4703 2650 22 907 4701 22 902 3733 4703 1693 1694 4044 4702 4302 3020 4702 1628 4036 3732 2098 5170 3180 3045 5170 1939 3180 3045 4136 5170 3020 4499 1628 4702 4496 3732 5170 4136 3173 3180 4302 4702 4235 3020 907 4703 3736 22 1693 4703 22 1694 4704 5259 5088 4189 2216 4790 67 1836 4727 3504 4533 3503 4789 3876 4076 4704 1322 2693 948 4728 3197 2267 615 5035 4705 3875 2654 4401 1313 4014 4372 3056 3056 2121 4014 2397 4401 5565 3875 21 1894 4690 3003 4706 2661 5565 5261 26 4217 4706 3003 4690 5727 4682 5912 5962 4707 2117 2670 3750 2661 5565 26 4705 30 3755 32 4708 5008 5546 5485 5451 4551 4712 1312 3764 2975 4708 3755 4406 4708 4712 30 4406 4648 4119 3744 4709 3527 4709 3744 4676 3529 4709 4648 3527 5855 5884 5592 5835 4194 5298 3934 4710 3989 5829 610 5724 5070 5166 3072 4711 4161 5070 2652 5022 5481 5530 5166 5265 5467 4582 625 5106 5166 5295 2652 4986 4714 1766 3750 4334 4712 4723 4708 30 4551 4712 2662 3498 4861 4712 2975 4406 2121 3056 5161 4152 847 3749 913 4714 913 4713 3749 847 2760 5016 2666 3354 4713 5016 3749 924 28 4713 3749 913 1766 4714 4707 913 3533 4714 3749 4334 3749 5016 4714 924 2664 4714 924 4713 3877 5298 5090 3934 5269 4715 2669 3061 5414 4062 3039 2214 3745 5484 4358 1756 4715 3203 3061 2340 2670 4715 4707 2669 2670 5260 4707 4715 4195 5090 3794 4716 4716 2949 3934 2554 2383 5380 4798 4946 4480 4717 4419 4583 2945 4717 2726 3642 5942 3794 1349 5918 4249 4717 4419 4480 3322 4717 4419 4249 4160 3683 3753 4718 925 5412 1308 922 4672 4718 925 3753 5241 5412 923 1308 4672 4718 3683 925 4718 922 3355 2663 923 5241 4407 926 5010 4325 4120 4177 4062 5186 4083 4720 4251 5203 4975 4276 5327 5478 4979 5085 4062 5414 4874 2214 2731 5801 5291 3464 3757 4720 4083 4053 5186 4627 4062 4083 4721 4975 4251 2739 4133 5203 4913 4251 1556 4722 3988 1955 4041 4722 4627 3012 4722 1955 1120 3756 1120 4722 3756 1956 2399 30 32 4723 4059 4722 1557 1950 1557 4722 1956 3012 1314 4723 30 2399 4724 2253 3765 3850 37 4724 943 3850 943 5003 4724 937 5003 4301 1316 4997 4724 2253 37 937 37 4724 937 943 3765 4724 3850 4301 4301 5003 3766 4724 5922 3242 5954 3230 4725 5397 4873 5272 3019 4726 4460 2888 5290 5761 5393 5698 2679 4873 3770 4725 3320 4873 4246 4725 2888 4726 2280 1699 1690 4726 1699 2280 2888 4782 4726 4460 2383 4726 1699 1690 2275 4726 2280 2888 2790 4798 4726 1699 4398 4726 3869 4460 4798 4726 2591 4045 2717 5123 2739 2718 5088 5122 3876 4727 3504 4727 3737 3503 2865 4729 2866 2543 952 4728 4374 947 953 4728 948 2693 3191 4728 2693 1778 947 4728 948 953 3939 4729 3782 4575 4729 4732 4511 4308 4575 4729 3947 2866 37 4730 1779 2258 1779 4730 4464 4143 4343 4878 4730 4410 4223 4731 3786 2422 3786 4731 3840 4249 4765 5392 4973 4731 4480 5089 4583 4908 4896 4938 3195 4510 1144 4883 4855 4451 4046 4897 4872 2061 3939 4732 4511 4175 3872 4784 1017 2208 4784 3872 1015 3865 3798 42 4411 4734 3273 85 3797 4735 2842 4735 3630 3797 4108 4735 3931 1869 2466 4735 3630 2842 5183 4736 2964 2844 4195 4736 3794 3791 2964 5538 4736 5183 4195 4736 4478 3794 3165 5611 3159 5344 4600 4737 3611 2851 4017 4737 4110 1637 5313 5594 4737 4110 5320 3943 5313 5300 2851 5110 4737 3611 817 4875 4739 3590 3112 5046 4738 4154 5047 5966 5045 5929 2714 4738 4154 3112 3816 5278 3818 4746 4674 3444 4339 3914 4743 5305 1049 2815 4386 5174 4719 4504 5658 5695 5639 5546 4173 5188 4148 5078 3159 5846 2061 5757 5345 5612 5489 1276 2822 4852 1360 2192 2822 4852 2458 4740 5830 610 5532 609 2455 4742 2821 3910 2451 4742 4156 4434 2833 4744 1363 2509 1862 5005 1863 4910 5005 5591 5305 4901 4744 2509 2300 1363 5402 5050 972 5238 2851 4745 3307 3617 3816 4747 2095 47 5278 47 3816 3818 3818 4746 4738 3816 4111 4746 2708 3816 3003 4841 3969 2016 3575 5823 4748 5766 3816 5278 4746 4747 47 5032 45 4840 5369 5712 5680 4512 4747 3816 2708 4746 2445 5899 2786 5894 970 4915 1328 1327 3385 4797 4748 3887 5892 5834 4797 5759 4413 5192 4750 3545 4237 5192 4413 3545 5151 5291 4767 54 4469 5135 4750 4297 3811 5528 3550 5135 4668 4951 4112 3512 4413 5279 4750 3814 2153 5441 4060 5319 5604 5327 5342 5478 5318 5628 5387 5473 4752 5387 5111 5318 2144 5067 3510 3695 4753 5282 827 4430 4636 5276 3865 4520 5056 1021 1015 1017 827 4753 3865 4659 3872 4880 4733 3865 4880 4733 3865 4753 1648 5059 2158 1027 5197 5541 5143 4145 2158 5975 4433 4877 5059 1033 1027 4197 982 4755 3827 4270 990 4983 1335 4976 3827 4756 4755 2222 55 4756 4269 2222 4983 4270 1335 4976 4756 55 990 983 990 4983 4756 983 3752 4757 2724 3829 4420 4694 52 4757 3314 4757 2199 4241 2199 4757 52 4241 4757 3314 3315 4420 3315 4757 52 2199 5000 3838 3346 4653 5124 5704 4248 4921 5632 5704 989 5583 2618 5478 599 5394 5426 5677 867 5561 3830 5000 3832 4760 3830 4758 4527 3838 5712 5680 3706 5675 4759 5720 5711 5537 4250 5325 4974 4758 3323 4760 3832 3553 4527 5124 2567 4921 4527 4760 4758 3830 3838 5000 3830 4758 54 5286 4446 5151 2314 4761 2421 4272 2314 4761 3836 2421 3869 4782 4726 4762 2888 4782 4762 2275 3869 4762 4726 3420 2635 4762 2275 2888 5522 4298 5284 5285 4828 5288 2422 3649 4250 4921 4527 4758 4764 5367 4828 4921 4298 4764 4758 4653 3840 5089 4973 4765 3840 4973 4731 4765 4505 5670 4630 5526 2705 4766 2747 4237 49 5523 5051 4299 2705 5192 2720 4766 5216 4139 4916 4157 2318 4766 2720 3466 5051 5523 4532 4299 5192 2705 2711 3546 2747 4766 3842 4237 5192 4237 3546 3545 4811 3002 4489 2526 54 5151 4446 4767 1378 5513 2421 4445 4267 4768 3345 3559 2744 4768 3559 3345 4421 5004 55 2567 4267 4768 55 3345 5549 5682 5452 2267 2744 5004 2745 2858 1661 5004 2567 3559 5004 4421 55 4768 3401 5218 4467 2750 4618 5464 4577 5200 3396 5663 5035 5515 4725 5397 2679 4873 4524 4770 2755 4290 2681 4770 2254 4290 4524 4770 3665 2755 3387 4770 3665 4524 5731 2412 5401 3193 2913 56 1816 4772 5637 957 4771 5559 4280 5358 5292 2099 3147 4772 3976 1816 5168 5558 833 5501 2751 4772 3976 3147 5397 3659 4577 3660 3374 5185 4989 5119 1821 4773 2762 1830 5324 5753 5353 5767 3973 5134 4774 4425 572 5080 788 4954 61 5294 2230 1001 4778 4824 3861 1007 3973 4774 1007 4425 2759 5807 5066 4775 2360 5363 3567 5134 3973 4824 1007 4774 5634 5807 5055 3360 2360 5363 4087 3567 5043 4776 3429 4409 2664 4776 2667 4333 4985 2664 4333 4776 2666 4776 2667 2664 2760 4985 4554 2664 4151 4777 4591 4924 4924 2673 4591 2290 4692 4777 3860 3363 4777 4552 4151 3860 4151 4777 3860 4591 2673 5116 4924 4777 2673 4924 4591 4777 3643 4777 3860 4692 4552 5116 3363 4777 3900 5116 4099 3363 5116 5357 3363 4803 2674 4803 3363 2599 4778 3362 1009 4492 2758 5316 2309 3567 4779 2767 1025 1836 5525 4191 4432 4586 4751 4779 4427 2777 4782 4849 4726 4762 4429 2439 2870 4781 4260 4781 2439 4429 2212 4781 827 1016 827 4781 2870 2439 1014 4781 4780 827 3518 4782 3425 2888 2888 4782 2275 4726 3869 4782 4460 4726 2275 4782 2280 4726 4782 2886 3425 2635 3119 5075 4501 2114 3204 4887 4677 4074 3872 4880 2208 4733 5076 4392 4887 4929 4392 5076 4461 4929 2208 5056 4784 1017 3872 4880 3865 4784 3865 4880 4753 64 5297 4784 1005 4880 2776 5495 807 5425 4218 5440 1010 64 870 5561 867 3248 3339 5557 3614 807 2625 4785 807 3661 4257 5039 4785 4393 4458 4786 2778 66 4402 3875 4787 4401 1348 4864 2778 2054 2054 5296 1348 4864 66 4786 68 4751 4787 4401 21 1303 66 4864 4786 1348 2656 4787 1303 3524 22 4787 4402 1689 22 4787 3524 4402 2367 4980 2614 2613 4788 863 865 869 869 4941 865 4788 4076 4943 4324 3421 70 2155 4192 4944 4528 5123 4576 2739 1025 1836 67 4790 1705 4943 4076 4196 5088 4704 4189 4533 3454 1849 1850 3453 2942 4790 67 2216 5727 4682 5845 5912 3018 1123 1967 3984 2853 4896 3195 2856 3307 5821 4895 2851 3937 4895 2101 3880 4895 2851 3937 2101 3157 5246 3828 4772 5834 5950 5899 5868 2960 5213 3619 4006 2618 4792 2619 4668 4792 868 3246 3882 3246 4792 4112 4668 7 4792 3882 868 5069 5725 5182 5707 4857 2147 2622 2190 2172 4794 3884 4793 2147 4857 4792 4112 2372 4792 2622 2618 2145 4792 4668 2147 1353 4962 1036 1029 1028 4793 3884 4222 2172 4794 4793 1029 4794 2172 3884 4321 4794 5837 73 4321 4321 4962 4222 4794 4794 2172 73 1029 73 4794 1029 1036 3884 4794 4321 4222 5837 2792 3808 4537 3251 4795 2155 4192 5059 5156 4796 4197 1033 5254 5059 2158 2155 4795 70 4192 4998 1837 1033 4197 70 5156 1023 4796 5059 3885 1033 4197 2573 5157 4638 2773 5499 5823 2172 4748 5995 6006 5994 5550 2841 5771 5733 3679 5301 5868 5302 814 4460 4798 4045 4726 4248 5234 4972 4809 5920 5851 5864 5900 5499 3887 4797 5153 4460 4798 4726 2790 4726 4798 2383 1699 2851 5381 5351 2332 4177 4904 4482 4325 4798 5920 1699 1684 5302 4670 1031 1354 5456 5916 5881 5301 2567 5500 3674 5377 4570 5545 5456 5524 5916 5977 5951 5950 4253 4800 3823 3898 5507 5530 5166 5408 3823 4800 4420 3898 1663 5392 5274 2422 4253 4800 4004 3823 3641 5108 4800 5073 4008 4950 4801 3509 4801 3336 599 4262 4927 5555 5233 5372 2781 4865 2442 69 5822 5887 5727 5845 4865 2055 2442 3794 2674 5116 3363 4803 4783 5423 2628 4391 3951 4803 3900 4552 4805 5303 5060 3281 5195 5944 2445 5694 3652 4846 4580 4064 3281 5923 4805 1847 4513 5227 1651 3299 3285 4805 1847 4513 5275 4732 4175 4806 3304 5744 4732 2547 2851 5275 2547 4732 4732 5086 4938 4806 5477 5721 5275 4175 5282 2775 2768 2848 2546 4836 4114 4807 2546 4836 4807 4601 4836 2546 4114 2379 4181 4807 2546 4114 4560 4836 2379 2380 3904 4808 4120 4325 4325 5141 4482 4946 4904 4325 4120 4808 2591 4946 4198 4798 4946 4177 4479 4482 4809 5355 5311 2354 822 4809 2354 2568 4809 5234 4972 821 2427 5355 4809 2354 4736 4478 5183 5538 4957 5508 630 631 3942 4809 4660 2427 5286 5513 2421 4446 4809 822 825 2568 328 4811 329 1509 4902 1144 4451 4497 3909 4812 79 3308 2820 4812 1053 2191 4065 4812 79 2191 3924 4812 79 3909 79 5588 5386 1047 4657 4812 4437 4435 1051 5308 4813 82 604 5196 82 817 5306 2825 2162 1061 5306 5307 4813 817 817 4813 82 1051 5306 2825 3919 2162 4989 5120 4281 3383 5100 3269 3921 4641 4814 5132 4543 5118 5118 5471 4475 4603 2761 5469 4548 3771 4632 5184 4155 5101 1284 4815 3923 4324 3047 4815 3 1284 2150 4815 3 3047 4816 4847 2822 2177 4596 4816 2457 4002 2458 4816 4002 2457 4144 4816 3909 3924 4597 4816 3924 4002 3635 4816 4596 3924 2177 4816 4002 2458 4816 4144 2456 4640 3635 4816 2457 4596 2456 4816 2458 2819 2192 4847 1360 2822 5084 5163 3418 3403 1070 4817 2840 3868 5339 5463 5184 4160 3578 2806 2449 4818 4818 4230 3933 4385 3933 5181 4818 4635 2173 4818 2449 2806 1850 4818 4230 2449 3933 4818 4385 4635 1850 4818 4385 4230 3930 4514 88 4819 2542 3930 88 4819 4019 4819 2103 3930 4019 4819 2542 2103 4819 2464 2843 4514 4819 1068 88 1071 4820 86 2298 2511 2298 4820 2511 2465 1369 5083 3444 4820 4820 3444 84 4240 84 4820 4240 86 5348 5733 5202 5613 722 5321 3078 726 3402 4882 3042 4561 3797 5505 4664 5113 2612 4831 2863 4822 3307 5821 2851 1637 2612 4822 2863 4196 2864 4822 3450 2863 2612 4831 4822 4681 2101 4895 2851 3307 4539 5944 2154 4536 4791 5596 4823 4895 2851 4895 3937 4823 4829 2851 1872 3937 3937 4895 3880 4823 4680 5214 5020 4607 5345 2061 4872 4897 1007 4987 4774 4824 3861 4824 1343 2433 5363 2758 4824 2434 3676 5208 4824 4846 4064 4884 4846 4580 1360 4847 4640 3114 2169 5208 1343 4884 804 4825 2850 1076 3390 4918 4826 4825 4614 4919 2264 3671 3286 4827 2803 2426 5082 5541 5143 5490 2803 4378 3942 4827 2427 2803 3942 4827 2426 4827 2803 2427 4581 4827 3942 4378 4581 5187 3942 4827 2567 5377 4828 4809 4639 4828 2422 3649 55 4828 3559 4042 4653 5713 4828 4042 2851 4829 1872 1079 4509 5377 4759 3559 4251 5123 2739 4975 4607 5081 4600 4829 2567 4921 4248 4828 4248 4828 2422 4809 567 5321 597 495 637 5683 4194 1650 2422 4921 4828 4248 3830 5367 3838 4527 4424 5092 1669 5053 5123 5211 4576 4469 5204 5123 4251 4975 3944 4830 4528 4279 5123 2718 2420 3664 2250 5123 2718 2420 2250 4913 1801 2717 2 4959 0 4444 2 4831 4681 0 2840 4561 3797 5007 3951 4833 4552 4585 4572 4832 2412 4068 2411 4832 2700 3978 4833 5116 2674 4803 3670 4832 4068 3051 4832 5048 3051 43 2978 4832 4020 3978 4832 961 2412 3978 2411 4832 2413 2700 2270 4832 3978 2094 4924 5116 2674 4585 5116 4585 4552 4833 4834 2283 2645 4559 5844 5543 5809 5800 3425 4837 4835 2886 3730 4956 2381 3500 5709 1298 5256 5014 2061 5955 2059 5861 4807 3958 4601 4836 3425 4835 2878 2886 1728 4835 2376 2377 4835 2377 4176 3517 2878 1729 3229 1726 2546 4836 4601 2379 3958 2380 4601 4836 4560 4836 2380 3958 2379 4836 4601 2380 2279 4837 4398 2378 4837 3425 4782 2886 4782 4837 2886 4762 4460 4837 4782 3869 1698 5299 618 4160 5299 2374 598 1646 5299 600 715 599 5397 5595 5351 1675 618 5299 704 619 2708 4840 2095 4747 3209 5299 619 2876 4366 5299 619 3972 5299 715 2784 714 5299 5595 601 600 2332 5595 5381 5351 2881 5736 600 5595 5299 618 4160 3209 47 4840 45 4747 2784 5299 714 2604 2619 5299 3778 2603 599 5425 5299 3696 5299 4402 2392 2603 5299 601 716 600 492 5299 598 1646 712 4954 713 4885 712 4839 2899 3066 647 5299 496 3711 5459 5020 4680 5214 2876 5299 619 2392 1691 4886 2600 2389 2016 4843 2019 4841 1104 4841 1107 2016 3003 4841 1102 3969 1895 4091 144 4844 738 5080 4842 2355 4843 2015 2012 2077 4842 602 2323 493 5080 758 759 760 4680 5081 4829 4823 594 4842 2355 739 4842 585 2355 761 587 4842 557 758 5080 763 760 762 616 4842 2323 746 4842 2355 739 738 5080 557 758 556 4954 5351 617 4204 4842 2355 595 594 745 4842 746 2323 719 4842 585 584 3066 4885 788 3473 2015 4843 1102 2077 4843 2077 2012 2013 4420 5311 3641 2422 4231 4845 4574 809 3567 5413 5134 5109 4603 5321 4623 5315 5312 5593 4592 5113 4816 4847 2192 2822 4512 5321 2457 4065 5097 5315 4664 4957 5227 5552 5458 811 5311 641 4469 2716 810 5311 812 4845 830 5311 4845 833 2420 5204 5123 4830 808 4845 4574 810 812 5315 810 813 5177 812 3938 4227 4313 5521 3541 3844 812 5311 1649 3578 3971 5311 809 3472 5234 5311 4809 2422 1370 5598 5314 2864 5134 5208 4774 2758 3879 625 626 4848 4848 2605 4205 1699 2605 4848 2273 3879 4205 5093 626 4848 1686 4848 2605 4667 3420 5210 4849 4726 3720 4849 16 2383 4849 5210 16 4726 4849 4726 2383 1690 4849 3720 2274 2383 4228 5209 839 3879 2422 4969 984 4850 2198 4850 2422 984 824 5149 2722 4639 824 4969 2722 4850 2959 4851 240 2946 3165 5846 3159 5757 2458 4852 2192 2456 5078 5727 5188 3707 4852 2458 4740 4593 2822 4852 4740 1360 4853 1566 4078 1132 5147 1143 4078 4853 3788 4854 2853 2860 2865 4896 4729 2860 4924 2662 4151 3920 1638 4854 3788 3304 3194 4896 2853 2856 3902 4896 2853 4854 4982 3719 1144 1564 4855 5079 3719 4982 3719 4982 1144 4855 2191 4856 2179 79 4512 4856 605 4065 2180 4856 4229 79 2191 4856 79 4065 3275 5466 4219 4143 4857 4792 4006 4599 4343 5466 5069 4858 5466 4498 3275 4858 5317 4792 4599 5213 5111 5201 4859 4330 4950 4008 4801 4859 3879 5504 803 2603 1504 326 3463 4862 5111 5394 2619 4979 3914 5202 3935 4339 5348 5703 5593 5113 3992 5525 4779 4191 5486 5232 4617 5455 4406 4861 3622 2975 4115 4862 1164 3463 2026 4862 4030 323 4862 3739 3463 4115 4862 323 2524 3369 3361 4863 2991 2759 3651 4863 2991 3361 4863 3361 4642 3656 2054 5296 2771 1348 2354 5491 636 5222 5707 5077 3539 5023 4385 2305 1849 3410 69 4865 71 4802 1055 4866 3912 3305 2055 5090 3794 4865 4795 4796 5059 70 3888 4865 4802 2781 4033 5005 4866 4910 3949 4868 4077 2872 5005 2031 1862 2821 2031 5005 1862 4866 2985 4867 4500 3740 4867 3181 2044 4034 3128 4867 2044 4034 3011 5255 133 4868 4868 4077 2875 1987 1092 4868 3011 133 3959 4868 3949 2872 1878 4868 133 1987 3956 4868 3011 1092 5255 2875 1988 4868 5014 5140 897 5256 1126 4869 402 1122 5008 4173 3796 4870 5188 4173 4148 4316 3914 4674 5244 4339 5545 6000 5977 5524 3159 5757 2061 5611 1276 4871 4044 4046 5273 4661 4590 5107 3313 5344 3006 4871 5846 3313 1276 5757 5999 6024 2061 6015 2061 5489 4897 5345 3006 5611 3165 5344 5490 5143 4918 5197 4897 4046 1276 4499 4246 4970 2682 4369 2214 4062 230 4874 3165 5344 4871 3006 4873 2679 3770 2238 5269 5356 29 5018 405 4874 230 4062 5019 4338 4062 4874 3757 5019 4338 4062 3590 4739 4476 4875 3589 4875 3799 3795 4875 817 3795 3590 4544 4875 4476 4739 4875 3589 3590 3795 4876 5472 34 3761 4876 3023 34 3025 2354 5491 5355 5223 5738 2158 4433 2798 4513 5227 5060 1651 5355 5491 3934 5223 6004 6012 5990 5983 3784 5169 5077 3190 4858 5654 4219 5466 4730 4878 4143 4305 4834 5882 4956 3730 2773 2778 4427 2777 3291 4963 4421 2567 996 4963 4421 4879 4964 4221 625 4961 4733 4880 4430 4753 1015 4880 3865 64 2435 5297 64 4880 2943 5297 3334 2208 4880 3872 2208 4784 1005 4880 4784 1015 2360 4880 3334 2435 1669 5092 4679 2570 4339 4821 3042 4882 4856 5177 4229 4512 5250 5497 5453 5091 4674 4339 3042 4882 644 1700 3338 5114 800 5114 798 1700 4561 4882 3042 4821 5312 4882 5113 4821 4883 5079 4451 4063 4043 4883 4497 4451 4884 3676 3861 4064 4883 1144 3719 4497 4883 4043 3719 4063 4883 5079 3719 4855 555 5080 763 760 3473 5080 713 4954 2237 5316 2169 2309 5109 2169 2309 2579 2434 5316 2758 5208 3434 5134 4425 4294 2169 5316 5208 4884 5767 5353 3073 5753 4954 5351 717 4885 4204 5080 717 4842 5080 3473 713 2901 4885 3066 712 3473 5459 5843 5602 2855 716 4954 717 4885 712 4954 4885 3473 496 5351 4885 4839 1691 4886 2159 2600 2600 4886 4622 2389 2388 4886 2389 3442 3442 4886 2389 4465 4341 4886 2159 4465 4891 5076 4481 4392 3204 4887 4783 4677 4608 4887 2374 4074 4392 4891 4501 4481 4891 5076 2374 4481 4074 5359 5075 2114 4677 4887 4783 4608 4677 5093 1699 2603 5242 3683 4160 3433 2379 4889 4609 2380 2380 4889 4609 1699 3734 5093 4317 1699 4677 5093 2603 4608 4923 3096 142 4573 2537 4923 1594 2813 2007 4923 3975 3096 4890 4097 2007 1891 2375 5373 5354 5038 4891 4501 4481 4016 4074 4887 2374 4891 3119 4891 1646 4501 4463 323 4105 4892 4892 4105 2051 4549 1155 4892 3010 2051 4105 4892 2051 3010 1155 4892 2051 4463 2827 4106 3922 4893 4893 2297 1364 1867 2300 4893 1867 2297 4693 3705 2632 4894 5249 4894 1720 3705 4680 5602 2855 5459 3108 4894 2632 3705 3108 4978 3200 2627 4894 5729 3200 5031 3587 5848 4438 5133 5086 4896 3902 4854 2866 4896 2865 3194 4896 2860 2853 4854 4897 1939 2058 4499 2059 4897 2058 4499 2369 4898 864 4289 4107 4899 2042 3161 4898 2134 2369 1636 2369 4898 1636 864 2880 4898 2134 2881 478 4899 479 4103 4899 479 4103 3161 4107 4899 479 2042 478 4899 4116 479 4899 4103 4502 4021 4127 4899 478 1164 2982 4899 3053 1926 3053 4899 4502 2979 1167 4899 4116 1925 1982 4900 2999 1277 2072 4900 1277 2999 1982 4900 3129 2999 1052 5005 2820 3306 3306 4901 4131 1057 4822 5006 3450 1371 1132 5147 4078 4853 1143 5349 3009 4902 5349 1143 2951 2504 4503 5349 5147 4067 3601 4902 2504 4451 2658 4903 2659 3460 4931 3459 4648 2658 5543 5337 3723 3725 5336 5684 5623 5335 4373 5898 2690 4547 4808 5304 4904 5141 5994 6021 5263 1753 4905 4790 2216 1836 3343 4905 3878 2216 4121 5173 4905 4779 3343 4905 4121 3878 5215 4906 4610 2870 4611 5215 4906 4610 4054 4906 4122 2870 5003 3850 4301 4997 1831 4906 2870 4610 2212 4906 4611 4054 4998 1027 3188 1837 4906 2437 2212 4611 1169 5488 5330 5332 5089 4717 4480 4583 5488 4028 2076 3052 5738 5982 5825 5975 3698 4907 1168 326 327 4907 1168 1166 5345 5612 1276 5611 2059 5489 2058 4897 3463 5488 326 5333 4583 5506 4584 4908 4908 5392 2422 4973 4973 2422 4480 4249 5089 5506 4583 4908 2247 966 49 4909 4494 4909 966 2247 2929 4909 49 4532 974 5279 4299 5051 4657 5005 3305 4033 4414 4909 4494 4486 4866 5005 1862 4910 2 5006 4831 0 5005 4657 3305 2820 3306 4910 4131 4901 1340 1817 994 4911 1338 4911 4355 4126 999 4911 994 1817 3145 4911 1817 1812 993 4911 994 999 5508 5693 5110 4953 4472 4912 4565 808 628 4912 629 808 810 4912 4574 808 828 5114 4565 4912 5487 629 630 5114 4913 1801 2717 2252 2717 5123 4975 2739 4975 4721 4251 4276 2991 5364 2759 4863 3360 4914 3170 3136 2414 4915 4468 973 1327 5145 3545 4673 1328 4915 4749 1327 4749 4915 1797 1327 1328 5238 4915 970 4468 5145 4915 4673 2414 4916 2248 1795 4050 4916 4157 2248 4139 4916 4157 4050 4468 4916 4673 2414 4535 5193 5145 4612 3782 5541 4145 4308 4917 804 3936 1076 2851 4917 3936 1075 5558 3549 4157 4655 5355 5491 5222 3934 3939 5477 4308 5275 4145 5314 1080 5197 3539 4919 3980 2323 2265 4919 3980 2408 2867 4919 2408 2924 4474 4919 4210 4614 3671 4919 2794 4614 3789 4933 1081 4920 2849 4920 4162 3198 2715 2079 3829 1811 4921 4527 4758 4764 3945 4920 3198 4162 4527 5367 4764 4921 4257 5039 3661 4785 4922 5539 4393 4018 2020 4923 1414 4890 4688 5712 4881 5177 5171 5504 2374 2603 1594 4923 3096 2538 2423 4921 5704 5582 3920 4924 4585 4151 4552 4924 4585 4777 4923 2007 1890 3096 4923 1890 2537 1594 142 4923 1414 2538 4923 4890 2539 2813 1765 4925 1307 1309 3640 4925 4632 2395 5826 5689 5718 5824 4099 5486 4927 4926 5330 5340 1168 3153 5400 5463 1698 4160 4617 4926 4861 2146 5068 5102 1712 3626 5555 3531 5372 3436 3153 5340 1168 3149 2599 5357 3363 2288 4632 5184 3858 4155 71 72 69 4928 74 4928 72 71 4928 72 3894 74 3086 4928 3089 1842 4929 5354 4887 4783 4598 5039 880 876 4891 5076 4392 4887 4405 5417 914 3529 4930 1758 2654 2659 919 5568 3686 5432 3529 5417 914 3459 2659 4931 1757 4903 2658 4931 4930 2659 4931 4903 4648 4119 1876 4933 1081 2608 5158 5375 4202 4504 4932 4381 3746 4620 3525 4932 4278 3210 4933 3593 2849 4162 5352 3636 5009 4202 4253 4934 3389 3174 4934 4253 3389 4304 1329 4934 1332 2868 3822 4934 4304 4253 4087 609 4168 4935 3567 5375 5363 4087 3318 4935 4471 4630 4003 4935 4630 2943 4939 5347 4178 3167 609 5700 5526 4471 3456 4935 4168 3318 3222 4936 4679 2232 3183 4936 4679 4424 5347 4936 3183 3167 2652 3072 904 5022 3563 5021 4936 4424 4511 5086 4938 4732 4939 3562 3439 3561 5021 3014 3692 3826 3439 5021 3561 4534 1717 4980 1718 4941 4940 4082 4557 3233 3233 5128 844 4940 3980 5338 5219 615 5337 5622 4508 5376 4980 1717 4186 4941 3241 4941 4186 873 3241 4980 4186 4941 4942 4199 854 1285 4199 4942 1708 1285 1286 4942 4190 864 4189 5191 4533 4164 4533 5381 3503 3447 5381 4164 4533 5191 4387 5191 4943 4164 1705 4943 4164 4387 2364 4943 4076 1705 1023 4944 70 4796 4998 1033 2788 3885 4195 5090 3877 4945 4281 5199 3536 4547 3877 5090 4716 3934 4177 4946 4325 4482 4195 5090 4945 3794 5335 5623 5380 5468 4182 4946 2383 4198 5587 5672 5360 5468 40 4947 3540 4214 3772 4947 4214 3540 2457 4948 2564 4322 5754 3228 5099 4949 5368 5504 5171 2603 5790 5608 5722 5736 3655 5099 4949 4462 5228 5517 5138 5503 2633 5067 3705 2144 5228 5689 5502 5517 3706 3030 2452 5248 3164 5727 3584 4682 1287 5057 2371 1289 4801 5085 4564 4262 5484 1755 1756 3745 3808 5837 4537 5775 4145 5143 4308 5541 5317 2190 2619 2553 4668 4951 1287 4112 1844 4962 1353 4952 1844 4962 1036 1353 4962 4321 4222 4952 1844 5225 1036 4952 1353 5225 1844 4952 5599 5767 4219 5697 4410 5725 2581 5182 5833 2695 3767 3196 3775 4953 2679 4288 2679 5110 4410 2332 5496 5666 5663 5239 739 5080 4842 738 572 5080 747 571 710 5080 555 713 5080 788 2901 790 5080 571 790 570 3473 5080 4954 788 4948 4955 2457 2564 716 4954 713 717 747 5080 4842 743 793 5080 569 2901 793 5080 570 569 4204 5080 747 4954 5080 572 788 571 812 5321 4955 2457 5550 5994 5940 6006 1297 5726 1742 4399 5132 4814 4543 4455 4641 5100 4456 4958 5315 4957 630 813 2340 5422 5356 2344 5110 3288 4737 3611 5315 4957 813 4623 3921 5100 4641 4958 5508 4957 5421 631 1373 4959 0 2468 2 5006 0 4959 5517 5718 5529 5661 3632 4961 4625 625 3677 4964 4961 3678 3476 4964 625 4961 4221 4964 3678 4961 3677 4961 4625 3678 4794 4793 1029 4962 4222 5837 4952 4321 2055 2845 2949 2189 1353 4962 1029 4793 4794 5837 4321 4962 3819 2778 4458 4427 4963 5004 2567 1661 2273 4964 625 2605 3476 4964 2605 625 4964 4228 3678 3879 3678 4964 3879 2605 2273 4964 3879 625 1305 5748 5410 4278 11 5342 1288 4009 5994 6021 1753 5957 3995 5346 1134 2956 3994 4966 2956 1134 232 4966 3452 1134 4966 3994 3996 1134 1199 5034 4239 4967 5035 614 2412 43 3719 4966 3063 4043 2219 4966 1963 2950 2659 5416 5264 914 2422 4969 2722 984 4672 5242 3683 4160 3354 5016 3754 4713 3228 5754 5099 5243 2827 5105 5095 1865 3209 5015 4968 2603 3429 5015 3209 4332 3686 5432 3451 3529 2422 4969 4850 2722 4590 5273 624 2891 4284 4991 4369 4618 4991 5631 4970 4369 4981 5657 2392 5395 4182 4971 2383 4479 4246 5272 4873 5074 2852 1069 2839 1871 4849 5769 2383 4971 4182 4971 4247 2383 1378 5513 4446 2421 5326 5393 5124 5284 2422 4973 4480 4908 1865 1064 1060 5475 4973 5474 5392 4765 4758 5124 4974 4921 5285 5761 5284 5656 5836 5553 5642 5408 5203 4975 2252 4913 4187 5290 4250 4974 5124 5393 5288 5284 2212 5830 1672 827 4251 5204 4913 4279 5204 4279 4628 4913 1810 4976 1335 3834 5123 4251 2739 4528 2252 5271 2739 5203 3664 5211 2739 4299 3778 5165 5754 5736 2717 4975 4913 2252 4913 5123 2250 5204 4576 5123 4469 2739 4270 4983 1335 4755 3327 4976 1335 4270 5048 963 961 3946 1810 4976 990 1335 5331 4257 5031 4393 3839 4976 3327 4270 5659 2113 3516 4977 4977 2629 3200 2627 1195 5420 4362 820 4259 5031 4364 4894 1629 5340 2194 1939 4978 3108 3200 4894 4894 5031 3200 4978 4364 5729 4894 5031 3831 5720 4267 3319 4564 5111 4859 4330 4859 5085 4801 4950 5085 5111 4564 4979 873 4980 3241 4941 3696 4979 4262 4564 11 5342 4009 5037 869 4980 2621 3241 3244 4980 4352 2621 5011 5418 1305 5027 4669 4980 2621 4186 873 4980 4941 869 1717 4980 2620 1718 1728 2638 4176 3517 2392 5146 2598 4287 4270 4983 4755 4756 3682 4985 847 4671 4269 4983 4756 990 2588 5650 2587 5049 2651 4986 3523 3072 3892 5066 3358 5054 3406 5048 2703 4984 2701 5366 3406 5292 2703 5049 3668 5048 4985 3431 3355 4523 3355 4985 847 3682 2760 4985 4523 4554 4986 621 2651 3523 2651 4986 3072 2652 5070 5481 5166 5265 3706 5680 3821 5675 5940 6020 5550 5931 4774 5363 5134 2758 1317 5199 3374 3779 1007 4987 4425 4774 4087 5134 2360 4425 3383 4989 3536 4281 5363 5830 4087 609 4246 4991 4369 4284 1051 5350 1868 5307 4425 5363 5134 4987 4873 5397 1675 5074 5363 5134 2758 3567 4246 5200 4284 4725 5593 3630 2842 2466 3315 3823 4242 5189 2319 4992 4581 3468 5184 5455 4634 5339 5253 5463 1760 1698 2022 4994 2897 2894 5328 5463 4522 4993 4522 5253 1760 3092 3376 4994 2022 4286 4994 2022 2897 4291 2897 4994 2011 2894 1795 5238 5050 970 646 5693 3659 2603 1776 4997 943 1316 4292 4996 1835 4611 5215 3819 2573 5190 4458 5190 3340 4996 4610 4996 4292 4611 4996 3568 4458 4611 3777 4997 3377 4301 4998 1837 2442 2781 3620 4999 969 3812 4764 5000 3838 4758 1890 5001 4097 2249 5001 3768 1892 4097 5001 1598 2007 1891 4237 5279 966 4413 4976 5580 990 4269 4414 5051 4416 5002 55 4768 3559 5004 4724 3766 937 5003 3850 5003 943 4997 2744 5004 4768 2745 1316 5003 937 3766 3850 5003 4724 943 4828 5004 2567 55 2858 5004 1661 3559 4828 5004 3559 2567 4963 5004 4421 2567 2745 5004 996 2858 996 5004 1661 2858 1862 5005 2821 1863 3845 5004 4768 4421 2815 5005 1863 2821 4131 5005 4910 3306 4657 5005 4910 4131 5005 4910 3306 4901 5005 5386 5305 1052 2814 5005 4743 2815 5005 4657 3306 4131 5006 2864 4822 3450 3402 5007 4561 2840 5727 4870 5078 5343 4882 5113 4561 5007 5779 5869 5804 5842 5174 5615 5375 4386 5788 5858 5756 5785 5493 5727 5708 5695 4088 5076 4481 2374 5778 5658 5695 5639 4484 5175 4483 5160 6038 6045 5341 6034 5175 4244 5148 5160 3416 5009 3636 4202 4325 5010 3904 4198 4198 1732 4177 5010 3983 5175 4484 3636 3983 5009 3636 3416 895 5010 1732 2382 34 5397 1675 3761 5027 5221 4327 5011 4333 5043 924 3061 4658 5221 2392 4619 4278 5027 1305 4403 4327 5027 4278 4359 2366 5398 8 4388 4467 5012 4616 4459 3270 5012 4616 3980 5136 4467 4459 5012 1117 5013 1958 4285 3723 897 3725 5014 1967 5013 2920 4285 3016 5013 4448 1970 1958 5013 1970 4285 5013 1967 2920 3034 3984 5013 1970 4448 3016 5013 4342 4448 5013 1117 1559 4342 1559 5013 1970 1958 4798 5851 5838 5765 5544 5844 5014 5797 3725 5544 844 5543 2603 5015 843 2598 3209 5015 2603 2876 3429 5015 4968 3209 4714 3750 924 5016 4334 5016 3750 4714 4713 5016 3754 3749 2667 5016 928 3754 2664 5016 924 2667 2760 5016 2664 2666 2357 5134 4294 4425 5413 5017 5134 5109 3434 5134 4294 5017 2360 5413 3330 4294 5508 5693 4953 5487 1132 4266 4338 5019 1980 5414 1132 5019 5269 5356 5018 2340 5269 4715 3061 2340 4053 5019 1980 4338 4874 5414 5019 4266 5019 3757 4053 4720 4062 5414 5019 4874 2855 3948 1372 5020 5819 3948 2839 2855 4680 5020 2855 4607 1874 5020 1372 4607 5715 5877 2412 5460 5450 5448 5231 5460 3561 5021 4939 3692 3439 5021 4936 4939 3563 5021 4424 3826 3167 5021 4936 3563 3561 5021 3692 4534 5021 3439 4424 4534 4424 5021 4534 3826 3072 3748 904 5022 4711 5022 3748 3072 3211 5022 904 3748 4161 5022 2652 3211 5325 5393 5284 5285 5707 4953 3539 4410 3064 5023 3432 3539 3784 5169 3190 4057 5162 3190 3987 5077 5654 4858 5069 5466 3521 5024 4383 900 4675 4383 906 5024 4937 5024 901 4383 2390 5024 3736 906 3521 5024 906 4383 5024 2390 3733 900 3733 5024 900 901 4937 4675 907 5025 902 5257 5025 4701 901 5257 5025 4937 3736 5025 907 4675 902 5025 907 4701 5026 5236 1712 5068 2368 5026 4477 2970 3626 5155 4477 5068 5788 5880 5810 3263 1712 5068 3626 5026 4477 5236 5068 5155 3472 5223 636 2354 4776 5043 2667 4333 5027 5657 5418 5042 5221 4658 2392 5096 5027 4327 4278 5011 3366 5472 2398 930 819 5420 820 822 5385 5420 5034 1659 5557 4393 4598 3661 4469 5558 641 5311 833 5558 5311 641 5982 5854 5890 5902 3200 5729 3614 5557 5901 5687 3943 5320 5331 5659 2113 5539 3200 5331 4977 4978 50 5032 48 47 5032 50 2093 1798 822 5420 1198 5034 822 5034 1198 4239 5034 1199 1660 4967 5420 822 1198 3471 1198 5420 1659 5034 1660 5384 5034 4967 615 5035 43 614 5420 822 3471 820 5136 3671 3197 4459 5240 4797 3385 3260 954 5044 1787 43 4300 5137 3545 3547 5663 5338 5144 5136 4572 5035 2412 43 3427 5452 2267 3542 0 5036 2 3923 4257 5039 4922 880 4196 5036 3421 3505 2612 5036 4681 4196 5085 5342 4950 5327 4009 5249 11 5037 5249 4693 11 2141 2779 5423 4391 2628 5046 5928 5930 5943 5354 4929 4887 5075 878 5424 5371 5252 4922 5039 4606 880 4501 5075 4074 4891 874 5359 3238 2114 3661 5039 2625 4785 1760 5357 4927 5372 4395 5040 4394 4150 2664 5043 4333 2667 3709 5734 5040 2112 4394 5040 3709 4150 2670 5260 2973 4707 5666 3541 2697 2406 6054 6058 6047 6057 5092 5610 4087 61 5666 2406 2697 5218 5634 5362 5584 1006 5430 1753 5263 1305 5418 5749 1305 5042 4312 5044 3396 2585 5044 3844 3396 4412 4312 5044 2585 43 79 2186 4512 4229 3427 5044 5035 4412 4138 5870 5806 1325 5877 4138 5871 3637 5479 5100 4456 2830 5045 1326 1789 1325 2700 5293 614 2412 5807 2231 5055 5066 5678 5460 5407 5047 736 5536 610 5531 5860 5778 5822 5727 3668 5049 3667 5048 963 5048 961 4280 4312 5437 43 5048 5048 3406 2701 4280 4312 5048 836 2587 3670 5048 43 3051 3406 5048 4984 4280 962 5049 3408 965 3667 5049 2587 5048 5049 2703 3668 2589 4655 5050 3549 4157 4654 5050 4415 4655 4579 5050 972 968 5050 4655 3549 4415 4529 5050 4415 972 5238 972 4654 5050 3844 5433 5403 1787 5051 5523 2739 4532 4416 5051 4532 4299 49 5523 4299 2739 5580 2734 5052 5287 4486 5051 4532 4416 4416 5279 5002 5051 4414 5051 4486 4416 5002 5279 966 5051 2567 5052 55 3839 5580 2734 3839 5052 55 5287 5052 4828 2732 5052 4828 3555 2733 5052 3839 2725 5092 3646 61 4425 5053 4424 1000 1823 2577 5092 1669 3646 61 5294 1003 5053 5093 5504 3879 4608 4424 5092 4679 1669 4425 5323 4988 2236 4679 5449 5396 5092 61 5092 4079 4087 2577 5092 3646 61 3646 5092 2569 2357 5066 4775 3656 2759 4775 5066 3656 5054 3892 5054 826 4642 4642 5066 3361 3651 3656 5066 2759 3361 826 5066 4425 5054 1009 5054 4642 826 2231 5439 5438 61 2235 5066 2231 3358 1006 5807 4775 5439 1008 5055 1011 2235 2578 5066 3358 3892 5066 1008 3361 3651 3360 5066 5055 3361 1008 5066 2578 3651 1015 5056 1017 4784 2207 5056 1017 1021 5057 3570 1287 2371 8 5057 1289 2371 1288 5057 1287 1289 4433 5223 4877 5058 5058 3806 4433 3574 2554 5491 4877 3934 5227 5896 2445 5766 5129 5738 4433 2798 5533 4060 5441 5319 5559 4137 5638 5732 2153 5441 2445 4060 5059 5254 4795 70 5059 2158 70 1648 3702 5061 4512 3581 5490 5197 4918 5314 4960 4201 2881 5974 5321 4420 2716 3823 5442 2556 73 2559 1847 5511 4513 5303 3901 5060 4805 4513 5061 3301 1046 1856 5194 2781 3888 4118 4232 5061 2557 79 3737 2126 2782 3257 3301 5061 3702 3405 4437 5063 3296 4435 5062 5444 3296 5305 5386 79 1049 5062 5063 5444 4437 3296 2820 5063 4437 4812 4437 5388 3306 1057 3919 5306 2162 4813 4812 4435 79 5063 3908 5350 2162 5307 4232 5063 3296 79 5062 5588 5386 79 5063 5305 5062 1052 5307 5308 4813 1051 5307 5308 5064 4813 1121 5065 1557 235 3919 5308 5064 2160 4813 5308 5306 82 1051 5445 5064 82 5768 5447 4369 5631 5065 1127 1559 1558 1117 5065 235 4449 1121 5065 1559 1557 2578 5066 3892 3651 4642 5066 5054 3361 826 5066 5054 2231 5066 2235 2231 5055 2577 5439 61 5066 5741 1001 2753 5635 2235 5066 3358 2578 1008 5066 5055 2578 4009 5247 5067 3705 3626 4477 5026 5068 4354 5236 1712 4647 4647 5155 3684 4201 3778 5165 2138 4488 5374 5070 4711 5265 4621 5503 5165 2138 5155 4354 5102 4201 5069 4143 4343 4878 4343 5069 4878 4410 4335 5139 5069 4517 5492 5664 5069 5527 4711 5022 3072 5070 5762 5904 5696 5133 4929 5087 4887 5076 5392 4908 2422 5073 5727 5343 5078 5493 5071 2457 4322 4948 5788 3926 4955 5658 4606 5076 2374 4608 4929 5072 4461 4391 5073 5506 3641 5108 4765 5392 4731 5289 2579 5413 3567 5109 5397 2679 5351 2332 5272 5655 5397 5074 4392 5359 5075 5038 3238 5354 4074 5075 4392 5075 4891 4887 3119 5075 2114 4074 5373 2375 874 5038 5038 5354 3238 5075 5373 4392 4391 4929 5347 5830 5396 610 2375 5354 2628 3204 4606 5087 3615 5076 4392 5076 4481 4461 4887 5087 4608 5076 4606 5087 5076 4608 4929 5087 5076 5072 3615 5076 2374 4606 4461 5076 5072 4929 4088 5087 5072 5076 616 5664 4305 3987 3539 5169 4057 5023 5507 5665 5530 5642 5077 5707 3539 5664 4142 5163 4252 3868 5079 4063 2503 4451 4354 5935 2366 5102 3999 5078 4870 4173 5641 5142 5369 3298 3165 5846 5757 3006 5407 5640 5619 5045 1461 5079 4063 2503 5546 5695 5188 5493 3063 5079 2956 1565 1137 5079 1565 2956 5079 3063 4063 3719 5079 4883 3719 4063 766 5080 763 2355 758 5080 556 760 4204 5080 4954 717 5080 761 759 4842 766 5080 762 763 557 5080 4842 717 713 5080 555 556 738 5080 2355 569 4607 5081 4829 4680 4600 2851 4829 5081 571 5080 743 570 743 5080 4842 740 2851 4823 4829 5081 5081 5596 5483 2851 2111 5574 4825 5082 4791 5596 4680 4823 5131 5143 4826 4918 3819 5215 3340 5190 4817 5084 2102 2840 5276 3865 4733 4753 5390 3444 4240 84 3418 5084 4344 2102 3100 5482 2843 3186 3444 5083 4339 3914 3444 5390 4240 5083 1369 5083 4339 3444 4344 5084 4017 2106 4817 5084 2840 3403 5482 3186 3418 3266 5886 5096 5795 2392 4262 5085 599 4801 4859 5327 4950 5201 4896 5086 4732 4854 3304 5086 4732 4806 1638 5086 3902 4854 5086 3304 4732 4854 4511 5086 4896 4938 4391 5087 1723 4783 5087 4088 5072 3871 4391 5087 5072 1723 4088 5087 3615 3871 1290 5087 5072 3871 4929 5087 5072 4391 3840 5089 2726 4717 4387 5088 3780 4943 5088 3780 4315 4208 4727 5405 3503 5381 5088 5191 4387 4208 5133 5479 4456 5390 5381 5405 3503 801 3416 1343 4483 1826 3876 5088 4704 4789 4164 5381 4533 3447 4315 5381 2543 801 4727 5381 3503 4533 4973 5089 4480 4908 5089 5506 4130 2726 5090 4716 3934 2554 5223 4877 3574 4433 5679 5379 1349 5476 5922 5953 3242 3419 4795 3885 4796 4944 2186 5091 3702 4512 5369 3581 5280 5091 5092 2230 1000 2232 5092 2570 3646 2569 4848 5093 626 3879 2380 5093 1699 4677 1699 5093 3879 2603 2380 5093 4889 1699 4968 5242 4672 4160 2614 5689 2367 5398 4546 5105 4595 4544 3915 5095 4106 2827 5105 5470 817 5121 5095 4893 2827 1865 4106 5105 3915 4595 4546 5121 4739 4440 4658 5096 4366 2392 1011 5651 5055 5634 912 5431 3528 2764 4981 5395 2392 5146 912 5649 3528 5431 619 5431 912 2764 5221 4619 4981 2392 5483 5842 5779 5804 5104 5505 3932 2847 4685 2806 2171 5181 4509 5378 3899 4193 3899 5500 4509 3674 5098 5815 3147 5720 4462 5228 5099 5138 2661 5103 3742 4620 4462 5138 4488 4621 5529 5736 2138 600 4949 5138 4462 5099 3921 5100 4958 4814 5674 5464 5447 5397 3771 5469 3852 2678 5762 5309 5514 5660 4550 5185 3849 4288 3724 3230 2128 4556 5100 5479 4456 5382 5400 4993 5184 5101 4155 5184 3858 4160 3640 5101 4632 3622 1712 5102 2366 3626 5102 5155 3626 5068 5073 5506 5108 5474 5229 3932 2847 5104 3932 5229 2847 1072 4590 5273 5107 624 5421 5104 2840 5262 5121 4546 4544 5105 4106 5105 5095 3915 4546 5121 4544 4739 4582 5467 5167 3677 5106 839 2347 3068 3631 5106 625 4582 5556 3068 839 5467 2347 5106 625 2345 5107 2341 624 3773 624 5130 4590 4473 5130 624 4590 5107 5866 3314 5862 5274 5392 5474 4908 5073 5740 3554 2724 5669 603 5321 604 3590 2747 4133 4628 3466 5439 5741 5635 61 3752 5669 2079 2724 5474 5506 5089 4908 2360 5413 3567 4386 831 5487 829 832 2163 5353 1781 5324 4846 5316 5134 4580 5034 635 3472 5420 828 5487 829 5114 4912 5508 810 4574 801 5508 630 5487 5104 5421 5315 5097 2190 5473 2619 2553 5420 2903 819 820 829 5508 832 5487 5703 5348 5593 5613 3879 5114 1700 840 5505 3797 2840 4561 2842 5771 2841 3797 5508 810 4574 4845 798 5114 3338 1700 4882 5113 5007 4674 4953 5508 831 2582 646 5114 645 3659 4953 5237 4995 831 829 5114 644 828 4552 5116 3900 3363 3444 5390 5083 3914 5472 3366 2398 5117 4570 5524 4670 4470 5117 4645 4073 4553 5514 5936 5152 5471 4543 5118 4603 4814 5120 4290 2755 2681 5673 4005 5471 2460 4958 5382 4456 5132 4288 2679 4550 5119 5118 5382 5322 5132 2752 5185 4288 3779 3375 5120 4290 4524 4543 5132 4475 5118 3375 5120 3383 4290 5120 2761 4989 4548 2755 5120 4550 4524 1349 5379 1026 5476 4440 5121 4739 2824 2319 3489 3147 1816 5122 5381 4727 5088 5211 3664 2739 5123 5122 5088 4789 4541 4727 5405 5122 3503 5123 2717 2250 2718 4279 5123 4528 4251 2727 5580 2222 2734 4758 5326 4921 4764 5632 2423 5579 989 5793 5578 5704 5582 5656 5713 5522 3662 4250 5124 4921 4974 3315 5125 3823 2199 5125 2719 4530 976 4530 5125 2202 3823 52 5281 2199 977 3315 5125 52 3823 976 5283 5281 5125 4530 5125 976 2202 5739 976 2862 1802 5630 976 5283 5281 5877 4320 4138 3637 844 5622 3723 5376 4679 5449 5092 2232 3549 5401 2412 3193 4138 5877 5806 5870 622 5128 1699 844 4508 5128 844 1699 5836 5128 2877 4082 621 5128 622 2877 4082 5128 4940 4491 621 5128 1699 622 3035 5129 2050 3809 4661 5509 2327 4662 5129 4433 3035 2798 3035 5129 2798 2050 4590 5130 4661 4473 2341 5130 2338 4661 4433 5716 5129 5540 4433 5825 5716 5798 4661 5509 2338 2327 4662 5509 1700 4571 5803 5541 5490 5598 4412 5515 5035 5452 5574 5803 4308 5541 4157 5135 4532 4297 4679 5610 4087 5092 4814 5382 5100 4958 5390 3587 84 4456 3242 5922 5954 5953 4469 5135 4297 4532 3811 5135 3550 4297 5017 5413 5134 4294 5518 6010 3458 2800 4774 4987 4425 5134 4414 5164 5135 4486 5365 5450 5231 5407 4416 5523 4750 4299 5077 5664 3539 3987 4486 5164 5135 4532 1829 5616 2762 1830 3547 5528 4139 4300 5585 5794 4710 5592 5718 5826 5722 5751 3868 5229 2840 1072 2581 5182 4517 4410 5324 5814 5023 5169 3200 5729 5557 5031 4521 2844 3253 5183 5891 4647 4201 4354 2756 5768 5399 2333 5836 5844 4491 5827 5140 5415 3067 897 5837 2556 3897 5225 4557 5820 5800 4328 4940 5809 4491 5128 3725 5544 5014 1298 3661 5710 4393 4785 4482 5360 5141 4904 4904 5141 4325 4808 5550 6007 5940 5480 4750 3545 3811 5361 5468 5684 5672 5360 4325 5141 4946 4808 5141 5468 5360 5335 5178 3397 3185 2852 5574 5803 5082 5706 3298 5142 3581 3405 5091 5280 3580 3301 4146 5706 3782 5477 4145 2851 4308 5143 5369 3298 3581 4512 3390 5143 2851 4145 5549 3541 4313 5521 5477 3939 3782 4146 5131 5143 5082 4826 4313 5521 4412 5452 5136 4769 4467 5144 5903 5943 3112 6008 4467 5219 5218 4616 4468 5145 4535 4915 2794 5663 2585 5239 3197 5338 3980 615 2750 5218 4467 4769 4615 5218 3621 4263 1327 5193 3545 5145 4612 5145 4468 4673 1327 5145 4673 4915 621 5752 5329 5603 4337 5147 4853 2951 1143 5147 2951 4853 4493 5349 3601 4902 5147 4337 1132 4329 4442 5350 3908 1868 4503 5147 4329 4067 2360 5375 3567 4087 3636 5375 4244 3567 2360 5375 4087 4935 4202 5375 3636 3567 2422 5149 4223 4639 2722 5149 4850 2422 4473 5212 839 4590 56 5513 5286 4446 5209 4228 839 5150 4473 5209 625 4571 5209 4473 625 5150 54 5286 2421 4446 5153 3889 4797 4799 3761 5674 5397 4048 2166 5673 4211 2460 5660 5118 5382 5322 5132 5152 4475 5118 5727 5609 5493 5708 4433 5854 5825 5798 5512 4507 17 2385 4354 5236 4647 5155 5844 5128 4508 1699 5102 5155 4201 4113 4354 5155 4647 4201 3626 5155 4113 4477 5497 4512 4881 5712 4998 1027 4197 5156 1023 5156 1027 4998 5059 5156 4197 1027 70 5156 4796 5059 4428 5157 3340 4264 3337 4638 3395 5157 2773 5157 4638 3337 4431 5157 3395 4487 5157 3569 3340 3819 3569 5157 2573 3819 5352 5409 5158 5009 5159 5698 5290 5393 5700 5799 5352 5148 4244 5175 3636 4484 5494 4630 3277 5409 4483 5813 5160 5175 5415 5844 5337 1699 5325 5393 5159 4974 3841 5516 4357 3837 5290 5516 3837 2731 4244 5352 5175 5148 2757 5161 3202 4646 5310 5654 5139 5069 1939 5170 3180 4124 4057 5324 5169 2352 5664 5162 3987 5077 2352 5353 5169 5162 4494 5528 4050 5137 4195 5538 4716 4478 3190 5169 5162 2352 5206 3494 4485 3710 3868 5206 3403 2977 3868 5206 2977 4562 5163 4142 4207 4562 1682 5528 4532 4050 5836 5166 3414 3523 4414 5164 4486 4494 4532 5528 4494 5164 4486 5164 4532 4494 5736 5529 5722 600 5164 4414 5135 5137 4621 5165 4488 2138 5503 5138 4621 5165 4986 5553 3523 5166 4621 5165 5138 4488 5138 5517 5165 5503 5138 5503 4621 5228 5404 5534 3797 5172 5553 4986 621 5329 5166 5836 3414 5408 3072 5166 3523 3414 3072 5166 4986 3523 3751 5724 5536 1672 2113 5331 4018 4978 5166 2652 3072 4986 4084 5167 3645 3677 5167 5467 625 5235 5467 625 3068 5106 3653 5167 4582 625 4654 5501 4655 5168 3549 5401 5321 2412 5075 4074 4887 5354 5126 5731 5401 5702 2309 5316 5109 3567 5324 5814 5753 5023 4392 5373 5075 4929 5169 5077 3190 5162 3190 5169 2352 4057 3539 5169 5023 5077 1628 5170 4702 4036 5170 4136 3020 4702 4136 5170 4499 3180 4499 5170 1939 4124 5170 2096 3045 2098 3020 5170 4702 4235 5250 5497 4881 5454 2619 5368 2603 3613 5372 5463 1760 4522 3544 5629 1680 1681 5680 4512 5641 5369 3696 5368 2603 2619 5471 5746 2460 5309 2840 5172 2323 2957 2941 5173 4779 4905 5244 5771 5498 5733 5172 5404 4665 3797 3271 5172 4665 2840 5525 3992 4518 4191 3992 5525 4518 5173 2941 5173 3250 4779 3878 5525 3250 5173 4121 5173 4779 3992 5174 5375 4504 4386 5700 5615 4471 4935 5158 5615 5174 5494 5615 5799 5526 5465 5813 5175 4483 5009 5158 5615 5409 5352 4471 5615 4630 4935 5263 6021 5430 1305 4244 5175 4484 5160 5175 3983 4483 5009 892 5176 4508 844 5647 2143 2136 844 1690 5176 1699 3954 3067 5644 4508 896 4508 5176 1699 844 4814 5382 5132 5322 5795 5886 5042 5096 3938 5248 3030 5177 1078 2852 88 5178 5594 2852 88 3113 5321 5680 812 5177 2184 5177 3938 3411 3595 5178 3943 3185 3930 5178 2542 88 2852 5594 88 5178 3595 5178 3185 1078 3930 5178 4737 2542 2976 5594 4017 88 1363 5179 3917 1362 1362 5179 3917 4456 5543 5809 5376 5337 3489 5812 3942 5764 3489 5815 5764 3942 5537 5500 4509 5180 4798 5838 5745 5765 2383 5851 5765 5789 4818 5181 3578 2806 3901 5181 2171 3578 5182 4517 5069 5139 2581 5725 5707 4953 4410 5182 4517 5069 5069 5725 4410 5182 4956 5882 5755 3730 4478 5183 2949 3253 2157 5183 4521 2964 3252 5183 3934 2964 2189 5183 3253 2949 2949 5538 3934 5183 5184 5463 4993 5400 3858 5400 5184 5101 5339 4927 4160 3433 5372 5463 4522 5233 4160 5339 3433 4238 3153 5340 3149 5332 5463 4634 5339 5184 3149 5340 1168 2072 4155 5339 4160 4238 2072 1938 1939 5340 4155 5339 5101 5184 3374 5185 5119 2752 5185 2752 4288 5119 1955 5186 3988 4052 4053 5186 4720 4052 5199 3849 4288 4547 3849 5199 4288 5185 3849 5199 4281 4547 4083 5186 4052 4720 5186 4041 3988 1129 3988 5186 1129 4052 4053 5268 1129 2935 3831 4992 3991 5187 3039 5414 2214 2940 4041 5414 3039 5268 4720 5414 4053 5019 5187 4581 3942 3831 3942 5187 2427 4827 5187 2223 1814 1813 4530 5189 2202 4167 5090 3934 5942 5222 5695 5406 604 5639 2716 5189 3823 4253 2716 5189 4242 3823 3389 5189 4304 4253 3389 5189 4167 4304 2573 5215 4610 2870 5215 2573 4531 5190 3550 5216 4297 4157 4673 5216 4612 5145 3819 5215 2573 3569 1835 5190 4996 4531 5381 3447 4164 601 5381 4164 4208 3304 3780 5259 4789 3215 4164 5381 601 3304 5088 5381 4533 5191 2603 5381 2329 3503 4750 5192 3811 3545 2428 3826 1822 3692 2711 5192 3545 2712 3546 5192 3545 2711 5192 4750 4237 4413 5123 5523 4469 2739 4916 5216 4157 4612 3547 5216 4139 5145 4915 5193 5145 4535 3811 5216 5193 4297 5193 1327 3545 1799 4495 5195 5194 5058 5944 5195 5691 5694 2050 5716 5540 5129 5692 1276 1939 5489 5694 5441 4539 2445 5102 5946 5935 600 5441 5694 4060 5533 4633 2445 3574 5195 5533 4495 5195 5194 5640 5991 5763 5045 3806 5195 3574 5058 5700 609 5526 5799 4118 5691 5194 5533 3590 4165 82 5196 3795 5196 4165 3590 82 5306 4813 817 5196 5308 4165 82 5196 4165 2825 3795 3919 5308 4813 5064 5490 5803 5598 3279 5197 4918 3390 5143 813 5321 812 5315 5491 4877 3934 3574 1370 5314 1080 2864 4918 5197 3390 1080 3252 5298 4194 2964 3794 5198 4195 3791 3791 5198 3877 2964 5198 3794 4195 4945 4195 5198 3877 3791 3774 5200 4577 2679 5272 5200 4246 4725 3485 5199 1317 2688 3374 5199 5185 3779 4373 5199 2688 3536 4281 5199 4989 3536 3774 5200 4618 4577 4284 5200 4618 3774 5484 1755 2973 2117 4859 4950 4330 5201 4079 5396 4679 5347 5005 5388 3306 1052 4330 5318 5111 5201 5327 5111 5085 4979 5327 4859 4950 5085 2842 5733 5703 4108 2420 5204 2250 5123 49 5271 2929 4532 4721 5271 4532 1682 4048 5397 3761 3893 4975 5271 4721 5203 4251 5203 4913 4975 5123 5204 4279 4830 5204 2420 2316 4830 4628 5204 2316 4830 5123 5204 4251 4279 1646 5205 3703 4397 2380 5205 4397 3703 3714 5205 2118 4397 4114 5205 4336 3122 4560 5205 2380 3207 3122 5205 4336 3231 4114 5205 3122 3958 4207 5163 4562 5206 5300 2292 3397 2839 6009 5300 2839 2292 3868 5206 4562 5163 4485 5206 3403 5163 3494 5206 4207 3710 5207 834 2679 4283 2679 5207 4216 4656 2238 5207 4216 2679 3861 5208 1343 4824 2758 4824 2434 5208 4774 5208 4824 2758 1343 5208 2434 4824 4824 5316 4774 4846 4824 5316 4846 5208 3861 5208 4884 1343 2237 5316 2309 2434 625 3879 4571 5209 5210 3420 4849 2922 4228 5209 625 5150 839 5209 4571 3879 5211 3944 4528 4576 5427 3869 4726 5210 4849 5210 2922 16 2378 5427 4398 2279 3420 5210 884 2922 5123 5523 5211 4469 16 5427 884 889 884 5427 2378 2279 3519 5625 3954 1684 4416 5523 4299 4532 5523 4416 4750 5135 4473 5212 5150 839 3632 5212 839 5150 2891 5212 625 4590 2891 5212 2345 625 5820 5014 5709 5256 3513 5213 2960 7 4605 5213 4604 806 7 5213 3613 4604 3882 5213 2960 4006 4600 5081 4607 5214 4680 5214 4607 5081 3185 5245 3943 3595 5245 5730 3595 2292 5459 2855 4680 5020 3819 5215 3569 3340 4122 5215 3569 2870 2573 5215 2870 3569 3340 5215 4996 5190 4157 4297 4612 5216 5215 4611 3568 4996 4531 5215 4996 4610 4297 5193 4612 5216 3568 5215 3569 4122 3811 5216 4297 3550 1192 5217 633 4466 3689 5217 4466 633 5217 497 4466 4629 1192 5217 4466 4629 4303 5217 628 497 4565 5217 4466 3689 4412 5521 5515 5452 1324 5218 1786 4411 3848 5218 3401 2750 5521 5682 5452 5549 1324 5218 4411 2405 5496 5662 5218 5144 5486 5339 4153 4238 5515 5666 3844 3396 5571 2663 5412 4718 5338 3197 3980 5012 5219 5663 5338 5144 5338 4616 3980 5219 3773 5273 624 5107 4577 5397 3660 2679 4246 5272 4970 4991 4981 5657 5221 2392 4359 5221 4327 5027 5221 4403 5042 5027 4403 5221 4658 4619 4359 5221 4619 4327 5942 4945 3794 5918 2554 5222 3934 5090 4586 5222 636 1026 3574 5491 4877 5223 4586 5355 2354 5222 4385 2305 3453 1849 5920 5954 5922 5953 5552 2445 5223 5355 2446 5226 2445 5224 5223 5551 2445 5224 1649 5227 3578 2185 3385 5227 2556 2801 1034 5224 1035 2446 4651 5355 2354 4586 5226 3385 4225 4275 5918 5835 1349 5885 5551 5223 2445 5058 5533 5194 4118 4495 5766 2556 3575 5776 2801 5227 2556 3575 2556 5766 3575 5227 5355 5552 5227 5311 4513 5227 3299 5060 4293 5227 3578 3299 5060 5227 3299 3578 809 5311 812 811 5888 5974 3684 5784 5262 2840 2977 5229 2614 5689 5228 2367 5504 4608 2374 2603 5922 2128 3724 3230 5228 4462 3655 3506 4462 5228 3655 5099 3932 5229 1072 2840 4562 5229 2977 3868 3572 5719 4225 5230 5770 5866 5818 5740 5240 3889 3572 5230 4799 5759 5686 4797 5165 3778 5754 4949 2412 5293 614 3193 4047 5401 3549 3378 5705 1349 5817 71 5872 5772 5828 5723 5232 5463 5233 4634 4927 5555 5372 4926 5184 5455 5339 5101 5184 5455 5101 4634 5311 640 833 641 4634 5455 5101 3622 5232 5463 4634 4927 3531 5555 5372 5233 4634 5233 5232 4617 5372 3436 1762 1763 3962 5555 3530 2394 5328 4522 3531 3371 5234 5311 821 4809 641 5311 5234 3641 625 5235 3645 5167 3677 5467 5167 5235 4477 5236 5155 2134 5058 5694 5195 2445 5236 4647 5155 3684 5155 5236 3684 2134 3364 5236 1712 5026 5236 4354 1712 5068 645 5237 5114 831 4288 5237 4995 2679 3463 5488 3052 326 645 5237 3659 5114 5693 2679 4953 5237 4915 5238 973 970 1795 5238 973 5050 5239 3671 3197 5136 2585 5663 3396 5239 2794 5663 5239 3197 5549 3542 2267 5452 5267 926 3683 5241 926 5267 3683 4160 5015 5242 4968 2603 4160 5242 3433 2603 5114 5242 843 2603 5015 5242 843 4968 5243 3228 3778 2545 2545 5383 3778 5243 4110 5594 4737 4017 5502 5754 5608 5243 5608 5790 5714 5688 5246 3157 3552 4763 5293 5460 5231 2412 5923 5060 3281 4805 3185 5245 3397 3943 3844 4147 1787 2697 5687 3943 5300 5245 2428 3826 2754 2066 2154 5971 2445 5961 4320 5877 4138 5870 3552 5246 3976 3828 11 5249 2141 9 5247 5067 3705 3695 5248 3938 4149 5177 5248 4688 4149 3706 3123 5248 2452 3030 2454 5248 2188 2452 5248 3706 605 4688 4314 5248 2817 4149 2141 5249 1720 9 4894 5249 4693 3705 5247 5249 4009 5037 5280 3301 3581 3405 2186 5250 5091 4881 3301 5280 3579 3405 3580 5280 5250 3579 3235 5252 881 878 2855 5910 5819 5843 12 5251 14 4860 5504 5171 4922 5370 881 5547 5424 5252 5039 5371 880 876 3363 5253 1760 1698 4777 5253 4692 4591 31 5253 1760 3363 133 5255 131 4868 5059 5254 70 2158 133 5255 1408 131 131 5564 5255 1408 3057 5255 3060 1408 1988 5255 131 1990 1988 5255 4868 131 5412 5241 923 5267 4834 5882 4328 5820 896 5625 5428 5560 5801 3552 2731 5291 3750 2669 3061 5258 4943 4324 4189 5259 3750 5411 928 5258 924 5411 5258 5043 3215 5259 4789 2364 5088 5259 4943 5191 5259 4076 4704 4789 4189 5259 5088 5191 4704 5259 4189 4324 2364 5259 4789 4076 925 5412 4718 5241 26 5103 24 5261 5263 5566 5266 5430 4852 6050 4740 6046 5041 5430 5260 5263 5260 2973 4707 5041 5565 2661 3742 4705 23 5565 24 21 3742 5261 5103 2661 5315 5421 2840 5110 5104 5421 2840 5315 5262 2840 5229 5104 5421 631 5104 5262 2973 5270 5263 5260 4404 3451 911 5264 5041 5263 5260 2973 5430 5263 29 5266 5263 5430 29 1753 5653 1697 5550 4332 2973 5270 5260 2670 911 5416 5264 2654 2659 5264 2654 4930 5070 5374 4711 4161 5412 4718 5241 5267 66 5296 4864 1348 5070 5265 5166 4711 6025 5897 5921 5850 2494 2782 1284 1706 924 5411 2667 5016 3683 5267 4718 4160 4718 5412 922 2663 5268 4041 2935 3039 3046 5268 2935 1980 3203 5269 5018 2340 5268 3039 2935 2938 2935 5268 2938 1980 5268 4062 5186 4041 4720 5268 5186 4053 4053 5268 2935 3046 1129 5268 5186 4041 2670 4715 5269 5270 4494 5271 1682 4532 5269 5018 4715 3203 5266 5270 5269 4715 29 5270 5269 5266 2680 5674 34 945 4975 5271 2739 4721 5398 2614 2620 2613 2739 5271 4532 4721 4975 5271 5203 2739 49 5271 4532 2739 5574 5541 4308 5143 5813 5409 4169 5465 5272 4246 4873 4725 3659 5693 5397 2603 5940 5841 5839 5906 5623 5780 5684 5601 5200 5397 4725 5272 4048 5397 3893 2580 5397 5200 4725 2679 2267 5682 5452 5035 5397 4873 5272 5074 2724 5770 5740 3314 5276 2775 3993 4520 5289 5392 4731 5274 4420 5274 3314 1663 2548 5744 2547 5275 2548 5706 5574 2111 4753 5282 5276 4659 4733 5276 4753 4430 5278 47 3818 4154 3865 5276 4659 4753 4636 5276 4659 3865 5276 2209 2360 4430 2360 5276 2848 3993 4154 5435 5278 47 5046 5446 4154 5045 5049 5437 2587 5048 3818 5278 4154 4746 5435 47 45 5278 4154 5575 5278 5435 5045 5435 1326 1325 5279 4299 4416 4750 3579 5142 3405 5280 5279 5002 4413 4750 4237 5279 4413 3814 4416 5279 4750 5002 5280 5091 3580 5250 2439 5282 4430 827 3581 5369 5280 5142 3580 5280 3579 3301 977 5630 5281 5577 52 5281 977 979 5283 976 2719 5125 5630 976 5281 5577 976 5630 2862 5577 4520 5282 5276 2775 4753 5282 4430 5276 2439 5282 827 2768 3333 5282 4659 2775 52 5283 2203 2565 3823 5125 52 5283 2565 3823 52 5283 2203 5283 3823 2565 5281 5739 979 5283 5326 5393 4974 5124 5579 5793 5656 3380 5124 5326 5284 5288 5393 5325 5159 5285 4979 2619 599 5394 4758 5326 4764 4298 5326 4974 4758 5124 4187 5290 4974 5159 5698 1336 5583 5632 5578 5704 2423 5632 985 5579 989 1336 4298 5713 5284 4653 54 5286 5151 2421 5286 4272 2421 4761 4446 5286 56 5151 2734 5580 2222 5287 2732 5287 4828 5052 4268 5287 2222 4828 4042 5287 55 4828 4268 5287 2734 2222 4042 5580 2222 55 5052 5580 5287 55 5159 5801 5290 5698 5704 5290 4248 5583 3649 5713 5582 3662 5288 4764 4828 4921 4828 5288 4921 2422 3380 5582 2722 5578 4921 5326 5288 4764 5475 817 5105 5470 2715 5876 2738 4130 2567 5290 4248 5124 2567 5290 5124 3841 2679 37 2755 4056 5409 4630 3277 5670 5805 5876 2079 5866 4765 5474 5289 4130 5515 5682 5663 5035 3466 4133 3166 1331 5392 5876 5474 5073 5704 5632 989 2423 4187 5290 5159 3841 5736 5165 5529 2138 5583 5801 2731 3464 5292 5618 1793 5366 2314 5291 54 3464 2314 5291 3464 4272 2701 5366 5358 3104 3837 5291 2731 3552 5358 3406 2701 3104 4074 5359 3238 5075 2696 5292 4771 2697 5047 5870 5045 5678 1000 5294 5092 5053 1001 2230 1000 5294 61 5294 5092 2230 1823 5294 1003 1000 1823 5294 5053 1003 2652 5374 3718 5295 4226 5724 5355 3989 5481 5668 5621 5603 5947 5984 5972 5983 5374 5569 5481 5265 1348 2440 68 5296 2771 5296 2440 1348 66 5296 68 4864 3334 5297 4880 2208 2208 5440 2207 5297 4784 5297 5056 2208 2435 5297 3334 64 2208 5440 5056 2207 2207 5297 64 2208 2435 5297 4880 3334 3335 5440 1021 1010 4311 5440 3335 64 5794 5585 4710 5690 5855 5794 4710 5811 4194 5298 4710 2964 3659 5693 5114 5237 5298 3877 2964 3934 2964 5298 4710 5198 2380 5299 1699 3703 620 2604 1699 5299 5299 1699 4402 2603 627 5299 1699 2604 1699 5299 4402 22 3703 5299 1699 627 4402 5299 620 22 3972 5299 620 4402 2374 5425 5299 598 2619 5299 2603 3696 1031 5301 814 2786 5301 2446 4670 4470 73 5923 5303 3281 4670 5524 5301 4470 3250 5525 4779 5173 3458 6010 1354 2800 1042 5511 5442 1651 5303 4805 4513 1847 5388 5444 5063 5305 5442 73 1029 1037 2385 5512 1299 17 4808 5304 5141 4946 5782 5864 5859 5851 4674 1367 4339 3444 5045 5991 4154 5046 2591 5380 5304 4946 3587 5390 5133 4456 1057 5591 5388 4901 82 5306 817 5196 1061 5306 2825 817 3590 5306 2825 5196 4165 5306 5196 2825 4441 5307 4813 2162 5306 5307 1061 4813 3915 5307 2162 1061 3263 5308 4165 2160 1868 5307 3908 1051 5307 5308 1051 5064 5308 3919 4813 5306 3263 5308 82 4165 5306 5308 5196 82 5306 5308 3919 4165 5383 5754 3778 5243 4664 4603 2460 5309 5626 5717 4439 4438 5517 5754 5529 5608 4475 5471 1658 4603 2461 5746 3273 2460 5322 5471 4603 5309 5322 5471 5118 4603 5746 4439 1864 2461 5529 5722 5718 5608 5746 5848 2828 5696 5664 5492 5069 4410 3811 5528 5135 5361 5707 5527 5069 5664 3575 5896 5226 5766 4580 5316 5134 5109 29 5356 27 5018 5468 5684 5360 5335 5552 5227 5226 2445 5321 5401 833 5315 3971 5311 4845 809 3797 5321 4603 5315 641 5311 3898 2716 5311 640 819 4845 4194 5683 5355 1650 5311 3938 812 1649 1371 5598 3450 1370 1370 5314 4918 1080 5131 5490 5143 4918 813 5508 630 5315 5321 4603 4623 3629 833 5321 5315 5311 5321 3197 615 5035 830 5315 5311 833 5311 5321 5177 3938 4469 5321 5311 2716 5321 5035 614 2412 5321 1682 613 495 4845 5315 5311 830 5315 812 810 5311 631 5508 3611 5421 4623 5315 4955 813 5321 5663 3197 5035 5104 5315 2840 5097 3295 5321 605 606 812 5321 5311 5315 3759 5321 642 495 4469 5321 2716 4157 4919 5321 2323 5315 4065 5321 604 605 5321 3549 614 613 642 5321 4242 495 4752 5387 4965 5111 5313 5320 4110 4737 5780 5851 5765 5782 1840 5319 2791 1034 3176 1041 1043 1357 5556 5467 3677 5235 2153 5319 4060 1840 3943 5687 5300 5320 4895 5842 2851 5821 5313 5320 5300 4110 5293 5870 2412 2700 5081 5596 2851 4823 4206 5321 3590 4955 5321 1663 2716 4242 722 5321 2323 3078 3549 5558 4157 5321 605 5321 726 606 724 5321 2323 725 567 5683 495 612 744 5321 613 597 4721 5321 3759 1682 5321 3030 3938 3295 567 5321 3078 597 596 5321 778 2323 5321 4721 4157 1682 725 5321 726 605 2557 5321 4512 812 5683 5311 5060 3578 596 5321 597 778 5177 5321 605 3030 3590 5321 604 3926 5321 2716 4721 3759 2716 5321 4242 642 4603 5322 5309 3269 5746 2828 2461 3273 4814 5479 5322 3269 4814 5382 4958 5132 1697 5653 5550 5633 3440 5613 5202 4108 61 5449 5092 5323 2672 5397 2603 3893 5613 2167 2842 4108 5347 4679 4936 2232 5347 3183 3989 3167 5610 5092 5449 5323 5324 5023 4057 5169 5324 3064 3432 2163 4384 1692 1747 1302 4057 5324 2352 2163 4187 5325 5159 4974 5201 5342 5327 4950 5326 4758 4921 5124 5284 5326 5325 4298 4758 5326 4298 5325 4921 5326 5124 5288 6051 3313 1276 6039 5326 5393 5325 4974 4859 5327 5201 5111 5697 5767 4219 5527 5478 5327 4979 5394 2618 5604 5478 5473 2618 5473 2619 2622 3092 5328 2286 4522 5233 5463 5328 4634 1760 5328 2286 3371 3523 5553 621 1699 2947 5330 1629 2195 4986 5553 621 3523 5595 600 5299 5736 2870 5830 1672 2212 5334 3169 4024 2086 1168 5330 1166 4907 5332 5488 3698 4566 2086 5334 2195 5330 3153 5330 1166 1168 3200 5331 4978 5031 5331 4259 4018 4978 3426 5798 3806 5540 1644 5561 1645 2552 1629 5332 5330 2194 4907 5332 1168 5330 1629 5340 5332 2194 1168 5340 3698 1938 4686 5332 3698 4566 2947 5332 2194 5330 5330 5340 3153 5332 5340 2194 2072 3149 2947 5332 3149 2194 4115 5636 5333 3463 326 5636 5333 1510 4127 1164 5606 5607 5333 5636 1164 5606 2076 5488 4024 4566 3612 5693 801 2851 2075 5607 5334 5333 5334 5488 2075 5333 5489 1276 1939 4897 2075 5488 4024 2076 5334 1166 3153 5330 2195 5334 3153 5330 4024 5607 3169 5334 2075 5607 5333 4115 2383 5765 5623 5601 4482 5380 5141 5335 4482 5336 5335 4971 4479 5380 4946 4482 5898 3196 3767 3776 5381 2851 3304 4208 5862 5073 4420 5818 5469 2761 4989 3374 4557 5800 4940 844 4508 5415 5337 1699 4508 5844 5337 5809 5045 5806 5678 5870 5377 2567 4828 3559 5544 5797 5014 5709 4616 5338 4467 5219 3197 5338 5136 5012 2615 4647 2366 1712 5663 3396 5035 2585 5219 5338 4467 5144 4467 5338 5136 5144 4173 5546 3926 5406 4907 5340 5332 3698 4632 5486 5455 5339 5487 828 829 830 4155 5339 4238 4153 5546 5681 5658 5485 5834 5950 5868 5759 2457 5341 4948 5071 2352 5614 2330 2163 4099 5486 3433 5339 5667 5788 5681 5658 2372 2145 1287 5342 2614 4941 1718 4980 4788 4941 2614 4980 2147 5342 1287 2145 1913 5346 2956 3063 5695 5546 5188 5406 5866 5770 3314 5740 2061 5847 5758 5846 3313 5611 3006 5344 3313 5757 5611 1276 2061 5612 5345 5611 5348 5613 5202 5593 2061 5489 2059 4897 3440 5613 5593 5202 5692 1939 2058 5489 232 5346 1134 3029 5346 4966 2956 3063 1963 5346 4966 232 4936 5347 4939 3167 3989 5347 3167 4178 4936 5347 2232 4939 4079 5396 4087 4679 3914 5348 5244 5202 4339 5348 3914 5312 4339 5348 5244 3914 4882 5348 5244 4339 2951 5349 2504 3601 5349 4503 4001 4040 4813 5350 4441 5064 3601 5349 4067 5147 4503 5349 4067 4040 5349 1143 4001 5147 4001 5349 4040 3009 2504 5349 4902 3601 4493 5349 4067 3601 5350 5064 1051 1067 1051 5350 1067 1868 5350 4442 3908 2162 2851 5351 602 2332 2332 4204 617 5351 602 5351 601 4204 5595 5397 2332 2329 4954 5351 4885 617 5351 4954 717 4204 717 5351 4204 601 2851 5351 601 602 5595 5397 2243 1675 5595 496 4839 5351 920 3531 1759 3371 3531 920 1759 1762 5375 4202 3636 5352 4244 5375 5352 5148 5353 1781 3073 4081 4783 5354 3204 2628 4929 5373 5354 4783 3350 5683 2427 3650 4140 5724 3961 3183 4226 5683 3650 5355 5703 2842 4592 3797 2288 5372 1763 5357 2427 5377 4809 5355 5683 637 494 607 736 5683 5536 3078 3961 5829 4079 3183 3823 5683 5321 4420 3989 5355 4226 2431 4226 5683 5355 5536 5355 5766 2445 5683 3751 5683 5355 637 4828 5683 5377 4042 963 5358 4280 2099 4764 5367 3838 4828 3406 5358 4984 3104 2701 5358 5292 4280 4783 5423 5373 2628 5075 5359 4501 2114 3238 5359 5038 5075 4392 5359 4501 5075 4798 5623 5587 5380 5917 5782 5745 5838 5360 5919 3713 5917 5842 5843 5821 5602 3447 5381 3503 601 1755 5879 2973 5643 4177 5360 4482 4904 5361 5135 5002 5137 4300 5361 3545 5137 4413 5361 5137 3545 5362 5634 3136 3360 4300 5361 3811 3545 5002 5361 5137 4413 3360 5364 5362 2759 61 5635 5439 5438 1829 5616 5364 2762 1821 5584 2753 1003 5148 5363 5160 4244 5363 4425 4087 4988 5160 5363 4484 4244 5148 5363 609 5160 3361 5364 4914 2759 5250 5620 5453 5454 5231 5715 5460 5510 5367 3830 3555 3835 2230 5449 2232 5092 5365 5450 5448 5231 5358 5292 1793 5366 5366 3406 3408 3179 5365 5619 5407 5231 4527 5367 4921 2567 5367 3555 2567 3835 5628 3199 5473 5368 2567 5367 4921 4828 5368 5504 2603 803 5425 4018 4922 5171 2619 5628 5368 3613 3796 5727 3707 3164 5662 3541 5549 5521 5454 5675 5497 4881 3581 5369 4512 5091 2557 5680 4512 5641 5280 5453 5091 5250 5093 5504 4608 626 3879 5504 2603 4608 5910 5819 2839 2855 1291 5562 5371 878 876 5563 5562 807 2374 5039 2625 5563 1291 5562 876 5371 4689 5371 1291 880 5039 5371 876 2625 4926 5372 4927 5357 3531 5555 5233 3530 5372 2288 1760 5357 4783 5423 4391 5373 5354 5373 2628 4783 2630 5423 2628 874 5423 2630 2779 3514 5075 5373 5038 5354 5663 3396 5239 5666 2652 5374 4161 3718 4087 609 4935 5375 5720 2319 3319 5815 5295 5621 5374 4698 4202 5375 3567 4504 3636 5375 5352 4244 4244 5375 5363 3567 4504 5375 3567 4386 5158 5375 4504 5174 5622 1730 844 3723 807 5710 4785 5425 5844 5544 5014 5337 3942 5377 2427 3831 4649 5378 4193 3147 4716 5538 3934 2949 4267 5377 3559 4759 4042 5377 3559 4267 5537 4759 4509 5377 4828 5377 5355 4809 5378 4509 3899 5180 5336 5623 2383 5380 5098 5537 4509 5378 3519 5900 2592 1684 5379 5679 1349 5462 4160 1698 1760 5463 2851 5381 3304 601 2591 5587 5380 4798 5821 5596 5602 4895 5660 5132 5133 5382 5514 5660 5471 5152 4440 5475 1064 5470 5383 2545 3778 4604 5034 5385 2175 635 1052 5588 79 2179 5062 5588 5063 5386 5385 5420 635 5034 5305 5062 1052 5386 1049 5386 5062 5305 5318 5628 5473 5597 5063 5386 1052 5062 5063 5588 1052 5386 3306 4901 1057 5388 2190 5597 5473 2553 5327 5461 5342 5201 5473 5597 5201 5318 5597 5473 5201 5461 5045 1789 5365 5450 5388 5005 5305 1052 1057 5444 4437 5388 5444 5388 5063 4437 5063 5388 5305 1052 1939 6083 1938 2072 3453 1849 1850 4385 3706 5680 4688 3821 4512 5641 5369 2557 5723 5874 5553 5772 5403 5044 4313 3844 5309 5762 5322 5660 4219 5697 5466 5654 5390 3914 3412 5083 5479 5133 4456 5382 84 5390 4456 4240 5073 4420 2422 5392 1663 5392 4420 5274 4731 5392 2422 5274 1663 5392 2422 4420 4973 5392 2422 4731 2731 5801 5516 3552 2724 5770 3314 2723 5327 5473 5461 5201 4974 5393 5159 5290 5438 2231 1003 5584 2618 5394 599 2619 4477 3364 5236 2134 4456 5479 5179 5390 5579 5793 5632 5656 5111 5394 4979 5327 5111 5473 5318 5387 4979 5478 599 5085 5429 5649 912 5431 3528 5480 2764 5431 5011 5657 4981 5410 1753 5430 1306 1305 5595 5397 2603 2243 2332 5397 2679 2329 4970 5655 5074 5631 5237 5397 2679 3660 2371 5398 2624 2620 3659 5464 4577 5220 2371 5398 2620 3697 5585 5679 5462 5690 5398 2620 3697 4683 5447 3537 4369 5220 2680 5399 2333 2756 4991 5631 4369 5447 4876 5573 4051 1675 5674 2680 34 5573 945 5399 2333 2680 5184 5463 5400 4160 4749 5402 972 5238 4572 832 833 5401 2585 5401 2412 832 4519 5401 2412 3886 5315 5401 832 2412 2585 5401 4572 2412 2412 5731 5401 5231 5401 5558 5321 833 5576 968 1328 5402 5050 5576 2706 970 4749 5402 1328 972 4313 5403 3844 3541 954 5433 1787 5403 3427 5403 4313 3542 5044 5403 1787 3844 3427 5434 5403 3542 5007 5113 3797 5404 4665 5007 3797 5404 5172 5534 3797 1658 5771 5244 5703 5733 4674 5498 5007 4665 5348 5733 5703 5244 3503 5405 2811 801 2319 3489 5764 3147 2554 70 3934 4877 5381 5405 801 4315 604 5188 4316 5406 3926 5639 604 5406 5882 5256 5415 5827 5188 5406 4173 4316 5406 3926 4173 4316 5078 5546 5343 4870 5188 5546 4173 5406 5188 5546 5078 4173 5546 5493 5078 5343 5735 5668 5621 5569 3074 5532 735 734 5947 6004 5983 5874 5836 1687 1699 5773 5770 2724 3554 2723 5765 5745 5782 5838 4630 5494 3277 3259 5671 5712 5497 5675 5258 5411 928 5043 4169 5670 4505 5526 3259 5535 4630 5494 5664 5527 5162 5814 4169 5670 5465 5409 2163 5614 1781 5353 5615 5158 5409 5494 922 5571 5412 5570 925 5412 922 4718 2663 5646 922 847 5646 923 5571 5570 3567 5413 2953 4386 5134 5413 2360 4294 5645 5773 1699 5747 1132 4266 5019 5414 3046 5414 4053 5268 5414 2940 1980 1132 4053 5414 1980 5019 2214 5414 4266 2940 5414 4720 4053 5268 4874 5414 4266 2214 3046 5414 1980 4053 2938 5414 5268 3039 4720 5414 5019 4062 5337 5415 3067 5140 1699 5645 5644 4508 3067 5645 897 5415 5709 5882 5256 1740 896 5644 4508 5176 5544 5844 5543 5337 2659 5416 2654 5264 911 5416 2654 909 4404 5416 914 5264 2659 5416 914 2654 4930 3459 914 5417 4405 5567 25 914 5432 4405 914 4404 3529 5417 3459 919 3844 5433 1787 3541 4895 5842 5821 5596 5410 5749 1305 5418 5011 5657 5027 5221 5042 5657 5418 5096 5658 3263 3926 4955 5418 5011 1305 5410 1659 5420 3471 635 1198 5420 3471 1659 819 5420 822 3472 634 5420 2903 635 5508 5693 3611 5110 3288 5421 3611 5110 5097 5508 4957 5421 2977 5421 2840 5262 2977 5421 3288 2840 5097 5508 5421 5315 29 5422 4408 27 4392 5423 5038 5373 2628 5423 5373 874 4392 5423 5373 4391 5373 5423 5038 874 2779 5423 3514 4391 5252 5371 5039 5424 2374 5547 3615 4606 881 5424 878 5252 4606 5424 5039 2374 881 5424 2374 878 5547 881 2374 3615 5425 599 5299 598 5171 5425 5368 2603 2776 5659 3339 5495 2626 5425 2776 807 3199 5425 3696 5368 3516 5624 5425 2776 4726 5210 16 5427 4045 5427 2591 2276 4398 5427 4726 2276 2591 5427 16 2276 5649 5978 5550 5431 4045 5427 4726 2591 889 5427 2276 16 884 5427 1728 889 5648 3422 5647 5581 5625 5176 896 5428 866 5561 3248 867 2277 5428 896 5176 2592 5625 5560 3519 5648 3230 3419 5647 5649 5879 5429 5643 5550 5643 5994 5995 619 5978 5431 5480 5480 3528 2764 2876 5551 5441 1034 5319 5417 5568 5432 5264 5550 1696 3528 1697 5550 5643 1696 5633 3529 5417 919 5432 4405 5432 5417 3529 954 5434 5433 5403 5417 5568 919 5432 5829 4079 5347 5396 5433 954 1787 4147 1787 5433 4147 3541 2267 5434 954 5391 3427 5434 3542 2267 5650 5437 5559 5436 3427 5434 2267 5391 3541 5434 5403 5433 954 5434 5403 5391 1326 5435 45 1325 2587 957 43 5436 47 5435 1326 1789 2588 5732 2587 5650 5637 43 957 5436 5437 5650 5049 2587 5895 5991 5966 5930 5437 5650 5638 5049 4312 5437 5048 2587 2701 5048 43 5437 5737 43 960 2261 5637 43 5436 5437 4312 5437 2587 43 2231 1003 61 5438 2231 5807 5760 5439 5124 5761 5393 5290 5635 61 1003 5438 1003 5635 5438 5584 5379 5476 5592 1026 1021 1005 1010 5440 4775 5066 61 5439 2577 5439 2231 61 4751 2574 1026 1350 5909 5804 2851 5875 4311 5440 64 2207 64 5440 1005 5297 5056 5440 5297 1005 4218 5440 64 3335 4282 5440 64 1010 2207 5440 1021 3335 2208 5440 5297 5056 4060 5694 5691 5533 5511 5442 73 5303 5551 2445 1034 5441 2445 5551 1034 5224 5058 5694 5533 5195 3797 5534 2460 1658 5627 1853 1042 5443 4060 5441 2445 4539 4754 5533 5441 5319 5533 4754 5058 4495 5442 73 1037 2558 1042 5554 5442 5443 1042 5743 5511 1847 5062 5444 5063 3296 1042 5586 5442 5554 5591 1057 5388 5444 5442 5554 2558 5443 5062 5444 5305 5063 3633 5444 4437 1057 3312 5445 1056 1051 4154 5446 5435 5045 1067 5445 1056 2176 2160 5445 82 5064 3312 5589 1051 1050 5446 5046 4154 5277 5655 5768 5573 4051 4169 5813 5465 5799 4970 5655 4991 5272 5399 5655 3537 5447 4138 5877 5871 5806 5448 5389 5231 5126 5126 5510 5231 5448 5111 5473 3199 5368 5401 5460 2412 5231 61 5449 5323 2230 1791 5629 1680 3544 5870 5293 5047 2411 5451 5681 5546 5485 5715 5448 5460 5510 5047 5460 5231 5293 5407 5460 5231 5047 4812 1052 5063 79 5453 5280 5091 5369 5321 5663 5035 5315 5683 737 611 612 5280 5620 5453 5250 5280 5620 5250 3579 5280 5620 5142 5453 4314 5680 3821 4149 4512 5497 5091 5369 5499 5823 4663 2172 5091 5497 5453 5369 5453 5671 5454 5620 4238 5486 5339 3433 5486 4925 3622 1765 4566 5488 326 4028 4617 5486 5455 3622 5101 5455 5339 4632 5232 5486 4926 4927 4926 5486 3622 4861 629 5487 4912 5114 4927 5455 4634 5232 4634 5455 3622 4617 5719 5728 5518 4225 2800 5518 3803 3458 5456 4670 5301 5302 5957 6006 5958 5940 2851 3788 4854 3304 5860 6017 5993 5727 5459 5548 5214 5483 5779 5459 5020 2855 5596 5459 5081 5483 4234 5871 2412 4519 4680 5602 5596 4791 4680 5596 5459 5081 4320 5877 2700 3637 5460 5678 5407 5450 2618 5604 2622 2372 4788 4941 865 2614 3450 5598 3279 5490 2618 5604 2372 5478 5473 5628 5387 5111 2377 2638 2634 889 2622 5604 2147 2145 2147 5473 2190 5461 5111 5628 3199 5473 4973 5474 4765 4908 5585 1024 637 5462 5592 5298 4710 3934 1349 5462 1024 5379 1024 5592 5379 5585 637 5585 5462 4710 5253 5463 1698 4993 5137 5528 5135 5164 4634 5463 4993 5184 4993 5463 1698 5400 5463 5372 1760 4927 5232 5463 4927 5233 5272 5464 4991 5397 2580 5464 3659 5220 4991 5464 5200 5397 2580 5464 5397 3659 4991 5464 5447 5220 4618 5464 5200 4991 5464 5674 2580 5397 5464 5655 4991 5447 5803 5131 3279 5490 5615 5813 5799 5465 5615 5813 5409 5352 5543 5800 5797 844 5700 5375 5352 5615 5654 5697 5069 5599 4858 5654 5069 5139 4498 5466 4343 4858 4498 5466 4143 4343 3275 5466 4858 4219 3458 6010 5457 1354 3068 5467 5106 839 5106 5467 3677 839 3068 5556 625 5467 5468 5141 5360 5304 5587 5745 5623 4798 5750 5940 5791 5841 5141 5468 5380 5304 2752 4288 5119 5469 4935 5700 609 4471 2679 5469 3852 5119 2683 5469 3374 2761 4603 1658 2460 5471 5095 5470 5121 4440 4440 5475 5470 1060 4440 5470 5121 2824 5105 5470 5121 5095 5309 4603 2460 5471 5673 1864 4211 2460 4048 5397 2580 5674 5152 5471 1658 4475 5118 5660 5471 5322 5472 3366 4876 3025 5727 4682 5756 5845 5412 5571 4718 5267 2398 5472 5117 2675 4876 5472 3025 34 2398 5572 2675 2242 5473 2619 5111 5394 3366 5472 930 3025 5327 5604 5461 5473 34 5572 930 933 930 5572 2398 2242 5674 5399 5655 3537 2622 5473 2619 2190 4115 5636 1164 5333 2147 5604 5473 5461 2738 5876 2079 4130 5073 5506 5474 4908 4908 5474 4765 5089 5870 5293 2411 2700 4765 5474 4130 5089 5095 5475 5470 1064 817 5475 1060 5470 4440 5475 1060 1064 5105 5475 5470 5095 3250 4432 1025 3648 1026 5592 1024 2444 4146 5803 3279 3947 2444 1026 5592 4586 5222 5592 1026 4586 3939 5477 5275 4175 5706 5744 5275 5721 3941 5701 4146 5477 3934 5491 3574 5223 5131 5803 5701 5706 5082 5721 5131 2111 5574 4308 2851 5143 5604 2618 2622 5473 5478 5473 5327 5394 5327 5604 5342 5461 2372 5604 2622 2145 2618 5478 5394 5473 5849 5943 958 1791 4113 4201 2881 5155 3528 5550 2876 5480 619 5480 2876 4366 1305 5878 5749 5840 2764 5480 2876 619 5840 5907 1305 5878 5673 5904 5848 5746 3528 5649 5550 5431 3528 5550 1755 1696 5482 3266 4344 3224 5166 2652 5295 5481 5070 5481 2652 5166 5530 5166 5295 5481 5374 5481 5295 2652 3710 5482 3100 3186 3930 5482 3403 5084 3929 5482 2843 3930 5482 4344 3418 5084 5482 3930 3403 2843 1677 3388 2255 2404 913 5484 4707 2117 5867 5548 5779 5804 5548 5804 4600 5483 5214 5483 5081 5459 2851 5483 5081 4600 2292 5687 5300 5245 5480 5940 2392 5886 5548 5459 5214 5020 5543 5844 5797 5800 5602 4680 2855 4791 4707 5484 2973 2117 4358 5484 913 1756 5727 4682 81 3584 5484 4707 2973 5041 3745 5484 912 4358 5409 4483 3146 5009 5343 5667 5658 5609 5546 5343 4870 5485 4024 5488 5334 5330 4617 5486 3622 4926 5486 1765 3622 2668 3622 5486 2668 4861 5232 5486 4927 5455 5508 810 4845 5315 326 5488 4907 5333 828 5508 830 5487 5487 831 829 5114 630 5508 3611 631 646 5693 5114 3659 3611 5693 5487 801 5332 5488 5330 4907 5334 5488 5333 5330 1169 5488 5332 4566 3698 5488 4907 326 5488 2075 4024 5334 2058 5783 1939 5692 5612 2061 5345 5489 3159 6051 2061 6039 5353 5814 5324 5169 1370 5490 4918 5314 5314 5598 5490 5541 5490 1370 5131 3279 3432 5707 3890 3539 5361 5528 5135 5137 5911 5966 5293 5929 5527 5707 5069 5697 5931 5940 2392 2598 1276 5913 5846 5847 5778 5695 5708 5727 4630 5615 5535 4935 4328 5882 5827 5820 4630 5535 4003 2943 5615 4630 5535 5494 5377 5683 611 4042 5700 5615 5526 4471 5659 5331 2113 4977 2626 5659 3339 2776 5144 5663 5496 5662 4393 5539 5031 5331 5331 5659 5539 5557 5495 5710 807 5425 2776 5659 5495 5425 4769 5144 5136 5496 5218 5496 5144 4769 2841 5771 3679 3797 3821 5680 4688 4149 5684 5765 5623 5672 5675 3821 4156 5671 995 1339 2576 2937 4512 5497 4881 5091 5497 5250 5453 5454 3679 5534 3797 5498 5404 5534 5498 3797 5471 5534 2460 4005 5007 5498 5404 4665 5499 5915 4748 2172 4203 5499 3887 4663 4797 5892 5759 5686 3887 5499 4748 4663 2567 5500 5377 4809 5500 5537 4509 5377 3899 5500 5180 4509 2555 5719 4353 3571 3549 5558 5321 5168 833 5558 5321 5311 5437 5638 960 5049 5517 5228 5138 5502 5502 5714 5608 5517 5754 5517 5165 5138 5099 5689 5502 5228 5790 5808 5784 5736 3797 5505 5113 4561 5113 5505 4821 4561 1808 2726 4130 5506 3641 5506 4908 4584 5089 5506 2726 4583 5108 5506 4130 5474 5506 5073 3641 4908 5481 5569 5530 5265 922 5571 2663 5412 5481 5603 5374 5295 5265 5530 5166 5507 813 5508 5315 810 2582 5315 5110 5508 2584 5508 832 5315 5693 5508 3611 5487 5421 5508 5110 5315 831 5508 5487 832 830 5508 5315 832 2584 5508 2582 832 3611 5508 5110 5421 829 5508 5487 830 4845 5508 5315 830 801 5508 3611 630 4957 5508 5315 630 828 5508 5487 4912 5097 5508 5315 4957 1700 624 4571 5509 5509 4661 2338 5130 5509 2327 4662 1700 4433 5798 5716 5540 2338 5509 624 2327 5231 5510 5460 5448 5676 5460 5448 5450 5885 1349 5942 71 4513 5511 1651 5060 5231 5715 5510 5401 5231 5715 5401 5460 5448 5715 5460 5676 5776 5775 3810 5766 5511 5586 1651 2556 1847 5511 1042 4513 17 5512 1299 15 5661 5517 5503 5529 5673 5936 5848 5904 5513 5286 2421 4761 5660 5514 5471 5309 5515 5666 3396 5663 5663 5338 5136 3197 5663 5239 3197 5136 867 5734 10 5774 5682 5521 5515 5662 5521 5666 3844 5515 3396 5515 4412 3844 4187 5516 4357 3841 2446 6000 5226 5524 4647 5974 4201 3684 3837 5516 3552 2731 3841 5516 3837 5290 5517 5718 5608 5529 5826 5790 5718 5722 5530 5723 5569 5668 5503 5529 5165 2138 5736 5808 4604 2603 5531 5829 610 5532 5437 5737 5637 43 4647 5974 3684 5888 5661 5751 5718 5722 3803 3571 3458 5518 4225 5518 3571 3803 5518 6010 2800 5457 5456 5916 5301 5524 4799 5759 5699 5685 1205 5519 5273 624 5369 5453 5142 5520 3773 5519 5273 4661 5829 3961 2870 5724 5680 4314 3411 4149 5680 5453 5520 5671 5718 5517 5608 5714 5460 5715 5401 2412 5713 4298 5284 5522 5326 5713 5288 4653 4750 5135 4469 5523 49 5523 2739 5051 4532 5523 4469 5135 5524 4570 4670 5456 5592 5918 5884 5298 5916 5951 5868 5950 4570 5524 4470 5226 5524 5899 5301 2446 4670 5524 5456 5301 5525 4432 3250 3648 5035 5391 43 5044 4651 5525 3648 4432 4169 5670 5409 3277 5813 4483 5409 5009 5148 5700 609 5375 4166 5526 4471 609 5844 4491 5800 5809 5148 5799 609 5700 4630 5526 4471 4166 5507 5642 5530 5408 5528 3547 4050 5137 5162 5664 3987 5527 5608 5754 5736 5243 5688 5790 5714 5784 5166 5553 5530 5329 5265 5569 5530 5507 4432 5724 1672 3395 5571 5412 923 5267 610 5532 609 735 5536 5829 5724 610 3065 5536 2885 736 3065 5536 592 2885 5069 5725 5707 4410 3961 5829 3183 5724 5829 1672 5536 5724 5683 611 736 5536 4140 5724 3183 3989 608 5532 734 609 736 5532 5531 610 610 5830 5532 5829 592 5532 734 608 3989 5829 3183 610 494 5532 5531 592 637 5532 608 1672 5533 4118 4754 4495 4060 5533 2791 5319 4118 5691 2791 5194 2445 5944 4539 5694 5534 4005 3797 2460 5353 5324 5767 1781 5535 4386 5174 4719 2943 5615 4935 5535 4630 5535 2943 4935 5615 5174 5494 5535 736 5683 3078 737 2427 5683 611 5377 3751 5683 5536 5355 2885 5536 562 3078 5707 5725 2582 4953 5683 5355 637 4194 3574 5683 5355 2445 4748 5896 5766 5834 5557 5659 3339 4977 611 5683 736 737 4242 5683 5321 1663 726 5683 606 5321 5766 2445 5227 5355 5683 637 607 1650 610 5536 611 4226 5477 5721 5706 5275 2949 5538 5183 4478 4509 5537 5180 5378 5009 4483 3146 1826 5537 4660 3942 5377 5815 5537 3831 5711 4759 5720 4267 5711 4809 5537 5500 5377 2964 5538 5183 3934 4018 5539 4393 5331 5710 807 3661 5557 4018 5659 5425 5539 4922 5539 4018 5425 4433 5540 5129 3809 4433 5540 3809 3806 5982 5825 5975 5890 3809 5540 3426 3806 5148 5799 5160 609 5314 5541 5197 4145 5082 5803 5131 5706 5314 5541 5490 5197 5708 5788 5658 5778 3782 5598 4145 5541 5672 5917 5745 5360 3718 5542 4698 5374 4024 5607 5334 2075 3661 5710 5557 4393 5794 5855 5592 5781 3426 5854 3806 5798 5710 5495 807 5557 5659 5710 5557 5495 2446 6000 5899 5896 4173 5546 4870 5008 2855 5867 5819 5020 1354 5545 4570 2800 5471 5660 5309 5322 5451 5546 3263 4173 3926 5788 4955 2457 5546 5658 5343 5485 5493 5658 5609 5343 4173 5546 3263 3926 5424 5547 4606 5252 2374 5547 4606 5424 5459 5779 5020 5548 5811 4710 5855 5883 5804 5909 5842 5869 5481 5603 5295 5530 3541 5549 4313 3542 5338 5796 5663 5219 4313 5549 5452 3542 2603 5550 5015 2392 5441 5551 4754 5319 2876 5550 4332 5015 5015 5940 2392 5550 3528 5550 4332 2876 5840 5940 5839 5907 5550 2876 2392 2603 5551 5223 5058 4754 1041 3176 3577 2958 5552 5227 2445 5355 2147 5604 5461 5342 5227 5552 811 5311 5226 5552 2445 5224 5553 5408 5166 5530 3662 5793 5656 5713 4986 5553 5166 5329 5828 5969 5947 5874 5836 5553 5772 5642 5586 5442 2559 2556 5586 1042 5442 1651 4926 5372 1763 5555 5555 4617 5232 5233 5232 5555 4927 4926 3436 5555 1763 5372 2394 5555 3530 4617 5232 5555 5233 4927 3530 5555 5233 4617 3962 5555 2394 1763 5382 5762 5322 5479 5467 5556 3677 839 5710 4393 5425 5539 5377 4267 3831 5711 5495 5557 3339 807 4364 5729 4393 4598 4364 5729 5031 4393 807 5710 3661 4785 5331 5557 5539 5031 3200 5557 3614 3339 5710 5659 5425 5495 4157 5558 4469 5321 5558 4297 4157 4469 5558 5168 4655 5501 2706 4157 1795 2248 5049 5638 3408 965 2277 5560 2644 896 5581 2592 3519 3422 1058 5626 4439 4438 3519 5625 5428 3954 2592 5581 3519 5560 2644 5581 4556 5560 4687 5561 2623 3248 5040 5774 867 5677 5561 870 2552 2623 866 5561 867 10 2872 5564 5255 2875 1644 5561 4687 1645 878 5563 5371 5424 5371 5563 2625 5039 5563 876 5371 2625 2115 5563 2374 807 131 5617 5564 1408 876 5563 807 2625 5563 878 5371 5562 5371 5563 5039 5424 2018 5617 1991 1089 5617 2018 1085 1089 5564 3060 1408 2062 5292 5366 4137 5618 2872 5564 2875 1085 2875 5564 1991 2018 2000 5564 5255 1085 5565 26 3875 23 5263 5566 5430 5260 5270 5566 5266 5263 5432 3451 5264 5568 25 2303 914 5567 909 5567 2303 25 4405 5567 914 5416 5568 5417 919 4930 5417 5568 5264 4930 5643 5550 1696 1755 4140 5724 3989 5355 4373 5898 4547 2688 1308 5412 923 5570 5646 2663 2287 847 5295 5621 4698 5603 5530 5603 5295 5329 5569 5735 5723 5665 5481 5621 5374 5603 922 5646 5571 5570 4160 5571 2663 2287 2242 5572 2675 1768 4718 5571 2663 4160 4048 5572 2580 2240 2675 5572 3761 2240 2580 5572 34 2240 3023 5573 4051 34 4048 5572 3761 2580 933 5572 2240 34 930 5572 1768 933 5074 5573 1675 4051 3023 5573 2756 4051 5074 5573 5397 1675 5655 5674 5397 5573 2680 5573 2756 3023 5675 5680 3821 5671 5399 5674 945 3537 5490 5574 5082 5541 5310 5725 5600 5707 4825 5574 2850 5143 2548 5574 2851 2111 4308 5706 5275 5477 5278 45 5435 5575 5281 2199 977 5577 5575 4746 4154 5278 5575 4154 5446 5435 5050 5576 5402 2706 968 5576 2706 5402 2248 5576 970 2706 5050 5576 970 5402 976 5739 5283 1802 977 5630 2862 979 2722 5578 985 3380 5759 6000 5834 5977 5632 5793 5578 5704 5761 5285 5698 5656 5761 5801 5583 5698 5578 5704 5582 2423 2722 5578 2423 985 3464 5583 1336 2731 2423 5579 985 5578 5704 5793 5288 5761 2222 4269 55 5580 5580 2727 3839 2734 4042 5580 55 5287 3839 5580 5052 55 4976 5580 3839 990 2277 5648 5581 5176 4921 5582 2423 2422 5288 5704 5124 4921 2277 5648 5647 5581 5647 2277 2644 2136 2592 5581 5560 4556 5648 844 2143 5647 2277 5647 2143 2136 3230 5648 3242 3422 5288 5761 5124 5704 989 5632 1336 5579 5290 5704 4248 5124 5285 5761 5393 5284 5616 5584 2753 1821 5760 1006 5438 5439 2762 5584 1006 2753 1003 5635 5584 2753 2536 1408 1592 5617 4194 5592 3934 5355 5298 5942 5592 5918 5592 5355 4586 5222 5198 5918 3794 4945 4592 5703 3797 5113 1024 5585 5379 5462 5592 5222 1026 5476 3411 5680 5177 5641 1024 5592 637 3343 812 5680 4227 5177 5623 5336 5335 5380 5511 5586 2556 5442 3176 2958 2173 3577 5588 5386 5005 1052 5736 5974 5946 5790 5304 5587 5360 5468 5587 5745 5360 5672 5864 5954 5917 5922 5386 4743 1047 5588 5386 5588 5005 4743 79 5588 1047 2179 5062 5588 79 5063 2392 5791 5590 5750 1056 5589 3312 3109 4436 1050 82 5589 1050 5589 3109 3312 1051 5589 82 1050 1656 5589 4436 1657 1858 5589 4436 1656 5589 2160 2176 5445 2176 5589 2563 1657 2973 6021 5879 5041 2392 5590 2598 5146 5795 5395 5410 5748 4152 3952 1769 4072 1057 5591 3633 5444 5005 5591 5388 5305 3633 5591 3296 5444 5005 5591 4901 5388 5592 1024 637 5585 4194 5592 4710 3934 5592 5705 5222 5476 2842 5703 4592 5593 5671 5712 5680 5497 5355 5592 4586 2444 3343 5592 5355 2444 2852 5594 5178 3397 2976 5594 88 3113 4108 5703 2842 5613 5595 3503 2881 2603 4839 5595 5351 601 4877 5058 4754 5975 5595 2672 4692 3711 496 5595 5299 647 5381 5595 2329 3503 601 5595 3618 600 4692 5595 3711 1698 4823 5596 2851 4895 4495 5981 4118 4754 1325 3178 2094 1789 3450 5598 2864 3279 1371 5598 2864 3450 5098 5764 5378 3147 5473 5628 2553 5597 5597 2190 5473 5461 5655 5464 4991 5272 5598 5314 4145 5541 5814 5169 5353 5162 1370 5598 5490 5314 3782 5598 3947 4145 4219 5697 5527 4143 4219 5697 5654 5599 4384 2159 1747 1692 5310 5725 5707 5182 5920 5922 5864 5859 2159 4382 1748 2962 5753 5599 5707 5697 5767 5814 5697 5753 5599 5767 5697 5753 2603 5974 5808 2881 2460 3273 5309 5746 4479 5769 5336 4971 2828 5746 5696 3273 5752 5874 5828 5865 5684 5336 5623 5601 5915 5948 5683 607 5836 6053 6043 5874 5668 5481 5621 5569 5481 5668 5530 5569 5553 5874 621 1699 4399 5726 3727 5605 5604 2372 5342 2145 5327 5604 5473 5478 2147 5604 5342 2145 3828 5720 4245 3147 5605 4013 4399 4698 5292 5737 5637 960 5937 5939 5869 5819 5415 5836 1699 5773 5645 5773 5415 1699 5605 5542 3718 2127 3169 5607 4116 4127 5333 5607 5606 1164 1166 5607 3154 5606 4022 5607 1164 4116 5292 5737 4771 5637 4024 5607 2075 4022 3694 5607 4127 3154 3153 5607 1166 5334 5736 5299 2603 3778 5517 5718 5689 5714 5736 5974 5808 2603 5138 5754 5502 5099 5972 6025 5987 5986 5667 5343 5658 5485 4664 5696 3269 5309 5493 5708 5658 5695 3282 5823 4663 2789 5610 5830 4087 4988 4679 5610 5092 5396 61 5610 4988 5323 1276 5861 5847 5783 2061 5345 5344 5611 5955 1939 2058 5861 3313 5913 3006 5846 1276 5611 5344 5345 3159 5913 2061 5846 2159 1748 4384 1747 5861 1939 2058 5783 2061 5692 5489 5612 3159 5963 2061 5913 5202 5733 4108 5613 6023 3165 3006 5998 4797 5896 4275 4748 2061 5692 2059 5489 3165 5757 5611 3006 5847 5914 1276 5913 5244 5771 5703 5404 5348 5703 5113 5244 5733 5348 5703 5613 5348 5733 5244 5202 2842 5771 3797 5703 3679 5771 5498 3797 1781 5614 4081 5353 3187 5614 39 1781 2402 5614 39 3187 3360 5616 5362 1006 4630 5615 5409 5494 5174 5615 4386 5535 5799 5615 5526 5700 2943 5615 4386 4935 2943 5615 5535 4386 5803 4146 5706 3782 5526 5615 4630 4471 1006 5616 5362 5584 2762 5616 5584 2753 2753 5616 1821 2762 1085 5617 1089 1593 2062 5617 1408 5564 131 5617 1991 5564 5617 1593 2062 1592 2062 5617 1592 1408 5617 131 2536 1408 1089 5617 2536 1593 1795 2706 5050 4157 4133 3466 2747 2705 5618 5292 1793 1794 5674 5768 5655 5399 5619 5045 5365 5407 5365 5619 5231 5389 5401 5895 3193 3378 5630 977 5281 979 4314 5680 3411 5641 4604 5736 2603 3778 3405 5620 5142 3579 5723 5874 5772 5828 5295 5621 5603 5374 5909 5821 1637 2851 2682 5631 2671 4369 5337 5622 3723 3067 1730 5622 3067 3723 844 5622 5376 4508 5337 5622 5376 3723 5336 5623 5601 2383 2166 5673 5152 4211 5765 4798 2383 5623 5468 5623 5380 5587 5915 73 2172 3281 3199 5734 2112 10 5843 5842 5459 5602 877 5624 2626 10 4508 5644 1699 5176 2113 5624 3709 2112 4150 5734 3709 5624 4150 5624 877 867 3954 5625 1699 1684 25 914 3741 4405 5644 5176 896 5625 5930 5928 6008 5943 5626 1058 2461 2828 5447 5674 5655 3537 5848 5936 5717 5133 5303 5743 3281 1847 1853 5627 2785 5443 1037 5627 5443 1843 1029 5743 5627 2785 1843 5627 2785 1029 5743 5442 1029 5627 1843 5627 5443 2785 5442 5743 5511 5627 5994 6021 2973 5263 5628 2619 2553 3613 5628 5387 5111 3199 5991 5045 4154 5763 5473 5628 5368 2619 976 5739 2862 5630 3611 5901 5875 2542 5946 2881 4113 5974 5336 5925 5601 5769 5447 5768 5655 5631 5285 5761 5698 5393 5447 5768 2333 5399 1336 5698 5579 5632 5285 5698 5159 5393 1336 5698 5583 3464 5583 5801 3464 5698 4308 5803 5706 3782 989 5632 5583 1336 1768 1769 3952 933 5930 5046 4154 5991 1696 5633 1697 5550 5908 5996 5994 5940 3360 3136 1011 5634 5940 5791 5841 5856 1003 5635 2753 1001 5438 5635 1006 5584 5439 5741 61 1006 5636 326 5333 3463 4115 5636 3463 1164 326 5636 1504 3463 5333 5636 5606 1510 5437 5737 43 960 5559 5436 960 5637 957 5637 5436 5559 5292 5638 3408 960 5437 5637 960 5436 5437 5737 960 5637 3408 4137 965 5638 5638 5292 5559 960 965 5650 5049 5638 5651 5807 2231 5055 5437 5638 5559 960 3926 5853 604 5639 3806 5981 4433 5973 5658 5695 5546 5493 5406 5695 604 5188 5639 3926 5546 5406 5658 5853 5788 3926 2113 5659 5425 4018 5659 5710 5425 5539 3412 5696 5133 5390 5970 6029 5979 6002 5407 5640 5045 5047 5047 5966 5293 5640 5510 5731 5126 5231 1036 4952 5225 5837 5748 5840 1305 5749 5530 5723 5665 5569 5553 5772 5642 5723 5418 5795 5410 5749 5773 1699 2919 1687 5643 5996 5633 5550 1699 5645 4508 5415 5649 5995 5879 5643 5841 5940 5839 5795 5644 1699 5625 1684 896 5645 3067 5644 1699 5747 1209 5644 1685 5644 1684 1699 4508 5645 3067 5415 896 5645 897 3067 4508 5645 5644 3067 3519 5648 3242 3954 2663 5646 5571 922 2644 5647 4556 5581 5648 5428 3519 5581 844 5648 2143 5176 844 5648 3419 5647 5648 2277 5647 2143 3242 5648 3419 3954 844 5648 5176 3419 5978 5649 5879 5431 5428 5648 5176 5581 5649 5429 912 1755 3419 5648 5176 3954 3422 5648 3519 5581 3422 5648 3242 3519 3528 5649 1755 5550 5429 5649 5643 1755 912 5649 1755 3528 965 5732 2588 5650 5742 5760 5634 5584 5436 5650 2587 5559 965 5732 5650 5638 5437 5650 2587 5436 2588 5650 5049 965 1011 5742 2235 5651 2235 5651 5055 1011 3364 4477 5236 5026 5933 5828 5792 5921 5227 5896 5226 2445 4539 5944 4536 5694 5874 5985 5983 5967 5940 6020 5931 5996 5821 5910 5842 5905 5550 6020 4332 5015 6020 5653 5550 4332 6021 1305 5263 1753 5655 5768 4051 5631 5768 5674 2756 5399 5466 5697 5069 5654 5310 5654 5069 5599 5397 5573 5074 5655 5284 5522 5285 5656 4970 5655 5272 5074 4051 5655 5074 5573 2756 5674 5573 2680 5655 4970 4991 5631 5464 5655 5397 5272 4991 5655 5631 5447 5284 5793 5522 5656 5410 5749 5748 1305 5221 5096 2392 5657 5011 5657 5221 4981 5858 6001 5949 5956 5658 5778 5695 5708 5788 6001 5880 3263 3263 5658 3926 5546 1672 5829 5536 5531 6018 6036 6029 6002 3926 5658 5639 5546 5539 5659 2113 4018 5659 5710 5539 5557 2776 5659 5425 3516 600 5661 2138 5529 5118 5660 5152 5471 5503 5689 5228 5517 5689 5826 5718 5751 5144 5796 5218 5219 4042 5683 611 612 2777 4779 3250 5525 5496 5663 5136 5239 5496 5666 5218 5662 5796 5144 5218 5662 5666 5521 3541 5662 5662 5666 5515 5663 2777 1025 3250 4779 5663 2794 832 3197 832 5663 5035 2585 5492 5664 4305 4410 3890 5725 5707 5600 616 5664 4410 4305 5492 5664 5527 4305 5023 5814 5707 5077 5707 5069 5599 5310 5697 5814 5707 5753 5496 5666 5662 5663 5772 5874 5553 5836 5724 3395 2870 1672 2138 5736 3778 600 5603 5850 4698 5792 5507 5665 5569 5530 6019 5731 5652 5702 2406 5666 3541 5218 5796 5549 2267 5682 5521 5666 5515 5662 5728 5457 5230 5518 5485 5681 5658 5667 5667 5810 5788 5785 5792 5723 5603 5787 5481 5668 5603 5530 4751 5525 4779 2777 5536 5829 610 5531 5530 5752 5553 5723 5777 5992 5895 5873 5603 5850 5621 4698 5669 5816 2079 5805 3752 5669 2566 2079 5670 4169 5465 5526 3692 1821 2429 3561 5867 5875 4600 5804 1001 5741 2229 61 5670 4169 4505 3277 4505 5670 3277 4630 5465 5670 5526 5615 4156 5671 5520 5620 5453 5671 5620 5520 4314 5671 4156 3821 3821 5675 4156 3706 5587 5672 5468 5623 5684 5468 5623 5335 958 5895 2749 5911 5958 5906 1305 5957 1755 5484 1756 2117 5527 5697 5069 5492 5673 5936 5152 5717 945 5674 2580 3537 2680 5674 945 5399 2580 5674 3761 4048 4439 5746 5626 2461 4005 5673 2166 2460 5746 5471 2460 5673 4005 5673 5152 2166 2756 5674 2680 5399 3706 5712 5675 4881 5620 5675 4156 5671 5671 5712 5675 5680 5453 5680 5497 5671 5454 5675 5671 5497 4687 5677 10 2112 1645 5677 5561 4687 3637 5871 2412 4234 4320 5877 5870 2700 5889 5676 5877 5715 867 5677 10 5561 2187 5677 2112 5426 5293 5870 5047 5678 5407 5678 5045 5450 4138 5870 1325 4320 2411 5870 1325 5045 5045 5806 5450 5678 5293 5678 5047 5460 5877 5678 5806 5870 5592 5817 5705 5781 5592 5918 5835 5884 4688 5680 5177 4149 5679 5781 1349 5690 5379 5679 5462 5585 5497 5712 4881 5675 5453 5680 5369 5497 5321 5680 4512 812 5989 6029 6002 5979 5789 5601 5780 5765 5681 5451 5546 3263 5546 5681 3263 5658 5727 5343 5493 5609 5796 5338 615 5219 5515 5682 5662 5663 5663 5796 5682 5662 5867 5869 5804 5779 5338 5796 615 5682 5521 5682 5549 5662 4242 5683 1663 495 5683 5311 4420 2422 607 5683 606 727 2716 5683 5321 3823 495 5683 3078 5321 494 5683 562 5536 5683 726 727 3078 494 5683 607 562 3578 5683 5321 606 611 5683 4226 5536 5683 4828 5377 5355 2422 5683 612 1663 4828 5683 612 2422 5311 5683 5355 2422 3823 5683 4420 1663 2383 5925 5769 1690 5923 5060 73 5303 5335 5769 5336 5684 5954 5864 5917 5900 5917 5684 5672 5780 5511 5766 5060 73 5623 5780 5765 5684 5429 5879 1755 5643 5916 5951 5881 5868 4797 5896 4748 5834 4797 5686 4799 4275 4799 5699 4797 5153 5240 5686 5230 4225 5601 5780 5684 5769 5686 6010 6000 5977 5892 5686 4225 5728 5245 5730 3943 3595 5243 5688 5608 5502 5687 5901 3943 5730 5459 5779 5548 5483 5960 5320 4110 5300 5960 6009 5819 5939 5243 5736 5688 5383 5957 1305 1753 5906 1349 5690 5462 5679 5322 5696 3269 5479 4945 5942 5090 5298 5546 5695 5639 5406 4536 5944 5691 5694 5194 5691 4633 5195 4118 5691 5533 2791 5612 5758 1276 5757 2679 5693 5110 2329 4420 5818 5770 5862 2059 5692 2058 5489 3503 5693 5381 801 5914 5964 1276 5963 5758 2061 5612 5692 3159 6059 2061 6051 5693 831 4953 5487 5487 5693 5114 801 5693 2329 2851 5110 2851 5693 801 5381 3503 5693 2603 5381 831 5693 5114 5487 5708 5822 5727 5756 3611 5693 801 3612 802 5693 2603 3503 5195 5944 5691 4633 5694 4536 4060 5691 5441 5694 5533 5058 2154 5944 2445 5924 5390 5133 5479 5696 5188 5727 5493 5695 2061 5612 5611 5757 5382 5762 5479 5133 3412 5848 5133 5696 5322 5696 5309 3269 5309 5904 5762 5514 4439 5746 5717 5626 5492 4143 5527 5697 5069 5697 4143 5492 5697 4219 5466 4143 5599 5753 5707 5600 5383 5754 5736 3778 5579 5698 5656 5632 5713 5284 4653 5326 5761 5801 5290 2731 5290 5801 5516 2731 4935 5700 5375 609 5868 5759 5685 5699 4308 5803 3782 5541 5802 5153 4797 5699 6045 6018 6036 6029 4797 5834 4748 5802 5615 5700 5375 4935 5700 5813 5352 5799 5082 5721 2111 5706 3941 5701 5477 4175 5082 5803 5490 5131 5706 4308 5275 5574 5731 5126 5389 5702 5126 5731 5389 5231 5579 5793 3380 5578 2842 5703 5593 5613 5404 5703 5113 3797 4592 5703 5113 5593 4108 5733 5703 5613 6025 5968 5972 5987 1349 5679 5476 5705 989 5704 2423 4248 5288 5704 4921 5582 5632 5761 5704 5583 4432 1025 3337 67 5761 5288 5124 5393 5761 5793 5284 5656 5782 5917 5859 5864 5592 5705 5476 5679 4146 5803 5706 5701 5803 5574 4308 5706 5082 5706 2111 5574 5876 5818 5805 5816 5707 4410 3539 5664 5980 6017 5727 5993 3782 5803 3947 5598 5574 5803 5541 5490 5131 5721 5706 5701 5721 5477 5701 4175 4953 5707 3539 2582 3539 5707 3890 2582 5069 5707 5664 4410 5023 5707 3432 3539 5077 5814 5664 5162 5822 5708 5727 5778 2059 6085 2061 2999 1298 5709 5544 5014 5680 5712 4688 5177 5788 5609 5785 5756 5493 5708 5609 5658 4328 5827 4557 5820 5726 5755 4956 4399 3500 5726 4399 1742 2361 5755 3727 4399 5537 5377 3831 5711 5369 5712 5497 5680 5680 5712 3706 4688 1722 5251 11 1292 3706 5712 4881 4688 4828 3649 4042 5713 5713 4764 4653 4828 5522 5793 5713 5656 5288 5713 3649 4764 5284 5713 5288 5326 3662 5793 5713 5582 5824 5714 5790 5784 5877 5889 2412 5871 5642 5723 5772 5872 4438 5848 5717 5133 5975 5825 4433 5890 5673 5848 5717 5746 5799 5465 4169 5526 5982 4754 5981 5975 5848 5936 5133 5904 5936 5514 5133 5904 5746 5626 2461 2828 5718 5517 5689 5661 5529 5736 5722 5608 5661 5751 5722 600 5102 5946 600 4113 4647 5891 2366 4354 4225 3571 5518 5719 5230 5728 4225 5686 5719 3572 4225 4353 4598 5729 5557 807 2555 5719 4225 4353 5082 5721 5706 5131 3942 5815 5537 3831 4509 5720 4245 4759 3828 5720 3147 3976 3831 5720 5711 4267 5537 5812 4515 4660 4175 5744 5275 4806 5661 5722 5529 600 5689 5824 5714 5718 5936 5673 5848 5717 2158 5975 5738 4433 5661 5722 5718 5529 5595 5974 2881 5736 5688 5790 5784 5736 3637 5877 2412 5871 5522 5793 5288 5713 5530 5723 5642 5665 5723 5530 5642 5553 5603 5752 5530 5723 6053 5983 6004 5874 5603 5723 5530 5668 5755 5882 5726 3730 3897 5837 5225 4952 5835 5811 5855 5883 1742 5726 3730 4956 3730 5755 4956 5726 1276 5757 5611 5612 1786 3848 2405 2108 3218 5726 1742 1297 4698 5726 5605 3718 5995 6021 6006 6007 3806 5981 5058 4433 5047 5870 2411 5045 5993 6011 6002 6005 5457 5728 2800 5518 5728 5518 5230 5719 3614 5729 807 5557 4393 5729 5557 4598 5729 4894 3200 3705 5869 5960 5910 5819 3595 5730 3943 2542 3378 5992 5938 5895 2542 5901 3943 4737 5783 1276 1939 5692 5672 5780 5684 5765 5401 5895 5731 3193 5047 5731 5293 5231 5731 5619 5389 5231 5969 5828 5786 5772 5510 5731 5401 5126 5911 5731 3193 5293 2412 5731 5231 5293 5047 5731 5640 5293 5650 5559 5638 5732 2587 5732 5559 5650 965 5732 5638 4137 2841 5733 4108 3679 3709 5734 2112 5624 3199 5734 5624 2112 4150 5734 867 5040 2842 5771 5733 2841 5202 5733 5244 3914 2842 5733 4108 2841 5040 5774 5734 867 2112 5774 5677 10 3199 5734 10 5624 4150 5734 5624 867 5668 5787 5603 5723 814 5899 5894 2786 5668 5735 5723 5569 5787 5668 5621 5735 5865 5967 621 5874 5665 5872 5735 5723 5595 5974 2603 2881 3778 5736 5299 600 5667 5788 5609 5785 5369 5712 4512 5497 4881 4512 4229 5177 5736 5808 5383 4604 5781 5855 5592 5835 5825 5738 4433 5716 5981 3806 5195 5973 5881 5977 5456 1354 5194 5981 4118 4495 61 2229 1006 5741 5716 5982 5738 2050 5738 5129 4433 5716 1848 1849 3454 2043 5281 5739 5630 979 2862 5739 979 5630 976 5739 5630 5283 5739 2862 979 1803 5740 2724 2079 5669 5073 5876 5474 5108 5876 5392 5862 5073 5866 5818 5740 5805 5404 5703 3797 5771 5439 5741 1006 5635 5743 5442 5511 5303 5760 5742 2231 5584 5742 5760 2231 5651 1011 5742 5634 3136 5511 5743 5303 1847 1853 5743 1847 2785 3281 5743 73 1029 5706 5744 2548 5275 4732 5744 4806 5275 2112 5774 10 5734 5745 5587 5623 5672 5672 5782 5765 5745 4798 5765 5745 5623 1864 5746 2461 2460 5696 5746 5309 3273 1209 5773 1699 2919 5746 5848 5626 2828 5677 867 10 5774 5790 5826 5718 5824 5828 5947 5934 5897 5808 5974 3684 4960 5042 5795 5096 5418 5795 5096 5657 2392 5751 5661 5718 5689 5928 5046 5930 5991 4895 5842 5596 2851 5997 5962 5989 5970 5395 5795 5657 2392 5042 5795 5418 5749 5795 5096 5418 5657 5395 5795 2392 5750 5931 5940 2598 5015 2392 5791 2598 5590 621 5752 5603 5792 5530 5752 5329 5553 5309 5936 5514 5471 5549 5796 5662 5682 3989 5829 5724 3183 5752 621 5329 5553 5988 1276 1939 5955 5814 5707 5077 5664 5752 5603 5530 5329 5767 5814 3073 5527 5753 3432 5707 5600 5169 5814 5023 5162 1781 5833 5767 3073 3228 5754 3778 4949 3228 5754 5243 3778 5754 5138 4949 5099 5529 5754 5736 5608 5755 2361 3727 3216 5847 2061 5758 5783 5708 5822 5788 5778 5658 5853 3926 5639 3313 6023 3006 5998 5875 5867 4600 5937 3313 5846 3006 5757 5835 1349 5781 5811 3313 5913 5846 1276 3165 5913 5846 3006 5848 3412 3587 2828 2061 5783 2059 5692 5848 5746 5626 5717 4799 5759 5685 5686 2446 5896 2445 5226 5632 5761 5583 5698 5892 5896 4797 5834 5438 5760 5439 2231 5634 5807 5651 5055 1006 5760 5584 5634 5742 5760 5651 5634 5761 5290 5704 5583 5632 5793 5761 5656 5704 5793 5582 5288 2731 5761 5583 5290 5679 5794 5592 5781 5284 5761 5393 5288 5514 5762 5660 5133 5309 5762 5696 5322 5762 5382 5322 5660 5731 5619 5640 5763 5322 5762 5696 5479 5896 5977 5685 5686 3942 5812 4515 5537 5966 5047 5293 5929 5045 5763 5640 5619 3942 5812 5537 5764 3489 5815 2319 5764 2169 1343 1826 4884 5815 3489 2319 3658 5098 5815 5537 5764 5335 5769 4971 5336 4798 5765 2383 1699 4748 5894 5834 5766 5840 5795 5748 5839 5683 5766 5311 5355 4143 5767 3767 5527 5631 5768 2671 4369 5447 5768 5399 5655 5447 5768 4369 2333 5769 5336 2383 4479 5769 5336 5684 5601 4849 5769 1690 2383 1737 4556 2128 5560 5863 2383 1690 5789 5073 5862 4420 5392 5740 5818 3554 5805 2723 5770 4420 3554 5392 5866 5274 5289 5669 5816 3554 2566 5805 3554 5740 5669 5862 4420 3314 5770 5851 5859 5789 5863 5498 5404 3797 5771 5244 5771 5404 5498 5060 5923 3901 4805 5934 6004 5983 5969 5864 5917 5859 5922 5874 5723 5752 5828 5683 5948 2445 607 5836 2648 3729 2593 5827 5836 3730 4347 3072 5836 3414 3523 4556 896 1737 4555 3808 5831 3810 5775 5511 5775 2556 5766 73 5831 4537 5775 5511 5775 73 2556 5775 5776 3808 3897 3808 5831 5775 4537 2556 5837 3897 5775 2801 5776 3575 2556 5837 4537 73 4321 5775 5776 3897 2556 5776 3897 2789 3808 3378 5992 5895 5777 5873 3544 5629 5849 4698 6097 5893 3738 2245 5895 3378 3193 3544 5777 5629 1681 5459 5843 2855 5779 5667 5788 5658 5609 1637 5959 4737 4110 5623 5780 5601 5765 4432 3250 1025 4790 5300 5901 5320 5687 5672 5917 5780 5782 5684 5917 5672 5360 5679 5781 5592 5705 3794 5918 5883 1349 2973 5879 5484 5041 5679 5794 5781 5690 5838 5917 5782 5864 5964 5999 1276 5998 36 5898 3535 2688 5782 5917 5780 5859 5861 1276 1939 5783 2059 5783 2058 5692 5758 5847 1276 5846 5823 3575 3887 2789 5808 5736 5383 5688 5808 5736 5688 5784 2881 5808 2603 4960 5903 5928 5943 6008 5658 5810 5681 3263 5793 5761 5284 5288 5859 5920 5851 5864 5658 5810 5788 5681 5723 5792 5603 5752 2870 5829 5724 1672 5347 5830 5829 5396 5787 5828 5792 5723 5668 5787 5723 5735 5967 5865 621 5933 5859 5925 5789 5863 3926 5853 5788 2457 5609 5788 5708 5756 3263 5788 4955 5658 5853 5658 5778 5639 4955 5949 2457 5788 5667 5810 5681 5788 5658 5853 5778 5788 5845 5949 5887 5912 5609 5788 5658 5708 5845 5949 5858 5788 5853 6017 5949 5993 5601 5789 5780 5769 2383 5851 1699 5765 3684 5974 4201 4960 5601 5925 5789 5769 5791 5940 5795 2392 5595 5974 5736 2603 862 3778 4389 7 3197 5682 5338 615 5608 5790 5688 5736 5714 5824 5790 5718 5824 5974 5784 5790 5840 5940 5886 5795 5341 6038 6034 5071 3806 5973 4633 5195 5787 5850 5603 5792 5830 2870 1672 5829 3380 5793 3662 5582 5284 5793 5288 5522 3380 5793 5656 3662 5793 5579 5632 5578 5839 5907 1305 5840 5585 5794 5679 5690 5585 5794 5592 5679 5791 5795 5750 2392 5989 6029 4955 6002 5418 5795 5657 5410 5940 5931 5550 5015 5750 5940 5841 5795 6017 5853 5887 5860 5795 5395 5748 5750 5410 5795 5748 5749 5749 5878 5042 5795 5480 5941 5940 5886 5218 5662 3541 5796 615 5796 2267 5682 4557 5827 5800 5820 5549 5796 3541 5662 5144 5796 5663 5662 5338 5796 5682 5663 5144 5796 5219 5663 5800 4491 4557 4940 844 5809 5543 5800 5809 4940 844 5128 5994 5550 5940 5996 4557 5827 4347 4491 5716 5982 5798 5825 4433 5798 5540 3806 3018 5013 1970 3984 958 5929 5928 5927 844 5809 5128 4508 4940 5809 844 5800 5543 5844 5809 5337 5809 844 5543 5376 5256 5827 5140 5415 5844 5014 5797 5820 5291 5801 3552 3464 2445 5899 5896 2446 5761 5801 5698 5290 5159 5801 5516 5290 5699 5932 5834 5802 5699 5834 4797 5802 5899 5932 5834 5868 5950 5868 5916 5899 2864 5803 3279 5598 4146 5803 5701 3279 5574 5803 5490 5082 5548 5867 5779 5020 3450 5803 2864 3947 5869 5937 5867 5875 5541 5803 3782 5598 3450 5803 3279 2864 5483 5842 2851 5596 2851 5804 5483 4600 5548 5804 5483 5779 5788 5860 5778 5822 6010 5686 5892 5728 5474 5876 4130 5108 5055 5807 5066 3360 5818 3554 5805 5816 5450 5806 5676 5460 5289 5876 5866 4130 1006 5807 5439 5760 2231 5807 5439 5066 5807 5634 5651 5760 5651 5807 5760 2231 5974 5891 4647 4201 4960 5808 2603 802 2061 5758 5757 5846 2603 5808 4604 802 5809 844 5376 4508 5376 5809 4508 5337 5140 5844 5415 5827 4940 5809 5800 4491 5709 5882 1740 5755 4557 5827 4491 5800 5845 5949 5912 5858 5785 5880 5788 5858 4945 5942 3794 5090 2319 3147 5764 3976 5690 4710 5794 5811 5781 5690 5794 5811 1349 5811 5690 5781 5794 5855 4710 5592 6021 5958 5941 1305 5537 5812 4660 5500 3489 5812 4515 3942 5700 5813 5615 5352 5409 5813 5009 5352 5175 5813 5352 5009 5697 5814 5527 5707 5813 5615 5409 5465 4169 5813 5799 4483 5700 5813 5799 5615 5707 5814 5527 5664 3942 5815 5764 5537 5353 5814 5162 5527 3073 5814 5753 5353 5023 5814 5753 5707 5767 5814 5753 3073 5669 5816 2566 2079 3976 5815 5764 2319 5815 3831 3658 3319 3658 5815 3319 2319 3147 5815 5764 3976 5711 5815 5720 3831 5537 5815 5720 5711 5108 5818 4800 5073 2565 5818 4800 5816 5592 5817 5222 5705 3554 5818 2565 5816 5818 5770 3554 4420 5592 5885 5222 5817 4800 4420 5073 5818 2565 5818 4420 4800 5392 5876 5862 5866 3554 5818 4420 2565 3143 5819 2839 2023 5976 5875 2542 5937 5320 5960 5901 5300 2023 5819 2869 3948 4328 5827 3730 4347 1349 5883 5811 5835 4834 5820 5797 5709 4491 5844 5800 5827 5823 5915 5766 2172 5499 5823 4748 4663 3887 5823 2789 4663 3282 5823 2172 4663 4354 5935 4201 5891 5298 5918 5198 4945 4225 5892 5728 5226 5849 5903 5873 5895 5974 5808 2881 4960 5982 5716 5798 2050 5825 5975 4433 5738 5891 5974 4647 5888 5892 6000 5226 5896 5751 5946 600 5935 5822 5727 5756 5845 5826 5935 5689 5891 5673 5936 5471 5152 6000 2446 5226 5896 5836 5882 5827 3730 5836 5844 5415 1699 5844 5836 5415 5827 5014 5844 5140 5820 5676 5889 5877 5871 5834 2445 5896 5766 5256 5827 5820 5140 6005 2819 604 2456 5792 5865 621 5752 5897 6025 5921 5984 5735 5828 5787 5723 5865 5947 5874 5828 5752 5828 5723 5792 3535 5898 4373 2688 5735 5832 5828 5786 6012 6043 5990 6037 5779 5910 5869 5842 5828 5969 5786 5934 5723 5874 5752 5553 5828 5969 5874 5772 4430 5830 827 608 4079 5830 2870 4087 5830 1672 5532 5829 5831 3810 5775 5766 5363 5830 4988 4087 64 5830 4087 4430 5396 5830 5610 610 5363 5830 609 4988 1672 5830 608 827 4430 5830 4087 827 2439 5830 4087 2870 73 5831 5775 5766 3810 5831 2172 5766 5831 73 4537 2172 5850 5857 5792 5787 5832 5735 5828 5787 5850 5921 5857 5897 5921 5850 5857 5792 5850 5787 5603 5621 36 5833 3073 3767 5896 5892 4797 4275 3073 5833 5767 3767 5884 5198 4710 5298 5834 5977 5950 5759 5699 5834 5759 4797 2792 5837 4321 4537 4491 5836 4347 4082 3218 5836 1741 1742 5672 5917 5782 5745 5836 1688 19 3523 4082 5836 3219 2384 3219 5836 1742 1741 5836 5827 4491 4347 5795 5841 5750 5839 5748 5840 5839 1305 5795 5840 5748 5749 5749 5878 5795 5840 614 958 2749 5911 2392 5856 2598 5791 5909 5959 4737 5905 5875 5959 5901 4737 5910 5779 5819 5843 5842 5483 5459 5596 5459 5842 5596 5602 5779 5910 5819 5869 5819 5843 5779 2855 4508 5844 1699 5337 5844 5836 4491 5128 5014 5844 5337 5140 5544 5844 5797 5543 5834 5899 2445 5894 4491 5844 5128 5809 5820 5844 5827 5800 5836 5844 1699 5128 3165 5963 5913 3006 2061 5955 5861 5914 5140 5844 5827 5820 896 4556 5560 2644 5822 5887 5788 5860 6041 1276 1939 6035 1276 5846 5757 5758 3159 5998 2061 5963 2061 5999 5964 5998 73 5923 3281 5915 3159 6023 2061 5998 2061 5914 5847 5913 2061 5861 2059 5783 3313 5998 3006 5963 6039 3313 1276 6023 5758 5847 5783 1276 6109 6121 4277 6110 5746 5904 5696 5309 5309 5936 5471 5904 3412 5848 5696 2828 5626 5848 5717 4438 3587 5848 2828 4438 5542 5850 4698 5621 5911 5991 5966 5895 4275 5896 5226 3575 5895 3544 958 2749 1791 5849 5629 3544 5542 5893 4698 5850 6035 1276 1939 6015 5782 5851 5765 5838 5851 4798 1699 5765 2383 5863 5851 5789 5730 6009 2292 5687 3954 5954 5920 5953 5853 3926 604 2457 38 5852 5833 36 3196 5898 3767 5852 2786 5932 814 5899 5853 5993 604 5860 3778 862 4389 3121 5890 5975 5945 4433 4433 5902 5854 3806 5195 5981 5194 5058 5540 5982 5798 2050 4433 5945 5890 5902 6012 6053 6031 6014 5787 5792 5828 5857 5795 5940 5886 2392 5857 5897 5828 5832 5940 5841 5906 5908 5832 5787 5828 5857 5850 5857 5787 5832 5456 5881 1354 5302 5789 5859 5851 5780 3263 5949 4955 5788 5858 5788 5756 5845 5949 5845 5887 5788 5970 5989 5956 5962 5782 5859 5780 5851 5727 6017 5912 5887 5674 34 5397 5573 1690 5953 5925 3954 5926 3517 4396 2878 3954 5925 1690 3419 3707 1858 3584 3582 3230 5954 2128 3422 1276 5955 5914 5861 4420 5862 3314 5274 2059 5861 2058 5783 5392 5862 4420 5274 6025 6044 6026 6033 5770 5866 3314 5862 5548 5867 4600 5804 1046 4512 3702 5061 5920 5954 3519 5900 3519 5920 5900 1684 5895 5992 5903 5873 2180 2186 79 4229 5780 5925 5769 5789 5752 5874 5865 621 4798 5920 5900 5851 5782 5864 5851 5838 3713 5926 2638 3517 3419 5953 5925 5922 1318 3623 941 1773 3611 5901 2542 4737 3954 5954 3242 3422 5792 5865 5752 5828 2851 5875 4600 4737 2855 5867 5779 5819 2751 2721 4422 1819 2855 5867 5020 5779 5894 5834 5802 4748 5392 5876 5289 5474 5862 5876 5073 5818 5899 2786 5301 2446 5301 5881 5456 5302 621 5865 5792 5933 5869 5960 5819 5939 2786 5899 5301 5868 5915 5948 607 5894 5320 5960 5959 5901 5875 5976 5939 5937 5867 5869 5779 5819 5821 5910 5843 5842 5649 5995 5643 5550 5293 5877 2412 5870 5870 4320 2700 2411 5877 5889 5715 2412 5870 2411 1325 4320 5293 5877 5460 2412 2700 5877 5870 2412 4133 2747 4628 4913 2412 5889 5401 4519 5676 5877 5460 5806 5665 5872 5723 5642 5772 5872 5828 5786 5828 5872 5735 5786 5887 5727 5845 5912 5895 5777 3544 3193 5895 5849 3544 5873 5777 5895 3544 5873 2245 5895 5777 3378 5752 5874 621 5553 2786 5971 2445 5948 5826 5935 5751 5689 3611 5901 4737 5875 5867 5875 5804 5869 5804 5909 2851 5842 2851 5875 5804 4600 5892 6010 5728 5226 5875 5959 5939 5901 4130 5816 5108 5876 2079 5876 5816 4130 5876 5392 5289 5866 5818 5876 5108 5816 2079 5876 2715 5866 5805 5876 5816 2079 5289 5876 4130 5474 5876 2079 2715 2738 5678 5877 5293 5870 5676 5877 5806 5871 5649 5879 5431 5429 5715 5877 5460 5676 2700 5877 2412 3637 5678 5877 5460 5293 5886 5795 5042 5878 5879 5995 5994 5643 5042 5886 5878 4366 5840 5886 5878 5795 5907 5941 5886 5940 5906 5958 1305 5907 1349 5918 5885 5942 5858 6001 5880 5949 2061 5847 5846 5913 5785 5880 5810 5788 1284 4324 3421 4076 5882 5755 5726 1740 5301 5881 5302 5868 1354 5977 5457 5951 4328 5882 3730 5827 5256 5882 5820 5827 5198 5884 4710 5883 5882 5709 4834 5755 5415 5882 5827 5836 5882 5755 4834 4956 5884 5855 4710 5883 5042 5886 4366 5096 5918 5592 5835 5885 5855 5884 5835 5883 4710 5884 5298 5592 4945 5942 5298 5918 5198 5918 5884 5883 1349 5835 5817 5885 4432 4790 1025 67 1025 4432 3337 3648 5592 5885 5817 5835 5592 5942 5222 5885 5096 5886 4366 2392 5841 5940 5856 5908 5940 6007 5941 5480 6020 5550 5931 5015 5935 5974 4201 5891 5822 5887 5845 5788 5887 5788 5860 5853 5995 6007 5550 5978 5950 5868 5759 5685 5913 3159 3165 5846 5889 5715 2412 5401 2412 5889 4519 5871 3561 4534 1821 1823 1842 5319 2791 4118 4754 5982 5981 4118 5834 2445 5766 5894 4433 5902 5890 5854 5974 3684 5784 5808 5759 5896 5892 5834 5946 5826 5722 5790 5935 4354 2366 5891 4354 5935 5102 4201 5826 5946 5751 5935 4647 5891 5888 2366 5309 5936 5904 5514 4797 5892 5686 4275 5759 6000 5977 5896 5685 5896 5686 5759 4698 6026 5987 6025 5893 5542 4698 5605 4698 6097 3738 4213 6011 6030 1360 6022 6028 5895 5938 6019 607 5915 5894 606 2786 5948 2445 5894 1650 5948 2445 5924 5896 4275 4748 3575 5766 5948 5894 2445 3193 5911 5293 614 2245 5895 3193 5777 5227 5896 5766 5226 4748 5896 3575 5766 5892 5896 5226 4275 5834 6000 5950 5977 5686 5896 5892 5759 5480 619 5978 6007 5832 5934 5897 5828 5857 5921 5828 5897 5897 5857 5850 5832 5921 5984 5947 5897 5975 5981 5058 4754 6037 6054 6047 6043 36 5898 5852 3535 2786 5932 5899 5868 5899 2445 2786 2446 5685 5977 5950 5951 5977 5916 5881 5456 5917 5864 5838 5900 5954 2128 3422 2592 5851 5900 5838 5864 1755 5879 5484 2973 3943 5901 5320 4737 3806 5981 5195 5058 5901 2542 3943 5730 3426 5973 3806 5902 5179 2830 5479 4456 5736 5946 5722 5790 4433 5981 5945 5973 3710 4207 2023 5206 5194 5981 4495 5058 5825 5982 5854 5890 5696 5848 5133 5904 5320 5960 4110 5959 5904 5309 5762 5696 5762 5904 5133 5514 5673 5904 5746 5471 5746 5904 5309 5471 5941 5480 4366 5886 5940 5840 5886 5907 5779 5910 5842 5843 5909 5960 5939 5959 5910 5842 5905 5909 5909 5842 5905 5821 5909 5960 5905 5910 4955 6002 2457 5989 5804 5909 5869 5875 5840 5907 5878 5886 5320 5959 4737 5901 5957 5940 5906 5908 1637 5909 4737 5905 5839 5907 5906 1305 2750 5218 1786 3848 5875 4737 2851 5909 1637 5909 2851 4737 3159 6059 6051 2084 5908 5996 5940 5931 5960 5909 5905 5959 5907 5941 1305 5878 5218 3356 2406 2697 4366 5941 5886 5878 5842 5910 5869 5909 5865 5967 5947 5933 3193 5911 2749 5895 2822 1360 3114 4847 3313 5963 3006 5913 6043 6047 6037 6031 5962 5997 5980 5727 1276 6064 6056 2072 2059 6041 2058 6035 2061 5964 5914 5963 3313 5963 5913 1276 5914 2061 5847 5861 3159 6084 2061 6079 3139 6085 2058 2999 5847 5914 5861 1276 3165 6023 3159 5998 5683 5915 607 606 3578 5915 5060 606 5823 5915 4748 5766 5915 5948 5766 5683 73 5915 5766 5060 5835 5918 5883 5884 5802 5915 5894 4748 5823 5915 2172 4748 5864 5954 5920 5900 5919 5360 3713 3220 5918 5198 3794 5883 5926 1743 4696 5919 3724 5919 2128 5917 6112 6123 3863 6121 3242 5954 3230 3422 5792 6025 5933 5850 5828 5933 5792 5865 5983 6053 6004 6012 5921 6025 5968 5972 5857 5921 5792 5828 5865 5947 5828 5933 2383 5925 1690 5336 5953 3242 3419 3954 5789 5925 1690 5863 5859 5953 5920 5922 3006 6039 3165 6023 6123 6112 3863 3493 5917 5954 5900 2592 3901 5923 3171 4805 3578 5923 5060 5915 5336 5925 1690 5601 5601 5925 1690 5789 5948 1650 2445 607 5780 5925 5789 5859 3720 3722 4400 16 4396 5926 2878 1729 4835 5926 2878 3517 5927 5895 5849 958 5966 5045 5929 5928 5895 5929 958 5927 6008 5903 5928 5927 5895 6027 6008 5992 5966 5895 5927 5929 5633 6020 5653 5550 614 5929 958 5911 5849 5928 5927 958 5954 3954 3242 5953 5927 5966 5929 5928 5940 5856 5908 5931 4738 5943 3112 2097 5901 5960 5687 5300 2392 5931 2598 5856 6022 5997 6002 6018 5840 5940 5795 5839 5930 5046 3112 4154 5958 6021 5941 6007 5834 5894 5802 5932 5899 5932 5894 5834 814 5932 5894 5899 2786 5932 5868 814 5832 5934 5828 5786 6053 5985 621 6014 5912 5949 5887 6017 6092 6110 621 6053 5921 5984 5972 5947 5974 5935 5102 5946 5936 5904 5673 5471 5869 5937 5819 5867 2542 5937 5875 3611 5875 5976 2542 5901 6034 6036 6018 6022 5911 5991 5731 5966 5687 6009 5939 5976 5952 6027 5895 5938 5687 5976 5939 5901 1354 6010 5545 2800 5939 5909 5875 5869 5869 5960 5909 5910 5875 5939 5869 5937 5839 5940 5906 5907 5791 5940 2392 5856 1305 5958 5941 5907 5480 5940 5550 2392 5940 5015 2392 2598 5978 5550 5431 5480 5592 5942 5885 5918 4319 5943 959 1792 3934 5942 5222 5592 3794 5942 4865 5090 34 5674 5397 3761 5943 1792 1800 959 3801 5943 4319 1792 2097 5943 3805 4738 5890 5982 5902 5945 3796 5727 4870 3707 1650 5944 2445 4633 5195 5944 4633 2445 1650 5944 5924 2445 5975 5981 4433 5058 5981 4495 5058 4754 6016 6033 6025 6026 5102 5974 5946 4113 4433 5973 5945 5902 5687 5976 5901 5730 7 862 3778 2138 5921 5968 5933 5947 5736 5946 600 5722 5826 5974 5888 5824 5826 5946 5935 5891 5826 5974 5891 5888 5826 5974 5824 5790 6016 6033 6026 6031 5947 5828 5933 5921 621 5985 5968 5987 2781 5982 2804 4118 5828 5947 5897 5921 5890 5982 5945 5975 2058 6085 2059 2999 2786 5948 5894 814 5948 5915 5766 5894 5766 5948 2445 5683 6005 2819 2456 6030 5956 5949 5858 5912 3313 6039 3006 6023 5853 5949 5788 2457 5788 6001 5949 5880 5858 5949 5880 5788 5730 6009 5687 5976 5949 5788 5887 5853 5973 5982 4118 5981 3006 6051 3165 6039 5685 5977 5951 5457 5686 6000 5896 5977 5916 5977 5881 5951 5685 5951 5950 5868 5916 6000 5899 5524 5759 5977 5685 5896 5995 5649 5879 5978 5643 5996 5550 5994 5759 5977 5950 5685 6019 5952 5895 5938 5903 6008 5992 5895 6019 5895 5930 5991 4682 5727 1360 1860 3378 5992 5777 5938 5928 6008 5927 5930 5731 6019 5652 5991 5727 4682 4870 5343 5955 1276 1939 5861 5859 5953 5925 5863 1046 79 4512 5061 3419 5953 3954 5925 1690 5953 5863 5925 5859 5953 5922 5925 3230 5954 5922 2128 5864 5954 5922 5920 3519 5954 2592 5900 3954 5954 3519 5920 5954 3422 3954 3519 2128 5954 5922 5917 3422 5954 2592 3519 3313 6074 3006 6065 2059 5955 2058 5861 2782 1706 2494 1707 1939 6015 2058 3139 2319 1816 3147 3976 5986 6016 6012 6013 5989 6005 5993 6002 5941 5940 5907 5958 6036 6011 6022 6030 4740 6050 5071 6038 5763 5045 4154 5619 5906 5958 5907 5940 1637 5959 5905 4737 6007 5958 5940 5941 5901 5960 5959 5939 2445 5965 1030 5961 5320 5959 4110 4737 1637 5959 4110 5905 5875 5959 4737 5909 5300 6009 5687 2292 5960 6009 2839 5819 5959 5960 4110 5905 6009 5300 5687 5960 5960 5901 5687 5939 2154 5961 2445 1030 5971 2786 2445 5961 814 5965 2786 5961 6030 6011 1360 6005 5989 6011 5997 6002 5949 5962 5912 5956 5727 6017 5962 5912 5989 6001 5979 5956 6017 5727 5962 5980 5914 5963 1276 5913 5989 6001 5949 5979 5964 2061 5914 5955 3313 5998 5963 1276 2061 6040 6024 6039 2061 5988 5955 5964 1276 5988 5964 5955 2072 6085 1277 6083 2061 5988 2059 5955 6000 5834 5950 5899 5914 5964 5955 1276 2445 5965 2786 1030 2445 5965 5961 2786 5966 5911 5293 5731 5928 5991 5930 5966 5927 5966 5928 5930 5293 5966 5731 5640 5640 5991 5045 5966 5966 5895 5929 5911 5640 5991 5731 5763 5911 5991 5895 5731 5865 5967 5874 5947 5989 6017 5949 5962 2061 6041 2059 6035 5947 5968 5933 5967 5969 5836 5874 5772 6093 6099 6098 6091 5962 5997 5989 5980 6041 1939 3139 6035 5933 6025 5921 5850 6025 6026 5987 6016 5985 6012 5987 6014 5981 5975 4433 5945 5930 6027 6008 5895 5874 6004 5836 5969 2445 5971 5924 5948 2154 5971 5924 2445 5989 6017 5962 5980 5921 5972 5968 5947 6012 6026 5987 6014 5983 5968 5967 5985 3257 2782 2494 1707 5972 5987 5983 5986 5194 5973 5195 4633 5945 5982 5973 5981 2445 5834 5896 5899 1842 2791 1034 1841 5945 5982 5981 5975 4433 5973 5902 3806 5784 5974 5808 5790 5974 5736 5808 5790 5826 5974 5790 5946 5102 5974 4113 4201 5195 5981 5973 5194 5875 5976 5901 5939 5716 5982 5825 5738 5982 5798 5825 5854 5730 5976 5901 2542 1877 6009 2839 2292 6009 5960 5687 5939 5518 6010 5457 3458 5686 6010 5457 5728 5545 5977 1354 5456 5226 6010 5545 6000 5685 5977 5457 5686 4366 6007 619 5480 5881 5977 1354 5951 4955 5989 2457 5949 5998 3159 3165 5963 5853 6017 5993 5860 6038 6022 6036 6034 6045 6050 2457 6036 5962 6017 5949 5912 5973 5982 2781 4118 5983 5947 5968 5972 5934 5983 5947 5969 5947 5983 5968 5967 5968 6025 4698 5987 5874 5983 5947 5967 5972 5987 5968 5983 6004 6053 6043 6012 5947 5984 5983 5934 6047 6058 6049 6057 5983 5984 5972 5986 5874 5985 5967 621 6063 6057 6061 6058 621 5985 5967 5968 5933 6025 4698 5968 5934 5990 5984 5983 5921 6025 5972 5984 5990 6032 6012 6031 5983 5987 5968 5985 5985 6053 621 5874 621 6042 6026 6044 5984 6025 5986 6013 6013 6025 5986 6016 6025 5933 5921 5968 6000 5977 5916 5950 5988 1939 2058 5955 2059 5988 2058 5955 6097 6112 6103 6108 5949 6003 2457 5853 5989 5970 5956 5979 6017 5989 5993 5980 6011 6036 6022 6002 5957 6006 5940 5994 4955 5989 5949 5979 5956 5989 5949 5962 5983 6013 5986 6012 6057 6063 6054 6058 6025 6049 6044 6033 6069 5836 6053 6043 6012 6032 6013 6016 6026 6012 5987 6016 6003 604 5993 6005 5763 5991 5731 5652 5991 5928 5046 5045 5928 5991 5966 5045 5895 6019 5930 5952 5991 5640 5731 5966 5949 6003 5993 5989 2061 5999 5998 6023 6011 5727 5993 5980 5989 6011 5993 5980 5989 6017 5993 5949 5989 6005 6002 6003 5908 5994 5957 5940 3848 1786 2405 5218 5978 6021 5995 6007 3844 4147 2697 3541 6021 5263 5430 5041 5633 6020 5550 5996 1276 6075 6074 6066 6018 6036 6002 6022 5964 5998 1276 5963 5727 6011 5993 6005 5970 6002 5979 5989 2061 6040 6039 6051 2061 5964 5963 5998 5071 6050 2457 5341 5999 2061 5964 5988 3313 6023 5998 1276 6040 2061 6024 6035 2061 6015 5988 5999 1276 6015 5999 5988 1276 6035 6024 6015 2061 6015 2059 5988 6015 1939 2058 5988 5964 5999 5988 1276 5686 6000 5892 5896 5545 6000 5524 5226 5916 6000 5950 5899 5990 6037 6032 6031 5892 6010 5226 6000 5834 6000 5896 5899 2446 6000 5524 5899 5759 6000 5896 5834 5989 6001 5956 5949 4955 6001 5949 3263 4955 6001 5979 5949 5409 4169 3146 3565 5788 6001 3263 5949 5970 6029 6002 6018 6018 6002 5970 5997 2819 6005 604 6003 5989 6029 5979 4955 5970 6002 5989 5997 5895 6028 5938 3378 6011 5989 5997 5980 5993 5853 604 6003 5934 6004 5990 5983 5341 6050 2457 6045 6088 6095 6082 6081 5853 2457 604 6003 5949 6003 5989 2457 2819 6003 604 2457 6002 6003 2457 5989 6003 5949 5993 5853 5983 6013 5990 5984 5989 6005 6003 5993 5836 6053 5874 1699 5997 6022 6011 1360 6043 5836 5874 6004 6011 6036 6005 6030 6011 5727 5980 5997 2061 6080 6079 6084 5930 6027 5895 5952 3934 5090 5942 5298 6007 5550 5978 5480 5927 5895 5930 6008 5958 6007 5940 6006 5922 3242 3230 3419 5550 6007 6006 5940 5958 6021 5957 1305 5941 6007 4366 5480 6021 5978 5995 5879 6021 5995 5994 5879 5995 6007 6006 5550 5958 6021 6007 6006 5903 6008 5895 5927 1877 6009 2869 2839 2839 2869 5819 6009 5937 6009 5939 5819 5937 6009 5976 5939 5457 6010 2800 5728 5545 6010 5977 6000 6010 5686 5457 5977 6010 5457 1354 5977 1354 6010 5977 5545 5727 6011 1360 5997 6031 6048 6037 6032 6013 5983 5986 5984 5999 6023 1276 5998 2061 6024 6023 6039 5727 6011 6005 1360 2782 4815 2494 1284 5989 6011 6002 5993 5987 6012 5983 5986 5983 6013 6012 5990 621 6014 5985 5987 5985 6012 5983 5987 6038 6034 6036 6050 6012 6053 6043 6031 6050 4852 4740 4593 3006 6084 2084 6079 6031 6044 6026 6042 6026 6097 6025 4698 5341 6050 6045 6038 6014 6053 6042 621 3313 6051 3006 6039 6015 1276 1939 5988 6024 5999 2061 6023 2059 6015 2058 5988 6101 6096 6098 6099 5986 6016 5987 6012 6016 6033 6031 6032 5860 6017 5727 5887 5997 6022 6002 6011 5817 1349 5885 71 5731 6028 3378 5702 5731 6019 5991 5895 4769 5218 1786 2750 5940 6020 5996 5550 2058 6056 3139 6041 2405 3848 2698 2108 5643 6021 5994 5879 5957 6021 6006 5994 3541 5666 2697 3844 5958 6021 6006 5957 3313 6059 6051 1276 2061 6060 6059 6065 1977 6089 2061 3040 2061 6035 6015 6024 6015 6024 1276 5999 1276 6041 6040 6035 2061 6035 2059 6015 2058 6035 3139 6015 1276 6024 6023 5999 5986 6025 5987 6016 5792 6025 4698 5933 621 6014 5987 6026 6081 5836 6053 6069 6013 6032 6025 6016 6025 5972 5984 5986 6071 6095 6081 6082 4698 6025 5850 5893 6098 6093 6090 6092 5895 6028 5731 6019 5895 6027 5992 5938 5731 6028 5702 6019 5895 6028 3378 5731 5983 6053 5985 5874 6022 6038 6036 6030 6002 6045 4955 2457 6050 4740 5071 4593 6003 6036 6002 2457 4740 6046 1360 4852 4852 6046 2456 2819 2457 6030 2819 6003 4740 6046 6038 1360 6022 6038 6030 1360 6026 6031 6012 6016 6062 6044 6061 6057 6014 6031 6012 6026 6050 6045 6038 6034 6012 6032 6016 6031 6089 3159 2061 1178 5985 6053 6012 6014 6012 6043 6037 6031 6002 6045 6036 6029 6012 6037 5990 6031 6032 5990 6012 6013 6033 6016 6025 6032 4740 6050 6038 6046 6061 6044 6025 6049 6033 6049 6047 6048 6033 6049 6044 6047 1276 6056 6041 2072 6005 6036 6002 6003 6045 6002 4955 6029 2061 6068 6064 6066 6003 6036 2457 6030 2457 6045 4955 5341 1939 6035 6015 3139 2059 6035 2058 6015 6005 6036 6003 6030 4852 6050 6046 2819 6018 6045 6036 6034 4852 6050 2819 4593 6011 6036 6002 6005 6052 6060 2061 6056 6031 6048 6033 6047 6044 6070 6062 6061 3165 6051 2084 3159 6057 6069 6062 6053 1360 6046 6038 6030 4698 6112 6097 4213 6057 6069 6067 6062 6043 6012 5990 6004 1939 6083 2072 6068 2782 4815 4324 2494 2494 1284 2150 1706 4852 6046 1360 2456 6048 6054 6047 6037 6030 6046 2457 2819 6074 3313 1276 6065 3159 6065 2061 6059 6024 6039 1276 6023 6044 6031 6026 6033 6051 3006 3165 2084 5983 6053 6012 5985 3165 6039 3159 6023 3313 6059 3006 6051 1276 6052 6051 6040 6035 6040 1276 6024 1276 6056 6052 6041 2061 6041 6035 6040 6052 6040 2061 6051 1276 6040 6039 6024 6040 6052 2061 6041 2058 6041 3139 6035 6056 1939 3139 6041 2061 6056 6041 6052 6032 6048 6025 6033 621 6042 6014 6026 6031 6053 6043 6047 6105 6098 6100 6095 6002 6045 2457 6036 6058 6063 6025 6061 6088 6096 6090 6094 6053 6031 6014 6042 6062 6093 6092 6071 6046 6030 2457 6036 5071 6050 5341 6038 4324 1284 3876 4076 2782 4815 1284 4324 2819 2456 6030 6046 6046 6050 6038 6036 6048 6031 6033 6032 1360 6046 6030 2456 6036 6046 6030 6038 2819 6050 6046 2457 6042 6047 6031 6044 6044 6057 6047 6049 6044 6047 6031 6033 6031 6048 6047 6037 6081 6082 6078 6071 2084 6089 1181 1178 6047 6069 6053 6043 6053 6031 6042 6047 6025 6049 6033 6048 6025 6061 6049 6058 6045 6050 6036 6034 6081 6110 6071 6053 6046 6050 6036 2457 6057 6063 6061 6062 4593 6050 2457 5071 2819 6050 2457 4593 6062 6072 6067 6063 3159 6079 2061 6074 2999 6089 6085 2061 3159 6074 2061 6065 6040 6051 1276 6039 2058 6064 3139 6056 6065 3313 1276 6059 2999 6083 2072 1938 3165 6051 3159 6039 3006 6059 2084 6051 6041 6052 1276 6040 1276 6064 6060 6056 2061 6056 2059 6041 6060 6052 2061 6059 621 6055 6042 6044 6110 6102 6109 6107 5874 6053 621 1699 6057 6044 6047 6055 6104 6113 6107 6111 6057 6053 6055 6047 6053 6062 6057 6055 6004 6053 5874 6043 5836 6081 6053 1699 6071 6110 6092 6053 6081 6062 6073 6069 6042 6055 6047 6044 6054 6069 6047 6043 6093 6062 6070 6071 6110 6095 6071 6082 6069 6054 6047 6057 6063 6097 6070 6072 6088 6090 6087 6082 6055 621 6042 6053 6042 6055 6053 6047 2061 6052 6051 6059 6048 6058 6025 6049 3313 6089 3006 6084 2059 6056 2058 6041 1939 6056 2072 6041 6068 1939 3139 6064 2061 6064 6056 6060 6062 6072 6070 6071 6054 6069 6067 6057 6047 6058 6048 6049 6110 6120 3287 2594 1277 6083 1276 2072 6076 6097 6093 6086 6044 6061 6057 6049 2999 6089 2061 1982 6084 3313 1276 6079 3313 6065 3006 6059 6052 6059 1276 6051 2058 6068 3139 6064 3006 6065 2084 6059 3313 6079 6074 1276 1276 6060 6059 6052 6060 6066 2061 6064 6056 6060 1276 6052 1276 6068 6066 6064 2061 6064 2059 6056 6066 6060 2061 6065 6049 6057 6058 6061 6095 6098 6094 6090 6061 6097 6025 6044 6078 6082 6077 6071 6097 6061 6063 6070 1939 6083 3139 1938 3287 6121 6120 6110 6078 6088 6087 6082 6044 6097 4698 6093 2061 6066 6065 6074 6057 6067 6063 6062 6062 6093 6055 6092 1276 6089 1277 3040 6075 6083 6068 1276 6061 6097 6063 6025 6087 6086 6082 6090 2059 6064 2058 6056 6064 2072 1939 6056 1939 6064 6056 3139 3006 6074 2084 6065 6089 1181 1178 3040 3159 6079 6074 2084 6060 6065 1276 6059 3313 6079 3006 6074 3159 6065 6059 2084 1276 6066 6065 6060 6066 6075 2061 6068 6064 6066 1276 6060 6083 6075 2061 6080 2061 6068 2059 6064 6075 6066 2061 6074 6090 6087 6086 6091 6067 6057 6063 6054 6072 6097 6076 6077 6105 6100 6102 6104 1276 6068 6064 2072 2999 6083 1938 3139 2059 6068 2058 6064 1939 6068 2072 6064 6083 1939 3139 6068 6062 6081 6071 6053 6047 6069 6057 6053 6062 6063 6061 6070 6071 6077 6072 6076 3139 6085 2999 6083 6112 6118 6109 6114 6093 6062 6055 6044 6062 6073 6072 6071 6072 6062 6070 6063 6093 6071 6070 6076 6090 6093 6091 6086 6062 6081 6073 6071 6062 6092 6053 6071 6062 6093 6070 6044 6093 6082 6090 6092 6077 6071 6072 6073 6073 6062 6072 6067 6077 6087 6082 6078 2061 6085 6084 6089 2072 6085 2999 1277 6062 6073 6069 6067 6112 6115 6114 6108 1181 6089 1627 3040 3159 6089 2061 6084 6066 6074 1276 6065 2999 6089 1982 6085 3313 6084 3006 6079 3159 6074 6065 2084 3006 6079 2084 6074 6068 6075 1276 6066 6075 6083 1276 6080 2061 6083 2059 6068 1276 6085 6084 6080 6088 6096 6087 6090 6071 6072 6070 6076 2059 6085 6083 2061 6077 6097 6086 6087 2061 6075 6074 6079 6120 1699 1687 2594 6110 6112 6109 621 6090 6096 6087 6091 6123 6097 6112 4213 6096 6091 6090 6098 6077 6071 6073 6078 4277 6112 621 3863 6105 6107 6104 6102 6087 6077 6082 6086 3493 6097 4213 1748 6071 6081 6073 6078 6077 6076 6071 6082 1276 6080 6079 6075 1627 6089 1276 3040 3159 6089 6084 2084 6075 6079 1276 6074 3139 6085 6083 2058 3313 6089 6084 1276 1982 6085 1277 2999 6075 6083 2061 6068 6080 6085 2061 6083 2059 6083 2058 6068 2061 6080 6075 6079 6085 6080 2061 6084 6062 6081 6053 6069 2058 6083 3139 6068 1276 6083 6068 2072 6070 6097 6044 6093 6093 6071 6076 6082 6071 6110 6082 6092 6099 6093 6097 6091 3159 6089 2084 1178 6080 6084 1276 6079 6089 1982 1277 1977 6089 3313 3006 1627 6085 6083 1276 1277 3159 6084 6079 2084 3006 6089 2084 6084 6083 6085 1276 6080 2072 6085 6083 2999 2058 6085 6083 2059 1982 6089 1277 6085 6093 6102 6098 6099 6110 6095 6082 6090 6082 6077 6076 6086 6102 6106 6100 6101 6070 6097 6093 6076 4622 6112 621 4277 6098 6096 6091 6099 6099 6112 6097 6093 4086 6123 4277 4341 4622 6123 4086 6121 6082 6093 6086 6076 6078 6088 6082 6081 6094 6101 6098 6100 6095 6088 6090 6094 6114 6120 6110 6105 6102 6112 6093 6109 6110 6112 4277 6109 1178 6089 3040 2061 6089 6085 1276 1277 6089 1977 1277 3040 3006 6089 1627 1181 6085 6089 1276 6084 1982 6089 2061 1977 6089 3006 2084 1181 3313 6089 1276 1627 6097 6086 6087 6091 6118 6124 6121 6120 6097 6076 6077 6086 6102 6101 6099 6103 6081 6110 6053 6095 6095 6110 6098 6090 6053 6092 6055 621 6055 6093 621 6092 6093 6098 6090 6091 6092 6062 6053 6055 6055 6093 6044 621 6061 6097 6044 6070 6082 6093 6090 6086 6107 6114 6112 6109 6071 6093 6092 6082 6095 6088 6082 6090 6106 6102 6100 6104 6110 4622 2594 3287 6094 6100 6098 6095 6098 6110 6105 6102 6081 6110 6095 6071 6082 6110 6090 6092 6095 5836 1699 6081 6086 6097 6093 6091 6098 6105 6100 6102 6097 6099 6091 6096 6097 6091 6087 6096 6094 6098 6096 6090 4213 3738 1748 6097 6097 4698 5893 6025 6026 6097 4698 6044 6110 6095 1699 6053 6026 6097 6044 6025 6070 6097 6076 6072 6109 6098 6093 6102 1699 621 4622 6110 6120 6114 6117 6105 4622 6112 4277 6110 6098 6109 6093 6092 6100 6102 6101 6098 6110 6095 6098 6105 6094 6101 6096 6098 6104 6113 6106 6107 5836 6120 1699 1687 6116 6114 6111 6117 6096 6101 6097 6099 6106 6101 6102 6103 6097 6103 6099 6101 6101 6099 6098 6102 6103 6112 6102 6107 6116 6115 6114 6118 6107 6106 6103 6108 6098 6110 6102 6109 6110 6121 6120 6118 6102 6110 6105 6107 6122 6118 6119 6116 6112 6099 6097 6103 6114 6113 6108 6115 6112 6119 6118 6115 6095 6110 1699 6105 6125 6122 6121 6123 3517 4176 5926 2638 6104 6111 6107 6105 6105 6120 6110 1699 6110 6090 6092 6098 6112 6118 6114 6115 6124 4622 3287 2600 6092 6110 6098 6109 6101 6106 6097 6103 6113 6106 6107 6108 6099 6112 6093 6102 6106 6103 6102 6107 6104 6107 6106 6102 6097 6119 6115 6116 4277 6123 6121 3863 4622 6110 2594 1699 6097 6108 6103 6106 6113 6116 6097 6115 6114 6111 6107 6113 6105 6114 6111 6107 6110 6092 621 6109 6107 6114 6109 6110 621 6109 6092 6093 6053 6110 621 1699 2600 6124 4622 4086 6112 4698 6097 6093 6117 6118 6116 6114 6118 6122 6119 6121 6105 6114 6107 6110 3287 6121 6110 4622 6116 6114 6113 6111 6103 6112 6107 6108 6115 6112 6097 6108 4622 6112 6110 621 6099 6112 6102 6103 6102 6112 6109 6107 6106 6113 6097 6108 2614 1713 865 3957 6114 6107 6112 6108 6112 6121 6109 6118 6114 6116 6113 6115 6107 6114 6113 6108 6097 6123 6112 6119 6118 6124 6117 6121 6118 6116 6115 6119 3517 4176 4835 5926 6097 6115 6108 6113 6122 6125 6097 6123 4277 6123 3863 4341 6121 6112 6109 4277 6123 3493 2962 6125 4086 6125 6123 2962 6122 6125 6121 6124 6114 6120 6118 6110 4622 6124 6121 4086 6114 6117 6105 6111 6109 6121 6110 6118 6114 6120 6117 6118 3287 6124 6120 6121 4622 6124 3287 6121 6097 6122 6119 6116 6121 6112 4277 3863 6109 6118 6110 6114 6119 6121 6112 6118 6097 6119 6112 6115 6110 6121 4277 4622 5926 4176 4835 2878 6110 6120 2594 1699 5836 6120 6105 1699 6118 6122 6121 6117 4341 6123 3493 2962 6112 6123 6121 6119 6118 6122 6117 6116 6123 6097 4213 3493 4176 5926 3229 2878 4086 6123 4341 2962 6117 6124 6122 6121 6122 6123 6119 6121 3863 6123 3493 4341 4622 6123 4277 4086 4213 6123 3493 6112 6097 6123 6119 6122 4622 6123 6121 4277 6097 6125 3493 6123 6121 6125 4086 6124 2600 6124 4086 2962 4086 6125 2962 6124 6118 6124 6120 6117 6121 6125 6123 4086 230 227 238 405 405 227 238 235 5943 5930 3112 6008 5824 5689 2615 5888 1715 5067 3510 2144 3957 3655 5228 2614 5714 5689 2615 5824 2615 5398 2366 5689 5849 5928 5943 5903 3247 5067 4950 3510 1715 5067 3247 3510 2144 4950 5067 4009 4330 4950 4009 5201 1715 3510 1716 2144 3247 5067 2144 4950 5684 5917 5360 3713 1715 5067 2144 3247 5727 4682 5962 5997 2147 1288 1287 5342 1288 2147 1287 4951 5859 5917 3713 5922 5922 2128 5917 3724 5780 5917 3713 5859 1791 3801 1792 5943 4177 5360 3713 4482 5997 1360 5727 1860 1791 2097 5943 1792 5684 5917 3713 5780 5839 1305 1753 5748 2973 6021 5041 5263 4138 1325 1789 3178 3164 5727 3707 3584 5727 4682 5609 5756 1360 1860 2822 3114 5727 4682 5343 5609 5997 1360 1860 6022 4740 1360 1860 2822 4682 5727 1860 5997 3796 3582 1858 3707 #simplex BoundaryDomain default 1 # dune-grid-2.11.0/doc/grids/dgf/simplex-testgrid-3-3.dgf000066400000000000000000000171671511655130300223700ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX 2.0000000000000001e-01 -9.9999999999999989e-01 1.0000000000000000e+01 1.2000000000000000e+00 -9.9999999999999944e-01 1.0000000000000000e+01 -8.5725275940314732e-17 -8.0000000000000004e-01 8.7500000000000000e+00 -5.1435165564188829e-16 1.9999999999999996e-01 8.7500000000000000e+00 -2.0000000000000001e-01 -1.0000000000000000e+00 7.5000000000000000e+00 -1.2000000000000000e+00 -1.0000000000000004e+00 7.5000000000000000e+00 6.1232339957367660e-17 -1.2000000000000000e+00 6.2500000000000000e+00 3.6739403974420599e-16 -2.2000000000000002e+00 6.2500000000000000e+00 2.0000000000000001e-01 -1.0000000000000000e+00 5.0000000000000000e+00 1.2000000000000000e+00 -9.9999999999999967e-01 5.0000000000000000e+00 2.0000000000000001e-01 -9.9999999999999989e-01 1.1000000000000000e+01 1.2000000000000000e+00 -9.9999999999999944e-01 1.1000000000000000e+01 -8.5725275940314732e-17 -8.0000000000000004e-01 9.7500000000000000e+00 -5.1435165564188829e-16 1.9999999999999996e-01 9.7500000000000000e+00 -2.0000000000000001e-01 -1.0000000000000000e+00 8.5000000000000000e+00 -1.2000000000000000e+00 -1.0000000000000004e+00 8.5000000000000000e+00 6.1232339957367660e-17 -1.2000000000000000e+00 7.2500000000000000e+00 3.6739403974420599e-16 -2.2000000000000002e+00 7.2500000000000000e+00 2.0000000000000001e-01 -1.0000000000000000e+00 6.0000000000000000e+00 1.2000000000000000e+00 -9.9999999999999967e-01 6.0000000000000000e+00 6.9999999999999996e-01 -9.9999999999999967e-01 1.0000000000000000e+01 8.4852813742385591e-01 -1.5147186257614187e-01 9.3750000000000000e+00 -3.0003846579110149e-16 -3.0000000000000004e-01 8.7500000000000000e+00 1.4142135623730931e-01 -8.5857864376269033e-01 9.3750000000000000e+00 4.9497474683058257e-01 -5.0502525316941616e-01 9.3750000000000000e+00 6.9999999999999996e-01 -9.9999999999999967e-01 1.1000000000000000e+01 8.4852813742385591e-01 -1.5147186257614187e-01 1.0375000000000000e+01 -3.0003846579110149e-16 -3.0000000000000004e-01 9.7500000000000000e+00 1.4142135623730931e-01 -8.5857864376269033e-01 1.0375000000000000e+01 4.9497474683058257e-01 -5.0502525316941616e-01 1.0375000000000000e+01 1.2000000000000000e+00 -9.9999999999999944e-01 1.0500000000000000e+01 2.0000000000000001e-01 -9.9999999999999989e-01 1.0500000000000000e+01 6.9999999999999996e-01 -9.9999999999999967e-01 1.0500000000000000e+01 -5.1435165564188829e-16 1.9999999999999996e-01 9.2500000000000000e+00 8.4852813742385591e-01 -1.5147186257614187e-01 9.8750000000000000e+00 -8.5725275940314732e-17 -8.0000000000000004e-01 9.2500000000000000e+00 -3.0003846579110149e-16 -3.0000000000000004e-01 9.2500000000000000e+00 1.4142135623730931e-01 -8.5857864376269033e-01 9.8750000000000000e+00 4.9497474683058257e-01 -5.0502525316941616e-01 9.8750000000000000e+00 -8.4852813742385658e-01 -1.5147186257614254e-01 8.1250000000000000e+00 -6.9999999999999996e-01 -1.0000000000000002e+00 7.5000000000000000e+00 -1.4142135623730942e-01 -8.5857864376269044e-01 8.1250000000000000e+00 -4.9497474683058296e-01 -5.0502525316941649e-01 8.1250000000000000e+00 -8.4852813742385658e-01 -1.5147186257614254e-01 9.1250000000000000e+00 -6.9999999999999996e-01 -1.0000000000000002e+00 8.5000000000000000e+00 -1.4142135623730942e-01 -8.5857864376269044e-01 9.1250000000000000e+00 -4.9497474683058296e-01 -5.0502525316941649e-01 9.1250000000000000e+00 -1.2000000000000000e+00 -1.0000000000000004e+00 8.0000000000000000e+00 -8.4852813742385658e-01 -1.5147186257614254e-01 8.6250000000000000e+00 -2.0000000000000001e-01 -1.0000000000000000e+00 8.0000000000000000e+00 -6.9999999999999996e-01 -1.0000000000000002e+00 8.0000000000000000e+00 -1.4142135623730942e-01 -8.5857864376269044e-01 8.6250000000000000e+00 -4.9497474683058296e-01 -5.0502525316941649e-01 8.6250000000000000e+00 -8.4852813742385602e-01 -1.8485281374238580e+00 6.8750000000000000e+00 2.1431318985078681e-16 -1.7000000000000000e+00 6.2500000000000000e+00 -1.4142135623730934e-01 -1.1414213562373097e+00 6.8750000000000000e+00 -4.9497474683058262e-01 -1.4949747468305838e+00 6.8750000000000000e+00 -8.4852813742385602e-01 -1.8485281374238580e+00 7.8750000000000000e+00 2.1431318985078681e-16 -1.7000000000000000e+00 7.2500000000000000e+00 -1.4142135623730934e-01 -1.1414213562373097e+00 7.8750000000000000e+00 -4.9497474683058262e-01 -1.4949747468305838e+00 7.8750000000000000e+00 3.6739403974420599e-16 -2.2000000000000002e+00 6.7500000000000000e+00 -8.4852813742385602e-01 -1.8485281374238580e+00 7.3750000000000000e+00 6.1232339957367660e-17 -1.2000000000000000e+00 6.7500000000000000e+00 2.1431318985078681e-16 -1.7000000000000000e+00 6.7500000000000000e+00 -1.4142135623730934e-01 -1.1414213562373097e+00 7.3750000000000000e+00 -4.9497474683058262e-01 -1.4949747468305838e+00 7.3750000000000000e+00 8.4852813742385724e-01 -1.8485281374238567e+00 5.6250000000000000e+00 6.9999999999999996e-01 -9.9999999999999978e-01 5.0000000000000000e+00 1.4142135623730953e-01 -1.1414213562373094e+00 5.6250000000000000e+00 4.9497474683058335e-01 -1.4949747468305832e+00 5.6250000000000000e+00 8.4852813742385724e-01 -1.8485281374238567e+00 6.6250000000000000e+00 6.9999999999999996e-01 -9.9999999999999978e-01 6.0000000000000000e+00 1.4142135623730953e-01 -1.1414213562373094e+00 6.6250000000000000e+00 4.9497474683058335e-01 -1.4949747468305832e+00 6.6250000000000000e+00 1.2000000000000000e+00 -9.9999999999999967e-01 5.5000000000000000e+00 8.4852813742385724e-01 -1.8485281374238567e+00 6.1250000000000000e+00 2.0000000000000001e-01 -1.0000000000000000e+00 5.5000000000000000e+00 6.9999999999999996e-01 -9.9999999999999978e-01 5.5000000000000000e+00 1.4142135623730953e-01 -1.1414213562373094e+00 6.1250000000000000e+00 4.9497474683058335e-01 -1.4949747468305832e+00 6.1250000000000000e+00 # SIMPLEX # CUBE 0 20 23 24 31 32 37 38 20 1 24 21 32 30 38 34 24 21 22 3 38 34 36 33 23 24 2 22 37 38 35 36 31 32 37 38 10 25 28 29 32 30 38 34 25 11 29 26 38 34 36 33 29 26 27 13 37 38 35 36 28 29 12 27 2 22 41 42 35 36 51 52 22 3 42 39 36 33 52 48 42 39 40 5 52 48 50 47 41 42 4 40 51 52 49 50 35 36 51 52 12 27 45 46 36 33 52 48 27 13 46 43 52 48 50 47 46 43 44 15 51 52 49 50 45 46 14 44 4 40 55 56 49 50 65 66 40 5 56 53 50 47 66 62 56 53 54 7 66 62 64 61 55 56 6 54 65 66 63 64 49 50 65 66 14 44 59 60 50 47 66 62 44 15 60 57 66 62 64 61 60 57 58 17 65 66 63 64 59 60 16 58 6 54 69 70 63 64 79 80 54 7 70 67 64 61 80 76 70 67 68 9 80 76 78 75 69 70 8 68 79 80 77 78 63 64 79 80 16 58 73 74 64 61 80 76 58 17 74 71 80 76 78 75 74 71 72 19 79 80 77 78 73 74 18 72 # BOUNDARYSEGMENTS 1 0 23 31 37 1 0 20 31 32 1 0 20 23 24 1 1 21 30 34 1 20 1 32 30 1 20 1 24 21 1 21 3 34 33 1 24 21 22 3 1 23 2 37 35 1 23 24 2 22 1 31 37 10 28 1 31 32 10 25 1 10 25 28 29 1 30 34 11 26 1 32 30 25 11 1 25 11 29 26 1 34 33 26 13 1 29 26 27 13 1 37 35 28 12 1 28 29 12 27 1 2 41 35 51 1 2 22 41 42 1 3 39 33 48 1 22 3 42 39 1 39 5 48 47 1 42 39 40 5 1 41 4 51 49 1 41 42 4 40 1 35 51 12 45 1 12 27 45 46 1 33 48 13 43 1 27 13 46 43 1 48 47 43 15 1 46 43 44 15 1 51 49 45 14 1 45 46 14 44 1 4 55 49 65 1 4 40 55 56 1 5 53 47 62 1 40 5 56 53 1 53 7 62 61 1 56 53 54 7 1 55 6 65 63 1 55 56 6 54 1 49 65 14 59 1 14 44 59 60 1 47 62 15 57 1 44 15 60 57 1 62 61 57 17 1 60 57 58 17 1 65 63 59 16 1 59 60 16 58 1 6 69 63 79 1 6 54 69 70 1 7 67 61 76 1 54 7 70 67 1 67 9 76 75 1 68 9 78 75 1 70 67 68 9 1 69 8 79 77 1 8 68 77 78 1 69 70 8 68 1 63 79 16 73 1 16 58 73 74 1 61 76 17 71 1 58 17 74 71 1 76 75 71 19 1 78 75 72 19 1 74 71 72 19 1 79 77 73 18 1 77 78 18 72 1 73 74 18 72 # # dune-grid-2.11.0/doc/grids/dgf/test1d-vertex.dgf000066400000000000000000000004161511655130300212700ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX dimension 1 0.0 0.25 0.5 0.6 0.7 0.8 0.9 1.0 # CUBE 0 1 1 2 2 3 3 4 4 5 5 6 6 7 # # dune-grid-2.11.0/doc/grids/dgf/test1d.dgf000066400000000000000000000003021511655130300177470ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INTERVAL 0 1 5 # dune-grid-2.11.0/doc/grids/dgf/test2d.dgf000066400000000000000000000003111511655130300177500ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INTERVAL 0 0 1 1 4 5 # dune-grid-2.11.0/doc/grids/dgf/test2d_offset.dgf000066400000000000000000000003231511655130300213210ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INTERVAL 0.5 -0.5 1 1 3 7 # dune-grid-2.11.0/doc/grids/dgf/test2ug.dgf000066400000000000000000000021431511655130300201450ustar00rootroot00000000000000% SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception DGF VERTEX firstindex 1 0.0000000000 0.0000000000 0.2500000000 0.0000000000 0.5000000000 0.0000000000 0.7500000000 0.0000000000 1.0000000000 0.0000000000 0.0000000000 0.2500000000 0.2500000000 0.2500000000 0.5000000000 0.2500000000 0.7500000000 0.2500000000 1.0000000000 0.2500000000 0.0000000000 0.5000000000 0.2500000000 0.5000000000 0.5000000000 0.5000000000 0.7500000000 0.5000000000 1.0000000000 0.5000000000 0.0000000000 0.7500000000 0.2500000000 0.7500000000 0.5000000000 0.7500000000 0.7500000000 0.7500000000 1.0000000000 0.7500000000 0.0000000000 1.0000000000 0.2500000000 1.0000000000 0.5000000000 1.0000000000 0.7500000000 1.0000000000 1.0000000000 1.0000000000 # CUBE map 0 1 3 2 4 5 7 6 1 2 7 6 2 3 8 7 3 4 9 8 4 5 10 9 6 7 12 11 7 8 13 12 8 9 14 13 9 10 15 14 11 12 17 16 12 13 18 17 13 14 19 18 14 15 20 19 16 17 22 21 17 18 23 22 18 19 24 23 19 20 25 24 # BOUNDARYDOMAIN default 1 # dune-grid-2.11.0/doc/grids/dgf/test3d.dgf000066400000000000000000000003161511655130300177560ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception INTERVAL 0 0 0 1 1 1 4 4 5 # dune-grid-2.11.0/doc/grids/dgf/torus-2.dgf000066400000000000000000000004571511655130300200710ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 1 1 3 3 # PeriodicFaceTransformation 1 0, 0 1 + 1 0 1 0, 0 1 + 0 1 # GridParameter refinementedge arbitrary # dune-grid-2.11.0/doc/grids/dgf/torus-3.dgf000066400000000000000000000006171511655130300200700ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Interval 0 0 0 1 1 1 2 2 2 # PeriodicFaceTransformation 1 0 0, 0 1 0, 0 0 1 + 1 0 0 1 0 0, 0 1 0, 0 0 1 + 0 1 0 1 0 0, 0 1 0, 0 0 1 + 0 0 1 # BoundaryDomain default 1 # GridParameter refinementedge arbitrary # dune-grid-2.11.0/doc/grids/dgf/unstr_cube.dgf000066400000000000000000000101161511655130300207200ustar00rootroot00000000000000DGF % SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root % SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception VERTEX firstindex 1 0 0 0.0909 0 0.1818 0 0.2727 0 0.3636 0 0.4545 0 0.5455 0 0.6364 0 0.7273 0 0.8182 0 0.9091 0 1 0 -0.0017 0.003 0.0853 0.0032 0.1854 0.003 0.2755 0.0025 0.3757 0.0033 0.4456 0.0035 0.5291 0.0033 0.6254 0.0026 0.7358 0.0035 0.8225 0.0034 0.8963 0.0029 0.9983 0.003 -0.0035 0.0061 0.0956 0.0063 0.1934 0.0059 0.2542 0.0059 0.3777 0.006 0.4452 0.0062 0.5298 0.006 0.6433 0.0062 0.7321 0.0059 0.7966 0.0055 0.9164 0.0062 0.9965 0.0061 -0.0052 0.0091 0.1004 0.0096 0.1877 0.0089 0.2605 0.0092 0.3688 0.0087 0.4637 0.0092 0.5427 0.0092 0.6176 0.0088 0.7149 0.0091 0.8217 0.0094 0.912 0.0086 0.9948 0.0091 -0.007 0.0121 0.0888 0.0117 0.1823 0.0127 0.2834 0.012 0.372 0.0127 0.442 0.0121 0.541 0.0123 0.6448 0.0127 0.7369 0.0117 0.7985 0.0115 0.9142 0.0122 0.993 0.0121 -0.0087 0.0152 0.0812 0.0157 0.1798 0.0157 0.2559 0.0157 0.3726 0.0148 0.4455 0.0146 0.5384 0.0157 0.6271 0.0153 0.7141 0.0148 0.8001 0.0148 0.9119 0.0149 0.9913 0.0152 -0.0105 0.0182 0.0905 0.0184 0.1609 0.0179 0.2646 0.0177 0.3642 0.0179 0.4306 0.0183 0.55 0.0181 0.6365 0.0183 0.715 0.0185 0.8223 0.0181 0.9118 0.0182 0.9895 0.0182 -0.0122 0.0212 0.0614 0.0208 0.1842 0.0214 0.2596 0.0212 0.3373 0.021 0.4268 0.0211 0.523 0.0212 0.6137 0.0211 0.7149 0.0218 0.82 0.0207 0.9072 0.0206 0.9878 0.0212 -0.014 0.0242 0.0842 0.0238 0.1749 0.0238 0.2539 0.0248 0.3356 0.0246 0.4372 0.0245 0.5319 0.0237 0.6121 0.0242 0.7178 0.0245 0.8216 0.0246 0.9083 0.0242 0.986 0.0242 -0.0157 0.0273 0.0932 0.0271 0.1721 0.0271 0.2628 0.027 0.3443 0.0279 0.4566 0.0267 0.5267 0.0275 0.6142 0.0273 0.7119 0.0268 0.7938 0.0271 0.9031 0.0276 0.9843 0.0273 -0.0175 0.0303 0.0586 0.0298 0.1492 0.0303 0.2498 0.0308 0.3432 0.0305 0.425 0.0298 0.5232 0.0302 0.6157 0.0304 0.7249 0.0303 0.8086 0.0308 0.8908 0.0305 0.9825 0.0303 -0.0192 0.0333 0.0717 0.0333 0.1626 0.0333 0.2535 0.0333 0.3444 0.0333 0.4353 0.0333 0.5262 0.0333 0.6171 0.0333 0.708 0.0333 0.7989 0.0333 0.8898 0.0333 0.9808 0.0333 # CUBE map 0 1 3 2 parameters 1 13 1 2 14 1 14 2 3 15 2 15 3 4 16 3 16 4 5 17 4 17 5 6 18 5 18 6 7 19 6 19 7 8 20 7 20 8 9 21 8 21 9 10 22 9 22 10 11 23 10 23 11 12 24 11 25 13 14 26 12 26 14 15 27 13 27 15 16 28 14 28 16 17 29 15 29 17 18 30 16 30 18 19 31 17 31 19 20 32 18 32 20 21 33 19 33 21 22 34 20 34 22 23 35 21 35 23 24 36 22 37 25 26 38 23 38 26 27 39 24 39 27 28 40 25 40 28 29 41 26 41 29 30 42 27 42 30 31 43 28 43 31 32 44 29 44 32 33 45 30 45 33 34 46 31 46 34 35 47 32 47 35 36 48 33 49 37 38 50 34 50 38 39 51 35 51 39 40 52 36 52 40 41 53 37 53 41 42 54 38 54 42 43 55 39 55 43 44 56 40 56 44 45 57 41 57 45 46 58 42 58 46 47 59 43 59 47 48 60 44 61 49 50 62 45 62 50 51 63 46 63 51 52 64 47 64 52 53 65 48 65 53 54 66 49 66 54 55 67 50 67 55 56 68 51 68 56 57 69 52 69 57 58 70 53 70 58 59 71 54 71 59 60 72 55 73 61 62 74 56 74 62 63 75 57 75 63 64 76 58 76 64 65 77 59 77 65 66 78 60 78 66 67 79 61 79 67 68 80 62 80 68 69 81 63 81 69 70 82 64 82 70 71 83 65 83 71 72 84 66 85 73 74 86 67 86 74 75 87 68 87 75 76 88 69 88 76 77 89 70 89 77 78 90 71 90 78 79 91 72 91 79 80 92 73 92 80 81 93 74 93 81 82 94 75 94 82 83 95 76 95 83 84 96 77 97 85 86 98 78 98 86 87 99 79 99 87 88 100 80 100 88 89 101 81 101 89 90 102 82 102 90 91 103 83 103 91 92 104 84 104 92 93 105 85 105 93 94 106 86 106 94 95 107 87 107 95 96 108 88 109 97 98 110 89 110 98 99 111 90 111 99 100 112 91 112 100 101 113 92 113 101 102 114 93 114 102 103 115 94 115 103 104 116 95 116 104 105 117 96 117 105 106 118 97 118 106 107 119 98 119 107 108 120 99 121 109 110 122 100 122 110 111 123 101 123 111 112 124 102 124 112 113 125 103 125 113 114 126 104 126 114 115 127 105 127 115 116 128 106 128 116 117 129 107 129 117 118 130 108 130 118 119 131 109 131 119 120 132 110 133 121 122 134 111 134 122 123 135 112 135 123 124 136 113 136 124 125 137 114 137 125 126 138 115 138 126 127 139 116 139 127 128 140 117 140 128 129 141 118 141 129 130 142 119 142 130 131 143 120 143 131 132 144 121 # BOUNDARYDOMAIN default 1 # GRIDPARAMETER closure none # dune-grid-2.11.0/doc/grids/gmsh/000077500000000000000000000000001511655130300162645ustar00rootroot00000000000000dune-grid-2.11.0/doc/grids/gmsh/CMakeLists.txt000066400000000000000000000012461511655130300210270ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(GRIDS circle1storder.msh circle2ndorder.msh circle.geo curved2d.geo curved2d.msh hybrid-testgrid-2d.msh hybrid-testgrid-3d.msh oned-testgrid.msh pyramid1storder.msh pyramid2ndorder.msh pyramid4.msh pyramid.geo pyramid.msh sphere.msh telescope1storder.msh telescope2ndorder.msh telescope.geo telescope.msh twotets.geo twotets.msh unitcube.msh) dune_symlink_to_source_files(FILES ${GRIDS}) install(FILES ${GRIDS} DESTINATION ${CMAKE_INSTALL_DOCDIR}/grids/gmsh) dune-grid-2.11.0/doc/grids/gmsh/circle.geo000066400000000000000000000007341511655130300202250ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // mesh width associated with points lc = 1; // Two antipodal points on the circle, the third point is the circle center Point(1) = {-1, 0, 0, lc}; Point(2) = {1, 0, 0, lc}; Point(3) = {0, 0, 0, lc}; Circle(1) = {1,3,2}; Circle(2) = {2,3,1}; Line Loop(100) = {1,2}; Plane Surface(200) = {100}; dune-grid-2.11.0/doc/grids/gmsh/circle1storder.msh000066400000000000000000000011051511655130300217170ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 8 1 -1 0 0 2 1 0 0 3 0 0 0 4 -0.5000000000004422 -0.8660254037841834 0 5 0.5000000000016158 -0.8660254037835057 0 6 0.5000000000004422 0.8660254037841834 0 7 -0.5000000000016158 0.8660254037835057 0 8 -0.02222222222229404 0.03849001794593358 0 $EndNodes $Elements 15 1 15 2 0 1 1 2 15 2 0 2 2 3 15 2 0 3 3 4 1 3 0 1 0 1 4 5 1 3 0 1 0 4 5 6 1 3 0 1 0 5 2 7 1 3 0 2 0 2 6 8 1 3 0 2 0 6 7 9 1 3 0 2 0 7 1 10 2 3 0 200 0 6 7 8 11 2 3 0 200 0 8 2 6 12 2 3 0 200 0 4 8 1 13 2 3 0 200 0 1 8 7 14 2 3 0 200 0 2 8 5 15 2 3 0 200 0 5 8 4 $EndElements dune-grid-2.11.0/doc/grids/gmsh/circle1storder.msh.license000066400000000000000000000002501511655130300233400ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/circle2ndorder.msh000066400000000000000000000022031511655130300216730ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 20 1 -1 0 0 2 1 0 0 3 0 0 0 4 -0.5000000000004422 -0.8660254037841834 0 5 0.5000000000016158 -0.8660254037835057 0 6 -0.8660254037845663 -0.4999999999997789 0 7 6.776189039135044e-13 -1 0 8 0.8660254037849052 -0.4999999999991919 0 9 0.5000000000004422 0.8660254037841834 0 10 -0.5000000000016158 0.8660254037835057 0 11 0.8660254037845663 0.4999999999997789 0 12 -6.776189039135044e-13 1 0 13 -0.8660254037849052 0.4999999999991919 0 14 -0.02222222222229404 0.03849001794593358 0 15 -0.261111111111955 0.4522577108647196 0 16 0.2388888888890741 0.4522577108650584 0 17 0.488888888888853 0.01924500897296679 0 18 -0.2611111111113681 -0.4137676929191249 0 19 -0.511111111111147 0.01924500897296679 0 20 0.2388888888896609 -0.4137676929187861 0 $EndNodes $Elements 15 1 15 2 0 1 1 2 15 2 0 2 2 3 15 2 0 3 3 4 8 3 0 1 0 1 4 6 5 8 3 0 1 0 4 5 7 6 8 3 0 1 0 5 2 8 7 8 3 0 2 0 2 9 11 8 8 3 0 2 0 9 10 12 9 8 3 0 2 0 10 1 13 10 9 3 0 200 0 9 10 14 12 15 16 11 9 3 0 200 0 14 2 9 17 11 16 12 9 3 0 200 0 4 14 1 18 19 6 13 9 3 0 200 0 1 14 10 19 15 13 14 9 3 0 200 0 2 14 5 17 20 8 15 9 3 0 200 0 5 14 4 20 18 7 $EndElements dune-grid-2.11.0/doc/grids/gmsh/circle2ndorder.msh.license000066400000000000000000000002501511655130300233140ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/curved2d.geo000066400000000000000000000015441511655130300205020ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // mesh width associated with points lc = 0.4; lc2 = 0.05; // points Point(1) = {-1, 0, 0, lc}; Point(2) = {1, 0, 0, lc}; Point(3) = {0, 0, 0, lc}; Point(4) = {2,0.5,0,lc}; Point(5) = {2.5,3,0,lc}; Point(6) = {-1,1,0,lc}; Point(7) = {1.3, 1.5, 0, lc2}; Point(8) = {1.5, 1.5, 0, lc2}; Point(9) = {1.7, 1.5, 0, lc2}; Point(10) = {-0.3, 0.5, 0, lc2}; Point(11) = { 0.1, 0.5, 0, lc2}; Point(12) = { 0.5, 0.5, 0, lc2}; // lines Circle(1) = {1,3,2}; BSpline(2) = {2,4,5,6,1}; Circle(3) = {7,8,9}; Circle(4) = {9,8,7}; Circle(5) = {10,11,12}; Circle(6) = {12,11,10}; Line Loop(100) = {1,2}; Line Loop(101) = {3,4}; Line Loop(102) = {5,6}; // surfaces Plane Surface(200) = {100,101,102}; dune-grid-2.11.0/doc/grids/gmsh/curved2d.msh000066400000000000000000000547271511655130300205320ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 248 1 -1 0 0 2 1 0 0 3 0 0 0 4 2 0.5 0 5 2.5 3 0 6 -1 1 0 7 1.3 1.5 0 8 1.5 1.5 0 9 1.7 1.5 0 10 -0.3 0.5 0 11 0.1 0.5 0 12 0.5 0.5 0 13 -0.9009688679086683 -0.4338837391045818 0 14 -0.623489801875822 -0.7818314824544021 0 15 -0.2225209339645683 -0.9749279121799397 0 16 0.2225209339613888 -0.9749279121806654 0 17 0.6234898018737107 -0.7818314824560859 0 18 0.9009688679080333 -0.4338837391059002 0 19 1.373787056535939 0.19982879155068 0 20 1.688726803058808 0.4816633463060683 0 21 1.918493405277135 0.8369957249197043 0 22 2.072877643535169 1.23148397645843 0 23 2.153403401739484 1.647096214255282 0 24 2.093455043710695 2.06185307265031 0 25 1.743569293610307 2.257103805766163 0 26 1.328467699246107 2.178485582789125 0 27 0.934510331827512 2.022044643367121 0 28 0.5567525403839818 1.829418254340538 0 29 0.1927147367485628 1.611911661898896 0 30 -0.1569888136270677 1.372052975441651 0 31 -0.4864162903234522 1.105189912808768 0 32 -0.7751616349925063 0.7953564862137084 0 33 -0.9700777144834498 0.4214728728498789 0 34 1.306814834741828 1.448236190980832 0 35 1.326794919241729 1.400000000002396 0 36 1.358578643759755 1.358578643765626 0 37 1.399999999997604 1.326794919244496 0 38 1.448236190978159 1.306814834742545 0 39 1.5 1.3 0 40 1.551763809021841 1.306814834742545 0 41 1.600000000002396 1.326794919244496 0 42 1.641421356240245 1.358578643765626 0 43 1.673205080758271 1.400000000002396 0 44 1.693185165258172 1.448236190980832 0 45 1.693185165258172 1.551763809019168 0 46 1.673205080758271 1.599999999997604 0 47 1.641421356240245 1.641421356234374 0 48 1.600000000002396 1.673205080755504 0 49 1.551763809021841 1.693185165257455 0 50 1.5 1.7 0 51 1.448236190978159 1.693185165257455 0 52 1.399999999997604 1.673205080755504 0 53 1.358578643759755 1.641421356234374 0 54 1.326794919241729 1.599999999997604 0 55 1.306814834741828 1.551763809019168 0 56 -0.2968458805259974 0.4498667065759104 0 57 -0.2874332644522707 0.4005240451372449 0 58 -0.2719105943571174 0.3527501789307175 0 59 -0.2505226720207155 0.3072985303650803 0 60 -0.2236067977548138 0.2648858990896652 0 61 -0.1915874509753215 0.2261811576357198 0 62 -0.1549695959065249 0.1917947028955158 0 63 -0.1143307179980471 0.1622688298032863 0 64 -0.07031171663157229 0.1380691790162006 0 65 -0.02360679775436833 0.1195773934833648 0 66 0.02504747416266091 0.1070850997091062 0 67 0.07488379218668462 0.1007893086287914 0 68 0.1251162078116826 0.1007893086286886 0 69 0.1749525258358091 0.1070850997088143 0 70 0.2236067977529617 0.1195773934829077 0 71 0.270311716630305 0.1380691790156043 0 72 0.3143307179969309 0.1622688298025779 0 73 0.3549695959055668 0.1917947028947231 0 74 0.3915874509745428 0.2261811576348907 0 75 0.4236067977542567 0.2648858990888985 0 76 0.4505226720203503 0.3072985303644159 0 77 0.4719105943569081 0.3527501789301887 0 78 0.4874332644521764 0.4005240451368776 0 79 0.4968458805259736 0.4498667065757221 0 80 0.4968458805259988 0.5501332934240781 0 81 0.4874332644522764 0.5994759548627329 0 82 0.4719105943571301 0.6472498210692504 0 83 0.4505226720207377 0.6927014696348794 0 84 0.4236067977548476 0.7351141009102883 0 85 0.3915874509753686 0.7738188423642299 0 86 0.3549695959065869 0.8082052971044329 0 87 0.3143307179981248 0.8377311701966645 0 88 0.270311716631666 0.8619308209837553 0 89 0.2236067977544778 0.8804226065165996 0 90 0.1749525258374632 0.8929149002908701 0 91 0.1251162078134531 0.8992106913711999 0 92 0.07488379218842738 0.8992106913713183 0 93 0.0250474741642332 0.8929149002911938 0 94 -0.02360679775298442 0.8804226065170849 0 95 -0.07031171663038746 0.8619308209843569 0 96 -0.1143307179970641 0.8377311701973376 0 97 -0.15496959590574 0.8082052971051336 0 98 -0.1915874509747238 0.7738188423649166 0 99 -0.2236067977543861 0.7351141009109234 0 100 -0.2505226720204351 0.6927014696354298 0 101 -0.2719105943569566 0.6472498210696885 0 102 -0.2874332644521983 0.599475954863037 0 103 -0.2968458805259792 0.550133293424234 0 104 0.7914810033931278 0.826191179833864 0 105 0.8428922197018522 1.034594774172838 0 106 0.1591789903166091 -0.3015043115456382 0 107 -0.2169213768954859 -0.2395420891129978 0 108 0.9129078932683427 0.4186737613922455 0 109 -0.4691358893554867 0.06522437286500314 0 110 -0.2464405539128716 0.8490102430975741 0 111 1.084651214495965 1.058576098000484 0 112 1.245813163396273 1.210707319807955 0 113 0.5805206416389268 0.8558270450378115 0 114 0.6144399511967561 1.010311046300803 0 115 1.065428930583475 1.439770855368061 0 116 0.6267358211812021 0.6538193231279216 0 117 0.01949892973358527 -0.04874895736526354 0 118 0.1526436279072068 -0.09792374153837377 0 119 0.6376687333271563 0.5772279216994204 0 120 0.6305919046988787 0.4724963378773522 0 121 0.9949025233460986 0.7741532068102027 0 122 0.8393732833138893 0.9430859744736274 0 123 -0.6848868918138272 0.2063398602526458 0 124 0.3864166827551607 0.1172130488753803 0 125 1.363539575888501 0.9501981386017154 0 126 0.6321692523020588 1.284284128249214 0 127 0.494931246214308 0.2843742375878367 0 128 0.6265179687822591 0.2001947351583349 0 129 1.126724741177572 0.3425403099299673 0 130 0.9181560723614015 1.250946224392545 0 131 -0.70945574783926 -0.06543836318556454 0 132 0.4559496494075353 0.185635261265627 0 133 1.812463226320033 1.444465329054045 0 134 0.7478754502109783 0.3308328228249869 0 135 0.3194368749183655 -0.5316614952417381 0 136 0.4817145095175829 1.41012936306369 0 137 1.337150458331161 0.5142953887237169 0 138 0.4997950372789428 0.9217650886717522 0 139 0.4136186899033272 0.8198626796380384 0 140 1.045096733002632 1.239001004233689 0 141 0.7358341780657234 0.8995427120616144 0 142 1.277316004250588 1.103114773178857 0 143 0.4921912941767489 0.8214744810877758 0 144 1.153108672307209 1.415287437674652 0 145 0.7701569629046213 1.103019630598194 0 146 1.135355311093175 1.136231663256769 0 147 0.678510492505537 0.8404027771563375 0 148 0.958923617576433 1.014138818108414 0 149 0.5122440402788507 0.7383978221413431 0 150 0.6871380623434764 0.7371509583682477 0 151 0.651298727684357 0.9309624593239058 0 152 0.513810869330987 1.026172106653988 0 153 0.5349401176969154 0.6610086552104952 0 154 0.7276571991548545 1.006511952916384 0 155 1.10030723500191 1.34212507588696 0 156 0.9256218367827467 0.8745316063452359 0 157 1.004165388101105 1.131775354020684 0 158 1.347881802980963 1.199849038529345 0 159 0.9840456689192124 1.381054884983714 0 160 0.09424692759168746 0.02149249868001206 0 161 1.204111403876019 0.9945832447977386 0 162 0.6954386656822423 0.6417125322745998 0 163 1.382798521650042 1.278016208532281 0 164 0.5434998556855758 0.4743136839363079 0 165 0.6320528461958924 1.125505611176176 0 166 1.078368740978879 0.913363286652972 0 167 0.7339092148148906 0.5251233467448377 0 168 0.8706526070150535 1.131793699056907 0 169 1.117912029805705 1.519810605370965 0 170 -0.01696262178583019 -0.5756857889473749 0 171 0.6122375774340977 -0.3206365412470319 0 172 0.5633764004484876 0.3716671981208215 0 173 0.4615602568356302 1.18001822504113 0 174 1.223988950221006 0.7736101731261111 0 175 0.9280746210330776 1.614656673868222 0 176 1.579014599019328 0.9675353158943514 0 177 -0.005906365675735987 -0.2107172478146781 0 178 0.3425077917452158 -0.1794566057847598 0 179 0.7788829437623702 1.216417238608897 0 180 1.451032879163125 1.132463753115063 0 181 1.518379148612846 1.22731351023398 0 182 1.081450753156068 1.684691554779004 0 183 1.062441201340987 0.5888449240637775 0 184 1.492491713976169 1.82853365289022 0 185 0.5435896878476253 0.00586138134168195 0 186 1.219167473985863 1.35264618738641 0 187 0.3670369126372511 0.001567006395291542 0 188 0.4050897134351371 0.9605895851909241 0 189 0.2654773287033908 -0.02554876613211149 0 190 0.3042922316515272 1.067047734980394 0 191 1.51848563196599 0.7540496812619445 0 192 0.3632311356859579 0.8650780063835585 0 193 0.2873476400014085 0.0793702440615421 0 194 1.163974756194026 1.25928789975545 0 195 1.303877500247847 1.352906694534138 0 196 -0.001760375542840775 0.05130713494786891 0 197 1.298477944419836 1.28264468981758 0 198 0.1868754103705836 0.04817777143258014 0 199 0.4318039706590877 0.875027511057513 0 200 0.5713426313638381 0.9506154923093255 0 201 0.6224495779907697 0.7832201945564389 0 202 1.225360229415382 1.573149233897615 0 203 0.5600439410474602 0.530118752266565 0 204 0.5899624008219607 0.721549109936122 0 205 1.226246733684458 1.457506922939089 0 206 0.5571421829462483 0.7796608642123271 0 207 1.445577551960454 1.233319682005748 0 208 1.680324289716694 1.964188658589591 0 209 0.4871373628049104 0.6937363922574649 0 210 -0.4045800728904691 -0.5245561464637917 0 211 0.8727445013059294 0.7961681743474311 0 212 0.5572779597051682 0.5952973167652023 0 213 0.8438703831868869 0.6635022604794008 0 214 1.276580292380345 1.402259199168573 0 215 1.627137593892584 1.751384250075101 0 216 0.4498862771266768 0.7696653532288386 0 217 1.348746522015017 1.319788231178824 0 218 1.231858334499 1.276321524191849 0 219 0.4646794299972046 0.7259230276345627 0 220 0.2328839046516309 1.292276712123163 0 221 0.7564220924180519 1.425805919058852 0 222 -0.2917679924300643 0.2927875091544451 0 223 0.1139539336817342 1.11251993800197 0 224 0.1920804873995531 0.9604054213400729 0 225 -0.497256143742109 -0.1831983855215804 0 226 -0.5303280703507318 0.4907674908156402 0 227 -0.362215654516594 0.5548870841106662 0 228 -0.07200260485146914 0.07365342267726092 0 229 -0.3864608821737852 0.719449268075756 0 230 -0.2776578472889676 -0.01992404747872491 0 231 -0.3615053159628324 0.380708476729766 0 232 -0.1527044802067103 0.09759273981071888 0 233 -0.1063017424280692 -0.03626429190653858 0 234 -0.2597236713672403 0.75401878481692 0 235 -0.4254270368206849 0.269868735371913 0 236 -0.01932197750276351 1.036067345278206 0 237 -0.3548921756905485 0.4657312203736912 0 238 0.08529331962410625 0.9667214979423268 0 239 0.2972596737864722 0.916706128730423 0 240 1.829473994212149 1.198458415484536 0 241 0.4211882678133204 1.058456912966609 0 242 1.643521503539802 1.163969279914828 0 243 1.796824394704522 1.707771586234434 0 244 1.311512416439003 1.819306746635071 0 245 -0.1596309811066559 0.991772153474997 0 246 -0.2733571363423217 0.173551383668032 0 247 1.700014193512149 1.315377764577655 0 248 1.206367882306575 1.723435589151798 0 $EndNodes $Elements 498 1 15 3 0 1 0 1 2 15 3 0 2 0 2 3 15 3 0 3 0 3 4 15 3 0 4 0 4 5 15 3 0 5 0 5 6 15 3 0 6 0 6 7 15 3 0 7 0 7 8 15 3 0 8 0 8 9 15 3 0 9 0 9 10 15 3 0 10 0 10 11 15 3 0 11 0 11 12 15 3 0 12 0 12 13 1 3 0 1 0 1 13 14 1 3 0 1 0 13 14 15 1 3 0 1 0 14 15 16 1 3 0 1 0 15 16 17 1 3 0 1 0 16 17 18 1 3 0 1 0 17 18 19 1 3 0 1 0 18 2 20 1 3 0 2 0 2 19 21 1 3 0 2 0 19 20 22 1 3 0 2 0 20 21 23 1 3 0 2 0 21 22 24 1 3 0 2 0 22 23 25 1 3 0 2 0 23 24 26 1 3 0 2 0 24 25 27 1 3 0 2 0 25 26 28 1 3 0 2 0 26 27 29 1 3 0 2 0 27 28 30 1 3 0 2 0 28 29 31 1 3 0 2 0 29 30 32 1 3 0 2 0 30 31 33 1 3 0 2 0 31 32 34 1 3 0 2 0 32 33 35 1 3 0 2 0 33 1 36 1 3 0 3 0 7 34 37 1 3 0 3 0 34 35 38 1 3 0 3 0 35 36 39 1 3 0 3 0 36 37 40 1 3 0 3 0 37 38 41 1 3 0 3 0 38 39 42 1 3 0 3 0 39 40 43 1 3 0 3 0 40 41 44 1 3 0 3 0 41 42 45 1 3 0 3 0 42 43 46 1 3 0 3 0 43 44 47 1 3 0 3 0 44 9 48 1 3 0 4 0 9 45 49 1 3 0 4 0 45 46 50 1 3 0 4 0 46 47 51 1 3 0 4 0 47 48 52 1 3 0 4 0 48 49 53 1 3 0 4 0 49 50 54 1 3 0 4 0 50 51 55 1 3 0 4 0 51 52 56 1 3 0 4 0 52 53 57 1 3 0 4 0 53 54 58 1 3 0 4 0 54 55 59 1 3 0 4 0 55 7 60 1 3 0 5 0 10 56 61 1 3 0 5 0 56 57 62 1 3 0 5 0 57 58 63 1 3 0 5 0 58 59 64 1 3 0 5 0 59 60 65 1 3 0 5 0 60 61 66 1 3 0 5 0 61 62 67 1 3 0 5 0 62 63 68 1 3 0 5 0 63 64 69 1 3 0 5 0 64 65 70 1 3 0 5 0 65 66 71 1 3 0 5 0 66 67 72 1 3 0 5 0 67 68 73 1 3 0 5 0 68 69 74 1 3 0 5 0 69 70 75 1 3 0 5 0 70 71 76 1 3 0 5 0 71 72 77 1 3 0 5 0 72 73 78 1 3 0 5 0 73 74 79 1 3 0 5 0 74 75 80 1 3 0 5 0 75 76 81 1 3 0 5 0 76 77 82 1 3 0 5 0 77 78 83 1 3 0 5 0 78 79 84 1 3 0 5 0 79 12 85 1 3 0 6 0 12 80 86 1 3 0 6 0 80 81 87 1 3 0 6 0 81 82 88 1 3 0 6 0 82 83 89 1 3 0 6 0 83 84 90 1 3 0 6 0 84 85 91 1 3 0 6 0 85 86 92 1 3 0 6 0 86 87 93 1 3 0 6 0 87 88 94 1 3 0 6 0 88 89 95 1 3 0 6 0 89 90 96 1 3 0 6 0 90 91 97 1 3 0 6 0 91 92 98 1 3 0 6 0 92 93 99 1 3 0 6 0 93 94 100 1 3 0 6 0 94 95 101 1 3 0 6 0 95 96 102 1 3 0 6 0 96 97 103 1 3 0 6 0 97 98 104 1 3 0 6 0 98 99 105 1 3 0 6 0 99 100 106 1 3 0 6 0 100 101 107 1 3 0 6 0 101 102 108 1 3 0 6 0 102 103 109 1 3 0 6 0 103 10 110 2 3 0 200 0 110 98 97 111 2 3 0 200 0 127 77 76 112 2 3 0 200 0 28 29 136 113 2 3 0 200 0 19 20 137 114 2 3 0 200 0 2 19 129 115 2 3 0 200 0 129 19 137 116 2 3 0 200 0 133 45 9 117 2 3 0 200 0 128 127 132 118 2 3 0 200 0 16 17 135 119 2 3 0 200 0 133 22 23 120 2 3 0 200 0 86 85 139 121 2 3 0 200 0 141 104 122 122 2 3 0 200 0 146 142 112 123 2 3 0 200 0 104 141 147 124 2 3 0 200 0 154 141 122 125 2 3 0 200 0 157 140 130 126 2 3 0 200 0 157 148 111 127 2 3 0 200 0 112 142 158 128 2 3 0 200 0 165 152 114 129 2 3 0 200 0 166 161 111 130 2 3 0 200 0 167 162 119 131 2 3 0 200 0 119 120 167 132 2 3 0 200 0 168 145 105 133 2 3 0 200 0 105 148 168 134 2 3 0 200 0 171 17 18 135 2 3 0 200 0 135 17 171 136 2 3 0 200 0 79 78 172 137 2 3 0 200 0 115 169 175 138 2 3 0 200 0 106 178 118 139 2 3 0 200 0 159 115 175 140 2 3 0 200 0 172 78 77 141 2 3 0 200 0 157 111 146 142 2 3 0 200 0 140 157 146 143 2 3 0 200 0 151 113 147 144 2 3 0 200 0 141 151 147 145 2 3 0 200 0 154 114 151 146 2 3 0 200 0 141 154 151 147 2 3 0 200 0 146 111 161 148 2 3 0 200 0 146 161 142 149 2 3 0 200 0 156 121 166 150 2 3 0 200 0 157 130 168 151 2 3 0 200 0 157 168 148 152 2 3 0 200 0 154 122 105 153 2 3 0 200 0 160 68 67 154 2 3 0 200 0 163 38 37 155 2 3 0 200 0 153 82 81 156 2 3 0 200 0 143 113 138 157 2 3 0 200 0 104 147 150 158 2 3 0 200 0 135 106 170 159 2 3 0 200 0 177 170 106 160 2 3 0 200 0 107 170 177 161 2 3 0 200 0 12 79 164 162 2 3 0 200 0 172 164 79 163 2 3 0 200 0 116 119 162 164 2 3 0 200 0 162 150 116 165 2 3 0 200 0 182 175 169 166 2 3 0 200 0 106 118 177 167 2 3 0 200 0 177 118 117 168 2 3 0 200 0 156 122 104 169 2 3 0 200 0 166 121 174 170 2 3 0 200 0 161 166 174 171 2 3 0 200 0 179 126 165 172 2 3 0 200 0 168 130 179 173 2 3 0 200 0 145 168 179 174 2 3 0 200 0 179 165 145 175 2 3 0 200 0 111 148 166 176 2 3 0 200 0 148 105 122 177 2 3 0 200 0 156 148 122 178 2 3 0 200 0 156 166 148 179 2 3 0 200 0 15 16 170 180 2 3 0 200 0 170 16 135 181 2 3 0 200 0 105 145 154 182 2 3 0 200 0 165 114 154 183 2 3 0 200 0 145 165 154 184 2 3 0 200 0 129 183 108 185 2 3 0 200 0 121 183 174 186 2 3 0 200 0 129 137 183 187 2 3 0 200 0 178 106 135 188 2 3 0 200 0 135 171 178 189 2 3 0 200 0 165 126 173 190 2 3 0 200 0 152 165 173 191 2 3 0 200 0 77 127 172 192 2 3 0 200 0 127 128 172 193 2 3 0 200 0 172 120 164 194 2 3 0 200 0 134 172 128 195 2 3 0 200 0 185 128 132 196 2 3 0 200 0 185 132 124 197 2 3 0 200 0 27 28 175 198 2 3 0 200 0 134 108 167 199 2 3 0 200 0 134 167 120 200 2 3 0 200 0 134 120 172 201 2 3 0 200 0 185 178 171 202 2 3 0 200 0 155 115 159 203 2 3 0 200 0 130 140 159 204 2 3 0 200 0 140 155 159 205 2 3 0 200 0 174 183 137 206 2 3 0 200 0 187 178 185 207 2 3 0 200 0 185 124 187 208 2 3 0 200 0 188 138 152 209 2 3 0 200 0 178 187 189 210 2 3 0 200 0 189 118 178 211 2 3 0 200 0 191 137 20 212 2 3 0 200 0 174 137 191 213 2 3 0 200 0 193 187 124 214 2 3 0 200 0 194 146 112 215 2 3 0 200 0 140 146 194 216 2 3 0 200 0 195 36 35 217 2 3 0 200 0 196 66 65 218 2 3 0 200 0 151 114 200 219 2 3 0 200 0 200 114 152 220 2 3 0 200 0 201 150 147 221 2 3 0 200 0 147 113 201 222 2 3 0 200 0 116 150 204 223 2 3 0 200 0 143 149 206 224 2 3 0 200 0 206 113 143 225 2 3 0 200 0 201 113 206 226 2 3 0 200 0 67 66 196 227 2 3 0 200 0 73 72 124 228 2 3 0 200 0 115 155 144 229 2 3 0 200 0 115 144 169 230 2 3 0 200 0 201 204 150 231 2 3 0 200 0 169 144 205 232 2 3 0 200 0 193 124 72 233 2 3 0 200 0 125 174 191 234 2 3 0 200 0 153 116 204 235 2 3 0 200 0 155 140 194 236 2 3 0 200 0 200 152 138 237 2 3 0 200 0 73 124 132 238 2 3 0 200 0 74 73 132 239 2 3 0 200 0 192 87 86 240 2 3 0 200 0 86 139 192 241 2 3 0 200 0 199 192 139 242 2 3 0 200 0 72 71 193 243 2 3 0 200 0 193 71 70 244 2 3 0 200 0 198 69 68 245 2 3 0 200 0 68 160 198 246 2 3 0 200 0 70 69 198 247 2 3 0 200 0 75 127 76 248 2 3 0 200 0 132 127 75 249 2 3 0 200 0 132 75 74 250 2 3 0 200 0 186 205 144 251 2 3 0 200 0 125 142 161 252 2 3 0 200 0 125 161 174 253 2 3 0 200 0 20 21 191 254 2 3 0 200 0 125 191 176 255 2 3 0 200 0 173 126 136 256 2 3 0 200 0 2 134 128 257 2 3 0 200 0 2 128 185 258 2 3 0 200 0 134 2 108 259 2 3 0 200 0 108 2 129 260 2 3 0 200 0 18 2 171 261 2 3 0 200 0 185 171 2 262 2 3 0 200 0 142 180 158 263 2 3 0 200 0 180 142 125 264 2 3 0 200 0 176 180 125 265 2 3 0 200 0 186 144 155 266 2 3 0 200 0 182 169 202 267 2 3 0 200 0 169 205 202 268 2 3 0 200 0 196 160 67 269 2 3 0 200 0 203 80 12 270 2 3 0 200 0 203 120 119 271 2 3 0 200 0 164 203 12 272 2 3 0 200 0 120 203 164 273 2 3 0 200 0 198 160 118 274 2 3 0 200 0 118 189 198 275 2 3 0 200 0 138 113 200 276 2 3 0 200 0 200 113 151 277 2 3 0 200 0 194 186 155 278 2 3 0 200 0 38 163 207 279 2 3 0 200 0 180 181 207 280 2 3 0 200 0 82 153 209 281 2 3 0 200 0 209 153 149 282 2 3 0 200 0 14 15 210 283 2 3 0 200 0 210 15 170 284 2 3 0 200 0 156 104 211 285 2 3 0 200 0 211 121 156 286 2 3 0 200 0 153 81 212 287 2 3 0 200 0 212 116 153 288 2 3 0 200 0 213 104 150 289 2 3 0 200 0 150 162 213 290 2 3 0 200 0 207 163 158 291 2 3 0 200 0 180 207 158 292 2 3 0 200 0 212 81 80 293 2 3 0 200 0 203 212 80 294 2 3 0 200 0 211 104 213 295 2 3 0 200 0 119 116 212 296 2 3 0 200 0 119 212 203 297 2 3 0 200 0 208 25 26 298 2 3 0 200 0 184 208 26 299 2 3 0 200 0 210 170 107 300 2 3 0 200 0 209 83 82 301 2 3 0 200 0 38 207 39 302 2 3 0 200 0 39 207 181 303 2 3 0 200 0 201 206 204 304 2 3 0 200 0 138 188 199 305 2 3 0 200 0 186 197 195 306 2 3 0 200 0 7 202 205 307 2 3 0 200 0 202 7 55 308 2 3 0 200 0 70 198 193 309 2 3 0 200 0 189 187 193 310 2 3 0 200 0 198 189 193 311 2 3 0 200 0 204 149 153 312 2 3 0 200 0 204 206 149 313 2 3 0 200 0 199 143 138 314 2 3 0 200 0 139 143 199 315 2 3 0 200 0 162 167 213 316 2 3 0 200 0 213 183 121 317 2 3 0 200 0 213 121 211 318 2 3 0 200 0 213 108 183 319 2 3 0 200 0 167 108 213 320 2 3 0 200 0 205 34 7 321 2 3 0 200 0 197 158 163 322 2 3 0 200 0 188 192 199 323 2 3 0 200 0 112 158 197 324 2 3 0 200 0 34 205 214 325 2 3 0 200 0 186 195 214 326 2 3 0 200 0 214 205 186 327 2 3 0 200 0 49 48 215 328 2 3 0 200 0 215 184 49 329 2 3 0 200 0 143 139 216 330 2 3 0 200 0 216 149 143 331 2 3 0 200 0 37 36 217 332 2 3 0 200 0 197 163 217 333 2 3 0 200 0 217 163 37 334 2 3 0 200 0 194 112 218 335 2 3 0 200 0 197 186 218 336 2 3 0 200 0 218 112 197 337 2 3 0 200 0 218 186 194 338 2 3 0 200 0 84 83 219 339 2 3 0 200 0 149 216 219 340 2 3 0 200 0 219 216 84 341 2 3 0 200 0 159 175 221 342 2 3 0 200 0 215 48 47 343 2 3 0 200 0 219 83 209 344 2 3 0 200 0 149 219 209 345 2 3 0 200 0 35 34 214 346 2 3 0 200 0 35 214 195 347 2 3 0 200 0 208 184 215 348 2 3 0 200 0 217 36 195 349 2 3 0 200 0 197 217 195 350 2 3 0 200 0 84 216 85 351 2 3 0 200 0 85 216 139 352 2 3 0 200 0 130 221 179 353 2 3 0 200 0 159 221 130 354 2 3 0 200 0 50 49 184 355 2 3 0 200 0 136 29 220 356 2 3 0 200 0 29 30 220 357 2 3 0 200 0 173 136 220 358 2 3 0 200 0 173 220 190 359 2 3 0 200 0 221 175 28 360 2 3 0 200 0 221 28 136 361 2 3 0 200 0 179 221 126 362 2 3 0 200 0 126 221 136 363 2 3 0 200 0 60 59 222 364 2 3 0 200 0 223 190 220 365 2 3 0 200 0 190 223 224 366 2 3 0 200 0 225 109 131 367 2 3 0 200 0 107 225 210 368 2 3 0 200 0 9 44 133 369 2 3 0 200 0 230 109 225 370 2 3 0 200 0 117 118 160 371 2 3 0 200 0 117 160 196 372 2 3 0 200 0 228 196 65 373 2 3 0 200 0 233 117 196 374 2 3 0 200 0 228 233 196 375 2 3 0 200 0 103 227 10 376 2 3 0 200 0 50 184 51 377 2 3 0 200 0 107 230 225 378 2 3 0 200 0 96 110 97 379 2 3 0 200 0 58 222 59 380 2 3 0 200 0 58 57 231 381 2 3 0 200 0 64 228 65 382 2 3 0 200 0 117 233 177 383 2 3 0 200 0 107 177 233 384 2 3 0 200 0 107 233 230 385 2 3 0 200 0 231 222 58 386 2 3 0 200 0 31 229 110 387 2 3 0 200 0 90 89 224 388 2 3 0 200 0 91 90 224 389 2 3 0 200 0 234 99 98 390 2 3 0 200 0 234 110 229 391 2 3 0 200 0 98 110 234 392 2 3 0 200 0 235 123 109 393 2 3 0 200 0 235 222 231 394 2 3 0 200 0 227 226 237 395 2 3 0 200 0 237 226 231 396 2 3 0 200 0 224 223 238 397 2 3 0 200 0 89 88 239 398 2 3 0 200 0 239 224 89 399 2 3 0 200 0 100 99 234 400 2 3 0 200 0 226 123 235 401 2 3 0 200 0 226 235 231 402 2 3 0 200 0 10 227 237 403 2 3 0 200 0 91 224 238 404 2 3 0 200 0 237 56 10 405 2 3 0 200 0 57 237 231 406 2 3 0 200 0 57 56 237 407 2 3 0 200 0 238 92 91 408 2 3 0 200 0 233 228 232 409 2 3 0 200 0 232 230 233 410 2 3 0 200 0 229 31 32 411 2 3 0 200 0 238 223 236 412 2 3 0 200 0 192 239 87 413 2 3 0 200 0 239 192 188 414 2 3 0 200 0 87 239 88 415 2 3 0 200 0 239 188 190 416 2 3 0 200 0 224 239 190 417 2 3 0 200 0 226 32 33 418 2 3 0 200 0 32 226 229 419 2 3 0 200 0 33 123 226 420 2 3 0 200 0 229 226 227 421 2 3 0 200 0 13 210 225 422 2 3 0 200 0 225 131 13 423 2 3 0 200 0 1 13 131 424 2 3 0 200 0 210 13 14 425 2 3 0 200 0 152 173 241 426 2 3 0 200 0 190 188 241 427 2 3 0 200 0 241 173 190 428 2 3 0 200 0 241 188 152 429 2 3 0 200 0 63 62 232 430 2 3 0 200 0 123 33 1 431 2 3 0 200 0 109 123 131 432 2 3 0 200 0 131 123 1 433 2 3 0 200 0 22 133 240 434 2 3 0 200 0 247 42 41 435 2 3 0 200 0 103 102 227 436 2 3 0 200 0 181 40 39 437 2 3 0 200 0 182 202 248 438 2 3 0 200 0 110 96 245 439 2 3 0 200 0 110 245 31 440 2 3 0 200 0 23 243 133 441 2 3 0 200 0 208 215 243 442 2 3 0 200 0 244 184 26 443 2 3 0 200 0 246 230 232 444 2 3 0 200 0 246 109 230 445 2 3 0 200 0 60 222 246 446 2 3 0 200 0 222 235 246 447 2 3 0 200 0 235 109 246 448 2 3 0 200 0 180 176 242 449 2 3 0 200 0 181 180 242 450 2 3 0 200 0 240 133 247 451 2 3 0 200 0 247 43 42 452 2 3 0 200 0 64 63 232 453 2 3 0 200 0 64 232 228 454 2 3 0 200 0 133 44 43 455 2 3 0 200 0 247 133 43 456 2 3 0 200 0 102 101 229 457 2 3 0 200 0 229 227 102 458 2 3 0 200 0 229 101 100 459 2 3 0 200 0 234 229 100 460 2 3 0 200 0 30 245 236 461 2 3 0 200 0 236 223 30 462 2 3 0 200 0 220 30 223 463 2 3 0 200 0 245 30 31 464 2 3 0 200 0 247 242 240 465 2 3 0 200 0 93 92 238 466 2 3 0 200 0 244 52 51 467 2 3 0 200 0 53 52 244 468 2 3 0 200 0 51 184 244 469 2 3 0 200 0 94 93 236 470 2 3 0 200 0 236 93 238 471 2 3 0 200 0 45 133 243 472 2 3 0 200 0 243 46 45 473 2 3 0 200 0 47 46 243 474 2 3 0 200 0 215 47 243 475 2 3 0 200 0 245 95 94 476 2 3 0 200 0 236 245 94 477 2 3 0 200 0 96 95 245 478 2 3 0 200 0 248 54 53 479 2 3 0 200 0 53 244 248 480 2 3 0 200 0 242 247 41 481 2 3 0 200 0 242 41 40 482 2 3 0 200 0 40 181 242 483 2 3 0 200 0 242 176 21 484 2 3 0 200 0 21 240 242 485 2 3 0 200 0 240 21 22 486 2 3 0 200 0 191 21 176 487 2 3 0 200 0 62 61 246 488 2 3 0 200 0 246 232 62 489 2 3 0 200 0 246 61 60 490 2 3 0 200 0 27 182 248 491 2 3 0 200 0 248 244 27 492 2 3 0 200 0 26 27 244 493 2 3 0 200 0 182 27 175 494 2 3 0 200 0 24 208 243 495 2 3 0 200 0 243 23 24 496 2 3 0 200 0 208 24 25 497 2 3 0 200 0 202 55 54 498 2 3 0 200 0 248 202 54 $EndElements dune-grid-2.11.0/doc/grids/gmsh/curved2d.msh.license000066400000000000000000000002501511655130300221310ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-2d-v4-ascii.msh000066400000000000000000000007471511655130300240310ustar00rootroot00000000000000$MeshFormat 4.1 0 8 $EndMeshFormat $Entities 0 0 1 0 1 0 0 0 1 1 0 0 0 $EndEntities $Nodes 1 16 1 16 2 1 0 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 0 0 0 0.5 0 0 0.5 0.5 0 0 0.5 0 0.25 0 0 0.5 0.25 0 0.25 0.5 0 0 0.25 0 0.25 0.25 0 1 0 0 1 0.5 0 0.75 0.25 0 1 1 0 0.5 1 0 0 1 0 0.25 0.75 0 $EndNodes $Elements 2 11 1 11 2 1 2 2 6 10 11 12 11 16 14 15 2 1 3 9 1 1 5 9 8 2 5 2 6 9 3 9 6 3 7 4 8 9 7 4 5 2 10 12 6 7 6 12 11 3 8 3 11 13 14 9 4 7 16 15 10 7 3 14 16 $EndElements dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-2d-v4-ascii.msh.license000066400000000000000000000002621511655130300254420ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-2d-v4-binary.msh000066400000000000000000000023621511655130300242200ustar00rootroot00000000000000$MeshFormat 4.1 1 8  $EndMeshFormat $Entities ?? $EndEntities $Nodes  ???????????????????????? $EndNodes $Elements               $EndElements dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-2d-v4-binary.msh.license000066400000000000000000000002621511655130300256360ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-2d.msh000066400000000000000000000011061511655130300224020ustar00rootroot00000000000000$MeshFormat 2.1 0 8 $EndMeshFormat $Nodes 16 1 0 0 0 2 0.5 0 0 3 0.5 0.5 0 4 0 0.5 0 5 0.25 0 0 6 0.5 0.25 0 7 0.25 0.5 0 8 0 0.25 0 9 0.25 0.25 0 10 1 0 0 11 1 0.5 0 12 0.75 0.25 0 13 1 1 0 14 0.5 1 0 15 0 1 0 16 0.25 0.75 0 $EndNodes $Elements 11 1 3 3 0 1 0 1 5 9 8 2 3 3 0 1 0 5 2 6 9 3 3 3 0 1 0 9 6 3 7 4 3 3 0 1 0 8 9 7 4 5 3 3 0 1 0 2 10 12 6 6 2 3 0 1 0 10 11 12 7 3 3 0 1 0 6 12 11 3 8 3 3 0 1 0 3 11 13 14 9 3 3 0 1 0 4 7 16 15 10 3 3 0 1 0 7 3 14 16 11 2 3 0 1 0 16 14 15 $EndElements dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-2d.msh.license000066400000000000000000000002501511655130300240220ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-3d-v4-ascii.msh000066400000000000000000000052261511655130300240270ustar00rootroot00000000000000$MeshFormat 4.1 0 8 $EndMeshFormat $Entities 0 0 0 1 1 0 0 0 1.5 1 1 0 0 $EndEntities $Nodes 1 61 1 61 3 1 0 61 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 0 0 0 0.5 0 0 0.5 0.5 0 0 0.5 0 0 0 0.5 0.5 0 0.5 0.5 0.5 0.5 0 0.5 0.5 0.25 0 0 0.5 0.25 0 0.25 0.5 0 0 0.25 0 0 0 0.25 0.5 0 0.25 0.5 0.5 0.25 0 0.5 0.25 0.25 0 0.5 0.5 0.25 0.5 0.25 0.5 0.5 0 0.25 0.5 0.25 0.25 0 0.25 0 0.25 0.5 0.25 0.25 0.25 0.5 0.25 0 0.25 0.25 0.25 0.25 0.5 0.25 0.25 0.25 1 0 0 1 0.5 0 1 0 0.5 1 0.5 0.5 0.75 0.25 0.25 1 1 0 0.5 1 0 1 1 0.5 0.5 1 0.5 0.75 0.75 0.25 0 1 0 0 1 0.5 0.25 0.75 0.25 0 0 1 0.5 0 1 0.5 0.5 1 0 0.5 1 0.25 0.25 0.75 1 0 1 1 0.5 1 0.75 0.25 0.75 1 1 1 0.5 1 1 0 1 1 0.25 0.75 0.75 1.5 0 0 1.5 0.5 0 1.5 1 0 1.5 0 0.5 1.5 0.5 0.5 1.5 1 0.5 1.5 0 1 1.5 0.5 1 1.5 1 1 $EndNodes $Elements 4 98 1 98 3 1 4 54 9 10 29 3 32 10 10 2 28 32 11 10 28 29 32 12 14 28 2 32 13 14 6 30 32 14 14 30 28 32 16 15 31 7 32 17 15 3 29 32 18 15 29 31 32 23 18 30 6 32 24 18 7 31 32 25 18 31 30 32 27 15 29 3 37 28 15 7 31 37 29 15 31 29 37 32 15 36 7 37 33 15 3 34 37 34 15 34 36 37 36 11 38 4 40 37 11 3 34 40 38 11 34 38 40 43 15 34 3 40 44 15 7 36 40 45 15 36 34 40 47 16 39 8 40 48 16 4 38 40 49 16 38 39 40 50 19 36 7 40 51 19 8 39 40 52 19 39 36 40 57 17 42 6 45 58 17 5 41 45 59 17 41 42 45 60 18 43 7 45 61 18 6 42 45 62 18 42 43 45 63 19 44 8 45 64 19 7 43 45 65 19 43 44 45 66 20 41 5 45 67 20 8 44 45 68 20 44 41 45 70 18 31 7 48 71 18 6 30 48 72 18 30 31 48 76 18 42 6 48 77 18 7 43 48 78 18 43 42 48 81 19 39 8 52 82 19 7 36 52 83 19 36 39 52 84 19 43 7 52 85 19 8 44 52 86 19 44 43 52 3 1 5 9 1 1 9 21 12 13 22 27 25 2 9 2 10 21 22 14 23 27 3 21 10 3 11 27 23 15 24 4 12 21 11 4 25 27 24 16 5 13 22 27 25 5 17 26 20 6 22 14 23 27 17 6 18 26 7 27 23 15 24 26 18 7 19 8 25 27 24 16 20 26 19 8 80 7 31 35 36 43 47 49 50 3 1 6 8 91 28 53 29 30 56 31 92 53 54 29 56 57 31 93 30 56 31 46 59 47 94 56 57 31 59 60 47 95 29 54 33 31 57 35 96 54 55 33 57 58 35 97 31 57 35 47 60 49 98 57 58 35 60 61 49 3 1 7 27 15 28 30 31 29 32 19 10 23 14 2 32 20 14 23 18 6 32 21 18 23 15 7 32 22 15 23 10 3 32 26 3 29 33 34 37 30 29 31 35 33 37 31 33 35 36 34 37 35 7 36 35 31 37 39 11 24 15 3 40 40 15 24 19 7 40 41 19 24 16 8 40 42 16 24 11 4 40 46 34 36 39 38 40 53 20 26 19 8 45 54 19 26 18 7 45 55 18 26 17 6 45 56 17 26 20 5 45 69 41 44 43 42 45 73 6 42 46 30 48 74 30 46 47 31 48 75 31 47 43 7 48 79 42 43 47 46 48 87 7 43 50 36 52 88 36 50 51 39 52 89 39 51 44 8 52 90 44 51 50 43 52 $EndElements dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-3d-v4-ascii.msh.license000066400000000000000000000002621511655130300254430ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-3d-v4-binary.msh000066400000000000000000000153321511655130300242220ustar00rootroot00000000000000$MeshFormat 4.1 1 8  $EndMeshFormat $Entities ??? $EndEntities $Nodes ===  !"#$%&'()*+,-./0123456789:;<=??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? $EndNodes $Elements bb6             %%% $%!"%""$%$ &(% "(& "&(+"(,$(-$"(/'(0&(1&'(2$(3'(4'$(9*-:)-;)*-<+-=*->*+-?,-@+-A+,-B)-C,-D,)-F0G0H0L*0M+0N+*0Q'4R$4S$'4T+4U,4V,+4          P#$+/12[58\5689]8.;/^89;</_6!9#`67!9:#a9#/<1b9:#<=1       !"%#!%!#$"%#$#%' ((()(* (."$'&(5-6-7-8-E),+*-I*.0J./0K/+0O*+/.0W+2$4X$23'4Y'3,4Z,32+4 $EndElements dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-3d-v4-binary.msh.license000066400000000000000000000002621511655130300256370ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-3d.msh000066400000000000000000000074121511655130300224110ustar00rootroot00000000000000$MeshFormat 2.1 0 8 $EndMeshFormat $Nodes 61 1 0 0 0 2 0.5 0 0 3 0.5 0.5 0 4 0 0.5 0 5 0 0 0.5 6 0.5 0 0.5 7 0.5 0.5 0.5 8 0 0.5 0.5 9 0.25 0 0 10 0.5 0.25 0 11 0.25 0.5 0 12 0 0.25 0 13 0 0 0.25 14 0.5 0 0.25 15 0.5 0.5 0.25 16 0 0.5 0.25 17 0.25 0 0.5 18 0.5 0.25 0.5 19 0.25 0.5 0.5 20 0 0.25 0.5 21 0.25 0.25 0 22 0.25 0 0.25 23 0.5 0.25 0.25 24 0.25 0.5 0.25 25 0 0.25 0.25 26 0.25 0.25 0.5 27 0.25 0.25 0.25 28 1 0 0 29 1 0.5 0 30 1 0 0.5 31 1 0.5 0.5 32 0.75 0.25 0.25 33 1 1 0 34 0.5 1 0 35 1 1 0.5 36 0.5 1 0.5 37 0.75 0.75 0.25 38 0 1 0 39 0 1 0.5 40 0.25 0.75 0.25 41 0 0 1 42 0.5 0 1 43 0.5 0.5 1 44 0 0.5 1 45 0.25 0.25 0.75 46 1 0 1 47 1 0.5 1 48 0.75 0.25 0.75 49 1 1 1 50 0.5 1 1 51 0 1 1 52 0.25 0.75 0.75 53 1.5 0 0 54 1.5 0.5 0 55 1.5 1 0 56 1.5 0 0.5 57 1.5 0.5 0.5 58 1.5 1 0.5 59 1.5 0 1 60 1.5 0.5 1 61 1.5 1 1 $EndNodes $Elements 98 1 5 3 0 1 0 1 9 21 12 13 22 27 25 2 5 3 0 1 0 9 2 10 21 22 14 23 27 3 5 3 0 1 0 21 10 3 11 27 23 15 24 4 5 3 0 1 0 12 21 11 4 25 27 24 16 5 5 3 0 1 0 13 22 27 25 5 17 26 20 6 5 3 0 1 0 22 14 23 27 17 6 18 26 7 5 3 0 1 0 27 23 15 24 26 18 7 19 8 5 3 0 1 0 25 27 24 16 20 26 19 8 9 4 3 0 1 0 10 29 3 32 10 4 3 0 1 0 10 2 28 32 11 4 3 0 1 0 10 28 29 32 12 4 3 0 1 0 14 28 2 32 13 4 3 0 1 0 14 6 30 32 14 4 3 0 1 0 14 30 28 32 15 7 3 0 1 0 28 30 31 29 32 16 4 3 0 1 0 15 31 7 32 17 4 3 0 1 0 15 3 29 32 18 4 3 0 1 0 15 29 31 32 19 7 3 0 1 0 10 23 14 2 32 20 7 3 0 1 0 14 23 18 6 32 21 7 3 0 1 0 18 23 15 7 32 22 7 3 0 1 0 15 23 10 3 32 23 4 3 0 1 0 18 30 6 32 24 4 3 0 1 0 18 7 31 32 25 4 3 0 1 0 18 31 30 32 26 7 3 0 1 0 3 29 33 34 37 27 4 3 0 1 0 15 29 3 37 28 4 3 0 1 0 15 7 31 37 29 4 3 0 1 0 15 31 29 37 30 7 3 0 1 0 29 31 35 33 37 31 7 3 0 1 0 33 35 36 34 37 32 4 3 0 1 0 15 36 7 37 33 4 3 0 1 0 15 3 34 37 34 4 3 0 1 0 15 34 36 37 35 7 3 0 1 0 7 36 35 31 37 36 4 3 0 1 0 11 38 4 40 37 4 3 0 1 0 11 3 34 40 38 4 3 0 1 0 11 34 38 40 39 7 3 0 1 0 11 24 15 3 40 40 7 3 0 1 0 15 24 19 7 40 41 7 3 0 1 0 19 24 16 8 40 42 7 3 0 1 0 16 24 11 4 40 43 4 3 0 1 0 15 34 3 40 44 4 3 0 1 0 15 7 36 40 45 4 3 0 1 0 15 36 34 40 46 7 3 0 1 0 34 36 39 38 40 47 4 3 0 1 0 16 39 8 40 48 4 3 0 1 0 16 4 38 40 49 4 3 0 1 0 16 38 39 40 50 4 3 0 1 0 19 36 7 40 51 4 3 0 1 0 19 8 39 40 52 4 3 0 1 0 19 39 36 40 53 7 3 0 1 0 20 26 19 8 45 54 7 3 0 1 0 19 26 18 7 45 55 7 3 0 1 0 18 26 17 6 45 56 7 3 0 1 0 17 26 20 5 45 57 4 3 0 1 0 17 42 6 45 58 4 3 0 1 0 17 5 41 45 59 4 3 0 1 0 17 41 42 45 60 4 3 0 1 0 18 43 7 45 61 4 3 0 1 0 18 6 42 45 62 4 3 0 1 0 18 42 43 45 63 4 3 0 1 0 19 44 8 45 64 4 3 0 1 0 19 7 43 45 65 4 3 0 1 0 19 43 44 45 66 4 3 0 1 0 20 41 5 45 67 4 3 0 1 0 20 8 44 45 68 4 3 0 1 0 20 44 41 45 69 7 3 0 1 0 41 44 43 42 45 70 4 3 0 1 0 18 31 7 48 71 4 3 0 1 0 18 6 30 48 72 4 3 0 1 0 18 30 31 48 73 7 3 0 1 0 6 42 46 30 48 74 7 3 0 1 0 30 46 47 31 48 75 7 3 0 1 0 31 47 43 7 48 76 4 3 0 1 0 18 42 6 48 77 4 3 0 1 0 18 7 43 48 78 4 3 0 1 0 18 43 42 48 79 7 3 0 1 0 42 43 47 46 48 80 5 3 0 1 0 7 31 35 36 43 47 49 50 81 4 3 0 1 0 19 39 8 52 82 4 3 0 1 0 19 7 36 52 83 4 3 0 1 0 19 36 39 52 84 4 3 0 1 0 19 43 7 52 85 4 3 0 1 0 19 8 44 52 86 4 3 0 1 0 19 44 43 52 87 7 3 0 1 0 7 43 50 36 52 88 7 3 0 1 0 36 50 51 39 52 89 7 3 0 1 0 39 51 44 8 52 90 7 3 0 1 0 44 51 50 43 52 91 6 3 0 1 0 28 53 29 30 56 31 92 6 3 0 1 0 53 54 29 56 57 31 93 6 3 0 1 0 30 56 31 46 59 47 94 6 3 0 1 0 56 57 31 59 60 47 95 6 3 0 1 0 29 54 33 31 57 35 96 6 3 0 1 0 54 55 33 57 58 35 97 6 3 0 1 0 31 57 35 47 60 49 98 6 3 0 1 0 57 58 35 60 61 49 $EndElements dune-grid-2.11.0/doc/grids/gmsh/hybrid-testgrid-3d.msh.license000066400000000000000000000002501511655130300240230ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/oned-testgrid.msh000066400000000000000000000005611511655130300215470ustar00rootroot00000000000000$MeshFormat 2.1 0 8 $EndMeshFormat $Nodes 10 1 0 0 0 2 0.2 0 0 3 0.5 0 0 4 0.85 0 0 5 1.1 0 0 6 1.3 0 0 7 1.35 0 0 8 1.5 0 0 9 1.8 0 0 10 2 0 0 $EndNodes $Elements 11 1 15 2 1 1 1 2 15 2 2 2 2 3 1 2 3 3 1 3 4 1 2 3 3 3 4 5 1 2 3 3 4 5 6 1 2 3 3 5 6 7 1 2 3 3 6 7 8 1 2 3 3 7 8 9 1 2 3 3 8 9 10 1 2 3 3 9 10 11 1 2 3 3 10 2 $EndElements dune-grid-2.11.0/doc/grids/gmsh/oned-testgrid.msh.license000066400000000000000000000002501511655130300231630ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/pyramid.geo000066400000000000000000000021501511655130300204230ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // mesh width associated with points lc = 1; // vertices of the pyramid Point(1) = {0, 0, 0, lc}; Point(2) = {1, 0, 0, lc}; Point(3) = {1, 1, 0, lc}; Point(4) = {0, 1, 0, lc}; Point(5) = {0.5, 0.5, 1, lc}; // lines of the pyramid Line(1) = {1,2}; Line(2) = {3,2}; Line(3) = {3,4}; Line(4) = {4,1}; Line(5) = {1,5}; Line(6) = {2,5}; Line(7) = {3,5}; Line(8) = {4,5}; // faces Line Loop(100) = {4,1,-2,3}; Plane Surface(200) = {100}; Physical Surface(300) = {200}; Line Loop(101) = {5,-8,4}; Plane Surface(201) = {101}; Physical Surface(301) = {201}; Line Loop(102) = {1,6,-5}; Plane Surface(202) = {102}; Physical Surface(302) = {202}; Line Loop(103) = {-2,7,-6}; Plane Surface(203) = {103}; Physical Surface(303) = {203}; Line Loop(104) = {3,8,-7}; Plane Surface(204) = {104}; Physical Surface(304) = {204}; // volume Surface Loop(400) = {200,-201,-202,-203,-204}; Volume(1000) = {400}; Physical Volume(1001) = {1000};dune-grid-2.11.0/doc/grids/gmsh/pyramid.msh000066400000000000000000000006411511655130300204430ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 6 1 0 0 0 2 1 0 0 3 1 1 0 4 0 1 0 5 0.5 0.5 1 6 0.5 0.5 0 $EndNodes $Elements 12 1 2 3 300 200 0 2 3 6 2 2 3 300 200 0 4 1 6 3 2 3 300 200 0 6 3 4 4 2 3 300 200 0 6 1 2 5 2 3 301 201 0 4 1 5 6 2 3 302 202 0 5 1 2 7 2 3 303 203 0 2 3 5 8 2 3 304 204 0 3 4 5 9 4 3 1001 1000 0 5 6 1 4 10 4 3 1001 1000 0 6 5 2 3 11 4 3 1001 1000 0 6 5 1 2 12 4 3 1001 1000 0 6 5 3 4 $EndElements dune-grid-2.11.0/doc/grids/gmsh/pyramid.msh.license000066400000000000000000000002501511655130300220600ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/pyramid1storder.msh000066400000000000000000000221601511655130300221270ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 53 1 0 0 0 2 1 0 0 3 1 1 0 4 0 1 0 5 0.5 0.5 1 6 0.3333333333326071 0 0 7 0.6666666666658988 0 0 8 1 0.6666666666673606 0 9 1 0.3333333333344899 0 10 0.6666666666673606 1 0 11 0.3333333333344899 1 0 12 0 0.6666666666673606 0 13 0 0.3333333333344899 0 14 0.1249999999996999 0.1249999999996999 0.2499999999993999 15 0.2499999999995108 0.2499999999995108 0.4999999999990216 16 0.3749999999996687 0.3749999999996687 0.7499999999993373 17 0.87500000000025 0.12499999999975 0.2499999999994999 18 0.7500000000004077 0.2499999999995924 0.4999999999991847 19 0.6250000000002762 0.3749999999997238 0.7499999999994477 20 0.8750000000002001 0.8750000000002001 0.2499999999995999 21 0.7500000000003261 0.7500000000003261 0.4999999999993478 22 0.6250000000002209 0.6250000000002209 0.7499999999995582 23 0.12499999999975 0.87500000000025 0.2499999999994999 24 0.2499999999995924 0.7500000000004077 0.4999999999991847 25 0.3749999999997238 0.6250000000002762 0.7499999999994477 26 0.3639033392546204 0.5954624009578063 0 27 0.7120448435523091 0.4711680458938197 0 28 0.7000000000003407 0.7730158730161253 0 29 0.5009013259129258 0.2406967446550917 0 30 0.1670166571151259 0.8195599259787936 0 31 0.7627931060058153 0.2108833544116794 0 32 0.1996896664166923 0.3060265242691247 0 33 0.1249999999997588 0.5000000000002864 0.2499999999995176 34 0.4999999999997289 0.1249999999997588 0.2499999999995177 35 0.8571428571430787 0.5000000000002397 0.2857142857138427 36 0.721428571428862 0.5000000000000207 0.5571428571422761 37 0.5000000000002397 0.8571428571430787 0.2857142857138427 38 0.5000000000000207 0.7214285714288619 0.5571428571422762 39 0.2677579146426077 0.2769359744783708 0.1646975042955377 40 0.5096482320657152 0.5406015447636159 0.6057595193216642 41 0.6388549377566251 0.6098836289304436 0.2173310761956732 42 0.267300242529202 0.7213833835303086 0.1944063184732271 43 0.7592291127947405 0.2554429346253858 0.1669026302597196 44 0.4160404007918626 0.4635766868828686 0.2447221945656728 45 0.4889192391812134 0.7526543648240001 0.1500770840667231 46 0.3630450926581165 0.5161961377420073 0.4241797003252677 47 0.6426676772766268 0.4024407957586388 0.2849231714347928 48 0.7532543778456801 0.7618227375108674 0.1699118677978942 49 0.5017862098224338 0.6219253262665483 0.3763919075597252 50 0.5471468075773914 0.2667908505325998 0.137726505228583 51 0.8005716097098666 0.5280050995872937 0.1243525177981781 52 0.1974383441906978 0.5011086013227118 0.1254955658413808 53 0.52545029219707 0.4153219564663576 0.4626686484106982 $EndNodes $Elements 228 1 2 3 300 200 0 8 3 28 2 2 3 300 200 0 28 3 10 3 2 3 300 200 0 27 9 8 4 2 3 300 200 0 27 8 28 5 2 3 300 200 0 11 26 28 6 2 3 300 200 0 28 10 11 7 2 3 300 200 0 27 28 26 8 2 3 300 200 0 29 27 26 9 2 3 300 200 0 29 6 7 10 2 3 300 200 0 11 4 30 11 2 3 300 200 0 12 26 30 12 2 3 300 200 0 30 4 12 13 2 3 300 200 0 30 26 11 14 2 3 300 200 0 7 2 31 15 2 3 300 200 0 9 27 31 16 2 3 300 200 0 31 2 9 17 2 3 300 200 0 29 7 31 18 2 3 300 200 0 29 31 27 19 2 3 300 200 0 32 1 6 20 2 3 300 200 0 13 1 32 21 2 3 300 200 0 12 13 32 22 2 3 300 200 0 32 6 29 23 2 3 300 200 0 29 26 32 24 2 3 300 200 0 12 32 26 25 2 3 301 201 0 4 12 23 26 2 3 301 201 0 25 16 5 27 2 3 301 201 0 13 1 14 28 2 3 301 201 0 12 33 23 29 2 3 301 201 0 33 24 23 30 2 3 301 201 0 13 33 12 31 2 3 301 201 0 14 33 13 32 2 3 301 201 0 15 33 14 33 2 3 301 201 0 16 25 24 34 2 3 301 201 0 24 33 15 35 2 3 301 201 0 15 16 24 36 2 3 302 202 0 5 16 19 37 2 3 302 202 0 14 1 6 38 2 3 302 202 0 17 7 2 39 2 3 302 202 0 34 7 17 40 2 3 302 202 0 18 34 17 41 2 3 302 202 0 6 7 34 42 2 3 302 202 0 34 14 6 43 2 3 302 202 0 34 15 14 44 2 3 302 202 0 19 16 18 45 2 3 302 202 0 34 18 15 46 2 3 302 202 0 16 15 18 47 2 3 303 203 0 2 9 17 48 2 3 303 203 0 19 22 5 49 2 3 303 203 0 8 3 20 50 2 3 303 203 0 35 8 20 51 2 3 303 203 0 21 35 20 52 2 3 303 203 0 35 9 8 53 2 3 303 203 0 35 17 9 54 2 3 303 203 0 35 18 17 55 2 3 303 203 0 36 18 35 56 2 3 303 203 0 36 21 22 57 2 3 303 203 0 21 36 35 58 2 3 303 203 0 19 18 36 59 2 3 303 203 0 22 19 36 60 2 3 304 204 0 10 20 3 61 2 3 304 204 0 4 23 11 62 2 3 304 204 0 22 25 5 63 2 3 304 204 0 10 37 20 64 2 3 304 204 0 37 21 20 65 2 3 304 204 0 11 37 10 66 2 3 304 204 0 23 37 11 67 2 3 304 204 0 37 23 24 68 2 3 304 204 0 21 38 22 69 2 3 304 204 0 24 38 37 70 2 3 304 204 0 38 21 37 71 2 3 304 204 0 25 22 38 72 2 3 304 204 0 24 25 38 73 4 3 1001 1000 0 1 13 14 39 74 4 3 1001 1000 0 46 44 53 15 75 4 3 1001 1000 0 46 24 33 15 76 4 3 1001 1000 0 46 44 15 33 77 4 3 1001 1000 0 43 18 35 47 78 4 3 1001 1000 0 49 45 37 41 79 4 3 1001 1000 0 14 6 39 34 80 4 3 1001 1000 0 25 24 40 16 81 4 3 1001 1000 0 39 50 26 44 82 4 3 1001 1000 0 52 42 33 44 83 4 3 1001 1000 0 13 14 39 33 84 4 3 1001 1000 0 19 40 16 5 85 4 3 1001 1000 0 41 36 21 49 86 4 3 1001 1000 0 48 21 37 41 87 4 3 1001 1000 0 26 41 28 45 88 4 3 1001 1000 0 39 50 29 26 89 4 3 1001 1000 0 43 17 7 2 90 4 3 1001 1000 0 31 50 43 27 91 4 3 1001 1000 0 52 42 44 26 92 4 3 1001 1000 0 48 37 10 45 93 4 3 1001 1000 0 39 15 44 33 94 4 3 1001 1000 0 48 20 3 10 95 4 3 1001 1000 0 48 8 3 20 96 4 3 1001 1000 0 31 50 27 29 97 4 3 1001 1000 0 17 43 7 34 98 4 3 1001 1000 0 37 11 42 23 99 4 3 1001 1000 0 46 42 49 44 100 4 3 1001 1000 0 8 35 20 48 101 4 3 1001 1000 0 12 42 23 33 102 4 3 1001 1000 0 12 13 52 33 103 4 3 1001 1000 0 48 37 45 41 104 4 3 1001 1000 0 5 25 40 16 105 4 3 1001 1000 0 44 47 53 34 106 4 3 1001 1000 0 39 26 52 44 107 4 3 1001 1000 0 17 43 35 9 108 4 3 1001 1000 0 12 23 42 4 109 4 3 1001 1000 0 23 11 42 4 110 4 3 1001 1000 0 46 42 44 33 111 4 3 1001 1000 0 18 16 53 15 112 4 3 1001 1000 0 43 18 47 34 113 4 3 1001 1000 0 19 53 16 40 114 4 3 1001 1000 0 53 49 44 46 115 4 3 1001 1000 0 39 29 50 6 116 4 3 1001 1000 0 37 11 10 45 117 4 3 1001 1000 0 43 31 9 2 118 4 3 1001 1000 0 44 45 49 41 119 4 3 1001 1000 0 39 15 33 14 120 4 3 1001 1000 0 31 50 29 7 121 4 3 1001 1000 0 49 21 41 37 122 4 3 1001 1000 0 19 40 5 22 123 4 3 1001 1000 0 47 49 41 44 124 4 3 1001 1000 0 26 12 42 30 125 4 3 1001 1000 0 26 11 42 45 126 4 3 1001 1000 0 6 29 50 7 127 4 3 1001 1000 0 53 18 15 34 128 4 3 1001 1000 0 11 26 42 30 129 4 3 1001 1000 0 44 45 41 26 130 4 3 1001 1000 0 44 45 26 42 131 4 3 1001 1000 0 52 42 26 12 132 4 3 1001 1000 0 47 49 44 53 133 4 3 1001 1000 0 29 27 26 50 134 4 3 1001 1000 0 43 27 47 51 135 4 3 1001 1000 0 8 51 27 9 136 4 3 1001 1000 0 40 21 36 49 137 4 3 1001 1000 0 35 18 36 47 138 4 3 1001 1000 0 41 47 35 36 139 4 3 1001 1000 0 19 53 40 36 140 4 3 1001 1000 0 53 16 46 15 141 4 3 1001 1000 0 47 27 41 51 142 4 3 1001 1000 0 23 42 24 33 143 4 3 1001 1000 0 6 1 14 39 144 4 3 1001 1000 0 17 43 9 2 145 4 3 1001 1000 0 51 28 48 8 146 4 3 1001 1000 0 1 13 39 32 147 4 3 1001 1000 0 39 29 6 32 148 4 3 1001 1000 0 13 39 52 33 149 4 3 1001 1000 0 39 32 26 29 150 4 3 1001 1000 0 6 1 39 32 151 4 3 1001 1000 0 25 24 38 40 152 4 3 1001 1000 0 40 21 49 38 153 4 3 1001 1000 0 22 25 38 40 154 4 3 1001 1000 0 46 16 53 40 155 4 3 1001 1000 0 46 16 24 15 156 4 3 1001 1000 0 44 27 41 47 157 4 3 1001 1000 0 48 21 41 35 158 4 3 1001 1000 0 48 21 35 20 159 4 3 1001 1000 0 44 27 47 50 160 4 3 1001 1000 0 41 36 35 21 161 4 3 1001 1000 0 51 28 8 27 162 4 3 1001 1000 0 52 42 12 33 163 4 3 1001 1000 0 43 27 9 31 164 4 3 1001 1000 0 44 45 42 49 165 4 3 1001 1000 0 12 42 30 4 166 4 3 1001 1000 0 42 11 30 4 167 4 3 1001 1000 0 43 27 51 9 168 4 3 1001 1000 0 31 43 7 2 169 4 3 1001 1000 0 31 50 7 43 170 4 3 1001 1000 0 53 15 44 34 171 4 3 1001 1000 0 13 39 32 52 172 4 3 1001 1000 0 39 15 14 34 173 4 3 1001 1000 0 18 47 53 36 174 4 3 1001 1000 0 39 15 34 44 175 4 3 1001 1000 0 26 12 32 52 176 4 3 1001 1000 0 19 40 22 36 177 4 3 1001 1000 0 44 39 33 52 178 4 3 1001 1000 0 39 32 52 26 179 4 3 1001 1000 0 22 25 40 5 180 4 3 1001 1000 0 24 49 40 46 181 4 3 1001 1000 0 26 28 41 27 182 4 3 1001 1000 0 48 21 20 37 183 4 3 1001 1000 0 48 37 20 10 184 4 3 1001 1000 0 45 11 10 28 185 4 3 1001 1000 0 45 11 28 26 186 4 3 1001 1000 0 24 16 46 40 187 4 3 1001 1000 0 11 37 42 45 188 4 3 1001 1000 0 46 42 33 24 189 4 3 1001 1000 0 46 42 24 49 190 4 3 1001 1000 0 24 40 49 38 191 4 3 1001 1000 0 53 49 46 40 192 4 3 1001 1000 0 43 18 34 17 193 4 3 1001 1000 0 43 18 17 35 194 4 3 1001 1000 0 50 47 34 43 195 4 3 1001 1000 0 53 47 18 34 196 4 3 1001 1000 0 47 49 53 36 197 4 3 1001 1000 0 50 47 43 27 198 4 3 1001 1000 0 28 48 3 10 199 4 3 1001 1000 0 28 8 3 48 200 4 3 1001 1000 0 51 28 27 41 201 4 3 1001 1000 0 51 28 41 48 202 4 3 1001 1000 0 45 28 10 48 203 4 3 1001 1000 0 41 45 48 28 204 4 3 1001 1000 0 49 21 37 38 205 4 3 1001 1000 0 12 13 32 52 206 4 3 1001 1000 0 48 51 35 41 207 4 3 1001 1000 0 40 21 38 22 208 4 3 1001 1000 0 40 21 22 36 209 4 3 1001 1000 0 43 51 35 9 210 4 3 1001 1000 0 49 24 37 42 211 4 3 1001 1000 0 44 27 50 26 212 4 3 1001 1000 0 50 43 34 7 213 4 3 1001 1000 0 39 50 34 6 214 4 3 1001 1000 0 6 50 34 7 215 4 3 1001 1000 0 50 47 44 34 216 4 3 1001 1000 0 39 50 44 34 217 4 3 1001 1000 0 44 27 26 41 218 4 3 1001 1000 0 48 51 8 35 219 4 3 1001 1000 0 19 53 36 18 220 4 3 1001 1000 0 41 47 51 35 221 4 3 1001 1000 0 49 45 42 37 222 4 3 1001 1000 0 23 37 24 42 223 4 3 1001 1000 0 49 24 38 37 224 4 3 1001 1000 0 47 49 36 41 225 4 3 1001 1000 0 19 53 18 16 226 4 3 1001 1000 0 53 49 40 36 227 4 3 1001 1000 0 43 51 47 35 228 4 3 1001 1000 0 8 35 51 9 $EndElements dune-grid-2.11.0/doc/grids/gmsh/pyramid1storder.msh.license000066400000000000000000000002501511655130300235440ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/pyramid2ndorder.msh000066400000000000000000000646071511655130300221170ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 287 1 0 0 0 2 1 0 0 3 1 1 0 4 0 1 0 5 0.5 0.5 1 6 0.3333333333326071 0 0 7 0.6666666666658988 0 0 8 0.1666666666663799 0 0 9 0.4999999999987903 0 0 10 0.8333333333329493 0 0 11 1 0.6666666666673606 0 12 1 0.3333333333344899 0 13 1 0.8333333333335889 0 14 1 0.5000000000013946 0 15 1 0.1666666666672449 0 16 0.6666666666673606 1 0 17 0.3333333333344899 1 0 18 0.8333333333335889 1 0 19 0.5000000000013946 1 0 20 0.1666666666672449 1 0 21 0 0.6666666666673606 0 22 0 0.3333333333344899 0 23 0 0.8333333333335889 0 24 0 0.5000000000013946 0 25 0 0.1666666666672449 0 26 0.1249999999996999 0.1249999999996999 0.2499999999993999 27 0.2499999999995108 0.2499999999995108 0.4999999999990216 28 0.3749999999996687 0.3749999999996687 0.7499999999993373 29 0.06249999999988481 0.06249999999988481 0.1249999999997696 30 0.1874999999996054 0.1874999999996054 0.3749999999992107 31 0.3124999999995897 0.3124999999995897 0.6249999999991794 32 0.4374999999998343 0.4374999999998343 0.8749999999996686 33 0.87500000000025 0.12499999999975 0.2499999999994999 34 0.7500000000004077 0.2499999999995924 0.4999999999991847 35 0.6250000000002762 0.3749999999997238 0.7499999999994477 36 0.9375000000000819 0.06249999999991804 0.1249999999998361 37 0.8125000000003288 0.1874999999996712 0.3749999999993423 38 0.6875000000003539 0.312499999999646 0.624999999999292 39 0.5625000000001457 0.4374999999998543 0.8749999999997087 40 0.8750000000002001 0.8750000000002001 0.2499999999995999 41 0.7500000000003261 0.7500000000003261 0.4999999999993478 42 0.6250000000002209 0.6250000000002209 0.7499999999995582 43 0.9375000000000768 0.9375000000000768 0.1249999999998464 44 0.812500000000282 0.812500000000282 0.3749999999994359 45 0.6875000000003033 0.6875000000003033 0.6249999999993935 46 0.5625000000000699 0.5625000000000699 0.8749999999998602 47 0.12499999999975 0.87500000000025 0.2499999999994999 48 0.2499999999995924 0.7500000000004077 0.4999999999991847 49 0.3749999999997238 0.6250000000002762 0.7499999999994477 50 0.06249999999991804 0.9375000000000819 0.1249999999998361 51 0.1874999999996712 0.8125000000003288 0.3749999999993423 52 0.312499999999646 0.6875000000003539 0.624999999999292 53 0.4374999999998543 0.5625000000001457 0.8749999999997087 54 0.3642317708336535 0.6704612406308721 0 55 0.6279541454621917 0.4598066009350121 0 56 0.7000000000003407 0.7730158730161253 0 57 0.2424850583664214 0.4641886685647242 0 58 0.1743912760420359 0.8342819768245582 0 59 0.4344356683619328 0.24277369480279 0 60 0.7361748063444772 0.1993135659825139 0 61 0.8500000000001704 0.8865079365080626 0 62 0.8500000000001704 0.7198412698417429 0 63 0.6833333333338507 0.8865079365080626 0 64 0.8139770727310959 0.396569967134751 0 65 0.8139770727310959 0.5632366338011864 0 66 0.4352196019143065 0.4619976347498681 0 67 0.4960929581479226 0.5651339207829421 0 68 0.3033584146000374 0.5673249545977981 0 69 0.6639770727312662 0.6164112369755687 0 70 0.3487825520840717 0.835230620315436 0 71 0.5321158854169972 0.7217385568234986 0 72 0.5166666666674153 0.8865079365080626 0 73 0.1821158854168268 0.6685639536491164 0 74 0.1212425291832107 0.5654276676160424 0 75 0.1212425291832107 0.398761000949607 0 76 0.08719563802101793 0.9171409884122791 0 77 0.2538623046882629 0.9171409884122791 0 78 0.2693115234378447 0.7523716087277151 0 79 0.08719563802101793 0.7504743217459594 0 80 0.3384603633641771 0.3534811816837571 0 81 0.2172178341809664 0.2880535140686399 0 82 0.8680874031722385 0.09965678299125694 0 83 0.8680874031722385 0.2663234496585019 0 84 0.701420736505188 0.09965678299125694 0 85 0.6820644759033345 0.329560083458763 0 86 0.5505511675139158 0.121386847401395 0 87 0.3838845008472699 0.121386847401395 0 88 0.5311949069120623 0.351290147868901 0 89 0.5853052373532049 0.2210436303926519 0 90 0.1666666666663036 0.1666666666672449 0 91 0.1249999999997588 0.5000000000002864 0.2499999999995176 92 0.06249999999987498 0.7708333333338053 0.1249999999997499 93 0.3749999999996962 0.4999999999999725 0.7499999999993925 94 0.06249999999984996 0.2291666666670949 0.1249999999996999 95 0.06249999999987942 0.5833333333338235 0.1249999999997588 96 0.1249999999997544 0.6875000000002682 0.2499999999995088 97 0.1874999999996756 0.6250000000003471 0.3749999999993512 98 0.06249999999987941 0.4166666666673882 0.1249999999997588 99 0.1249999999997294 0.3124999999999932 0.2499999999994588 100 0.1874999999996348 0.3749999999998986 0.3749999999992696 101 0.3124999999996305 0.5625000000000382 0.624999999999261 102 0.2499999999995516 0.4999999999999593 0.4999999999991031 103 0.4999999999997289 0.1249999999997588 0.2499999999995177 104 0.4999999999999725 0.3749999999996963 0.7499999999993925 105 0.2291666666661535 0.06249999999984995 0.1249999999997 106 0.7708333333330744 0.06249999999987494 0.12499999999975 107 0.5833333333328139 0.06249999999987939 0.1249999999997588 108 0.6874999999999895 0.1249999999997544 0.2499999999995088 109 0.6250000000000683 0.1874999999996756 0.3749999999993512 110 0.416666666666168 0.06249999999987939 0.1249999999997588 111 0.3124999999997145 0.1249999999997294 0.2499999999994588 112 0.3749999999996199 0.1874999999996348 0.3749999999992697 113 0.5625000000000382 0.3124999999996306 0.624999999999261 114 0.4999999999999593 0.2499999999995516 0.4999999999991032 115 0.8571428571430787 0.5000000000002397 0.2857142857138427 116 0.721428571428862 0.5000000000000207 0.5571428571422761 117 0.937500000000125 0.2291666666671199 0.1249999999997499 118 0.6250000000002486 0.4999999999999724 0.749999999999503 119 0.9375000000001 0.7708333333337803 0.1249999999997999 120 0.9285714285715393 0.5833333333338002 0.1428571428569213 121 0.8660714285716393 0.6875000000002198 0.2678571428567213 122 0.8035714285717024 0.6250000000002829 0.3928571428565952 123 0.9285714285715393 0.4166666666673648 0.1428571428569213 124 0.8660714285716644 0.3124999999999948 0.2678571428566713 125 0.8035714285717431 0.374999999999916 0.3928571428565137 126 0.7357142857146348 0.3749999999998065 0.5285714285707304 127 0.7892857142859703 0.5000000000001301 0.4214285714280594 128 0.735714285714594 0.6250000000001734 0.528571428570812 129 0.6732142857145414 0.5625000000001208 0.6535714285709171 130 0.6732142857145691 0.4374999999998722 0.6535714285708618 131 0.5000000000002397 0.8571428571430787 0.2857142857138427 132 0.5000000000000207 0.7214285714288619 0.5571428571422762 133 0.7708333333337803 0.9375000000001 0.1249999999998 134 0.2291666666671199 0.937500000000125 0.1249999999997499 135 0.4999999999999724 0.6250000000002486 0.749999999999503 136 0.5833333333338002 0.9285714285715393 0.1428571428569213 137 0.6875000000002198 0.8660714285716393 0.2678571428567214 138 0.6250000000002829 0.8035714285717024 0.3928571428565952 139 0.4166666666673648 0.9285714285715393 0.1428571428569213 140 0.3124999999999948 0.8660714285716644 0.2678571428566713 141 0.374999999999916 0.8035714285717431 0.3928571428565137 142 0.6250000000001734 0.735714285714594 0.528571428570812 143 0.5625000000001208 0.6732142857145413 0.6535714285709172 144 0.3749999999998065 0.7357142857146348 0.5285714285707304 145 0.5000000000001301 0.7892857142859703 0.4214285714280594 146 0.4374999999998722 0.6732142857145691 0.6535714285708618 147 0.5507338098255551 0.4645248381895007 0.5232986855614836 148 0.6871257079361344 0.7402703534781812 0.1694269396025537 149 0.751692308501738 0.2468389771003291 0.1662827588942261 150 0.2088642291311507 0.7974762027386184 0.1190515764304819 151 0.621076941373279 0.5917617191280349 0.3174423759792704 152 0.2564997849770231 0.5758801697118795 0.167985698486623 153 0.4990675101293739 0.5178873429989318 0.7122112289472471 154 0.5479737072400569 0.2226359257205258 0.1242514202537581 155 0.3132876990438742 0.3022227801207888 0.1755659325932987 156 0.4123158017662573 0.7022454839443384 0.2291668773873243 157 0.4030419597391343 0.4877355518220097 0.3436452769766968 158 0.7714852815618992 0.4891908777361041 0.1373566265155888 159 0.4170502343781348 0.5399432695427411 0.5583766322351125 160 0.6280766912827445 0.3804105926549629 0.2700593444029668 161 0.6360811906272086 0.4822624190947607 0.5402207713518798 162 0.587866904912888 0.5447624190948608 0.6366493427805209 163 0.6503669049129406 0.6072624190949134 0.5116493427804157 164 0.6498330078708974 0.2347374514104274 0.1452670895739921 165 0.6898232269819649 0.3533227890176706 0.08314137944711306 166 0.5879639263511243 0.3412212633277689 0.06212571012687906 167 0.642074256792267 0.2109747458515198 0.06212571012687906 168 0.7439335574231076 0.2230762715414215 0.08314137944711306 169 0.5878669049129157 0.4197624190946123 0.6366493427804656 170 0.6503669049129814 0.3572624190945465 0.5116493427803341 171 0.4628669049126118 0.4197624190945847 0.6366493427804105 172 0.7185628539682303 0.7451351767392536 0.3347134698009507 173 0.7721342825396065 0.6201351767392105 0.2275706126581982 174 0.6541013246547067 0.666016036303108 0.243434657790912 175 0.7391098992581788 0.5458808595641373 0.3015783308465565 176 0.6855384706868025 0.6708808595641804 0.4087211879893091 177 0.593562853968187 0.79870660531063 0.2275706126581982 178 0.6768961873017475 0.8701351767390906 0.08471346980127684 179 0.5102295206353121 0.8701351767390906 0.08471346980127684 180 0.3311579008829248 0.726122741972373 0.3645834386932545 181 0.2686579008830036 0.7886227419722942 0.2395834386934121 182 0.4561579008832485 0.7796941705437086 0.2574405815505835 183 0.8435628539680672 0.8701351767390906 0.08471346980127684 184 0.7810628539681672 0.8076351767391906 0.2097134698010768 185 0.483892022101845 0.502234053866121 0.540837658898298 186 0.4100460970586346 0.5138394106823754 0.4510109546059047 187 0.4768878847823447 0.4761301950057552 0.4334719812690903 188 0.5253669049127878 0.5929767048091813 0.5402207713518798 189 0.4515209798695775 0.6045820616254358 0.4503940670594865 190 0.4585251171890777 0.6306859204858015 0.5577597446886944 191 0.2865479999824021 0.7339687216847453 0.05952578821524093 192 0.1044321145655753 0.7320714347029895 0.05952578821524093 193 0.1916277525865933 0.8158790897815883 0.05952578821524093 194 0.5605384706867593 0.7244522881355568 0.3015783308465565 195 0.3335251171888636 0.6449716347715744 0.5291883161171486 196 0.3265209798693633 0.6188677759112087 0.4218226384879408 197 0.814314069352489 0.4945954388681719 0.2115354561147157 198 0.8857426407809497 0.5779287722017323 0.06867831325779439 199 0.8857426407809497 0.411262105535297 0.06867831325779439 200 0.2532498924883078 0.6629400848561435 0.3339928492429038 201 0.3297708723580787 0.5318078607669445 0.2558154877316599 202 0.190749892488391 0.5379400848560829 0.2089928492430703 203 0.2640209798694466 0.4938677759111481 0.2968226384881072 204 0.7091794875838184 0.1234194885501645 0.08314137944711306 205 0.813346154250994 0.1859194885500395 0.208141379446863 206 0.875846154250869 0.1234194885501645 0.08314137944711306 207 0.5120594505562066 0.5397486354750223 0.3305438264779836 208 0.585905375599417 0.5281432786587679 0.420370530770377 209 0.5605384706866499 0.6565951452784484 0.4372926165607733 210 0.6280154183724681 0.4201085967949875 0.1350296722014834 211 0.6898844998922412 0.3136247848776459 0.2181710516485964 212 0.6997809864223219 0.4348007351955335 0.2037079854592778 213 0.7615887950318185 0.3680149274182166 0.1518196927049074 214 0.6997197135120454 0.4744987393355581 0.06867831325779439 215 0.1044321145655753 0.8987381013693092 0.05952578821524093 216 0.1669321145654503 0.8362381013694342 0.1845257882149909 217 0.4370337550645489 0.5714436714996041 0.7311056144733474 218 0.4370337550645212 0.4464436714993002 0.7311056144732921 219 0.4995337550646869 0.508943671499466 0.8561056144736235 220 0.456157900883139 0.7118370276866002 0.3931548672648002 221 0.4076788807526958 0.594990517883174 0.2864060771820106 222 0.5155593255109394 0.4340730722384862 0.3068523106898318 223 0.6245768163280117 0.4860861558914988 0.2937508601911186 224 0.5894052505541498 0.4224677154222318 0.3966790149822252 225 0.5620337550648251 0.4464436714993278 0.7311056144733474 226 0.6712527564010704 0.5458808595640278 0.4372926165607732 227 0.400366904912533 0.3572624190945058 0.5116493427802526 228 0.3960251171889293 0.5824716347715087 0.6541883161172801 229 0.3960251171889018 0.4574716347712049 0.6541883161172248 230 0.4580588722537544 0.5289153062708365 0.6352939305911798 231 0.3265209798693225 0.3688677759107603 0.4218226384878592 232 0.2816438495216925 0.2761113900601498 0.3377829662961601 233 0.3581648293915043 0.3949791659713993 0.2596056047849977 234 0.2191438495218165 0.4011113900605376 0.2127829662964081 235 0.1282498924885116 0.62127341818962 0.08399284924331148 236 0.1282498924885116 0.4546067515231847 0.08399284924331148 237 0.7508461542510728 0.2484194885499607 0.3331413794467054 238 0.8044175828224083 0.3734194885502844 0.2259985223040344 239 0.6890383456415761 0.3152052963272776 0.3850296722010758 240 0.7426097742129116 0.4402052963276013 0.2778868150584047 241 0.6073201869529778 0.1113179628602629 0.06212571012687906 242 0.6962811114675891 0.5404762984320695 0.2273995012474296 243 0.6245155434177354 0.5257841600315235 0.1587211879896352 244 0.4066438495218015 0.2136113900602738 0.2127829662964082 245 0.3233105161882407 0.1511113900603944 0.08778296629664933 246 0.440653520286332 0.1113179628602629 0.06212571012687906 247 0.4306307031419656 0.2624293529206573 0.1499086764235284 248 0.5239868536198929 0.1738179628601423 0.1871257101266379 249 0.1907498924883865 0.7254400848560647 0.2089928492430614 250 0.2326820070540869 0.6866781862252489 0.1435186374585524 251 0.3738616837029035 0.2724982374617894 0.08778296629664933 252 0.4912046878009948 0.2327048102616579 0.06212571012687906 253 0.470620922253033 0.3810146905279004 0.08778296629664933 254 0.6258461542507334 0.1859194885500439 0.2081413794468719 255 0.3335251171888228 0.394971634771126 0.5291883161170671 256 0.875846154250869 0.2900861552174095 0.08314137944711306 257 0.5880251992614007 0.3015232591877443 0.1971553823283624 258 0.2191438495217871 0.2136113900602444 0.2127829662963493 259 0.2710987812328203 0.8987381013693092 0.05952578821524093 260 0.5249006599774645 0.4912060905942163 0.6177549572543654 261 0.2848937420104487 0.4390514749163341 0.1717758155399608 262 0.1566438495219371 0.3177780567276394 0.08778296629664933 263 0.8435628539680672 0.7034685100727709 0.08471346980127684 264 0.4706821951633093 0.3413166863878758 0.2228126384981327 265 0.5640383456412367 0.2527052963273608 0.2600296722012422 266 0.4515209798694316 0.3063677759108843 0.2968226384881072 267 0.6747526313558032 0.4402052963274917 0.4136011007726214 268 0.7293054947490167 0.6147306156071426 0.1533917830590712 269 0.1566438495219371 0.1511113900603944 0.08778296629664933 270 0.5497207548511959 0.7212579187112598 0.199296908494939 271 0.3728245675503736 0.8511227419721692 0.1145834386936621 272 0.5166963715697681 0.6470036015361866 0.2733046266832974 273 0.525366904912642 0.2947624190946298 0.3866493427805007 274 0.3882737862999555 0.6863533622876052 0.1145834386936621 275 0.310590015448704 0.7498608433414784 0.1741092269089031 276 0.2778863787051478 0.3832057243427565 0.08778296629664933 277 0.4422269652196075 0.5178433853234458 0.08399284924331148 278 0.2494924216717223 0.5200344191383018 0.08399284924331148 279 0.6935628539682375 0.7566431132471532 0.08471346980127684 280 0.6575399266991631 0.6000384772065966 0.08471346980127684 281 0.525678739384894 0.7053657970545266 0.08471346980127684 282 0.5154980526006631 0.4737710763785109 0.1718226384883484 283 0.5201349736142246 0.5810260424396753 0.1145834386936621 284 0.3103657779053384 0.6231707051713757 0.08399284924331148 285 0.3344077933716402 0.6390628268281089 0.1985762879369736 286 0.4995337550646973 0.6196579572138968 0.6346770430447617 287 0.5620337550647974 0.5714436714995763 0.7311056144734027 $EndNodes $Elements 220 1 9 3 300 200 0 11 3 56 13 61 62 2 9 3 300 200 0 56 3 16 61 18 63 3 9 3 300 200 0 55 12 11 64 14 65 4 9 3 300 200 0 57 55 54 66 67 68 5 9 3 300 200 0 55 11 56 65 62 69 6 9 3 300 200 0 17 54 56 70 71 72 7 9 3 300 200 0 56 16 17 63 19 72 8 9 3 300 200 0 55 56 54 69 71 67 9 9 3 300 200 0 54 21 57 73 74 68 10 9 3 300 200 0 57 21 22 74 24 75 11 9 3 300 200 0 17 4 58 20 76 77 12 9 3 300 200 0 21 54 58 73 78 79 13 9 3 300 200 0 58 4 21 76 23 79 14 9 3 300 200 0 58 54 17 78 70 77 15 9 3 300 200 0 59 57 22 80 75 81 16 9 3 300 200 0 60 2 12 82 15 83 17 9 3 300 200 0 7 2 60 10 82 84 18 9 3 300 200 0 12 55 60 64 85 83 19 9 3 300 200 0 6 7 59 9 86 87 20 9 3 300 200 0 55 57 59 66 80 88 21 9 3 300 200 0 59 60 55 89 85 88 22 9 3 300 200 0 59 7 60 86 84 89 23 9 3 300 200 0 22 1 6 25 8 90 24 9 3 300 200 0 59 22 6 81 90 87 25 9 3 301 201 0 4 21 47 23 92 50 26 9 3 301 201 0 49 28 5 93 32 53 27 9 3 301 201 0 22 1 26 25 29 94 28 9 3 301 201 0 21 91 47 95 96 92 29 9 3 301 201 0 91 48 47 97 51 96 30 9 3 301 201 0 22 91 21 98 95 24 31 9 3 301 201 0 26 91 22 99 98 94 32 9 3 301 201 0 27 91 26 100 99 30 33 9 3 301 201 0 28 49 48 93 52 101 34 9 3 301 201 0 48 91 27 97 100 102 35 9 3 301 201 0 27 28 48 31 101 102 36 9 3 302 202 0 5 28 35 32 104 39 37 9 3 302 202 0 26 1 6 29 8 105 38 9 3 302 202 0 33 7 2 106 10 36 39 9 3 302 202 0 103 7 33 107 106 108 40 9 3 302 202 0 34 103 33 109 108 37 41 9 3 302 202 0 6 7 103 9 107 110 42 9 3 302 202 0 103 26 6 111 105 110 43 9 3 302 202 0 103 27 26 112 30 111 44 9 3 302 202 0 35 28 34 104 113 38 45 9 3 302 202 0 103 34 27 109 114 112 46 9 3 302 202 0 28 27 34 31 114 113 47 9 3 303 203 0 2 12 33 15 117 36 48 9 3 303 203 0 35 42 5 118 46 39 49 9 3 303 203 0 11 3 40 13 43 119 50 9 3 303 203 0 115 11 40 120 119 121 51 9 3 303 203 0 41 115 40 122 121 44 52 9 3 303 203 0 115 12 11 123 14 120 53 9 3 303 203 0 115 33 12 124 117 123 54 9 3 303 203 0 115 34 33 125 37 124 55 9 3 303 203 0 116 34 115 126 125 127 56 9 3 303 203 0 116 41 42 128 45 129 57 9 3 303 203 0 41 116 115 128 127 122 58 9 3 303 203 0 35 34 116 38 126 130 59 9 3 303 203 0 42 35 116 118 130 129 60 9 3 304 204 0 16 40 3 133 43 18 61 9 3 304 204 0 4 47 17 50 134 20 62 9 3 304 204 0 42 49 5 135 53 46 63 9 3 304 204 0 16 131 40 136 137 133 64 9 3 304 204 0 131 41 40 138 44 137 65 9 3 304 204 0 17 131 16 139 136 19 66 9 3 304 204 0 47 131 17 140 139 134 67 9 3 304 204 0 131 47 48 140 51 141 68 9 3 304 204 0 41 132 42 142 143 45 69 9 3 304 204 0 48 132 131 144 145 141 70 9 3 304 204 0 132 41 131 142 138 145 71 9 3 304 204 0 49 42 132 135 143 146 72 9 3 304 204 0 48 49 132 52 146 144 73 11 3 1001 1000 0 116 147 42 41 161 162 129 128 45 163 74 11 3 1001 1000 0 149 154 55 60 164 166 165 168 85 167 75 11 3 1001 1000 0 35 147 34 28 169 170 38 104 113 171 76 11 3 1001 1000 0 41 148 115 151 172 173 122 176 175 174 77 11 3 1001 1000 0 148 131 16 17 177 136 178 179 19 139 78 11 3 1001 1000 0 48 156 47 131 180 181 51 141 140 182 79 11 3 1001 1000 0 148 3 16 40 183 18 178 184 133 43 80 11 3 1001 1000 0 159 147 157 132 185 187 186 190 189 188 81 11 3 1001 1000 0 54 21 150 58 73 192 191 78 193 79 82 11 3 1001 1000 0 131 148 16 40 177 178 136 137 133 184 83 11 3 1001 1000 0 41 148 151 131 172 174 176 138 194 177 84 11 3 1001 1000 0 159 48 132 157 195 144 190 186 189 196 85 11 3 1001 1000 0 12 115 11 158 123 120 14 199 198 197 86 11 3 1001 1000 0 48 152 157 91 200 201 196 97 203 202 87 11 3 1001 1000 0 2 7 33 149 10 106 36 206 205 204 88 11 3 1001 1000 0 151 157 147 132 207 187 208 209 188 189 89 11 3 1001 1000 0 55 160 149 158 210 211 165 214 213 212 90 11 3 1001 1000 0 47 21 4 150 92 23 50 216 215 192 91 11 3 1001 1000 0 49 28 153 5 93 218 217 53 219 32 92 11 3 1001 1000 0 48 156 132 157 180 220 144 196 189 221 93 11 3 1001 1000 0 157 160 151 147 222 223 207 187 208 224 94 11 3 1001 1000 0 28 35 153 5 104 225 218 32 219 39 95 11 3 1001 1000 0 41 116 151 115 128 226 176 122 175 127 96 11 3 1001 1000 0 28 147 34 27 171 170 113 31 114 227 97 11 3 1001 1000 0 49 28 159 153 93 229 228 217 230 218 98 11 3 1001 1000 0 27 157 155 91 231 233 232 100 234 203 99 11 3 1001 1000 0 21 22 152 91 24 236 235 95 202 98 100 11 3 1001 1000 0 12 158 11 55 199 198 14 64 65 214 101 11 3 1001 1000 0 149 34 115 160 237 125 238 211 240 239 102 11 3 1001 1000 0 149 154 60 7 164 167 168 204 84 241 103 11 3 1001 1000 0 55 160 158 151 210 212 214 243 242 223 104 11 3 1001 1000 0 48 157 27 91 196 231 102 97 100 203 105 11 3 1001 1000 0 103 6 155 154 110 245 244 248 247 246 106 11 3 1001 1000 0 21 47 152 150 92 249 235 192 250 216 107 11 3 1001 1000 0 59 155 154 55 251 247 252 88 166 253 108 11 3 1001 1000 0 151 116 41 147 226 128 176 208 163 161 109 11 3 1001 1000 0 48 152 91 47 200 202 97 51 96 249 110 11 3 1001 1000 0 7 33 149 103 106 205 204 107 254 108 111 11 3 1001 1000 0 48 156 131 132 180 182 141 144 145 220 112 11 3 1001 1000 0 27 159 157 48 255 186 231 102 196 195 113 11 3 1001 1000 0 33 12 149 115 117 256 205 124 238 123 114 11 3 1001 1000 0 149 55 12 60 165 64 256 168 83 85 115 11 3 1001 1000 0 21 152 47 91 235 249 92 95 96 202 116 11 3 1001 1000 0 28 48 49 159 101 52 93 229 228 195 117 11 3 1001 1000 0 154 160 149 55 257 211 164 166 165 210 118 11 3 1001 1000 0 27 26 91 155 30 99 100 232 234 258 119 11 3 1001 1000 0 47 150 4 17 216 215 50 134 20 259 120 11 3 1001 1000 0 35 147 28 153 169 171 104 225 218 260 121 11 3 1001 1000 0 155 91 152 22 234 202 261 262 236 98 122 11 3 1001 1000 0 6 7 154 103 9 241 246 110 248 107 123 11 3 1001 1000 0 149 154 7 103 164 241 204 254 107 248 124 11 3 1001 1000 0 148 40 115 11 184 121 173 263 120 119 125 11 3 1001 1000 0 3 148 11 40 183 263 13 43 119 184 126 11 3 1001 1000 0 155 160 157 103 264 222 233 244 266 265 127 11 3 1001 1000 0 151 116 160 115 226 267 223 175 240 127 128 11 3 1001 1000 0 149 34 160 103 237 239 211 254 265 109 129 11 3 1001 1000 0 148 151 158 115 174 242 268 173 197 175 130 11 3 1001 1000 0 6 22 1 155 90 25 8 245 269 262 131 11 3 1001 1000 0 26 6 1 155 105 8 29 258 269 245 132 11 3 1001 1000 0 149 34 103 33 237 109 254 205 108 37 133 11 3 1001 1000 0 131 148 156 17 177 270 182 139 271 179 134 11 3 1001 1000 0 12 2 33 149 15 36 117 256 205 206 135 11 3 1001 1000 0 151 156 132 131 272 220 209 194 145 182 136 11 3 1001 1000 0 34 147 160 103 170 224 239 109 265 273 137 11 3 1001 1000 0 160 151 115 158 223 175 240 212 197 242 138 11 3 1001 1000 0 47 156 17 131 181 271 134 140 139 182 139 11 3 1001 1000 0 17 54 156 150 70 274 271 259 275 191 140 11 3 1001 1000 0 157 152 155 91 201 261 233 203 234 202 141 11 3 1001 1000 0 57 155 55 152 276 253 66 278 277 261 142 11 3 1001 1000 0 155 91 22 26 234 98 262 258 94 99 143 11 3 1001 1000 0 103 155 6 26 244 245 110 111 105 258 144 11 3 1001 1000 0 147 132 42 41 188 143 162 163 45 142 145 11 3 1001 1000 0 27 159 48 28 255 195 102 31 101 229 146 11 3 1001 1000 0 147 157 103 27 187 266 273 227 112 231 147 11 3 1001 1000 0 160 116 151 147 267 226 223 224 208 161 148 11 3 1001 1000 0 28 147 159 153 171 185 229 218 230 260 149 11 3 1001 1000 0 160 116 34 115 267 126 239 240 125 127 150 11 3 1001 1000 0 149 34 33 115 237 37 205 238 124 125 151 11 3 1001 1000 0 56 148 16 17 279 178 63 72 19 179 152 11 3 1001 1000 0 148 151 55 158 174 243 280 268 214 242 153 11 3 1001 1000 0 11 148 158 115 263 268 198 120 197 173 154 11 3 1001 1000 0 148 56 54 17 279 71 281 179 70 72 155 11 3 1001 1000 0 148 56 55 54 279 69 280 281 67 71 156 11 3 1001 1000 0 2 7 149 60 10 204 206 82 168 84 157 11 3 1001 1000 0 157 160 155 55 222 264 233 282 253 210 158 11 3 1001 1000 0 149 158 160 115 213 212 211 238 240 197 159 11 3 1001 1000 0 149 158 115 12 213 197 238 256 123 199 160 11 3 1001 1000 0 12 2 149 60 15 206 256 83 168 82 161 11 3 1001 1000 0 150 21 4 58 192 23 215 193 76 79 162 11 3 1001 1000 0 17 54 150 58 70 191 259 77 193 78 163 11 3 1001 1000 0 150 58 4 17 193 76 215 259 20 77 164 11 3 1001 1000 0 35 116 34 147 130 126 38 169 170 161 165 11 3 1001 1000 0 147 103 34 27 273 109 170 227 114 112 166 11 3 1001 1000 0 157 160 55 151 222 210 282 207 243 223 167 11 3 1001 1000 0 151 157 156 55 207 221 272 243 283 282 168 11 3 1001 1000 0 35 116 147 42 130 161 169 118 162 129 169 11 3 1001 1000 0 41 148 131 40 172 177 138 44 137 184 170 11 3 1001 1000 0 132 131 41 151 145 138 142 209 176 194 171 11 3 1001 1000 0 41 148 40 115 172 184 44 122 121 173 172 11 3 1001 1000 0 151 156 131 148 272 182 194 174 177 270 173 11 3 1001 1000 0 151 156 148 55 272 270 174 243 280 283 174 11 3 1001 1000 0 21 57 54 152 74 68 73 235 284 278 175 11 3 1001 1000 0 21 22 57 152 24 75 74 235 278 236 176 11 3 1001 1000 0 57 152 55 54 278 277 66 68 67 284 177 11 3 1001 1000 0 48 156 157 152 180 221 196 200 201 285 178 11 3 1001 1000 0 54 156 152 55 274 285 284 67 277 283 179 11 3 1001 1000 0 11 148 55 158 263 280 65 198 214 268 180 11 3 1001 1000 0 56 3 16 148 61 18 63 279 178 183 181 11 3 1001 1000 0 27 26 155 103 30 258 232 112 244 111 182 11 3 1001 1000 0 3 56 11 148 61 62 13 183 263 279 183 11 3 1001 1000 0 149 55 158 12 165 214 213 256 199 64 184 11 3 1001 1000 0 27 157 103 155 231 266 112 232 244 233 185 11 3 1001 1000 0 152 156 157 55 285 221 201 277 282 283 186 11 3 1001 1000 0 56 148 55 11 279 280 69 62 65 263 187 11 3 1001 1000 0 155 160 154 55 264 257 247 253 166 210 188 11 3 1001 1000 0 154 160 155 103 257 264 247 248 244 265 189 11 3 1001 1000 0 54 21 152 150 73 235 284 191 250 192 190 11 3 1001 1000 0 49 159 132 153 228 190 146 217 286 230 191 11 3 1001 1000 0 49 153 42 5 217 287 135 53 46 219 192 11 3 1001 1000 0 153 35 42 5 225 118 287 219 46 39 193 11 3 1001 1000 0 49 153 132 42 217 286 146 135 143 287 194 11 3 1001 1000 0 159 147 132 153 185 188 190 230 286 260 195 11 3 1001 1000 0 35 147 153 42 169 260 225 118 287 162 196 11 3 1001 1000 0 153 147 132 42 260 188 286 287 143 162 197 11 3 1001 1000 0 59 60 55 154 89 85 88 252 166 167 198 11 3 1001 1000 0 59 7 60 154 86 84 89 252 167 241 199 11 3 1001 1000 0 34 116 160 147 126 267 239 170 224 161 200 11 3 1001 1000 0 6 7 59 154 9 86 87 246 252 241 201 11 3 1001 1000 0 57 155 152 22 276 261 278 75 236 262 202 11 3 1001 1000 0 27 159 28 147 255 229 31 227 171 185 203 11 3 1001 1000 0 152 150 156 54 250 275 285 284 274 191 204 11 3 1001 1000 0 159 48 49 132 195 52 228 190 146 144 205 11 3 1001 1000 0 27 159 147 157 255 185 227 231 187 186 206 11 3 1001 1000 0 151 157 132 156 207 189 209 272 220 221 207 11 3 1001 1000 0 147 132 41 151 188 142 163 208 176 209 208 11 3 1001 1000 0 157 160 147 103 222 224 187 266 273 265 209 11 3 1001 1000 0 6 22 155 59 90 262 245 87 251 81 210 11 3 1001 1000 0 57 155 22 59 276 262 75 80 81 251 211 11 3 1001 1000 0 6 155 154 59 245 247 246 87 252 251 212 11 3 1001 1000 0 57 155 59 55 276 251 80 66 88 253 213 11 3 1001 1000 0 156 152 48 47 285 200 180 181 51 249 214 11 3 1001 1000 0 55 152 155 157 277 261 253 282 233 201 215 11 3 1001 1000 0 149 160 154 103 211 257 164 254 248 265 216 11 3 1001 1000 0 156 148 54 17 270 281 274 271 70 179 217 11 3 1001 1000 0 156 148 55 54 270 280 283 274 67 281 218 11 3 1001 1000 0 47 17 156 150 134 271 181 216 275 259 219 11 3 1001 1000 0 22 26 1 155 94 29 25 262 269 258 220 11 3 1001 1000 0 152 156 150 47 285 275 250 249 216 181 $EndElements dune-grid-2.11.0/doc/grids/gmsh/pyramid2ndorder.msh.license000066400000000000000000000002501511655130300235200ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/pyramid4.msh000066400000000000000000000006411511655130300205270ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 6 1 0 0 0 2 1 0 0 3 1 1 0 4 0 1 0 5 0.5 0.5 1 6 0.5 0.5 0 $EndNodes $Elements 12 1 2 3 300 200 0 2 3 6 2 2 3 300 200 0 4 1 6 3 2 3 300 200 0 6 3 4 4 2 3 300 200 0 6 1 2 5 2 3 301 201 0 4 1 5 6 2 3 302 202 0 5 1 2 7 2 3 303 203 0 2 3 5 8 2 3 304 204 0 3 4 5 9 4 3 1001 1000 0 5 6 1 4 10 4 3 1001 1000 0 6 5 2 3 11 4 3 1001 1000 0 6 5 1 2 12 4 3 1001 1000 0 6 5 3 4 $EndElements dune-grid-2.11.0/doc/grids/gmsh/pyramid4.msh.license000066400000000000000000000002501511655130300221440ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/sphere.msh000066400000000000000000001066541511655130300202770ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 319 1 0 0 0 2 1 0 0 3 0 1 0 4 -1 0 0 5 0 -1 0 6 0 0 -1 7 0 0 1 8 0.9749279121822653 0.2225209339543793 0 9 0.9009688679037553 0.4338837391147836 0 10 0.7818314824689672 0.6234898018575581 0 11 0.623489801858605 0.7818314824681323 0 12 0.4338837391158249 0.9009688679032538 0 13 0.2225209339549976 0.9749279121821242 0 14 -0.2225209339543793 0.9749279121822653 0 15 -0.4338837391147836 0.9009688679037553 0 16 -0.6234898018575581 0.7818314824689672 0 17 -0.7818314824681323 0.623489801858605 0 18 -0.9009688679032538 0.4338837391158249 0 19 -0.9749279121821242 0.2225209339549976 0 20 -0.9749279121822653 -0.2225209339543793 0 21 -0.9009688679037553 -0.4338837391147836 0 22 -0.7818314824689672 -0.6234898018575581 0 23 -0.623489801858605 -0.7818314824681323 0 24 -0.4338837391158249 -0.9009688679032538 0 25 -0.2225209339549976 -0.9749279121821242 0 26 0.2225209339543793 -0.9749279121822653 0 27 0.4338837391147836 -0.9009688679037553 0 28 0.6234898018575581 -0.7818314824689672 0 29 0.7818314824681323 -0.623489801858605 0 30 0.9009688679032538 -0.4338837391158249 0 31 0.9749279121821242 -0.2225209339549976 0 32 0 0.9749279121822653 -0.2225209339543793 33 0 0.9009688679037553 -0.4338837391147836 34 0 0.7818314824689672 -0.6234898018575581 35 0 0.623489801858605 -0.7818314824681323 36 0 0.4338837391158249 -0.9009688679032538 37 0 0.2225209339549976 -0.9749279121821242 38 0 -0.2225209339543793 -0.9749279121822653 39 0 -0.4338837391147836 -0.9009688679037553 40 0 -0.6234898018575581 -0.7818314824689672 41 0 -0.7818314824681323 -0.623489801858605 42 0 -0.9009688679032538 -0.4338837391158249 43 0 -0.9749279121821242 -0.2225209339549976 44 0 -0.9749279121822653 0.2225209339543793 45 0 -0.9009688679037553 0.4338837391147836 46 0 -0.7818314824689672 0.6234898018575581 47 0 -0.623489801858605 0.7818314824681323 48 0 -0.4338837391158249 0.9009688679032538 49 0 -0.2225209339549976 0.9749279121821242 50 0 0.2225209339543793 0.9749279121822653 51 0 0.4338837391147836 0.9009688679037553 52 0 0.6234898018575581 0.7818314824689672 53 0 0.7818314824681323 0.623489801858605 54 0 0.9009688679032538 0.4338837391158249 55 0 0.9749279121821242 0.2225209339549976 56 0.9749279121822653 0 0.2225209339543793 57 0.9009688679037553 0 0.4338837391147836 58 0.7818314824689672 0 0.6234898018575581 59 0.623489801858605 0 0.7818314824681323 60 0.4338837391158249 0 0.9009688679032538 61 0.2225209339549976 0 0.9749279121821242 62 -0.2225209339543793 0 0.9749279121822653 63 -0.4338837391147836 0 0.9009688679037553 64 -0.6234898018575581 0 0.7818314824689672 65 -0.7818314824681323 0 0.623489801858605 66 -0.9009688679032538 0 0.4338837391158249 67 -0.9749279121821242 0 0.2225209339549976 68 -0.9749279121822653 0 -0.2225209339543793 69 -0.9009688679037553 0 -0.4338837391147836 70 -0.7818314824689672 0 -0.6234898018575581 71 -0.623489801858605 0 -0.7818314824681323 72 -0.4338837391158249 0 -0.9009688679032538 73 -0.2225209339549976 0 -0.9749279121821242 74 0.2225209339543793 0 -0.9749279121822653 75 0.4338837391147836 0 -0.9009688679037553 76 0.6234898018575581 0 -0.7818314824689672 77 0.7818314824681323 0 -0.623489801858605 78 0.9009688679032538 0 -0.4338837391158249 79 0.9749279121821242 0 -0.2225209339549976 80 -0.6399596922098768 0.4393788952291748 0.6303949387279609 81 -0.5437209854004701 0.749526371048941 0.3775946360018201 82 -0.8777147592892988 0.3499526028154908 0.3273377111003125 83 -0.3588285009753752 0.1337372911292748 0.9237729395523386 84 -0.8019252176542082 0.5060240589617201 0.3175777023692886 85 -0.4384972253546365 0.5105785142018973 0.7396146051773641 86 -0.698546814188752 0.2084418609381405 0.684532204498364 87 -0.7049613213985063 0.6773761287458944 0.2102168298145924 88 -0.2435856103926377 0.66137751684849 0.7093982172355463 89 -0.5553227191141744 0.3385807860607333 0.7595918173243678 90 -0.7781775319525404 0.3835180480426054 0.4973465950319182 91 -0.8369906880509861 0.1848729051087921 0.5150423255156535 92 -0.93840897281476 0.3093857084021769 0.1538475972423044 93 -0.181695233637137 0.8360214750191582 0.5177402199755561 94 -0.5422894444727826 0.6326281926503853 0.5529048094177766 95 -0.3885847980450405 0.752633057063091 0.5315499375826894 96 -0.9381849022050933 0.1534537602098869 0.3102596215298827 97 -0.9805527231327269 0.1333951359223168 0.143951710199151 98 -0.523929145850573 0.1728745036803063 0.834033965798502 99 -0.3324068825103956 0.8683197629595089 0.3681391770970084 100 -0.4067617205199555 0.649346779196149 0.642568022132469 101 -0.3245976483038544 0.9276241626497057 0.1847965897521911 102 -0.857500257601549 0.4876592792239807 0.1639565052080116 103 -0.168586839402226 0.9274659605302179 0.3337444675768099 104 -0.6987949308779712 0.5766779770059076 0.4232353428243267 105 -0.2095656667139807 0.4659127564853596 0.85965547440759 106 -0.1752873340941405 0.2335110996791686 0.9564240256459446 107 -0.5057546614323654 0.8388585081236518 0.2013172267541818 108 -0.3853529804895249 0.3127289018257006 0.8681611108490931 109 -0.1701995800285241 0.9735875428539726 0.1521821256182145 110 -0.636323284945616 -0.6369047455291815 0.4352528255605344 111 -0.5174943850497641 -0.4285897776433444 0.7406148553341305 112 -0.8763522477505249 -0.3324819648447744 0.3485146781924124 113 -0.3789282879215185 -0.9003742124277033 0.2138682543250861 114 -0.7907946775522665 -0.3317174246541121 0.5143999690278473 115 -0.4017617953101094 -0.7769523310777016 0.4846983959764293 116 -0.6982921826337262 -0.6851164437588845 0.2073728192502723 117 -0.6959007789389509 -0.2138326335382428 0.6855637903990125 118 -0.191629341180377 -0.7152495587576155 0.6720835247912353 119 -0.5519379768976861 -0.7737297075267119 0.3109771846112157 120 -0.1691449250468849 -0.8365192657507149 0.5211770451188047 121 -0.7760576802995909 -0.5032645592637648 0.380077965997855 122 -0.8369856639329605 -0.5152187988339172 0.1844033288713544 123 -0.937799451364692 -0.1564109615674998 0.3099480603611076 124 -0.5336417041547991 -0.1900368387688521 0.8240828426180848 125 -0.5453825485507994 -0.6039330880928093 0.5812251722378496 126 -0.9382863546279528 -0.3103710201738213 0.1526058536074186 127 -0.980686844870107 -0.1440351031225591 0.1323147813631886 128 -0.5439446670250047 -0.8236768863409279 0.1602516337600678 129 -0.18717648772593 -0.5281207888438537 0.8282834024858463 130 -0.3702690950477084 -0.6097641508504188 0.700777052699515 131 -0.6814710528138087 -0.4511744096893867 0.5762281286246556 132 -0.8522748238347992 -0.1729362690004879 0.4936807384550796 133 -0.1876283014783124 -0.9208011585523697 0.3419369048420735 134 -0.1611580445579965 -0.9745019236458088 0.1561220211400721 135 -0.3277154715183433 -0.3432853437570904 0.8802032393084487 136 -0.3422972893783519 -0.1346542565592988 0.9298928953781157 137 -0.1668699215507884 -0.2015708822195094 0.9651547071443429 138 -0.3391019325004072 -0.4907826608126761 0.8025847364734262 139 -0.1310919833837768 -0.3666699054370763 0.9210689834856416 140 0.3309549533891821 0.1850671053163956 0.9253210174620343 141 0.8487262374833054 0.3660455468857676 0.3816731997567173 142 0.2325160673812569 0.3813953838879717 0.8946920361546209 143 0.7114422108033649 0.1680979961121924 0.6823437875369613 144 0.5230928099607951 0.8293304799774439 0.1964303111734594 145 0.8440028780423852 0.1702362032451349 0.5086047354880329 146 0.9323313297733431 0.3235783076493384 0.1614167597923457 147 0.366262594536248 0.9140575344633549 0.1742140509096462 148 0.2112319623133884 0.9088804724402215 0.3596072092075949 149 0.6918387054217848 0.6929762096978808 0.2028378132229479 150 0.3938247794571826 0.6756545806092689 0.6232117864636504 151 0.7049674700481643 0.4495329444064857 0.5485808947339726 152 0.9380135237308735 0.1557373408825372 0.3096393223620449 153 0.1663199670233514 0.6275222639964367 0.7606270286797187 154 0.8374839300279411 0.5130401375322425 0.1881767366755313 155 0.9805861997398644 0.1346594029910131 0.1425396438393007 156 0.1798762023413422 0.8154423008068242 0.5501803394216567 157 0.5487441651842468 0.2139703613806137 0.8081438768108644 158 0.1748061426878885 0.9693051789606889 0.172888063551445 159 0.5408545792091577 0.7399550966372245 0.3999284674902259 160 0.6700756797532411 0.3214560187273462 0.6690774330577859 161 0.5910238860634995 0.592162493015073 0.5477539118697129 162 0.4049470888816385 0.8550384923484917 0.3239244229889199 163 0.3406581778332126 0.8182146489454153 0.4631163937138116 164 0.7700311215547381 0.312568733433261 0.5561949826428492 165 0.5421591524323611 0.4567012912429259 0.7053278556890178 166 0.4055343361099458 0.371662074071534 0.8351102950704842 167 0.7245505767272531 0.5690659856614377 0.3888320533692937 168 0.3512537487202224 0.5149191964535487 0.7819712431628305 169 0.1320122699556744 0.2066264480878434 0.9694731927865524 170 -0.6364194049539066 0.63680869578232 -0.435252829943857 171 -0.4278275583755694 0.5181458828677303 -0.7406000434523475 172 -0.9002769586083357 0.3791579535065994 -0.2138706246580219 173 -0.3322223412846621 0.8764533675640822 -0.3485079775800224 174 -0.3310327361230584 0.7911012694021502 -0.5143696230972316 175 -0.776537199944588 0.402532139882556 -0.4847245129594638 176 -0.6850394539515892 0.6983677189075619 -0.2073727940631488 177 -0.2128318481373118 0.6962805054650048 -0.6854896513645218 178 -0.7150797186832111 0.1921285441557966 -0.6721217288918085 179 -0.773590494041167 0.5521319880188701 -0.3109791236328792 180 -0.8364156737616577 0.1695758105194453 -0.5212032858420076 181 -0.5028742155394632 0.776313936629121 -0.380071302706435 182 -0.5151922636670737 0.837002028550899 -0.1844031877687488 183 -0.1562898293231247 0.9378207506960196 -0.3099447189646936 184 -0.1895370731851836 0.5338768930460337 -0.824045606116499 185 -0.602996016883954 0.5464091251674521 -0.5812339215460725 186 -0.3103636723474542 0.9382887927162987 -0.1526058070651075 187 -0.1440305345825802 0.9806875194916013 -0.1323147543596946 188 -0.8236312518999193 0.5440136894353543 -0.1602518848585112 189 -0.5277109903518442 0.18804451638137 -0.8283479767107375 190 -0.609276623068864 0.3710107159604848 -0.7008088507034497 191 -0.4500763303637129 0.682224761825729 -0.5761949940759303 192 -0.1725561848978504 0.8523642601485115 -0.4936593269401273 193 -0.9207422881121122 0.1879013864382462 -0.3419454749761386 194 -0.9744840764682224 0.1612651032578731 -0.1561228720626898 195 -0.3411856327694863 0.3298770839484269 -0.8802121752608105 196 -0.1345381090782955 0.342360879373695 -0.9298862970708338 197 -0.1963944183447922 0.1726068695854918 -0.9652129822038801 198 -0.4899754272559811 0.3401770813901143 -0.8026229712525192 199 -0.3653948213042553 0.1335550478780772 -0.9212218374258807 200 0.6303949397814106 0.6399596911715434 -0.4393788952300903 201 0.3775946392860918 0.5437209829624294 -0.7495263711630004 202 0.9237729396953228 0.3588285006078504 -0.1337372911277305 203 0.3273377115028129 0.8777147591351641 -0.3499526028255858 204 0.3175777033379543 0.8019252172434455 -0.5060240590047504 205 0.7396146062546571 0.4384972236002912 -0.5105785141480247 206 0.6845322047083758 0.6985468139829397 -0.2084418609381866 207 0.2102168315028993 0.7049613207753813 -0.6773761288704464 208 0.7093982179449723 0.2435856086473068 -0.6613775167303607 209 0.7595918180126051 0.5553227181788755 -0.3385807860507307 210 0.4973465957891958 0.7781775314620555 -0.3835180480557856 211 0.5150423255553336 0.8369906880265584 -0.1848729051088401 212 0.1538475974073784 0.9384089727863971 -0.3093857084061193 213 0.5177402211252699 0.1816952311966288 -0.8360214748375548 214 0.5529048121723387 0.5422894416704489 -0.6326281926451142 215 0.5315499397107804 0.3885847952966824 -0.7526330569790973 216 0.3102596215409291 0.9381849022014705 -0.1534537602097018 217 0.1439517102060557 0.980552723131748 -0.1333951359220618 218 0.834033966098739 0.5239291453733238 -0.1728745036782054 219 0.3681391830835778 0.332406876057353 -0.8683197628917285 220 0.6425680239452699 0.4067617178173614 -0.649346779095223 221 0.1847965921157193 0.3245976466834938 -0.9276241627458581 222 0.1639565056504605 0.8575002575032787 -0.4876592792480228 223 0.33374446857905 0.1685868378246639 -0.927465960456322 224 0.4232353445925347 0.6987949297560132 -0.5766779770677281 225 0.8596554746533561 0.2095656658041354 -0.4659127564411414 226 0.9564240257206256 0.1752873336948566 -0.2335110996730136 227 0.2013172334164534 0.5057546580165464 -0.8388585085842019 228 0.8681611112428553 0.3853529796159201 -0.3127289018090635 229 0.1521821386287443 0.1701995679157101 -0.9735875429378127 230 -0.6368086967925762 -0.43525282994382 -0.6364194039430576 231 -0.5181458842231308 -0.7406000434212674 -0.4278275567878334 232 -0.3791579539847454 -0.2138706246629556 -0.900276958405789 233 -0.8764533677745306 -0.3485079775660678 -0.3322223407441053 234 -0.7911012700398435 -0.5143696230339919 -0.3310327346973643 235 -0.4025321414860945 -0.48472451301376 -0.7765371990794724 236 -0.6983677190648195 -0.2073727940630961 -0.6850394537912878 237 -0.6962805062541186 -0.6854896512099854 -0.2128318460534534 238 -0.1921285451951003 -0.6721217289713101 -0.7150797183292441 239 -0.5521319884227682 -0.3109791236369133 -0.7735904937512725 240 -0.1695758114165463 -0.5212032858966259 -0.8364156735457436 241 -0.7763139371624378 -0.3800713026925462 -0.5028742147266506 242 -0.8370020285849693 -0.1844031877684549 -0.515192263611827 243 -0.9378207507403488 -0.3099447189577363 -0.1562898290709238 244 -0.5338768935352509 -0.8240456060389003 -0.1895370721445594 245 -0.546409127303304 -0.5812339215639785 -0.6029960149312769 246 -0.9382887927213747 -0.1526058070650108 -0.3103636723321559 247 -0.9806875194930089 -0.1323147543596383 -0.1440305345730476 248 -0.5440136895790557 -0.1602518848590339 -0.8236312518049019 249 -0.1880445181882627 -0.8283479768449603 -0.5277109894972865 250 -0.3710107175040882 -0.7008088507694897 -0.6092766220529463 251 -0.6822247633931432 -0.5761949940066767 -0.4500763280764893 252 -0.8523642603345378 -0.493659326895538 -0.1725561841065123 253 -0.1879013870068093 -0.341945474993979 -0.9207422879894566 254 -0.1612651034807908 -0.1561228720644615 -0.9744840764310485 255 -0.3298770884389145 -0.880212175276466 -0.341185628387446 256 -0.3423608795060554 -0.9298862970570907 -0.1345381088364644 257 -0.1726068814291917 -0.9652129823026115 -0.1963944074503838 258 -0.3401770836272406 -0.8026229713316368 -0.4899754255732014 259 -0.1335550530016038 -0.9212218377418263 -0.3653948186350089 260 0.515189472939738 -0.3462846474858494 0.7840068557657361 261 0.8702682412940425 -0.3408737454769167 0.3555816050353456 262 0.3356515613702528 -0.9080728415116031 0.2504830210987453 263 0.3303009708886189 -0.3328292076244511 0.8832474099492824 264 0.1944723924398996 -0.1869718287181203 0.9629236853689411 265 0.7739310396100941 -0.340399756736934 0.5340025763434809 266 0.3732527457789898 -0.7745007606728113 0.5107161241684871 267 0.7097456492413843 -0.6785240470918054 0.1893838190054354 268 0.7000633989392401 -0.212840467913928 0.6816231896611342 269 0.1595758060050646 -0.5633302303750908 0.8106754058705501 270 0.1543871058906951 -0.8536408103941561 0.497455513955071 271 0.7400344481977739 -0.5399506809800682 0.4010015930015454 272 0.8350260851292175 -0.5175263913133596 0.1868097198968622 273 0.9366969910865007 -0.1582705442347298 0.3123286437666876 274 0.4008033687694554 -0.1687808184235771 0.9004830342184817 275 0.1203779548196618 -0.94405358882485 0.3070374072004198 276 0.1660355622147001 -0.3967048108472608 0.9028053417712411 277 0.3496163276844338 -0.641617762129388 0.6827115574944712 278 0.6472928450870343 -0.4442007627121819 0.6194333338665658 279 0.1693584409258914 -0.7280312248599277 0.6642953064083057 280 0.9380846240837802 -0.3107943742971057 0.1529839696270929 281 0.551553468081752 -0.6215937905112361 0.5562462866796194 282 0.3424589242127952 -0.4791092815263365 0.8081931585842166 283 0.4891168055219944 -0.5303556270475137 0.6924504743409438 284 0.9806706817073777 -0.1440963711976021 0.1323678580595378 285 0.5621441329756619 -0.8108296871538035 0.1629392285212692 286 0.8492782520000772 -0.1761797058529027 0.4976817878175551 287 0.5638368430766688 -0.7478154280195025 0.3505140510811859 288 0.1380741487743828 -0.9779828934318485 0.1564768020982636 289 0.5541750513171431 -0.1404610985999234 0.8204637056431835 290 0.7840068555903511 -0.515189476315588 -0.346284642860466 291 0.3555816050239246 -0.8702682414696223 -0.3408737450405661 292 0.2504830211044711 -0.3356515617565175 -0.9080728413672484 293 0.8832474099554999 -0.3303009787454446 -0.3328291998108077 294 0.9629236853296566 -0.1944724066683781 -0.1869718141211707 295 0.5340025762872235 -0.7739310401983257 -0.3403997554877876 296 0.5107161242142905 -0.3732527469471232 -0.7745007600796531 297 0.1893838190052639 -0.7097456494961105 -0.6785240468254059 298 0.6816231895051539 -0.7000633997323741 -0.2128404658047227 299 0.8106754060742291 -0.1595758084669697 -0.5633302293845918 300 0.4974555139894001 -0.1543871064790102 -0.8536408102677498 301 0.401001592991391 -0.7400344487215409 -0.5399506802697556 302 0.1868097198967168 -0.8350260851459788 -0.517526391286368 303 0.3123286437606279 -0.9366969911252344 -0.1582705440174491 304 0.9004830337902895 -0.4008033727131622 -0.1687808113429675 305 0.3070374072062939 -0.1203779550281137 -0.9440535887963596 306 0.9028053421574679 -0.1660355686150224 -0.3967048072895306 307 0.6827115576019838 -0.3496163298894213 -0.6416177608134961 308 0.6194333338163984 -0.6472928462675223 -0.4442007610619236 309 0.664295306485219 -0.1693584418983054 -0.7280312245635397 310 0.1529839696270597 -0.9380846240855332 -0.3107943742918313 311 0.5562462866937303 -0.5515534695610762 -0.6215937891859726 312 0.80819315872302 -0.3424589284278833 -0.4791092782793224 313 0.6924504743612186 -0.4891168079644408 -0.5303556247685128 314 0.132367858059529 -0.9806706817075962 -0.144096371196123 315 0.1629392285222735 -0.5621441332716371 -0.8108296869484036 316 0.4976817877753373 -0.8492782521792926 -0.1761797051082499 317 0.3505140510890543 -0.5638368438274382 -0.7478154274497504 318 0.1564768020992885 -0.138074148900024 -0.9779828934139462 319 0.8204637053731726 -0.5541750525154707 -0.1404610954492348 $EndNodes $Elements 723 1 15 2 0 1 1 2 15 2 0 2 2 3 15 2 0 3 3 4 15 2 0 4 4 5 15 2 0 5 5 6 15 2 0 6 6 7 15 2 0 7 7 8 1 3 0 1 0 2 8 9 1 3 0 1 0 8 9 10 1 3 0 1 0 9 10 11 1 3 0 1 0 10 11 12 1 3 0 1 0 11 12 13 1 3 0 1 0 12 13 14 1 3 0 1 0 13 3 15 1 3 0 2 0 3 14 16 1 3 0 2 0 14 15 17 1 3 0 2 0 15 16 18 1 3 0 2 0 16 17 19 1 3 0 2 0 17 18 20 1 3 0 2 0 18 19 21 1 3 0 2 0 19 4 22 1 3 0 3 0 4 20 23 1 3 0 3 0 20 21 24 1 3 0 3 0 21 22 25 1 3 0 3 0 22 23 26 1 3 0 3 0 23 24 27 1 3 0 3 0 24 25 28 1 3 0 3 0 25 5 29 1 3 0 4 0 5 26 30 1 3 0 4 0 26 27 31 1 3 0 4 0 27 28 32 1 3 0 4 0 28 29 33 1 3 0 4 0 29 30 34 1 3 0 4 0 30 31 35 1 3 0 4 0 31 2 36 1 3 0 5 0 3 32 37 1 3 0 5 0 32 33 38 1 3 0 5 0 33 34 39 1 3 0 5 0 34 35 40 1 3 0 5 0 35 36 41 1 3 0 5 0 36 37 42 1 3 0 5 0 37 6 43 1 3 0 6 0 6 38 44 1 3 0 6 0 38 39 45 1 3 0 6 0 39 40 46 1 3 0 6 0 40 41 47 1 3 0 6 0 41 42 48 1 3 0 6 0 42 43 49 1 3 0 6 0 43 5 50 1 3 0 7 0 5 44 51 1 3 0 7 0 44 45 52 1 3 0 7 0 45 46 53 1 3 0 7 0 46 47 54 1 3 0 7 0 47 48 55 1 3 0 7 0 48 49 56 1 3 0 7 0 49 7 57 1 3 0 8 0 7 50 58 1 3 0 8 0 50 51 59 1 3 0 8 0 51 52 60 1 3 0 8 0 52 53 61 1 3 0 8 0 53 54 62 1 3 0 8 0 54 55 63 1 3 0 8 0 55 3 64 1 3 0 9 0 2 56 65 1 3 0 9 0 56 57 66 1 3 0 9 0 57 58 67 1 3 0 9 0 58 59 68 1 3 0 9 0 59 60 69 1 3 0 9 0 60 61 70 1 3 0 9 0 61 7 71 1 3 0 10 0 7 62 72 1 3 0 10 0 62 63 73 1 3 0 10 0 63 64 74 1 3 0 10 0 64 65 75 1 3 0 10 0 65 66 76 1 3 0 10 0 66 67 77 1 3 0 10 0 67 4 78 1 3 0 11 0 4 68 79 1 3 0 11 0 68 69 80 1 3 0 11 0 69 70 81 1 3 0 11 0 70 71 82 1 3 0 11 0 71 72 83 1 3 0 11 0 72 73 84 1 3 0 11 0 73 6 85 1 3 0 12 0 6 74 86 1 3 0 12 0 74 75 87 1 3 0 12 0 75 76 88 1 3 0 12 0 76 77 89 1 3 0 12 0 77 78 90 1 3 0 12 0 78 79 91 1 3 0 12 0 79 2 92 2 3 0 14 0 89 80 86 93 2 3 0 14 0 82 90 84 94 2 3 0 14 0 92 18 19 95 2 3 0 14 0 91 90 82 96 2 3 0 14 0 90 86 80 97 2 3 0 14 0 65 91 66 98 2 3 0 14 0 93 53 54 99 2 3 0 14 0 53 93 88 100 2 3 0 14 0 91 86 90 101 2 3 0 14 0 88 52 53 102 2 3 0 14 0 95 88 93 103 2 3 0 14 0 82 96 91 104 2 3 0 14 0 96 66 91 105 2 3 0 14 0 97 19 4 106 2 3 0 14 0 67 97 4 107 2 3 0 14 0 19 97 92 108 2 3 0 14 0 85 80 89 109 2 3 0 14 0 86 65 64 110 2 3 0 14 0 91 65 86 111 2 3 0 14 0 82 92 96 112 2 3 0 14 0 96 67 66 113 2 3 0 14 0 96 92 97 114 2 3 0 14 0 96 97 67 115 2 3 0 14 0 64 98 86 116 2 3 0 14 0 98 89 86 117 2 3 0 14 0 95 99 81 118 2 3 0 14 0 95 93 99 119 2 3 0 14 0 63 98 64 120 2 3 0 14 0 83 98 63 121 2 3 0 14 0 17 87 16 122 2 3 0 14 0 95 81 94 123 2 3 0 14 0 94 80 85 124 2 3 0 14 0 88 100 85 125 2 3 0 14 0 94 100 95 126 2 3 0 14 0 100 94 85 127 2 3 0 14 0 100 88 95 128 2 3 0 14 0 17 102 87 129 2 3 0 14 0 102 84 87 130 2 3 0 14 0 103 54 55 131 2 3 0 14 0 104 84 90 132 2 3 0 14 0 80 104 90 133 2 3 0 14 0 80 94 104 134 2 3 0 14 0 18 102 17 135 2 3 0 14 0 54 103 93 136 2 3 0 14 0 103 99 93 137 2 3 0 14 0 104 87 84 138 2 3 0 14 0 87 104 81 139 2 3 0 14 0 104 94 81 140 2 3 0 14 0 99 103 101 141 2 3 0 14 0 83 63 62 142 2 3 0 14 0 50 106 7 143 2 3 0 14 0 106 62 7 144 2 3 0 14 0 106 83 62 145 2 3 0 14 0 102 82 84 146 2 3 0 14 0 92 82 102 147 2 3 0 14 0 18 92 102 148 2 3 0 14 0 107 99 101 149 2 3 0 14 0 107 81 99 150 2 3 0 14 0 16 107 15 151 2 3 0 14 0 81 107 87 152 2 3 0 14 0 107 16 87 153 2 3 0 14 0 52 105 51 154 2 3 0 14 0 88 105 52 155 2 3 0 14 0 88 85 105 156 2 3 0 14 0 85 108 105 157 2 3 0 14 0 108 85 89 158 2 3 0 14 0 108 98 83 159 2 3 0 14 0 89 98 108 160 2 3 0 14 0 14 15 101 161 2 3 0 14 0 15 107 101 162 2 3 0 14 0 51 106 50 163 2 3 0 14 0 105 106 51 164 2 3 0 14 0 106 108 83 165 2 3 0 14 0 106 105 108 166 2 3 0 14 0 14 109 3 167 2 3 0 14 0 109 55 3 168 2 3 0 14 0 109 14 101 169 2 3 0 14 0 109 103 55 170 2 3 0 14 0 101 103 109 171 2 3 0 16 0 119 113 115 172 2 3 0 16 0 119 110 116 173 2 3 0 16 0 46 120 45 174 2 3 0 16 0 112 121 114 175 2 3 0 16 0 123 66 67 176 2 3 0 16 0 122 121 112 177 2 3 0 16 0 121 116 110 178 2 3 0 16 0 22 122 21 179 2 3 0 16 0 64 124 63 180 2 3 0 16 0 124 64 117 181 2 3 0 16 0 117 111 124 182 2 3 0 16 0 122 116 121 183 2 3 0 16 0 118 46 47 184 2 3 0 16 0 118 120 46 185 2 3 0 16 0 118 115 120 186 2 3 0 16 0 112 126 122 187 2 3 0 16 0 126 21 122 188 2 3 0 16 0 20 127 4 189 2 3 0 16 0 67 127 123 190 2 3 0 16 0 127 67 4 191 2 3 0 16 0 115 110 119 192 2 3 0 16 0 116 22 23 193 2 3 0 16 0 122 22 116 194 2 3 0 16 0 126 20 21 195 2 3 0 16 0 112 123 126 196 2 3 0 16 0 126 123 127 197 2 3 0 16 0 126 127 20 198 2 3 0 16 0 23 128 116 199 2 3 0 16 0 128 119 116 200 2 3 0 16 0 24 128 23 201 2 3 0 16 0 128 113 119 202 2 3 0 16 0 113 128 24 203 2 3 0 16 0 65 117 64 204 2 3 0 16 0 125 110 115 205 2 3 0 16 0 118 130 115 206 2 3 0 16 0 130 125 115 207 2 3 0 16 0 131 114 121 208 2 3 0 16 0 132 114 117 209 2 3 0 16 0 65 132 117 210 2 3 0 16 0 110 131 121 211 2 3 0 16 0 110 125 131 212 2 3 0 16 0 66 132 65 213 2 3 0 16 0 131 117 114 214 2 3 0 16 0 117 131 111 215 2 3 0 16 0 131 125 111 216 2 3 0 16 0 113 24 25 217 2 3 0 16 0 113 133 115 218 2 3 0 16 0 133 120 115 219 2 3 0 16 0 134 25 5 220 2 3 0 16 0 44 134 5 221 2 3 0 16 0 134 113 25 222 2 3 0 16 0 132 112 114 223 2 3 0 16 0 123 112 132 224 2 3 0 16 0 66 123 132 225 2 3 0 16 0 130 111 125 226 2 3 0 16 0 135 124 111 227 2 3 0 16 0 45 133 44 228 2 3 0 16 0 120 133 45 229 2 3 0 16 0 134 44 133 230 2 3 0 16 0 133 113 134 231 2 3 0 16 0 136 63 124 232 2 3 0 16 0 137 49 7 233 2 3 0 16 0 62 137 7 234 2 3 0 16 0 124 135 136 235 2 3 0 16 0 136 62 63 236 2 3 0 16 0 137 62 136 237 2 3 0 16 0 136 135 137 238 2 3 0 16 0 138 111 130 239 2 3 0 16 0 138 129 135 240 2 3 0 16 0 111 138 135 241 2 3 0 16 0 47 129 118 242 2 3 0 16 0 129 47 48 243 2 3 0 16 0 130 118 129 244 2 3 0 16 0 130 129 138 245 2 3 0 16 0 139 49 137 246 2 3 0 16 0 135 139 137 247 2 3 0 16 0 129 139 135 248 2 3 0 16 0 49 139 48 249 2 3 0 16 0 129 48 139 250 2 3 0 18 0 144 11 12 251 2 3 0 18 0 9 146 8 252 2 3 0 18 0 147 12 13 253 2 3 0 18 0 54 148 55 254 2 3 0 18 0 145 58 57 255 2 3 0 18 0 12 147 144 256 2 3 0 18 0 152 141 145 257 2 3 0 18 0 57 152 145 258 2 3 0 18 0 52 153 53 259 2 3 0 18 0 8 155 2 260 2 3 0 18 0 155 56 2 261 2 3 0 18 0 155 8 146 262 2 3 0 18 0 58 143 59 263 2 3 0 18 0 58 145 143 264 2 3 0 18 0 146 141 152 265 2 3 0 18 0 56 152 57 266 2 3 0 18 0 146 152 155 267 2 3 0 18 0 155 152 56 268 2 3 0 18 0 54 156 148 269 2 3 0 18 0 157 59 143 270 2 3 0 18 0 55 158 3 271 2 3 0 18 0 158 13 3 272 2 3 0 18 0 158 55 148 273 2 3 0 18 0 158 147 13 274 2 3 0 18 0 148 147 158 275 2 3 0 18 0 53 156 54 276 2 3 0 18 0 157 60 59 277 2 3 0 18 0 144 159 149 278 2 3 0 18 0 153 156 53 279 2 3 0 18 0 150 156 153 280 2 3 0 18 0 157 140 60 281 2 3 0 18 0 10 154 9 282 2 3 0 18 0 141 146 154 283 2 3 0 18 0 146 9 154 284 2 3 0 18 0 161 159 150 285 2 3 0 18 0 147 162 144 286 2 3 0 18 0 162 159 144 287 2 3 0 18 0 162 147 148 288 2 3 0 18 0 163 159 162 289 2 3 0 18 0 148 163 162 290 2 3 0 18 0 156 150 163 291 2 3 0 18 0 150 159 163 292 2 3 0 18 0 156 163 148 293 2 3 0 18 0 60 140 61 294 2 3 0 18 0 160 157 143 295 2 3 0 18 0 141 164 145 296 2 3 0 18 0 160 164 151 297 2 3 0 18 0 164 141 151 298 2 3 0 18 0 164 143 145 299 2 3 0 18 0 160 143 164 300 2 3 0 18 0 154 10 149 301 2 3 0 18 0 149 11 144 302 2 3 0 18 0 11 149 10 303 2 3 0 18 0 160 165 157 304 2 3 0 18 0 165 161 150 305 2 3 0 18 0 161 165 151 306 2 3 0 18 0 151 165 160 307 2 3 0 18 0 51 153 52 308 2 3 0 18 0 153 51 142 309 2 3 0 18 0 140 166 142 310 2 3 0 18 0 165 166 157 311 2 3 0 18 0 166 140 157 312 2 3 0 18 0 151 167 161 313 2 3 0 18 0 149 167 154 314 2 3 0 18 0 159 167 149 315 2 3 0 18 0 159 161 167 316 2 3 0 18 0 141 167 151 317 2 3 0 18 0 141 154 167 318 2 3 0 18 0 142 168 153 319 2 3 0 18 0 150 168 165 320 2 3 0 18 0 168 150 153 321 2 3 0 18 0 166 168 142 322 2 3 0 18 0 166 165 168 323 2 3 0 18 0 61 169 7 324 2 3 0 18 0 169 50 7 325 2 3 0 18 0 169 51 50 326 2 3 0 18 0 169 140 142 327 2 3 0 18 0 140 169 61 328 2 3 0 18 0 142 51 169 329 2 3 0 20 0 172 179 175 330 2 3 0 20 0 170 179 176 331 2 3 0 20 0 180 70 69 332 2 3 0 20 0 181 173 174 333 2 3 0 20 0 33 183 32 334 2 3 0 20 0 181 182 173 335 2 3 0 20 0 176 181 170 336 2 3 0 20 0 182 16 15 337 2 3 0 20 0 184 35 36 338 2 3 0 20 0 35 184 177 339 2 3 0 20 0 171 177 184 340 2 3 0 20 0 176 182 181 341 2 3 0 20 0 70 178 71 342 2 3 0 20 0 180 178 70 343 2 3 0 20 0 175 178 180 344 2 3 0 20 0 186 173 182 345 2 3 0 20 0 15 186 182 346 2 3 0 20 0 187 14 3 347 2 3 0 20 0 187 32 183 348 2 3 0 20 0 32 187 3 349 2 3 0 20 0 170 175 179 350 2 3 0 20 0 16 176 17 351 2 3 0 20 0 16 182 176 352 2 3 0 20 0 14 186 15 353 2 3 0 20 0 183 173 186 354 2 3 0 20 0 183 186 187 355 2 3 0 20 0 187 186 14 356 2 3 0 20 0 188 17 176 357 2 3 0 20 0 179 188 176 358 2 3 0 20 0 188 18 17 359 2 3 0 20 0 172 188 179 360 2 3 0 20 0 188 172 18 361 2 3 0 20 0 177 34 35 362 2 3 0 20 0 170 185 175 363 2 3 0 20 0 190 178 175 364 2 3 0 20 0 185 190 175 365 2 3 0 20 0 174 191 181 366 2 3 0 20 0 174 192 177 367 2 3 0 20 0 192 34 177 368 2 3 0 20 0 191 170 181 369 2 3 0 20 0 185 170 191 370 2 3 0 20 0 192 33 34 371 2 3 0 20 0 177 191 174 372 2 3 0 20 0 191 177 171 373 2 3 0 20 0 185 191 171 374 2 3 0 20 0 18 172 19 375 2 3 0 20 0 193 172 175 376 2 3 0 20 0 180 193 175 377 2 3 0 20 0 19 194 4 378 2 3 0 20 0 194 68 4 379 2 3 0 20 0 172 194 19 380 2 3 0 20 0 173 192 174 381 2 3 0 20 0 173 183 192 382 2 3 0 20 0 183 33 192 383 2 3 0 20 0 171 190 185 384 2 3 0 20 0 184 195 171 385 2 3 0 20 0 193 69 68 386 2 3 0 20 0 193 180 69 387 2 3 0 20 0 68 194 193 388 2 3 0 20 0 172 193 194 389 2 3 0 20 0 36 196 184 390 2 3 0 20 0 197 37 6 391 2 3 0 20 0 73 197 6 392 2 3 0 20 0 195 184 196 393 2 3 0 20 0 37 196 36 394 2 3 0 20 0 37 197 196 395 2 3 0 20 0 195 196 197 396 2 3 0 20 0 171 198 190 397 2 3 0 20 0 189 198 195 398 2 3 0 20 0 198 171 195 399 2 3 0 20 0 189 71 178 400 2 3 0 20 0 71 189 72 401 2 3 0 20 0 178 190 189 402 2 3 0 20 0 189 190 198 403 2 3 0 20 0 73 199 197 404 2 3 0 20 0 199 195 197 405 2 3 0 20 0 199 189 195 406 2 3 0 20 0 199 73 72 407 2 3 0 20 0 72 189 199 408 2 3 0 22 0 209 200 206 409 2 3 0 22 0 203 210 204 410 2 3 0 22 0 212 33 32 411 2 3 0 22 0 211 210 203 412 2 3 0 22 0 210 206 200 413 2 3 0 22 0 11 211 12 414 2 3 0 22 0 213 76 75 415 2 3 0 22 0 76 213 208 416 2 3 0 22 0 211 206 210 417 2 3 0 22 0 208 77 76 418 2 3 0 22 0 215 208 213 419 2 3 0 22 0 203 216 211 420 2 3 0 22 0 216 12 211 421 2 3 0 22 0 217 32 3 422 2 3 0 22 0 13 217 3 423 2 3 0 22 0 32 217 212 424 2 3 0 22 0 205 200 209 425 2 3 0 22 0 206 11 10 426 2 3 0 22 0 211 11 206 427 2 3 0 22 0 216 13 12 428 2 3 0 22 0 203 212 216 429 2 3 0 22 0 216 212 217 430 2 3 0 22 0 216 217 13 431 2 3 0 22 0 10 218 206 432 2 3 0 22 0 218 209 206 433 2 3 0 22 0 215 219 201 434 2 3 0 22 0 215 213 219 435 2 3 0 22 0 9 218 10 436 2 3 0 22 0 202 218 9 437 2 3 0 22 0 34 207 35 438 2 3 0 22 0 215 201 214 439 2 3 0 22 0 214 200 205 440 2 3 0 22 0 208 220 205 441 2 3 0 22 0 214 220 215 442 2 3 0 22 0 220 214 205 443 2 3 0 22 0 220 208 215 444 2 3 0 22 0 34 222 207 445 2 3 0 22 0 222 204 207 446 2 3 0 22 0 223 75 74 447 2 3 0 22 0 224 204 210 448 2 3 0 22 0 200 224 210 449 2 3 0 22 0 200 214 224 450 2 3 0 22 0 33 222 34 451 2 3 0 22 0 75 223 213 452 2 3 0 22 0 223 219 213 453 2 3 0 22 0 224 207 204 454 2 3 0 22 0 207 224 201 455 2 3 0 22 0 224 214 201 456 2 3 0 22 0 219 223 221 457 2 3 0 22 0 202 9 8 458 2 3 0 22 0 226 8 2 459 2 3 0 22 0 79 226 2 460 2 3 0 22 0 226 202 8 461 2 3 0 22 0 222 203 204 462 2 3 0 22 0 212 203 222 463 2 3 0 22 0 33 212 222 464 2 3 0 22 0 227 219 221 465 2 3 0 22 0 227 201 219 466 2 3 0 22 0 35 227 36 467 2 3 0 22 0 201 227 207 468 2 3 0 22 0 227 35 207 469 2 3 0 22 0 77 225 78 470 2 3 0 22 0 208 225 77 471 2 3 0 22 0 208 205 225 472 2 3 0 22 0 205 228 225 473 2 3 0 22 0 228 205 209 474 2 3 0 22 0 228 218 202 475 2 3 0 22 0 209 218 228 476 2 3 0 22 0 37 36 221 477 2 3 0 22 0 36 227 221 478 2 3 0 22 0 78 226 79 479 2 3 0 22 0 225 226 78 480 2 3 0 22 0 226 228 202 481 2 3 0 22 0 226 225 228 482 2 3 0 22 0 37 229 6 483 2 3 0 22 0 229 74 6 484 2 3 0 22 0 229 37 221 485 2 3 0 22 0 229 223 74 486 2 3 0 22 0 221 223 229 487 2 3 0 24 0 239 232 235 488 2 3 0 24 0 239 230 236 489 2 3 0 24 0 40 240 39 490 2 3 0 24 0 233 241 234 491 2 3 0 24 0 243 21 20 492 2 3 0 24 0 242 241 233 493 2 3 0 24 0 241 236 230 494 2 3 0 24 0 70 242 69 495 2 3 0 24 0 23 244 24 496 2 3 0 24 0 244 23 237 497 2 3 0 24 0 237 231 244 498 2 3 0 24 0 242 236 241 499 2 3 0 24 0 238 40 41 500 2 3 0 24 0 238 240 40 501 2 3 0 24 0 238 235 240 502 2 3 0 24 0 233 246 242 503 2 3 0 24 0 246 69 242 504 2 3 0 24 0 247 20 4 505 2 3 0 24 0 68 247 4 506 2 3 0 24 0 20 247 243 507 2 3 0 24 0 235 230 239 508 2 3 0 24 0 236 70 71 509 2 3 0 24 0 242 70 236 510 2 3 0 24 0 233 243 246 511 2 3 0 24 0 246 68 69 512 2 3 0 24 0 246 243 247 513 2 3 0 24 0 246 247 68 514 2 3 0 24 0 71 248 236 515 2 3 0 24 0 248 239 236 516 2 3 0 24 0 72 248 71 517 2 3 0 24 0 248 232 239 518 2 3 0 24 0 232 248 72 519 2 3 0 24 0 22 237 23 520 2 3 0 24 0 245 230 235 521 2 3 0 24 0 238 250 235 522 2 3 0 24 0 250 245 235 523 2 3 0 24 0 251 234 241 524 2 3 0 24 0 252 234 237 525 2 3 0 24 0 22 252 237 526 2 3 0 24 0 230 251 241 527 2 3 0 24 0 230 245 251 528 2 3 0 24 0 21 252 22 529 2 3 0 24 0 251 237 234 530 2 3 0 24 0 237 251 231 531 2 3 0 24 0 251 245 231 532 2 3 0 24 0 232 72 73 533 2 3 0 24 0 232 253 235 534 2 3 0 24 0 253 240 235 535 2 3 0 24 0 38 254 6 536 2 3 0 24 0 254 73 6 537 2 3 0 24 0 254 232 73 538 2 3 0 24 0 252 233 234 539 2 3 0 24 0 243 233 252 540 2 3 0 24 0 21 243 252 541 2 3 0 24 0 250 231 245 542 2 3 0 24 0 255 244 231 543 2 3 0 24 0 39 253 38 544 2 3 0 24 0 240 253 39 545 2 3 0 24 0 254 38 253 546 2 3 0 24 0 253 232 254 547 2 3 0 24 0 256 24 244 548 2 3 0 24 0 25 257 5 549 2 3 0 24 0 257 43 5 550 2 3 0 24 0 244 255 256 551 2 3 0 24 0 256 25 24 552 2 3 0 24 0 257 25 256 553 2 3 0 24 0 256 255 257 554 2 3 0 24 0 258 231 250 555 2 3 0 24 0 258 249 255 556 2 3 0 24 0 231 258 255 557 2 3 0 24 0 41 249 238 558 2 3 0 24 0 249 41 42 559 2 3 0 24 0 250 238 249 560 2 3 0 24 0 250 249 258 561 2 3 0 24 0 259 43 257 562 2 3 0 24 0 255 259 257 563 2 3 0 24 0 249 259 255 564 2 3 0 24 0 43 259 42 565 2 3 0 24 0 249 42 259 566 2 3 0 26 0 49 264 7 567 2 3 0 26 0 264 61 7 568 2 3 0 26 0 47 269 48 569 2 3 0 26 0 270 46 45 570 2 3 0 26 0 270 262 266 571 2 3 0 26 0 271 261 265 572 2 3 0 26 0 57 273 56 573 2 3 0 26 0 263 274 264 574 2 3 0 26 0 275 45 44 575 2 3 0 26 0 48 276 49 576 2 3 0 26 0 276 264 49 577 2 3 0 26 0 275 270 45 578 2 3 0 26 0 262 270 275 579 2 3 0 26 0 61 274 60 580 2 3 0 26 0 61 264 274 581 2 3 0 26 0 271 272 261 582 2 3 0 26 0 276 263 264 583 2 3 0 26 0 272 29 30 584 2 3 0 26 0 276 48 269 585 2 3 0 26 0 260 274 263 586 2 3 0 26 0 267 272 271 587 2 3 0 26 0 265 278 271 588 2 3 0 26 0 46 279 47 589 2 3 0 26 0 279 269 47 590 2 3 0 26 0 280 261 272 591 2 3 0 26 0 30 280 272 592 2 3 0 26 0 282 260 263 593 2 3 0 26 0 282 269 277 594 2 3 0 26 0 284 31 2 595 2 3 0 26 0 284 56 273 596 2 3 0 26 0 56 284 2 597 2 3 0 26 0 276 282 263 598 2 3 0 26 0 276 269 282 599 2 3 0 26 0 281 277 266 600 2 3 0 26 0 29 267 28 601 2 3 0 26 0 29 272 267 602 2 3 0 26 0 282 283 260 603 2 3 0 26 0 282 277 283 604 2 3 0 26 0 278 281 271 605 2 3 0 26 0 277 269 279 606 2 3 0 26 0 279 270 266 607 2 3 0 26 0 270 279 46 608 2 3 0 26 0 277 279 266 609 2 3 0 26 0 31 280 30 610 2 3 0 26 0 273 261 280 611 2 3 0 26 0 273 280 284 612 2 3 0 26 0 284 280 31 613 2 3 0 26 0 278 268 260 614 2 3 0 26 0 268 278 265 615 2 3 0 26 0 260 283 278 616 2 3 0 26 0 285 28 267 617 2 3 0 26 0 285 27 28 618 2 3 0 26 0 283 277 281 619 2 3 0 26 0 283 281 278 620 2 3 0 26 0 285 262 27 621 2 3 0 26 0 59 268 58 622 2 3 0 26 0 286 58 268 623 2 3 0 26 0 265 286 268 624 2 3 0 26 0 281 287 271 625 2 3 0 26 0 287 267 271 626 2 3 0 26 0 286 57 58 627 2 3 0 26 0 27 262 26 628 2 3 0 26 0 26 288 5 629 2 3 0 26 0 44 288 275 630 2 3 0 26 0 288 44 5 631 2 3 0 26 0 289 268 59 632 2 3 0 26 0 289 274 260 633 2 3 0 26 0 268 289 260 634 2 3 0 26 0 60 289 59 635 2 3 0 26 0 60 274 289 636 2 3 0 26 0 262 288 26 637 2 3 0 26 0 262 275 288 638 2 3 0 26 0 261 286 265 639 2 3 0 26 0 261 273 286 640 2 3 0 26 0 273 57 286 641 2 3 0 26 0 262 287 266 642 2 3 0 26 0 262 285 287 643 2 3 0 26 0 287 281 266 644 2 3 0 26 0 287 285 267 645 2 3 0 28 0 31 294 2 646 2 3 0 28 0 294 79 2 647 2 3 0 28 0 299 77 78 648 2 3 0 28 0 76 300 75 649 2 3 0 28 0 292 300 296 650 2 3 0 28 0 291 301 295 651 2 3 0 28 0 303 27 26 652 2 3 0 28 0 304 293 294 653 2 3 0 28 0 75 305 74 654 2 3 0 28 0 306 78 79 655 2 3 0 28 0 294 306 79 656 2 3 0 28 0 300 305 75 657 2 3 0 28 0 300 292 305 658 2 3 0 28 0 304 31 30 659 2 3 0 28 0 294 31 304 660 2 3 0 28 0 302 301 291 661 2 3 0 28 0 293 306 294 662 2 3 0 28 0 41 302 42 663 2 3 0 28 0 78 306 299 664 2 3 0 28 0 304 290 293 665 2 3 0 28 0 302 297 301 666 2 3 0 28 0 308 295 301 667 2 3 0 28 0 309 76 77 668 2 3 0 28 0 299 309 77 669 2 3 0 28 0 291 310 302 670 2 3 0 28 0 310 42 302 671 2 3 0 28 0 290 312 293 672 2 3 0 28 0 299 312 307 673 2 3 0 28 0 43 314 5 674 2 3 0 28 0 26 314 303 675 2 3 0 28 0 314 26 5 676 2 3 0 28 0 312 306 293 677 2 3 0 28 0 299 306 312 678 2 3 0 28 0 307 311 296 679 2 3 0 28 0 297 41 40 680 2 3 0 28 0 302 41 297 681 2 3 0 28 0 313 312 290 682 2 3 0 28 0 307 312 313 683 2 3 0 28 0 311 308 301 684 2 3 0 28 0 299 307 309 685 2 3 0 28 0 300 309 296 686 2 3 0 28 0 309 300 76 687 2 3 0 28 0 309 307 296 688 2 3 0 28 0 291 303 310 689 2 3 0 28 0 310 43 42 690 2 3 0 28 0 310 303 314 691 2 3 0 28 0 310 314 43 692 2 3 0 28 0 298 308 290 693 2 3 0 28 0 308 298 295 694 2 3 0 28 0 313 290 308 695 2 3 0 28 0 40 315 297 696 2 3 0 28 0 39 315 40 697 2 3 0 28 0 307 313 311 698 2 3 0 28 0 311 313 308 699 2 3 0 28 0 292 315 39 700 2 3 0 28 0 298 29 28 701 2 3 0 28 0 28 316 298 702 2 3 0 28 0 316 295 298 703 2 3 0 28 0 317 311 301 704 2 3 0 28 0 297 317 301 705 2 3 0 28 0 27 316 28 706 2 3 0 28 0 292 39 38 707 2 3 0 28 0 318 38 6 708 2 3 0 28 0 318 74 305 709 2 3 0 28 0 74 318 6 710 2 3 0 28 0 298 319 29 711 2 3 0 28 0 304 319 290 712 2 3 0 28 0 319 298 290 713 2 3 0 28 0 319 30 29 714 2 3 0 28 0 304 30 319 715 2 3 0 28 0 318 292 38 716 2 3 0 28 0 305 292 318 717 2 3 0 28 0 316 291 295 718 2 3 0 28 0 303 291 316 719 2 3 0 28 0 27 303 316 720 2 3 0 28 0 317 292 296 721 2 3 0 28 0 315 292 317 722 2 3 0 28 0 311 317 296 723 2 3 0 28 0 315 317 297 $EndElements dune-grid-2.11.0/doc/grids/gmsh/sphere.msh.license000066400000000000000000000002501511655130300217010ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/telescope.geo000066400000000000000000000035371511655130300207530ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // mesh width associated with points lc = 0.5; // circle r = 1.0; cx = 0.0; cy = 0.0; cz = 0.0; pbase=0; lbase=0; sbase=0; // points Point(pbase+1) = {cx, cy, cz, lc}; Point(pbase+2) = {cx+r, cy, cz, lc}; Point(pbase+3) = {cx, cy+r, cz, lc}; Point(pbase+4) = {cx, cy, cz+r, lc}; Point(pbase+5) = {cx-r, cy, cz, lc}; Point(pbase+6) = {cx, cy-r, cz, lc}; Point(pbase+7) = {cx+r, cy, cz-r, lc}; Point(pbase+8) = {cx, cy+r, cz-r, lc}; Point(pbase+9) = {cx-r, cy, cz-r, lc}; Point(pbase+10)= {cx, cy-r, cz-r, lc}; Point(pbase+11)= {cx, cy, cz-r, lc}; // lines Circle(lbase+1) = {2,1,3}; Circle(lbase+2) = {3,1,4}; Circle(lbase+3) = {4,1,2}; Circle(lbase+4) = {3,1,5}; Circle(lbase+5) = {5,1,4}; Circle(lbase+6) = {5,1,6}; Circle(lbase+7) = {6,1,4}; Circle(lbase+8) = {6,1,2}; Circle(lbase+9) = {8,11,9}; Circle(lbase+10)= {9,11,10}; Circle(lbase+11)= {10,11,7}; Circle(lbase+12)= {7,11,8}; Line(lbase+13)= {8,3}; Line(lbase+14)= {9,5}; Line(lbase+15)= {10,6}; Line(lbase+16)= {7,2}; Line Loop(lbase+101) = {1,2,3}; Line Loop(lbase+102) = {4,5,-2}; Line Loop(lbase+103) = {6,7,-5}; Line Loop(lbase+104) = {8,-3,-7}; Line Loop(lbase+105) = {12,13,-1,-16}; Line Loop(lbase+106) = {9,14,-4,-13}; Line Loop(lbase+107) = {10,15,-6,-14}; Line Loop(lbase+108) = {11,16,-8,-15}; Line Loop(lbase+109) = {9,10,11,12}; // surfaces Ruled Surface(sbase+1) = {101}; Ruled Surface(sbase+2) = {102}; Ruled Surface(sbase+3) = {103}; Ruled Surface(sbase+4) = {104}; Ruled Surface(sbase+5) = {105}; Ruled Surface(sbase+6) = {106}; Ruled Surface(sbase+7) = {107}; Ruled Surface(sbase+8) = {108}; Plane Surface(sbase+9) = {109}; Surface Loop(sbase+400) = {1,2,3,4,5,6,7,8,9}; // volume Volume(1000) = {400}; dune-grid-2.11.0/doc/grids/gmsh/telescope.msh000066400000000000000000000264671511655130300207770ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 69 1 0 0 0 2 1 0 0 3 0 1 0 4 0 0 1 5 -1 0 0 6 0 -1 0 7 1 0 -1 8 0 1 -1 9 -1 0 -1 10 0 -1 -1 11 0 0 -1 12 0.8660254037857157 0.499999999997788 0 13 0.4999999999988419 0.8660254037851073 0 14 0 0.8660254037857157 0.499999999997788 15 0 0.4999999999988419 0.8660254037851073 16 0.499999999997788 0 0.8660254037857157 17 0.8660254037851073 0 0.4999999999988419 18 -0.499999999997788 0.8660254037857157 0 19 -0.8660254037851073 0.4999999999988419 0 20 -0.8660254037857157 0 0.499999999997788 21 -0.4999999999988419 0 0.8660254037851073 22 -0.8660254037857157 -0.499999999997788 0 23 -0.4999999999988419 -0.8660254037851073 0 24 0 -0.8660254037857157 0.499999999997788 25 0 -0.4999999999988419 0.8660254037851073 26 0.499999999997788 -0.8660254037857157 0 27 0.8660254037851073 -0.4999999999988419 0 28 -0.499999999997788 0.8660254037857157 -1 29 -0.8660254037851073 0.4999999999988419 -1 30 -0.8660254037857157 -0.499999999997788 -1 31 -0.4999999999988419 -0.8660254037851073 -1 32 0.499999999997788 -0.8660254037857157 -1 33 0.8660254037851073 -0.4999999999988419 -1 34 0.8660254037857157 0.499999999997788 -1 35 0.4999999999988419 0.8660254037851073 -1 36 0.4272342705359127 0.6393242049539736 0.6393242049536496 37 0.783972649638455 0.4144136670742724 0.4622209397689749 38 -0.5756145374659047 0.4217647653741238 0.7005586249178744 39 -0.3587678219942536 0.7995405141199002 0.4816851836857609 40 -0.7421211276574317 0.5653384650233741 0.3600675656727181 41 -0.4272342705362692 -0.6393242049538544 0.6393242049535305 42 -0.7841187705118203 -0.4403829723142243 0.4372877672959997 43 0.6393242049535306 -0.4272342705362692 0.6393242049538543 44 0.4144137207998477 -0.7839726502710042 0.4622208905273362 45 0.4067366430757783 0.9135454576426106 -0.6 46 -0.8090169943746613 0.5877852522928669 -0.4 47 -0.5372996083469864 -0.8433914458127821 -0.4166666666666666 48 -0.8696385745817051 -0.4936889198670557 -0.5694444444444444 49 0.7898354734238094 -0.6133187792016374 -0.7384259259259259 50 0.942256510237846 -0.3348920257551621 -0.5476851851851852 51 0.08855070144868839 -0.5551020776831219 -1 52 0.5564665713954644 -0.2939114004333228 -1 53 0.2763744884777239 0.4835149139342805 -1 54 -0.4708520348518781 0.126552230485235 -1 55 0.5921702158047604 0.1215896719695019 -1 56 0.05590735039306384 0.005620213338362633 -1 57 -0.2507659332939976 0.4969521269237394 -1 58 -0.4487365644657806 -0.2981591729404032 -1 59 -0.0107163236287631 -0.5165297360796159 -0.4826379948480783 60 -0.2785000916387222 0.4649263787124072 -0.5874830372392191 61 0.1003494840643143 0.3674491020185399 0.3492945689807368 62 0.2094954267293344 0.4494464609885045 -0.4559830381707816 63 -0.4742529396974615 -0.142897395566676 -0.4247984740750855 64 0.4970184329849747 -0.3388597062458725 -0.5738613267497686 65 0.5168689061294469 0.1145391761782698 -0.6103003968313175 66 -0.3866749056813206 -0.5928945465994709 -0.7178434211508453 67 0.06708779234851506 -0.2300809424044148 0.04490448606369453 68 -0.4094274737047707 0.2635778372084727 0.1017412411987709 69 0.4396370265786172 -0.1074929328354941 0.3979938362552485 $EndNodes $Elements 338 1 15 3 0 1 0 1 2 15 3 0 2 0 2 3 15 3 0 3 0 3 4 15 3 0 4 0 4 5 15 3 0 5 0 5 6 15 3 0 6 0 6 7 15 3 0 7 0 7 8 15 3 0 8 0 8 9 15 3 0 9 0 9 10 15 3 0 10 0 10 11 15 3 0 11 0 11 12 1 3 0 1 0 2 12 13 1 3 0 1 0 12 13 14 1 3 0 1 0 13 3 15 1 3 0 2 0 3 14 16 1 3 0 2 0 14 15 17 1 3 0 2 0 15 4 18 1 3 0 3 0 4 16 19 1 3 0 3 0 16 17 20 1 3 0 3 0 17 2 21 1 3 0 4 0 3 18 22 1 3 0 4 0 18 19 23 1 3 0 4 0 19 5 24 1 3 0 5 0 5 20 25 1 3 0 5 0 20 21 26 1 3 0 5 0 21 4 27 1 3 0 6 0 5 22 28 1 3 0 6 0 22 23 29 1 3 0 6 0 23 6 30 1 3 0 7 0 6 24 31 1 3 0 7 0 24 25 32 1 3 0 7 0 25 4 33 1 3 0 8 0 6 26 34 1 3 0 8 0 26 27 35 1 3 0 8 0 27 2 36 1 3 0 9 0 8 28 37 1 3 0 9 0 28 29 38 1 3 0 9 0 29 9 39 1 3 0 10 0 9 30 40 1 3 0 10 0 30 31 41 1 3 0 10 0 31 10 42 1 3 0 11 0 10 32 43 1 3 0 11 0 32 33 44 1 3 0 11 0 33 7 45 1 3 0 12 0 7 34 46 1 3 0 12 0 34 35 47 1 3 0 12 0 35 8 48 1 3 0 13 0 8 3 49 1 3 0 14 0 9 5 50 1 3 0 15 0 10 6 51 1 3 0 16 0 7 2 52 2 3 0 1 0 16 15 4 53 2 3 0 1 0 13 3 14 54 2 3 0 1 0 16 36 15 55 2 3 0 1 0 12 37 2 56 2 3 0 1 0 37 17 2 57 2 3 0 1 0 13 37 12 58 2 3 0 1 0 37 13 36 59 2 3 0 1 0 37 16 17 60 2 3 0 1 0 36 16 37 61 2 3 0 1 0 13 14 36 62 2 3 0 1 0 14 15 36 63 2 3 0 2 0 19 5 20 64 2 3 0 2 0 15 21 4 65 2 3 0 2 0 15 38 21 66 2 3 0 2 0 39 14 3 67 2 3 0 2 0 18 39 3 68 2 3 0 2 0 39 15 14 69 2 3 0 2 0 38 15 39 70 2 3 0 2 0 20 21 38 71 2 3 0 2 0 40 39 18 72 2 3 0 2 0 39 40 38 73 2 3 0 2 0 19 40 18 74 2 3 0 2 0 20 40 19 75 2 3 0 2 0 20 38 40 76 2 3 0 3 0 23 6 24 77 2 3 0 3 0 21 25 4 78 2 3 0 3 0 21 41 25 79 2 3 0 3 0 42 20 5 80 2 3 0 3 0 22 42 5 81 2 3 0 3 0 42 21 20 82 2 3 0 3 0 42 23 41 83 2 3 0 3 0 23 42 22 84 2 3 0 3 0 41 21 42 85 2 3 0 3 0 24 25 41 86 2 3 0 3 0 23 24 41 87 2 3 0 4 0 27 2 17 88 2 3 0 4 0 25 16 4 89 2 3 0 4 0 43 27 17 90 2 3 0 4 0 44 24 6 91 2 3 0 4 0 26 44 6 92 2 3 0 4 0 27 44 26 93 2 3 0 4 0 44 27 43 94 2 3 0 4 0 44 25 24 95 2 3 0 4 0 43 25 44 96 2 3 0 4 0 16 25 43 97 2 3 0 4 0 17 16 43 98 2 3 0 5 0 45 34 35 99 2 3 0 5 0 35 8 45 100 2 3 0 5 0 45 8 3 101 2 3 0 5 0 13 45 3 102 2 3 0 5 0 7 12 2 103 2 3 0 5 0 34 45 13 104 2 3 0 5 0 34 12 7 105 2 3 0 5 0 13 12 34 106 2 3 0 6 0 29 46 28 107 2 3 0 6 0 5 19 46 108 2 3 0 6 0 18 46 19 109 2 3 0 6 0 8 18 3 110 2 3 0 6 0 28 18 8 111 2 3 0 6 0 28 46 18 112 2 3 0 6 0 5 29 9 113 2 3 0 6 0 5 46 29 114 2 3 0 7 0 47 23 22 115 2 3 0 7 0 6 23 47 116 2 3 0 7 0 9 48 5 117 2 3 0 7 0 48 22 5 118 2 3 0 7 0 22 48 47 119 2 3 0 7 0 30 48 9 120 2 3 0 7 0 31 48 30 121 2 3 0 7 0 31 47 48 122 2 3 0 7 0 6 47 10 123 2 3 0 7 0 47 31 10 124 2 3 0 8 0 33 49 32 125 2 3 0 8 0 2 50 7 126 2 3 0 8 0 49 50 27 127 2 3 0 8 0 50 2 27 128 2 3 0 8 0 10 26 6 129 2 3 0 8 0 50 33 7 130 2 3 0 8 0 49 33 50 131 2 3 0 8 0 32 26 10 132 2 3 0 8 0 26 49 27 133 2 3 0 8 0 32 49 26 134 2 3 0 9 0 32 33 52 135 2 3 0 9 0 51 32 52 136 2 3 0 9 0 10 51 31 137 2 3 0 9 0 32 51 10 138 2 3 0 9 0 7 52 33 139 2 3 0 9 0 55 7 34 140 2 3 0 9 0 52 7 55 141 2 3 0 9 0 34 53 55 142 2 3 0 9 0 56 52 55 143 2 3 0 9 0 53 56 55 144 2 3 0 9 0 34 35 53 145 2 3 0 9 0 51 52 56 146 2 3 0 9 0 9 54 29 147 2 3 0 9 0 8 53 35 148 2 3 0 9 0 28 29 57 149 2 3 0 9 0 57 29 54 150 2 3 0 9 0 51 56 58 151 2 3 0 9 0 56 54 58 152 2 3 0 9 0 57 54 56 153 2 3 0 9 0 58 30 31 154 2 3 0 9 0 31 51 58 155 2 3 0 9 0 9 58 54 156 2 3 0 9 0 9 30 58 157 2 3 0 9 0 8 28 57 158 2 3 0 9 0 57 53 8 159 2 3 0 9 0 57 56 53 160 4 3 0 1000 0 51 64 59 32 161 4 3 0 1000 0 59 63 67 56 162 4 3 0 1000 0 38 61 39 15 163 4 3 0 1000 0 4 67 21 61 164 4 3 0 1000 0 66 10 51 59 165 4 3 0 1000 0 21 67 25 41 166 4 3 0 1000 0 44 69 67 25 167 4 3 0 1000 0 62 63 68 60 168 4 3 0 1000 0 58 59 66 51 169 4 3 0 1000 0 37 12 69 61 170 4 3 0 1000 0 6 67 24 44 171 4 3 0 1000 0 37 17 69 2 172 4 3 0 1000 0 21 67 68 61 173 4 3 0 1000 0 42 67 21 41 174 4 3 0 1000 0 46 68 63 60 175 4 3 0 1000 0 60 53 56 57 176 4 3 0 1000 0 67 41 24 25 177 4 3 0 1000 0 66 10 59 47 178 4 3 0 1000 0 51 64 32 52 179 4 3 0 1000 0 18 8 3 60 180 4 3 0 1000 0 4 67 61 69 181 4 3 0 1000 0 32 26 64 59 182 4 3 0 1000 0 18 60 46 28 183 4 3 0 1000 0 62 63 60 56 184 4 3 0 1000 0 63 67 68 42 185 4 3 0 1000 0 10 59 32 51 186 4 3 0 1000 0 13 45 62 3 187 4 3 0 1000 0 17 37 69 16 188 4 3 0 1000 0 23 67 42 41 189 4 3 0 1000 0 34 62 13 45 190 4 3 0 1000 0 23 59 67 6 191 4 3 0 1000 0 69 27 67 2 192 4 3 0 1000 0 67 23 6 24 193 4 3 0 1000 0 46 68 5 63 194 4 3 0 1000 0 62 63 56 67 195 4 3 0 1000 0 58 59 51 56 196 4 3 0 1000 0 43 17 69 16 197 4 3 0 1000 0 45 34 62 35 198 4 3 0 1000 0 8 45 62 35 199 4 3 0 1000 0 68 46 19 18 200 4 3 0 1000 0 19 68 18 40 201 4 3 0 1000 0 44 26 67 27 202 4 3 0 1000 0 19 68 40 20 203 4 3 0 1000 0 58 66 30 31 204 4 3 0 1000 0 68 61 38 21 205 4 3 0 1000 0 66 51 31 58 206 4 3 0 1000 0 63 60 56 54 207 4 3 0 1000 0 18 8 60 28 208 4 3 0 1000 0 52 65 56 64 209 4 3 0 1000 0 63 29 5 46 210 4 3 0 1000 0 7 34 65 12 211 4 3 0 1000 0 58 59 56 63 212 4 3 0 1000 0 22 63 48 5 213 4 3 0 1000 0 69 4 25 16 214 4 3 0 1000 0 60 53 57 8 215 4 3 0 1000 0 64 2 7 65 216 4 3 0 1000 0 62 56 60 53 217 4 3 0 1000 0 37 13 12 61 218 4 3 0 1000 0 62 63 67 68 219 4 3 0 1000 0 61 62 67 68 220 4 3 0 1000 0 63 9 30 48 221 4 3 0 1000 0 5 68 42 63 222 4 3 0 1000 0 63 60 54 29 223 4 3 0 1000 0 38 68 20 40 224 4 3 0 1000 0 67 6 26 44 225 4 3 0 1000 0 38 61 68 39 226 4 3 0 1000 0 4 67 69 25 227 4 3 0 1000 0 63 5 29 9 228 4 3 0 1000 0 21 61 38 15 229 4 3 0 1000 0 61 4 69 16 230 4 3 0 1000 0 67 65 12 2 231 4 3 0 1000 0 39 68 38 40 232 4 3 0 1000 0 67 62 12 65 233 4 3 0 1000 0 61 67 12 69 234 4 3 0 1000 0 4 61 21 15 235 4 3 0 1000 0 5 63 42 22 236 4 3 0 1000 0 62 61 3 68 237 4 3 0 1000 0 2 64 50 27 238 4 3 0 1000 0 47 63 48 22 239 4 3 0 1000 0 61 62 13 12 240 4 3 0 1000 0 30 66 58 63 241 4 3 0 1000 0 51 64 52 56 242 4 3 0 1000 0 2 69 12 67 243 4 3 0 1000 0 42 63 23 22 244 4 3 0 1000 0 60 29 46 28 245 4 3 0 1000 0 7 65 2 12 246 4 3 0 1000 0 69 27 2 17 247 4 3 0 1000 0 46 5 68 19 248 4 3 0 1000 0 64 7 2 50 249 4 3 0 1000 0 23 59 6 47 250 4 3 0 1000 0 16 37 69 61 251 4 3 0 1000 0 21 68 67 42 252 4 3 0 1000 0 21 68 42 20 253 4 3 0 1000 0 67 62 65 56 254 4 3 0 1000 0 5 68 20 42 255 4 3 0 1000 0 63 67 42 23 256 4 3 0 1000 0 38 68 21 20 257 4 3 0 1000 0 61 62 12 67 258 4 3 0 1000 0 15 4 61 16 259 4 3 0 1000 0 67 64 27 26 260 4 3 0 1000 0 23 63 47 22 261 4 3 0 1000 0 23 59 47 63 262 4 3 0 1000 0 25 69 16 43 263 4 3 0 1000 0 4 67 25 21 264 4 3 0 1000 0 30 66 48 31 265 4 3 0 1000 0 44 69 25 43 266 4 3 0 1000 0 32 59 10 26 267 4 3 0 1000 0 37 69 12 2 268 4 3 0 1000 0 8 3 62 45 269 4 3 0 1000 0 68 40 39 18 270 4 3 0 1000 0 12 62 13 34 271 4 3 0 1000 0 2 64 67 65 272 4 3 0 1000 0 68 46 18 60 273 4 3 0 1000 0 51 64 56 59 274 4 3 0 1000 0 5 68 19 20 275 4 3 0 1000 0 69 27 17 43 276 4 3 0 1000 0 44 69 43 27 277 4 3 0 1000 0 62 3 61 13 278 4 3 0 1000 0 63 5 9 48 279 4 3 0 1000 0 58 9 30 63 280 4 3 0 1000 0 32 64 49 33 281 4 3 0 1000 0 49 64 27 50 282 4 3 0 1000 0 48 66 30 63 283 4 3 0 1000 0 32 64 33 52 284 4 3 0 1000 0 58 9 63 54 285 4 3 0 1000 0 8 53 62 60 286 4 3 0 1000 0 56 58 63 54 287 4 3 0 1000 0 34 65 53 55 288 4 3 0 1000 0 60 8 57 28 289 4 3 0 1000 0 56 55 53 65 290 4 3 0 1000 0 47 66 48 63 291 4 3 0 1000 0 37 13 61 36 292 4 3 0 1000 0 37 36 61 16 293 4 3 0 1000 0 61 36 13 14 294 4 3 0 1000 0 36 15 61 16 295 4 3 0 1000 0 12 62 34 65 296 4 3 0 1000 0 53 34 62 65 297 4 3 0 1000 0 62 34 53 35 298 4 3 0 1000 0 8 62 53 35 299 4 3 0 1000 0 6 10 59 26 300 4 3 0 1000 0 3 8 62 60 301 4 3 0 1000 0 62 56 53 65 302 4 3 0 1000 0 59 67 6 26 303 4 3 0 1000 0 32 64 26 49 304 4 3 0 1000 0 33 64 50 7 305 4 3 0 1000 0 64 27 26 49 306 4 3 0 1000 0 59 67 26 64 307 4 3 0 1000 0 33 64 7 52 308 4 3 0 1000 0 66 10 47 31 309 4 3 0 1000 0 66 59 63 47 310 4 3 0 1000 0 66 10 31 51 311 4 3 0 1000 0 10 6 59 47 312 4 3 0 1000 0 23 59 63 67 313 4 3 0 1000 0 14 39 61 15 314 4 3 0 1000 0 61 36 14 15 315 4 3 0 1000 0 39 14 61 3 316 4 3 0 1000 0 14 13 61 3 317 4 3 0 1000 0 48 66 47 31 318 4 3 0 1000 0 18 39 68 3 319 4 3 0 1000 0 67 41 23 24 320 4 3 0 1000 0 52 65 64 7 321 4 3 0 1000 0 52 65 7 55 322 4 3 0 1000 0 52 65 55 56 323 4 3 0 1000 0 56 57 54 60 324 4 3 0 1000 0 54 57 29 60 325 4 3 0 1000 0 57 29 60 28 326 4 3 0 1000 0 2 64 27 67 327 4 3 0 1000 0 44 69 27 67 328 4 3 0 1000 0 67 64 56 65 329 4 3 0 1000 0 59 67 64 56 330 4 3 0 1000 0 68 60 18 3 331 4 3 0 1000 0 68 60 3 62 332 4 3 0 1000 0 39 61 68 3 333 4 3 0 1000 0 58 59 63 66 334 4 3 0 1000 0 63 60 29 46 335 4 3 0 1000 0 54 63 29 9 336 4 3 0 1000 0 7 34 55 65 337 4 3 0 1000 0 24 67 25 44 338 4 3 0 1000 0 49 64 50 33 $EndElements dune-grid-2.11.0/doc/grids/gmsh/telescope.msh.license000066400000000000000000000002501511655130300223760ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/telescope1storder.msh000066400000000000000000000264671511655130300224630ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 69 1 0 0 0 2 1 0 0 3 0 1 0 4 0 0 1 5 -1 0 0 6 0 -1 0 7 1 0 -1 8 0 1 -1 9 -1 0 -1 10 0 -1 -1 11 0 0 -1 12 0.8660254037857157 0.499999999997788 0 13 0.4999999999988419 0.8660254037851073 0 14 0 0.8660254037857157 0.499999999997788 15 0 0.4999999999988419 0.8660254037851073 16 0.499999999997788 0 0.8660254037857157 17 0.8660254037851073 0 0.4999999999988419 18 -0.499999999997788 0.8660254037857157 0 19 -0.8660254037851073 0.4999999999988419 0 20 -0.8660254037857157 0 0.499999999997788 21 -0.4999999999988419 0 0.8660254037851073 22 -0.8660254037857157 -0.499999999997788 0 23 -0.4999999999988419 -0.8660254037851073 0 24 0 -0.8660254037857157 0.499999999997788 25 0 -0.4999999999988419 0.8660254037851073 26 0.499999999997788 -0.8660254037857157 0 27 0.8660254037851073 -0.4999999999988419 0 28 -0.499999999997788 0.8660254037857157 -1 29 -0.8660254037851073 0.4999999999988419 -1 30 -0.8660254037857157 -0.499999999997788 -1 31 -0.4999999999988419 -0.8660254037851073 -1 32 0.499999999997788 -0.8660254037857157 -1 33 0.8660254037851073 -0.4999999999988419 -1 34 0.8660254037857157 0.499999999997788 -1 35 0.4999999999988419 0.8660254037851073 -1 36 0.4272342705359127 0.6393242049539736 0.6393242049536496 37 0.783972649638455 0.4144136670742724 0.4622209397689749 38 -0.5756145374659047 0.4217647653741238 0.7005586249178744 39 -0.3587678219942536 0.7995405141199002 0.4816851836857609 40 -0.7421211276574317 0.5653384650233741 0.3600675656727181 41 -0.4272342705362692 -0.6393242049538544 0.6393242049535305 42 -0.7841187705118203 -0.4403829723142243 0.4372877672959997 43 0.6393242049535306 -0.4272342705362692 0.6393242049538543 44 0.4144137207998477 -0.7839726502710042 0.4622208905273362 45 0.4067366430757783 0.9135454576426106 -0.6 46 -0.8090169943746613 0.5877852522928669 -0.4 47 -0.5372996083469864 -0.8433914458127821 -0.4166666666666666 48 -0.8696385745817051 -0.4936889198670557 -0.5694444444444444 49 0.7898354734238094 -0.6133187792016374 -0.7384259259259259 50 0.942256510237846 -0.3348920257551621 -0.5476851851851852 51 0.08855070144868839 -0.5551020776831219 -1 52 0.5564665713954644 -0.2939114004333228 -1 53 0.2763744884777239 0.4835149139342805 -1 54 -0.4708520348518781 0.126552230485235 -1 55 0.5921702158047604 0.1215896719695019 -1 56 0.05590735039306384 0.005620213338362633 -1 57 -0.2507659332939976 0.4969521269237394 -1 58 -0.4487365644657806 -0.2981591729404032 -1 59 -0.0107163236287631 -0.5165297360796159 -0.4826379948480783 60 -0.2785000916387222 0.4649263787124072 -0.5874830372392191 61 0.1003494840643143 0.3674491020185399 0.3492945689807368 62 0.2094954267293344 0.4494464609885045 -0.4559830381707816 63 -0.4742529396974615 -0.142897395566676 -0.4247984740750855 64 0.4970184329849747 -0.3388597062458725 -0.5738613267497686 65 0.5168689061294469 0.1145391761782698 -0.6103003968313175 66 -0.3866749056813206 -0.5928945465994709 -0.7178434211508453 67 0.06708779234851506 -0.2300809424044148 0.04490448606369453 68 -0.4094274737047707 0.2635778372084727 0.1017412411987709 69 0.4396370265786172 -0.1074929328354941 0.3979938362552485 $EndNodes $Elements 338 1 15 3 0 1 0 1 2 15 3 0 2 0 2 3 15 3 0 3 0 3 4 15 3 0 4 0 4 5 15 3 0 5 0 5 6 15 3 0 6 0 6 7 15 3 0 7 0 7 8 15 3 0 8 0 8 9 15 3 0 9 0 9 10 15 3 0 10 0 10 11 15 3 0 11 0 11 12 1 3 0 1 0 2 12 13 1 3 0 1 0 12 13 14 1 3 0 1 0 13 3 15 1 3 0 2 0 3 14 16 1 3 0 2 0 14 15 17 1 3 0 2 0 15 4 18 1 3 0 3 0 4 16 19 1 3 0 3 0 16 17 20 1 3 0 3 0 17 2 21 1 3 0 4 0 3 18 22 1 3 0 4 0 18 19 23 1 3 0 4 0 19 5 24 1 3 0 5 0 5 20 25 1 3 0 5 0 20 21 26 1 3 0 5 0 21 4 27 1 3 0 6 0 5 22 28 1 3 0 6 0 22 23 29 1 3 0 6 0 23 6 30 1 3 0 7 0 6 24 31 1 3 0 7 0 24 25 32 1 3 0 7 0 25 4 33 1 3 0 8 0 6 26 34 1 3 0 8 0 26 27 35 1 3 0 8 0 27 2 36 1 3 0 9 0 8 28 37 1 3 0 9 0 28 29 38 1 3 0 9 0 29 9 39 1 3 0 10 0 9 30 40 1 3 0 10 0 30 31 41 1 3 0 10 0 31 10 42 1 3 0 11 0 10 32 43 1 3 0 11 0 32 33 44 1 3 0 11 0 33 7 45 1 3 0 12 0 7 34 46 1 3 0 12 0 34 35 47 1 3 0 12 0 35 8 48 1 3 0 13 0 8 3 49 1 3 0 14 0 9 5 50 1 3 0 15 0 10 6 51 1 3 0 16 0 7 2 52 2 3 0 1 0 16 15 4 53 2 3 0 1 0 13 3 14 54 2 3 0 1 0 16 36 15 55 2 3 0 1 0 12 37 2 56 2 3 0 1 0 37 17 2 57 2 3 0 1 0 13 37 12 58 2 3 0 1 0 37 13 36 59 2 3 0 1 0 37 16 17 60 2 3 0 1 0 36 16 37 61 2 3 0 1 0 13 14 36 62 2 3 0 1 0 14 15 36 63 2 3 0 2 0 19 5 20 64 2 3 0 2 0 15 21 4 65 2 3 0 2 0 15 38 21 66 2 3 0 2 0 39 14 3 67 2 3 0 2 0 18 39 3 68 2 3 0 2 0 39 15 14 69 2 3 0 2 0 38 15 39 70 2 3 0 2 0 20 21 38 71 2 3 0 2 0 40 39 18 72 2 3 0 2 0 39 40 38 73 2 3 0 2 0 19 40 18 74 2 3 0 2 0 20 40 19 75 2 3 0 2 0 20 38 40 76 2 3 0 3 0 23 6 24 77 2 3 0 3 0 21 25 4 78 2 3 0 3 0 21 41 25 79 2 3 0 3 0 42 20 5 80 2 3 0 3 0 22 42 5 81 2 3 0 3 0 42 21 20 82 2 3 0 3 0 42 23 41 83 2 3 0 3 0 23 42 22 84 2 3 0 3 0 41 21 42 85 2 3 0 3 0 24 25 41 86 2 3 0 3 0 23 24 41 87 2 3 0 4 0 27 2 17 88 2 3 0 4 0 25 16 4 89 2 3 0 4 0 43 27 17 90 2 3 0 4 0 44 24 6 91 2 3 0 4 0 26 44 6 92 2 3 0 4 0 27 44 26 93 2 3 0 4 0 44 27 43 94 2 3 0 4 0 44 25 24 95 2 3 0 4 0 43 25 44 96 2 3 0 4 0 16 25 43 97 2 3 0 4 0 17 16 43 98 2 3 0 5 0 45 34 35 99 2 3 0 5 0 35 8 45 100 2 3 0 5 0 45 8 3 101 2 3 0 5 0 13 45 3 102 2 3 0 5 0 7 12 2 103 2 3 0 5 0 34 45 13 104 2 3 0 5 0 34 12 7 105 2 3 0 5 0 13 12 34 106 2 3 0 6 0 29 46 28 107 2 3 0 6 0 5 19 46 108 2 3 0 6 0 18 46 19 109 2 3 0 6 0 8 18 3 110 2 3 0 6 0 28 18 8 111 2 3 0 6 0 28 46 18 112 2 3 0 6 0 5 29 9 113 2 3 0 6 0 5 46 29 114 2 3 0 7 0 47 23 22 115 2 3 0 7 0 6 23 47 116 2 3 0 7 0 9 48 5 117 2 3 0 7 0 48 22 5 118 2 3 0 7 0 22 48 47 119 2 3 0 7 0 30 48 9 120 2 3 0 7 0 31 48 30 121 2 3 0 7 0 31 47 48 122 2 3 0 7 0 6 47 10 123 2 3 0 7 0 47 31 10 124 2 3 0 8 0 33 49 32 125 2 3 0 8 0 2 50 7 126 2 3 0 8 0 49 50 27 127 2 3 0 8 0 50 2 27 128 2 3 0 8 0 10 26 6 129 2 3 0 8 0 50 33 7 130 2 3 0 8 0 49 33 50 131 2 3 0 8 0 32 26 10 132 2 3 0 8 0 26 49 27 133 2 3 0 8 0 32 49 26 134 2 3 0 9 0 32 33 52 135 2 3 0 9 0 51 32 52 136 2 3 0 9 0 10 51 31 137 2 3 0 9 0 32 51 10 138 2 3 0 9 0 7 52 33 139 2 3 0 9 0 55 7 34 140 2 3 0 9 0 52 7 55 141 2 3 0 9 0 34 53 55 142 2 3 0 9 0 56 52 55 143 2 3 0 9 0 53 56 55 144 2 3 0 9 0 34 35 53 145 2 3 0 9 0 51 52 56 146 2 3 0 9 0 9 54 29 147 2 3 0 9 0 8 53 35 148 2 3 0 9 0 28 29 57 149 2 3 0 9 0 57 29 54 150 2 3 0 9 0 51 56 58 151 2 3 0 9 0 56 54 58 152 2 3 0 9 0 57 54 56 153 2 3 0 9 0 58 30 31 154 2 3 0 9 0 31 51 58 155 2 3 0 9 0 9 58 54 156 2 3 0 9 0 9 30 58 157 2 3 0 9 0 8 28 57 158 2 3 0 9 0 57 53 8 159 2 3 0 9 0 57 56 53 160 4 3 0 1000 0 51 64 59 32 161 4 3 0 1000 0 59 63 67 56 162 4 3 0 1000 0 38 61 39 15 163 4 3 0 1000 0 4 67 21 61 164 4 3 0 1000 0 66 10 51 59 165 4 3 0 1000 0 21 67 25 41 166 4 3 0 1000 0 44 69 67 25 167 4 3 0 1000 0 62 63 68 60 168 4 3 0 1000 0 58 59 66 51 169 4 3 0 1000 0 37 12 69 61 170 4 3 0 1000 0 6 67 24 44 171 4 3 0 1000 0 37 17 69 2 172 4 3 0 1000 0 21 67 68 61 173 4 3 0 1000 0 42 67 21 41 174 4 3 0 1000 0 46 68 63 60 175 4 3 0 1000 0 60 53 56 57 176 4 3 0 1000 0 67 41 24 25 177 4 3 0 1000 0 66 10 59 47 178 4 3 0 1000 0 51 64 32 52 179 4 3 0 1000 0 18 8 3 60 180 4 3 0 1000 0 4 67 61 69 181 4 3 0 1000 0 32 26 64 59 182 4 3 0 1000 0 18 60 46 28 183 4 3 0 1000 0 62 63 60 56 184 4 3 0 1000 0 63 67 68 42 185 4 3 0 1000 0 10 59 32 51 186 4 3 0 1000 0 13 45 62 3 187 4 3 0 1000 0 17 37 69 16 188 4 3 0 1000 0 23 67 42 41 189 4 3 0 1000 0 34 62 13 45 190 4 3 0 1000 0 23 59 67 6 191 4 3 0 1000 0 69 27 67 2 192 4 3 0 1000 0 67 23 6 24 193 4 3 0 1000 0 46 68 5 63 194 4 3 0 1000 0 62 63 56 67 195 4 3 0 1000 0 58 59 51 56 196 4 3 0 1000 0 43 17 69 16 197 4 3 0 1000 0 45 34 62 35 198 4 3 0 1000 0 8 45 62 35 199 4 3 0 1000 0 68 46 19 18 200 4 3 0 1000 0 19 68 18 40 201 4 3 0 1000 0 44 26 67 27 202 4 3 0 1000 0 19 68 40 20 203 4 3 0 1000 0 58 66 30 31 204 4 3 0 1000 0 68 61 38 21 205 4 3 0 1000 0 66 51 31 58 206 4 3 0 1000 0 63 60 56 54 207 4 3 0 1000 0 18 8 60 28 208 4 3 0 1000 0 52 65 56 64 209 4 3 0 1000 0 63 29 5 46 210 4 3 0 1000 0 7 34 65 12 211 4 3 0 1000 0 58 59 56 63 212 4 3 0 1000 0 22 63 48 5 213 4 3 0 1000 0 69 4 25 16 214 4 3 0 1000 0 60 53 57 8 215 4 3 0 1000 0 64 2 7 65 216 4 3 0 1000 0 62 56 60 53 217 4 3 0 1000 0 37 13 12 61 218 4 3 0 1000 0 62 63 67 68 219 4 3 0 1000 0 61 62 67 68 220 4 3 0 1000 0 63 9 30 48 221 4 3 0 1000 0 5 68 42 63 222 4 3 0 1000 0 63 60 54 29 223 4 3 0 1000 0 38 68 20 40 224 4 3 0 1000 0 67 6 26 44 225 4 3 0 1000 0 38 61 68 39 226 4 3 0 1000 0 4 67 69 25 227 4 3 0 1000 0 63 5 29 9 228 4 3 0 1000 0 21 61 38 15 229 4 3 0 1000 0 61 4 69 16 230 4 3 0 1000 0 67 65 12 2 231 4 3 0 1000 0 39 68 38 40 232 4 3 0 1000 0 67 62 12 65 233 4 3 0 1000 0 61 67 12 69 234 4 3 0 1000 0 4 61 21 15 235 4 3 0 1000 0 5 63 42 22 236 4 3 0 1000 0 62 61 3 68 237 4 3 0 1000 0 2 64 50 27 238 4 3 0 1000 0 47 63 48 22 239 4 3 0 1000 0 61 62 13 12 240 4 3 0 1000 0 30 66 58 63 241 4 3 0 1000 0 51 64 52 56 242 4 3 0 1000 0 2 69 12 67 243 4 3 0 1000 0 42 63 23 22 244 4 3 0 1000 0 60 29 46 28 245 4 3 0 1000 0 7 65 2 12 246 4 3 0 1000 0 69 27 2 17 247 4 3 0 1000 0 46 5 68 19 248 4 3 0 1000 0 64 7 2 50 249 4 3 0 1000 0 23 59 6 47 250 4 3 0 1000 0 16 37 69 61 251 4 3 0 1000 0 21 68 67 42 252 4 3 0 1000 0 21 68 42 20 253 4 3 0 1000 0 67 62 65 56 254 4 3 0 1000 0 5 68 20 42 255 4 3 0 1000 0 63 67 42 23 256 4 3 0 1000 0 38 68 21 20 257 4 3 0 1000 0 61 62 12 67 258 4 3 0 1000 0 15 4 61 16 259 4 3 0 1000 0 67 64 27 26 260 4 3 0 1000 0 23 63 47 22 261 4 3 0 1000 0 23 59 47 63 262 4 3 0 1000 0 25 69 16 43 263 4 3 0 1000 0 4 67 25 21 264 4 3 0 1000 0 30 66 48 31 265 4 3 0 1000 0 44 69 25 43 266 4 3 0 1000 0 32 59 10 26 267 4 3 0 1000 0 37 69 12 2 268 4 3 0 1000 0 8 3 62 45 269 4 3 0 1000 0 68 40 39 18 270 4 3 0 1000 0 12 62 13 34 271 4 3 0 1000 0 2 64 67 65 272 4 3 0 1000 0 68 46 18 60 273 4 3 0 1000 0 51 64 56 59 274 4 3 0 1000 0 5 68 19 20 275 4 3 0 1000 0 69 27 17 43 276 4 3 0 1000 0 44 69 43 27 277 4 3 0 1000 0 62 3 61 13 278 4 3 0 1000 0 63 5 9 48 279 4 3 0 1000 0 58 9 30 63 280 4 3 0 1000 0 32 64 49 33 281 4 3 0 1000 0 49 64 27 50 282 4 3 0 1000 0 48 66 30 63 283 4 3 0 1000 0 32 64 33 52 284 4 3 0 1000 0 58 9 63 54 285 4 3 0 1000 0 8 53 62 60 286 4 3 0 1000 0 56 58 63 54 287 4 3 0 1000 0 34 65 53 55 288 4 3 0 1000 0 60 8 57 28 289 4 3 0 1000 0 56 55 53 65 290 4 3 0 1000 0 47 66 48 63 291 4 3 0 1000 0 37 13 61 36 292 4 3 0 1000 0 37 36 61 16 293 4 3 0 1000 0 61 36 13 14 294 4 3 0 1000 0 36 15 61 16 295 4 3 0 1000 0 12 62 34 65 296 4 3 0 1000 0 53 34 62 65 297 4 3 0 1000 0 62 34 53 35 298 4 3 0 1000 0 8 62 53 35 299 4 3 0 1000 0 6 10 59 26 300 4 3 0 1000 0 3 8 62 60 301 4 3 0 1000 0 62 56 53 65 302 4 3 0 1000 0 59 67 6 26 303 4 3 0 1000 0 32 64 26 49 304 4 3 0 1000 0 33 64 50 7 305 4 3 0 1000 0 64 27 26 49 306 4 3 0 1000 0 59 67 26 64 307 4 3 0 1000 0 33 64 7 52 308 4 3 0 1000 0 66 10 47 31 309 4 3 0 1000 0 66 59 63 47 310 4 3 0 1000 0 66 10 31 51 311 4 3 0 1000 0 10 6 59 47 312 4 3 0 1000 0 23 59 63 67 313 4 3 0 1000 0 14 39 61 15 314 4 3 0 1000 0 61 36 14 15 315 4 3 0 1000 0 39 14 61 3 316 4 3 0 1000 0 14 13 61 3 317 4 3 0 1000 0 48 66 47 31 318 4 3 0 1000 0 18 39 68 3 319 4 3 0 1000 0 67 41 23 24 320 4 3 0 1000 0 52 65 64 7 321 4 3 0 1000 0 52 65 7 55 322 4 3 0 1000 0 52 65 55 56 323 4 3 0 1000 0 56 57 54 60 324 4 3 0 1000 0 54 57 29 60 325 4 3 0 1000 0 57 29 60 28 326 4 3 0 1000 0 2 64 27 67 327 4 3 0 1000 0 44 69 27 67 328 4 3 0 1000 0 67 64 56 65 329 4 3 0 1000 0 59 67 64 56 330 4 3 0 1000 0 68 60 18 3 331 4 3 0 1000 0 68 60 3 62 332 4 3 0 1000 0 39 61 68 3 333 4 3 0 1000 0 58 59 63 66 334 4 3 0 1000 0 63 60 29 46 335 4 3 0 1000 0 54 63 29 9 336 4 3 0 1000 0 7 34 55 65 337 4 3 0 1000 0 24 67 25 44 338 4 3 0 1000 0 49 64 50 33 $EndElements dune-grid-2.11.0/doc/grids/gmsh/telescope1storder.msh.license000066400000000000000000000002501511655130300240620ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/telescope2ndorder.msh000066400000000000000000001037761511655130300224360ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $Nodes 368 1 0 0 0 2 1 0 0 3 0 1 0 4 0 0 1 5 -1 0 0 6 0 -1 0 7 1 0 -1 8 0 1 -1 9 -1 0 -1 10 0 -1 -1 11 0 0 -1 12 0.8660254037857157 0.499999999997788 0 13 0.4999999999988419 0.8660254037851073 0 14 0.965925826289377 0.2588190451013686 0 15 0.7071067811875745 0.7071067811855205 0 16 0.2588190451019369 0.9659258262892247 0 17 0 0.8660254037857157 0.499999999997788 18 0 0.4999999999988419 0.8660254037851073 19 0 0.965925826289377 0.2588190451013686 20 0 0.7071067811875745 0.7071067811855205 21 0 0.2588190451019369 0.9659258262892247 22 0.499999999997788 0 0.8660254037857157 23 0.8660254037851073 0 0.4999999999988419 24 0.2588190451013686 0 0.965925826289377 25 0.7071067811855205 0 0.7071067811875745 26 0.9659258262892247 0 0.2588190451019369 27 -0.499999999997788 0.8660254037857157 0 28 -0.8660254037851073 0.4999999999988419 0 29 -0.2588190451013686 0.965925826289377 0 30 -0.7071067811855205 0.7071067811875745 0 31 -0.9659258262892247 0.2588190451019369 0 32 -0.8660254037857157 0 0.499999999997788 33 -0.4999999999988419 0 0.8660254037851073 34 -0.965925826289377 0 0.2588190451013686 35 -0.7071067811875745 0 0.7071067811855205 36 -0.2588190451019369 0 0.9659258262892247 37 -0.8660254037857157 -0.499999999997788 0 38 -0.4999999999988419 -0.8660254037851073 0 39 -0.965925826289377 -0.2588190451013686 0 40 -0.7071067811875745 -0.7071067811855205 0 41 -0.2588190451019369 -0.9659258262892247 0 42 0 -0.8660254037857157 0.499999999997788 43 0 -0.4999999999988419 0.8660254037851073 44 0 -0.965925826289377 0.2588190451013686 45 0 -0.7071067811875745 0.7071067811855205 46 0 -0.2588190451019369 0.9659258262892247 47 0.499999999997788 -0.8660254037857157 0 48 0.8660254037851073 -0.4999999999988419 0 49 0.2588190451013686 -0.965925826289377 0 50 0.7071067811855205 -0.7071067811875745 0 51 0.9659258262892247 -0.2588190451019369 0 52 -0.499999999997788 0.8660254037857157 -1 53 -0.8660254037851073 0.4999999999988419 -1 54 -0.2588190451013686 0.965925826289377 -1 55 -0.7071067811855205 0.7071067811875745 -1 56 -0.9659258262892247 0.2588190451019369 -1 57 -0.8660254037857157 -0.499999999997788 -1 58 -0.4999999999988419 -0.8660254037851073 -1 59 -0.965925826289377 -0.2588190451013686 -1 60 -0.7071067811875745 -0.7071067811855205 -1 61 -0.2588190451019369 -0.9659258262892247 -1 62 0.499999999997788 -0.8660254037857157 -1 63 0.8660254037851073 -0.4999999999988419 -1 64 0.2588190451013686 -0.965925826289377 -1 65 0.7071067811855205 -0.7071067811875745 -1 66 0.9659258262892247 -0.2588190451019369 -1 67 0.8660254037857157 0.499999999997788 -1 68 0.4999999999988419 0.8660254037851073 -1 69 0.965925826289377 0.2588190451013686 -1 70 0.7071067811875745 0.7071067811855205 -1 71 0.2588190451019369 0.9659258262892247 -1 72 0 1 -0.5000000000013305 73 -1 0 -0.5000000000013305 74 0 -1 -0.5000000000013305 75 1 0 -0.5000000000013305 76 0.4272342705359127 0.6393242049539736 0.6393242049536496 77 0.783972649638455 0.4144136670742724 0.4622209397689749 78 0.2639440683680972 0.2424897290403735 0.9335589215915745 79 0.2639440683686942 0.9335589215915659 0.2424897290397563 80 0.4708211030835322 0.3273312563149256 0.8192568202526594 81 0.2145398103477674 0.5923438481360068 0.7765960567446704 82 0.8335492808351762 0.508963469591458 0.2148296605233681 83 0.9473758621309027 0.1790666057851566 0.2653566026016916 84 0.8317455661314032 0.1891126219205571 0.521953761794169 85 0.6594464218141503 0.6917021584874902 0.2944121952301924 86 0.4708211030840908 0.8192568202524669 0.3273312563146042 87 0.6251724618832548 0.5367973492214507 0.5665756778857122 88 0.6572300438608349 0.2589256911659589 0.7078178832870187 89 0.2145398103477645 0.7765960567451859 0.5923438481353319 90 -0.5756145374659047 0.4217647653741238 0.7005586249178744 91 -0.3587678219942536 0.7995405141199002 0.4816851836857609 92 -0.7421211276574317 0.5653384650233741 0.3600675656727181 93 -0.9335589215915661 0.2639440683686942 0.2424897290397563 94 -0.2424897290403178 0.2639440683687048 0.9335589215914172 95 -0.2890957732542816 0.4667697606922859 0.8357928118796998 96 -0.5548881202569517 0.2116471089152448 0.8045524689450186 97 -0.1640447259653378 0.8374140298651624 0.5213703774361812 98 -0.1612522773092885 0.9509626872510798 0.26394634022614 99 -0.4872647709266795 0.8420970823282991 0.231182929620542 100 -0.226138619738255 0.6655474863004898 0.7112720071407115 101 -0.4769499828398436 0.6332636948034698 0.6095045584020933 102 -0.747729332214833 0.2119621756668422 0.6292637617344088 103 -0.5546829721034054 0.6959639389732772 0.4560274071887929 104 -0.6585007319376337 0.7385430932300502 0.144675103178778 105 -0.6813211519137715 0.4979196327665888 0.5365421952283687 106 -0.8252348661745683 0.5338917803788799 0.1842470691590841 107 -0.8451201185529073 0.2925468129948286 0.4474241247671931 108 -0.4272342705362692 -0.6393242049538544 0.6393242049535305 109 -0.7841187705118203 -0.4403829723142243 0.4372877672959997 110 -0.2639440683686942 -0.9335589215915661 0.2424897290397563 111 -0.2639440683687048 -0.2424897290403178 0.9335589215914172 112 -0.4708211030842687 -0.3273312563147673 0.8192568202522995 113 -0.214539810347956 -0.5923438481359801 0.7765960567446387 114 -0.8327305809381441 -0.2028460404685871 0.5151827476115999 115 -0.9480334540284094 -0.2277671068100692 0.2221592111489733 116 -0.832613824646544 -0.5160234082415546 0.2011816620724265 117 -0.6584392062575394 -0.2778730758761637 0.6994600527307198 118 -0.6582957292421613 -0.7005029592936747 0.275576372140892 119 -0.4708211030842607 -0.8192568202523839 0.3273312563145676 120 -0.6252111144770192 -0.5528282940735425 0.5509010252360586 121 -0.2145398103479531 -0.7765960567451543 0.5923438481353052 122 0.6393242049535306 -0.4272342705362692 0.6393242049538543 123 0.4144137207998477 -0.7839726502710042 0.4622208905273362 124 0.9335589215914172 -0.2639440683687048 0.2424897290403178 125 0.2424897290397562 -0.2639440683686942 0.9335589215915661 126 0.8192568202522995 -0.4708211030842687 0.3273312563147672 127 0.7765960567446388 -0.214539810347956 0.5923438481359798 128 0.189112649820964 -0.8317455681823113 0.5219537484172113 129 0.1790667098766053 -0.9473758649610493 0.2653565222550055 130 0.50896348421851 -0.8335492789994207 0.214829632992519 131 0.6917021768173185 -0.6594464195534586 0.2944121572291248 132 0.5367973820834134 -0.6251724620509297 0.5665756465659045 133 0.2589257296498588 -0.6572300463755033 0.7078178668743408 134 0.3273312563145676 -0.4708211030842607 0.8192568202523839 135 0.5923438481353052 -0.2145398103479531 0.7765960567451543 136 0.4067366430757783 0.9135454576426106 -0.6 137 0.6691306063597983 0.7431448254765478 -0.8 138 0.4539904997389402 0.8910065241886769 -0.8 139 0.2079116908177475 0.978147600733808 -0.8 140 0.2079116908177475 0.9781476007338081 -0.3 141 0.4539904997389402 0.8910065241886769 -0.3 142 0.9659258262893988 0.2588190451012872 -0.5 143 0.7071067811869778 0.7071067811861174 -0.5 144 0.8660254037857157 0.499999999997788 -0.5 145 -0.8090169943746613 0.5877852522928669 -0.4 146 -0.8386705679456556 0.5446390350146705 -0.7 147 -0.6691306063577283 0.7431448254784117 -0.7 148 -0.8386705679456556 0.5446390350146705 -0.2 149 -0.9510565162950784 0.3090169943751789 -0.2 150 -0.6691306063577283 0.7431448254784117 -0.2 151 -0.2588190451012872 0.9659258262893988 -0.5 152 -0.499999999997788 0.8660254037857157 -0.5 153 -0.9659258262892413 0.2588190451018749 -0.5 154 -0.5372996083469864 -0.8433914458127821 -0.4166666666666666 155 -0.8696385745817051 -0.4936889198670557 -0.5694444444444444 156 -0.5187732581600324 -0.8549118706732434 -0.2083333333333333 157 -0.7223639620607053 -0.6915130557812772 -0.2083333333333333 158 -0.2798290140310845 -0.9600498543859017 -0.2083333333333333 159 -0.9668605314577964 -0.2553051364723151 -0.7847222222222222 160 -0.9668605314577964 -0.2553051364723152 -0.2847222222222222 161 -0.8678377261237609 -0.4968477444009786 -0.2847222222222222 162 -0.724873593676082 -0.6888819007573957 -0.4930555555555556 163 -0.8678377261237609 -0.4968477444009787 -0.7847222222222223 164 -0.7096732139223464 -0.7045309996310507 -0.7847222222222222 165 -0.5187732581600324 -0.8549118706732434 -0.7083333333333333 166 -0.2798290140310845 -0.9600498543859017 -0.7083333333333333 167 0.7898354734238094 -0.6133187792016374 -0.7384259259259259 168 0.942256510237846 -0.3348920257551621 -0.5476851851851852 169 0.8298669155941656 -0.5579613807444258 -0.869212962962963 170 0.657178854385432 -0.7537346703904838 -0.869212962962963 171 0.9854583984719614 -0.1699168763868881 -0.2738425925925926 172 0.9854583984719614 -0.1699168763868881 -0.7738425925925925 173 0.8771636245450036 -0.4801916031909261 -0.6430555555555556 174 0.9079019941245541 -0.4191825009046277 -0.2738425925925926 175 0.8298669155941656 -0.5579613807444258 -0.369212962962963 176 0.2588190451012872 -0.9659258262893988 -0.5 177 0.9079019941245541 -0.4191825009046277 -0.7738425925925926 178 0.499999999997788 -0.8660254037857157 -0.5 179 0.657178854385432 -0.7537346703904838 -0.369212962962963 180 0.08855070144868839 -0.5551020776831219 -1 181 0.5564665713954644 -0.2939114004333228 -1 182 0.2763744884777239 0.4835149139342805 -1 183 -0.4708520348518781 0.126552230485235 -1 184 0.5921702158047604 0.1215896719695019 -1 185 0.05590735039306384 0.005620213338362633 -1 186 -0.2507659332939976 0.4969521269237394 -1 187 -0.4487365644657806 -0.2981591729404032 -1 188 0.7112459875902859 -0.3969557002160824 -1 189 0.5282332856966262 -0.5799684021095193 -1 190 0.2942753507232382 -0.7105637407344187 -1 191 0.3225086364220764 -0.4245067390582223 -1 192 0.04427535072434419 -0.777551038841561 -1 193 -0.2057246492750768 -0.7105637407341145 -1 194 0.7782332856977322 -0.1469557002166614 -1 195 0.7960851079023802 0.06079483598475097 -1 196 0.7290978097952381 0.310794835983645 -1 197 0.5743183936001124 -0.08616086423191044 -1 198 0.5711999461317199 0.4917574569660342 -1 199 0.4342723521412422 0.3025522929518912 -1 200 0.3061869608942641 -0.1441455935474801 -1 201 0.3240387830989121 0.06360494265393229 -1 202 0.1661409194353939 0.2445675636363216 -1 203 0.3881872442382829 0.6747701588596939 -1 204 0.07222902592087611 -0.2747409321723797 -1 205 -0.735426017425939 0.06327611524261748 -1 206 -0.6684387193184926 0.3132761152420385 -1 207 0.138187244238862 0.7417574569671402 -1 208 -0.5583956685395525 0.4984760634612906 -1 209 -0.3753829666458928 0.6814887653547275 -1 210 -0.3608089840729378 0.3117521787044871 -1 211 -0.1964146070363584 -0.1462694798010203 -1 212 -0.1800929315085461 -0.4266306253117625 -1 213 -0.2074723422294071 0.06608622191179879 -1 214 -0.4597942996588293 -0.08580347122758414 -1 215 -0.09742929145046689 0.251286170131051 -1 216 -0.6573809841257481 -0.3990795864690956 -1 217 -0.4743682822323113 -0.5820922883627553 -1 218 -0.7243682822328903 -0.1490795864702016 -1 219 -0.1253829666469988 0.7484760634618697 -1 220 0.01280427759186317 0.4902335204290099 -1 221 -0.0107163236287631 -0.5165297360796159 -0.4826379948480783 222 -0.2785000916387222 0.4649263787124072 -0.5874830372392191 223 0.1003494840643143 0.3674491020185399 0.3492945689807368 224 0.2094954267293344 0.4494464609885045 -0.4559830381707816 225 -0.4742529396974615 -0.142897395566676 -0.4247984740750855 226 0.4970184329849747 -0.3388597062458725 -0.5738613267497686 227 0.5168689061294469 0.1145391761782698 -0.6103003968313175 228 -0.3866749056813206 -0.5928945465994709 -0.7178434211508453 229 0.06708779234851506 -0.2300809424044148 0.04490448606369453 230 -0.4094274737047707 0.2635778372084727 0.1017412411987709 231 0.4396370265786172 -0.1074929328354941 0.3979938362552485 232 0.2927845672168315 -0.4469808919644972 -0.7869306633748843 233 0.2431510546781058 -0.4276947211627442 -0.5282496607989234 234 0.03891718890996265 -0.5358159068813689 -0.7413189974240392 235 0.2446418381845125 -0.6912775699326659 -0.7413189974240392 236 0.4985092164913814 -0.6024425550157941 -0.7869306633748843 237 -0.2424846316631123 -0.329713565823146 -0.4537182344615819 238 -0.2035825736744732 -0.1864891689855454 -0.1899469940056955 239 0.02818573435987598 -0.3733053392420154 -0.2188667543921919 240 0.02259551338215037 -0.2554547613706267 -0.7413189974240392 241 0.06149757137078945 -0.1122303645330261 -0.4775477569681527 242 -0.2091727946521988 -0.06863859111415668 -0.7123992370375427 243 -0.2376325267007952 0.3946069336963318 0.5249265969493055 244 -0.1292091689649697 0.5834948080692201 0.4154898763332489 245 0.05017474203215713 0.4337245510086909 0.6076599863829221 246 0.03354389617425753 -0.1150404712022074 0.5224522430318472 247 -0.2164561038251634 -0.1150404712022074 0.4554649449244009 248 0.05017474203215713 0.1837245510092699 0.6746472844903684 249 -0.1998252579672638 0.1837245510092699 0.6076599863829221 250 0.08371863820641465 0.06868407980706251 0.1970995275222157 251 -0.1933374528406603 -0.7964472732997354 -0.8589217105754227 252 -0.1490621021163161 -0.5739983121412964 -0.8589217105754227 253 -0.1986956146550419 -0.5547121413395435 -0.6002407079994618 254 -0.005358161814381549 -0.758264868039808 -0.7413189974240392 255 0.03354389617425753 -0.3650404712016284 0.4554649449244009 256 -0.1800732390938771 -0.4347025736791347 0.3421143455086125 257 0.4270253736892324 -0.4457327915532491 0.4301073633912923 258 0.2533624094635661 -0.1687869376199545 0.2214491611594715 259 0.2407507565741814 -0.5070267963377095 0.2535626882955154 260 0.2198185132893086 -0.303746466417168 0.6320096200201779 261 -0.1323787564840635 0.1532745327109143 -0.4403907561229335 262 -0.4418402067011161 0.06034022082089834 -0.1615286164381573 263 -0.09996602348771812 0.3565121490984886 -0.1771208984860054 264 -0.03450233245469388 0.4571864198504558 -0.5217330377050003 265 -0.3439637826717464 0.3642521079604399 -0.2428708980202241 266 -0.3763765156680918 0.1610144915728656 -0.5061407556571523 267 -0.2297264440472719 -0.4073444545100096 -0.7413189974240392 268 -0.4177057350735506 -0.4455268597699371 -0.8589217105754227 269 0.6528312151821665 0.196253533581147 0.1989969181276242 270 0.6118048381085361 0.1534603671193892 0.4301073880121117 271 0.4421610668513846 0.3909313845464061 0.4057577543748558 272 0.2699932553214657 0.1299780845915229 0.3736442026179926 273 0.4831874439250149 0.433724551008164 0.1746472844903684 274 0.03354389617425753 -0.6150404712022074 0.02245224303184726 275 0.03354389617425753 -0.5480531730950653 0.2724522430307413 276 0.6528312151818623 -0.05374646641774705 0.4489969181270452 277 0.7198185132893086 -0.05374646641774705 0.1989969181276242 278 -0.1711698406781278 0.01674844740202891 0.07332286363123269 279 -0.4547137368518063 0.1317889186042363 0.483883322491939 280 -0.1545389948202282 0.3155134696135062 0.2255179050897538 281 -0.3585154890816526 -0.3352319573593195 0.2410961266798471 282 -0.609222234039716 0.4256815447506698 -0.1491293794006146 283 -0.6416349670360614 0.2224439283630955 -0.4123992370375428 284 -0.5437585430066918 0.5263558155026371 -0.4937415186196096 285 -0.001062801580499123 0.4742206463233438 -0.7937415186196095 286 -0.1112963706228292 0.2352732960253849 -0.7937415186196095 287 -0.2646330124663599 0.4809392528180733 -0.7937415186196095 288 -0.4619872570141536 -0.7181429962061265 -0.567255043908756 289 -0.2740079659878747 -0.679960590946199 -0.4496523307573724 290 0.5267425021902196 -0.3163855533395977 -0.7869306633748843 291 -0.3892500458182551 0.6654758912490615 -0.2937415186196096 292 -0.1392500458193611 0.7324631893562036 -0.2937415186196096 293 -0.1392500458193611 0.7324631893562036 -0.7937415186196095 294 0.2198185132893086 -0.05374646641774705 0.6989969181276242 295 0.4985092164913814 -0.6024425550157941 -0.2869306633748843 296 0.2446418381845125 -0.6912775699326659 -0.2413189974240391 297 -0.3892500458182551 0.6654758912490615 -0.7937415186196095 298 0.1327013885611991 0.2275333371634336 -0.7279915190853908 299 -0.6291858551046409 -0.2916401839404502 0.006244646610457066 300 -0.5967731221082955 -0.08840256755287582 0.2695145042473853 301 0.3081160349025563 0.6814959593155576 -0.5279915190853908 302 0.3547477133640882 0.6577359323868059 -0.2279915190853908 303 0.1047477133646672 0.7247232304942522 -0.2279915190853908 304 0.4698185132882026 -0.05374646641774705 0.6320096200204821 305 -0.2164561038251634 -0.5480531730947611 0.02245224303184726 306 0.537760415257525 0.4747232304931463 -0.7279915190853908 307 -0.2553581618138025 -0.6912775699323617 -0.2413189974240391 308 -0.005358161814381549 -0.758264868039808 -0.2413189974240391 309 0.6528312151818623 -0.303746466417168 0.1989969181276242 310 0.4665565980668112 -0.3650404712016284 0.02245224303184726 311 0.5335438961742576 -0.1150404712022074 0.02245224303184726 312 -0.7047137368523854 0.1317889186042363 0.05087062059938543 313 -0.7371264698487308 -0.071448697783338 -0.2123992370375428 314 0.1382916095389247 0.1096827592920449 -0.2055392760535436 315 0.5394806157660739 -0.2673636016858817 0.5186590206045514 316 0.3547477133640882 0.6577359323868059 -0.7279915190853908 317 0.1047477133646672 0.7247232304942522 -0.7279915190853908 318 -0.637726438744939 0.3817889186036573 0.05087062059938543 319 -0.4547137368512794 0.5648016204970941 0.05087062059938543 320 -0.5757743006811011 0.4144581511159234 0.2309044034357445 321 0.2835438961731516 -0.5480531730950653 0.02245224303184726 322 -0.6377264387452432 0.1317889186042363 0.3008706205982795 323 -0.6263501547335182 -0.5464472732986295 -0.8589217105754227 324 -0.4433374528400813 -0.7294599751922891 -0.8589217105754227 325 -0.4925210055853377 0.3426713012912982 0.4011499330583226 326 -0.4725524872746698 -0.008172582540720522 -0.7123992370375427 327 -0.3746760632453001 0.295739304598821 -0.7937415186196095 328 0.5366677387624557 -0.0896861121275265 -0.8051501984156588 329 0.2863881282612554 0.06007969475831623 -0.8051501984156588 330 0.2764628916890193 -0.1666197464537549 -0.7869306633748843 331 0.5069436695572108 -0.1121602650338014 -0.5920808617905431 332 -0.6701391717412843 0.178551302216083 -0.7123992370375427 333 0.6914471549575814 0.307269588088029 -0.8051501984156588 334 0.7584344530647235 0.05726958808913491 -0.8051501984156588 335 0.6914471549575814 0.307269588088029 -0.3051501984156588 336 -0.4614947520816211 -0.2205282842535396 -0.7123992370375427 337 -0.6701391717415885 -0.321448697782232 -0.2123992370375428 338 -0.6719457571395833 -0.3182931577168658 -0.497121459259765 339 0.7485092164924874 -0.1694298531229363 -0.2869306633748843 340 0.7485092164924874 -0.1694298531229363 -0.7869306633748843 341 0.7584344530647235 0.05726958808913491 -0.3051501984156588 342 0.2429349576035292 0.4664806874613925 -0.7279915190853908 343 0.3001747420315781 0.6167372529018236 0.1746472844903684 344 0.1549224553968243 0.4084477815035222 -0.05334423459502241 345 -0.7371264698487308 -0.071448697783338 -0.7123992370375427 346 -0.6701391717415885 -0.321448697782232 -0.7123992370375427 347 -0.5722627477119148 0.4824631893556245 -0.7937415186196095 348 -0.3840976478495122 0.5315591756641864 0.2917132124422658 349 0.3001747420310512 0.1837245510092699 0.6076599863832263 350 0.291978349238981 -0.05777088311307251 -0.2826979553838115 351 0.4665565980671154 0.1349595287966866 0.02245224303184726 352 0.537760415257525 0.4747232304931463 -0.2279915190853908 353 0.3631821664293907 0.2819928185833872 -0.5331417175010496 354 0.05017474203215713 0.68372455100927 0.1746472844903684 355 -0.2047137368523853 0.6317889186042364 0.05087062059938543 356 0.7196374716114103 -0.3368758660005173 -0.560773255967477 357 0.6815219183850409 -0.4194298531223573 -0.2869306633748843 358 -0.5057762740222239 -0.4931444206897291 -0.4207325703708761 359 -0.430463922689391 -0.3678959710830735 -0.5713209476129655 360 -0.4871264698481517 -0.5044613996758917 -0.2123992370375428 361 0.2820531126667449 -0.2844703243251437 -0.264478420343037 362 -0.6281567401315129 -0.5432917332332633 -0.6436439327976449 363 0.6434269532043921 -0.476089242723755 -0.6561436263378473 364 0.6815219183850409 -0.4194298531223573 -0.7869306633748843 365 0.3966216973035854 0.2990270450562751 -0.8051501984156588 366 0.5545195609671036 0.1180644240738859 -0.8051501984156588 367 0.2637918773001134 0.5033866534862568 0.4943093869671932 368 0.05017474203215713 0.6167372529021278 0.4246472844892624 $EndNodes $Elements 338 1 15 3 0 1 0 1 2 15 3 0 2 0 2 3 15 3 0 3 0 3 4 15 3 0 4 0 4 5 15 3 0 5 0 5 6 15 3 0 6 0 6 7 15 3 0 7 0 7 8 15 3 0 8 0 8 9 15 3 0 9 0 9 10 15 3 0 10 0 10 11 15 3 0 11 0 11 12 8 3 0 1 0 2 12 14 13 8 3 0 1 0 12 13 15 14 8 3 0 1 0 13 3 16 15 8 3 0 2 0 3 17 19 16 8 3 0 2 0 17 18 20 17 8 3 0 2 0 18 4 21 18 8 3 0 3 0 4 22 24 19 8 3 0 3 0 22 23 25 20 8 3 0 3 0 23 2 26 21 8 3 0 4 0 3 27 29 22 8 3 0 4 0 27 28 30 23 8 3 0 4 0 28 5 31 24 8 3 0 5 0 5 32 34 25 8 3 0 5 0 32 33 35 26 8 3 0 5 0 33 4 36 27 8 3 0 6 0 5 37 39 28 8 3 0 6 0 37 38 40 29 8 3 0 6 0 38 6 41 30 8 3 0 7 0 6 42 44 31 8 3 0 7 0 42 43 45 32 8 3 0 7 0 43 4 46 33 8 3 0 8 0 6 47 49 34 8 3 0 8 0 47 48 50 35 8 3 0 8 0 48 2 51 36 8 3 0 9 0 8 52 54 37 8 3 0 9 0 52 53 55 38 8 3 0 9 0 53 9 56 39 8 3 0 10 0 9 57 59 40 8 3 0 10 0 57 58 60 41 8 3 0 10 0 58 10 61 42 8 3 0 11 0 10 62 64 43 8 3 0 11 0 62 63 65 44 8 3 0 11 0 63 7 66 45 8 3 0 12 0 7 67 69 46 8 3 0 12 0 67 68 70 47 8 3 0 12 0 68 8 71 48 8 3 0 13 0 8 3 72 49 8 3 0 14 0 9 5 73 50 8 3 0 15 0 10 6 74 51 8 3 0 16 0 7 2 75 52 9 3 0 1 0 22 18 4 78 21 24 53 9 3 0 1 0 13 3 17 16 19 79 54 9 3 0 1 0 22 76 18 80 81 78 55 9 3 0 1 0 12 77 2 82 83 14 56 9 3 0 1 0 77 23 2 84 26 83 57 9 3 0 1 0 13 77 12 85 82 15 58 9 3 0 1 0 77 13 76 85 86 87 59 9 3 0 1 0 77 22 23 88 25 84 60 9 3 0 1 0 76 22 77 80 88 87 61 9 3 0 1 0 13 17 76 79 89 86 62 9 3 0 1 0 17 18 76 20 81 89 63 9 3 0 2 0 28 5 32 31 34 93 64 9 3 0 2 0 18 33 4 94 36 21 65 9 3 0 2 0 18 90 33 95 96 94 66 9 3 0 2 0 91 17 3 97 19 98 67 9 3 0 2 0 27 91 3 99 98 29 68 9 3 0 2 0 91 18 17 100 20 97 69 9 3 0 2 0 90 18 91 95 100 101 70 9 3 0 2 0 32 33 90 35 96 102 71 9 3 0 2 0 92 91 27 103 99 104 72 9 3 0 2 0 91 92 90 103 105 101 73 9 3 0 2 0 28 92 27 106 104 30 74 9 3 0 2 0 32 92 28 107 106 93 75 9 3 0 2 0 32 90 92 102 105 107 76 9 3 0 3 0 38 6 42 41 44 110 77 9 3 0 3 0 33 43 4 111 46 36 78 9 3 0 3 0 33 108 43 112 113 111 79 9 3 0 3 0 109 32 5 114 34 115 80 9 3 0 3 0 37 109 5 116 115 39 81 9 3 0 3 0 109 33 32 117 35 114 82 9 3 0 3 0 109 38 108 118 119 120 83 9 3 0 3 0 38 109 37 118 116 40 84 9 3 0 3 0 108 33 109 112 117 120 85 9 3 0 3 0 42 43 108 45 113 121 86 9 3 0 3 0 38 42 108 110 121 119 87 9 3 0 4 0 48 2 23 51 26 124 88 9 3 0 4 0 43 22 4 125 24 46 89 9 3 0 4 0 122 48 23 126 124 127 90 9 3 0 4 0 123 42 6 128 44 129 91 9 3 0 4 0 47 123 6 130 129 49 92 9 3 0 4 0 48 123 47 131 130 50 93 9 3 0 4 0 123 48 122 131 126 132 94 9 3 0 4 0 123 43 42 133 45 128 95 9 3 0 4 0 122 43 123 134 133 132 96 9 3 0 4 0 22 43 122 125 134 135 97 9 3 0 4 0 23 22 122 25 135 127 98 9 3 0 5 0 136 67 68 137 70 138 99 9 3 0 5 0 68 8 136 71 139 138 100 9 3 0 5 0 136 8 3 139 72 140 101 9 3 0 5 0 13 136 3 141 140 16 102 9 3 0 5 0 7 12 2 142 14 75 103 9 3 0 5 0 67 136 13 137 141 143 104 9 3 0 5 0 67 12 7 144 142 69 105 9 3 0 5 0 13 12 67 15 144 143 106 9 3 0 6 0 53 145 52 146 147 55 107 9 3 0 6 0 5 28 145 31 148 149 108 9 3 0 6 0 27 145 28 150 148 30 109 9 3 0 6 0 8 27 3 151 29 72 110 9 3 0 6 0 52 27 8 152 151 54 111 9 3 0 6 0 52 145 27 147 150 152 112 9 3 0 6 0 5 53 9 153 56 73 113 9 3 0 6 0 5 145 53 149 146 153 114 9 3 0 7 0 154 38 37 156 40 157 115 9 3 0 7 0 6 38 154 41 156 158 116 9 3 0 7 0 9 155 5 159 160 73 117 9 3 0 7 0 155 37 5 161 39 160 118 9 3 0 7 0 37 155 154 161 162 157 119 9 3 0 7 0 57 155 9 163 159 59 120 9 3 0 7 0 58 155 57 164 163 60 121 9 3 0 7 0 58 154 155 165 162 164 122 9 3 0 7 0 6 154 10 158 166 74 123 9 3 0 7 0 154 58 10 165 61 166 124 9 3 0 8 0 63 167 62 169 170 65 125 9 3 0 8 0 2 168 7 171 172 75 126 9 3 0 8 0 167 168 48 173 174 175 127 9 3 0 8 0 168 2 48 171 51 174 128 9 3 0 8 0 10 47 6 176 49 74 129 9 3 0 8 0 168 63 7 177 66 172 130 9 3 0 8 0 167 63 168 169 177 173 131 9 3 0 8 0 62 47 10 178 176 64 132 9 3 0 8 0 47 167 48 179 175 50 133 9 3 0 8 0 62 167 47 170 179 178 134 9 3 0 9 0 62 63 181 65 188 189 135 9 3 0 9 0 180 62 181 190 189 191 136 9 3 0 9 0 10 180 58 192 193 61 137 9 3 0 9 0 62 180 10 190 192 64 138 9 3 0 9 0 7 181 63 194 188 66 139 9 3 0 9 0 184 7 67 195 69 196 140 9 3 0 9 0 181 7 184 194 195 197 141 9 3 0 9 0 67 182 184 198 199 196 142 9 3 0 9 0 185 181 184 200 197 201 143 9 3 0 9 0 182 185 184 202 201 199 144 9 3 0 9 0 67 68 182 70 203 198 145 9 3 0 9 0 180 181 185 191 200 204 146 9 3 0 9 0 9 183 53 205 206 56 147 9 3 0 9 0 8 182 68 207 203 71 148 9 3 0 9 0 52 53 186 55 208 209 149 9 3 0 9 0 186 53 183 208 206 210 150 9 3 0 9 0 180 185 187 204 211 212 151 9 3 0 9 0 185 183 187 213 214 211 152 9 3 0 9 0 186 183 185 210 213 215 153 9 3 0 9 0 187 57 58 216 60 217 154 9 3 0 9 0 58 180 187 193 212 217 155 9 3 0 9 0 9 187 183 218 214 205 156 9 3 0 9 0 9 57 187 59 216 218 157 9 3 0 9 0 8 52 186 54 209 219 158 9 3 0 9 0 186 182 8 220 207 219 159 9 3 0 9 0 186 185 182 215 202 220 160 11 3 0 1000 0 180 226 221 62 232 233 234 190 235 236 161 11 3 0 1000 0 221 225 229 185 237 238 239 240 241 242 162 11 3 0 1000 0 90 223 91 18 243 244 101 95 100 245 163 11 3 0 1000 0 4 229 33 223 246 247 36 248 249 250 164 11 3 0 1000 0 228 10 180 221 251 192 252 253 234 254 165 11 3 0 1000 0 33 229 43 108 247 255 111 112 113 256 166 11 3 0 1000 0 123 231 229 43 257 258 259 133 255 260 167 11 3 0 1000 0 224 225 230 222 261 262 263 264 265 266 168 11 3 0 1000 0 187 221 228 180 267 253 268 212 252 234 169 11 3 0 1000 0 77 12 231 223 82 269 270 271 272 273 170 11 3 0 1000 0 6 229 42 123 274 275 44 129 128 259 171 11 3 0 1000 0 77 23 231 2 84 276 270 83 277 26 172 11 3 0 1000 0 33 229 230 223 247 278 279 249 280 250 173 11 3 0 1000 0 109 229 33 108 281 247 117 120 112 256 174 11 3 0 1000 0 145 230 225 222 282 262 283 284 266 265 175 11 3 0 1000 0 222 182 185 186 285 202 286 287 215 220 176 11 3 0 1000 0 229 108 42 43 256 121 275 255 45 113 177 11 3 0 1000 0 228 10 221 154 251 254 253 288 289 166 178 11 3 0 1000 0 180 226 62 181 232 236 190 191 189 290 179 11 3 0 1000 0 27 8 3 222 151 72 29 291 292 293 180 11 3 0 1000 0 4 229 223 231 246 250 248 294 272 258 181 11 3 0 1000 0 62 47 226 221 178 295 236 235 233 296 182 11 3 0 1000 0 27 222 145 52 291 284 150 152 147 297 183 11 3 0 1000 0 224 225 222 185 261 266 264 298 286 242 184 11 3 0 1000 0 225 229 230 109 238 278 262 299 300 281 185 11 3 0 1000 0 10 221 62 180 254 235 64 192 190 234 186 11 3 0 1000 0 13 136 224 3 141 301 302 16 303 140 187 11 3 0 1000 0 23 77 231 22 84 270 276 25 304 88 188 11 3 0 1000 0 38 229 109 108 305 281 118 119 120 256 189 11 3 0 1000 0 67 224 13 136 306 302 143 137 141 301 190 11 3 0 1000 0 38 221 229 6 307 239 305 41 274 308 191 11 3 0 1000 0 231 48 229 2 309 310 258 277 311 51 192 11 3 0 1000 0 229 38 6 42 305 41 274 275 44 110 193 11 3 0 1000 0 145 230 5 225 282 312 149 283 313 262 194 11 3 0 1000 0 224 225 185 229 261 242 298 314 241 238 195 11 3 0 1000 0 187 221 180 185 267 234 212 211 204 240 196 11 3 0 1000 0 122 23 231 22 127 276 315 135 304 25 197 11 3 0 1000 0 136 67 224 68 137 306 301 138 316 70 198 11 3 0 1000 0 8 136 224 68 139 301 317 71 316 138 199 11 3 0 1000 0 230 145 28 27 282 148 318 319 30 150 200 11 3 0 1000 0 28 230 27 92 318 319 30 106 104 320 201 11 3 0 1000 0 123 47 229 48 130 321 259 131 310 50 202 11 3 0 1000 0 28 230 92 32 318 320 106 93 107 322 203 11 3 0 1000 0 187 228 57 58 268 323 216 217 60 324 204 11 3 0 1000 0 230 223 90 33 280 243 325 279 96 249 205 11 3 0 1000 0 228 180 58 187 252 193 324 268 217 212 206 11 3 0 1000 0 225 222 185 183 266 286 242 326 213 327 207 11 3 0 1000 0 27 8 222 52 151 293 291 152 297 54 208 11 3 0 1000 0 181 227 185 226 328 329 200 290 330 331 209 11 3 0 1000 0 225 53 5 145 332 153 313 283 149 146 210 11 3 0 1000 0 7 67 227 12 69 333 334 142 335 144 211 11 3 0 1000 0 187 221 185 225 267 240 211 336 242 237 212 11 3 0 1000 0 37 225 155 5 337 338 161 39 160 313 213 11 3 0 1000 0 231 4 43 22 294 46 260 304 125 24 214 11 3 0 1000 0 222 182 186 8 285 220 287 293 219 207 215 11 3 0 1000 0 226 2 7 227 339 75 340 331 334 341 216 11 3 0 1000 0 224 185 222 182 298 286 264 342 285 202 217 11 3 0 1000 0 77 13 12 223 85 15 82 271 273 343 218 11 3 0 1000 0 224 225 229 230 261 238 314 263 278 262 219 11 3 0 1000 0 223 224 229 230 344 314 250 280 278 263 220 11 3 0 1000 0 225 9 57 155 345 59 346 338 163 159 221 11 3 0 1000 0 5 230 109 225 312 300 115 313 299 262 222 11 3 0 1000 0 225 222 183 53 266 327 326 332 206 347 223 11 3 0 1000 0 90 230 32 92 325 322 102 105 107 320 224 11 3 0 1000 0 229 6 47 123 274 49 321 259 130 129 225 11 3 0 1000 0 90 223 230 91 243 280 325 101 348 244 226 11 3 0 1000 0 4 229 231 43 246 258 294 46 260 255 227 11 3 0 1000 0 225 5 53 9 313 153 332 345 56 73 228 11 3 0 1000 0 33 223 90 18 249 243 96 94 95 245 229 11 3 0 1000 0 223 4 231 22 248 294 272 349 304 24 230 11 3 0 1000 0 229 227 12 2 350 335 351 311 14 341 231 11 3 0 1000 0 91 230 90 92 348 325 101 103 105 320 232 11 3 0 1000 0 229 224 12 227 314 352 351 350 335 353 233 11 3 0 1000 0 223 229 12 231 250 351 273 272 269 258 234 11 3 0 1000 0 4 223 33 18 248 249 36 21 94 245 235 11 3 0 1000 0 5 225 109 37 313 299 115 39 116 337 236 11 3 0 1000 0 224 223 3 230 344 354 303 263 355 280 237 11 3 0 1000 0 2 226 168 48 339 356 171 51 174 357 238 11 3 0 1000 0 154 225 155 37 358 338 162 157 161 337 239 11 3 0 1000 0 223 224 13 12 344 302 343 273 15 352 240 11 3 0 1000 0 57 228 187 225 323 268 216 346 336 359 241 11 3 0 1000 0 180 226 181 185 232 290 191 204 200 330 242 11 3 0 1000 0 2 231 12 229 277 269 14 311 351 258 243 11 3 0 1000 0 109 225 38 37 299 360 118 116 40 337 244 11 3 0 1000 0 222 53 145 52 347 146 284 297 147 55 245 11 3 0 1000 0 7 227 2 12 334 341 75 142 14 335 246 11 3 0 1000 0 231 48 2 23 309 51 277 276 26 124 247 11 3 0 1000 0 145 5 230 28 149 312 282 148 318 31 248 11 3 0 1000 0 226 7 2 168 340 75 339 356 171 172 249 11 3 0 1000 0 38 221 6 154 307 308 41 156 158 289 250 11 3 0 1000 0 22 77 231 223 88 270 304 349 272 271 251 11 3 0 1000 0 33 230 229 109 279 278 247 117 281 300 252 11 3 0 1000 0 33 230 109 32 279 300 117 35 114 322 253 11 3 0 1000 0 229 224 227 185 314 353 350 241 329 298 254 11 3 0 1000 0 5 230 32 109 312 322 34 115 114 300 255 11 3 0 1000 0 225 229 109 38 238 281 299 360 118 305 256 11 3 0 1000 0 90 230 33 32 325 279 96 102 35 322 257 11 3 0 1000 0 223 224 12 229 344 352 273 250 351 314 258 11 3 0 1000 0 18 4 223 22 21 248 245 78 349 24 259 11 3 0 1000 0 229 226 48 47 361 357 310 321 50 295 260 11 3 0 1000 0 38 225 154 37 360 358 156 40 157 337 261 11 3 0 1000 0 38 221 154 225 307 289 156 360 358 237 262 11 3 0 1000 0 43 231 22 122 260 304 125 134 135 315 263 11 3 0 1000 0 4 229 43 33 246 255 46 36 111 247 264 11 3 0 1000 0 57 228 155 58 323 362 163 60 164 324 265 11 3 0 1000 0 123 231 43 122 257 260 133 132 134 315 266 11 3 0 1000 0 62 221 10 47 235 254 64 178 176 296 267 11 3 0 1000 0 77 231 12 2 270 269 82 83 14 277 268 11 3 0 1000 0 8 3 224 136 72 303 317 139 301 140 269 11 3 0 1000 0 230 92 91 27 320 103 348 319 99 104 270 11 3 0 1000 0 12 224 13 67 352 302 15 144 143 306 271 11 3 0 1000 0 2 226 229 227 339 361 311 341 350 331 272 11 3 0 1000 0 230 145 27 222 282 150 319 265 291 284 273 11 3 0 1000 0 180 226 185 221 232 330 204 234 240 233 274 11 3 0 1000 0 5 230 28 32 312 318 31 34 93 322 275 11 3 0 1000 0 231 48 23 122 309 124 276 315 127 126 276 11 3 0 1000 0 123 231 122 48 257 315 132 131 126 309 277 11 3 0 1000 0 224 3 223 13 303 354 344 302 343 16 278 11 3 0 1000 0 225 5 9 155 313 73 345 338 159 160 279 11 3 0 1000 0 187 9 57 225 218 59 216 336 346 345 280 11 3 0 1000 0 62 226 167 63 236 363 170 65 169 364 281 11 3 0 1000 0 167 226 48 168 363 357 175 173 174 356 282 11 3 0 1000 0 155 228 57 225 362 323 163 338 346 359 283 11 3 0 1000 0 62 226 63 181 236 364 65 189 188 290 284 11 3 0 1000 0 187 9 225 183 218 345 336 214 326 205 285 11 3 0 1000 0 8 182 224 222 207 342 317 293 264 285 286 11 3 0 1000 0 185 187 225 183 211 336 242 213 326 214 287 11 3 0 1000 0 67 227 182 184 333 365 198 196 199 366 288 11 3 0 1000 0 222 8 186 52 293 219 287 297 209 54 289 11 3 0 1000 0 185 184 182 227 201 199 202 329 365 366 290 11 3 0 1000 0 154 228 155 225 288 362 162 358 338 359 291 11 3 0 1000 0 77 13 223 76 85 343 271 87 367 86 292 11 3 0 1000 0 77 76 223 22 87 367 271 88 349 80 293 11 3 0 1000 0 223 76 13 17 367 86 343 368 79 89 294 11 3 0 1000 0 76 18 223 22 81 245 367 80 349 78 295 11 3 0 1000 0 12 224 67 227 352 306 144 335 333 353 296 11 3 0 1000 0 182 67 224 227 198 306 342 365 353 333 297 11 3 0 1000 0 224 67 182 68 306 198 342 316 203 70 298 11 3 0 1000 0 8 224 182 68 317 342 207 71 203 316 299 11 3 0 1000 0 6 10 221 47 74 254 308 49 296 176 300 11 3 0 1000 0 3 8 224 222 72 317 303 292 264 293 301 11 3 0 1000 0 224 185 182 227 298 202 342 353 365 329 302 11 3 0 1000 0 221 229 6 47 239 274 308 296 49 321 303 11 3 0 1000 0 62 226 47 167 236 295 178 170 179 363 304 11 3 0 1000 0 63 226 168 7 364 356 177 66 172 340 305 11 3 0 1000 0 226 48 47 167 357 50 295 363 179 175 306 11 3 0 1000 0 221 229 47 226 239 321 296 233 295 361 307 11 3 0 1000 0 63 226 7 181 364 340 66 188 194 290 308 11 3 0 1000 0 228 10 154 58 251 166 288 324 165 61 309 11 3 0 1000 0 228 221 225 154 253 237 359 288 358 289 310 11 3 0 1000 0 228 10 58 180 251 61 324 252 193 192 311 11 3 0 1000 0 10 6 221 154 74 308 254 166 289 158 312 11 3 0 1000 0 38 221 225 229 307 237 360 305 238 239 313 11 3 0 1000 0 17 91 223 18 97 244 368 20 245 100 314 11 3 0 1000 0 223 76 17 18 367 89 368 245 20 81 315 11 3 0 1000 0 91 17 223 3 97 368 244 98 354 19 316 11 3 0 1000 0 17 13 223 3 79 343 368 19 354 16 317 11 3 0 1000 0 155 228 154 58 362 288 162 164 165 324 318 11 3 0 1000 0 27 91 230 3 99 348 319 29 355 98 319 11 3 0 1000 0 229 108 38 42 256 119 305 275 110 121 320 11 3 0 1000 0 181 227 226 7 328 331 290 194 340 334 321 11 3 0 1000 0 181 227 7 184 328 334 194 197 195 366 322 11 3 0 1000 0 181 227 184 185 328 366 197 200 201 329 323 11 3 0 1000 0 185 186 183 222 215 210 213 286 327 287 324 11 3 0 1000 0 183 186 53 222 210 208 206 327 347 287 325 11 3 0 1000 0 186 53 222 52 208 347 287 209 297 55 326 11 3 0 1000 0 2 226 48 229 339 357 51 311 310 361 327 11 3 0 1000 0 123 231 48 229 257 309 131 259 310 258 328 11 3 0 1000 0 229 226 185 227 361 330 241 350 329 331 329 11 3 0 1000 0 221 229 226 185 239 361 233 240 330 241 330 11 3 0 1000 0 230 222 27 3 265 291 319 355 29 292 331 11 3 0 1000 0 230 222 3 224 265 292 355 263 303 264 332 11 3 0 1000 0 91 223 230 3 244 280 348 98 355 354 333 11 3 0 1000 0 187 221 225 228 267 237 336 268 359 253 334 11 3 0 1000 0 225 222 53 145 266 347 332 283 146 284 335 11 3 0 1000 0 183 225 53 9 326 332 206 205 56 345 336 11 3 0 1000 0 7 67 184 227 69 196 195 334 366 333 337 11 3 0 1000 0 42 229 43 123 275 255 45 128 133 259 338 11 3 0 1000 0 167 226 168 63 363 356 173 169 177 364 $EndElements dune-grid-2.11.0/doc/grids/gmsh/telescope2ndorder.msh.license000066400000000000000000000002501511655130300240360ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/twotets.geo000066400000000000000000000021471511655130300204750ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception cl1 = 1; Point(1) = {0, 0, 0, cl1}; Point(2) = {1, 0, 0, cl1}; Point(3) = {0, 1, 0, cl1}; Point(4) = {0, 0, 1, cl1}; Point(5) = {-1, 1, 1, cl1}; Line(1) = {1, 2}; Line(2) = {1, 3}; Line(3) = {1, 4}; Line(4) = {2, 3}; Line(5) = {2, 4}; Line(6) = {3, 4}; Line(7) = {1, 5}; Line(8) = {3, 5}; Line(9) = {4, 5}; Line Loop(11) = {7, -9, -3}; Plane Surface(11) = {11}; Line Loop(13) = {6, 9, -8}; Plane Surface(13) = {13}; Line Loop(15) = {8, -7, 2}; Plane Surface(15) = {15}; Line Loop(17) = {1, 5, -3}; Plane Surface(17) = {17}; Line Loop(19) = {4, 6, -5}; Plane Surface(19) = {19}; Line Loop(21) = {1, 4, -2}; Plane Surface(21) = {21}; Line Loop(23) = {2, 6, -3}; Plane Surface(23) = {23}; Surface Loop(25) = {15, 13, 11, 23}; Volume(25) = {25}; Surface Loop(27) = {21, 17, 19, 23}; Volume(27) = {27}; Physical Surface(30) = {15, 21}; Physical Surface(31) = {11, 17}; Physical Surface(32) = {13, 19}; Physical Volume(28) = {25}; Physical Volume(29) = {27}; dune-grid-2.11.0/doc/grids/gmsh/twotets.msh000066400000000000000000000074711511655130300205170ustar00rootroot00000000000000$MeshFormat 2.2 0 8 $EndMeshFormat $Nodes 29 1 0 0 0 2 1 0 0 3 0 1 0 4 0 0 1 5 -1 1 1 6 0.4999999999990217 0 0 7 0 0.4999999999990217 0 8 0 0 0.4999999999990217 9 0.5000000000011831 0.4999999999988169 0 10 0.5000000000011831 0 0.4999999999988169 11 0 0.5000000000011831 0.4999999999988169 12 -0.4999999999990217 0.4999999999990217 0.4999999999990217 13 -0.4999999999990217 1 0.4999999999990217 14 -0.4999999999990217 0.4999999999990217 1 15 -0.2499999999995108 0.2499999999995108 0.699999999999674 16 -0.2083333333329257 0.2083333333329257 0.4083333333331975 17 -0.2444444444439661 0.7055555555551098 0.2444444444439662 18 -0.2083333333329258 0.4166666666665035 0.2083333333329256 19 0.2500000000001972 0 0.2499999999998028 20 0.2500000000001972 0.2499999999998028 0 21 0 0.2500000000001972 0.2499999999998028 22 -0.1300848045720147 0.3232565360616024 0.6333757271827776 23 -0.1368138099010673 0.4040897196507469 0.3646449072268327 24 -0.338510349377699 0.5437581025079489 0.56484059921944 25 -0.1255919865743673 0.6473490174241726 0.3195898661872817 26 0.1468127642860371 0.3433894754304297 0.1665790783870729 27 0.3433890776871278 0.1468133342034417 0.1665795029120951 28 0.126129655606731 0.1261299910966539 0.2150137081272691 29 0.1960658026119753 0.1960690858164958 0.3852470029826681 $EndNodes $Elements 112 1 2 2 31 11 1 16 8 2 2 2 31 11 4 8 15 3 2 2 31 11 12 14 15 4 2 2 31 11 15 8 16 5 2 2 31 11 15 16 12 6 2 2 31 11 4 15 14 7 2 2 31 11 1 12 16 8 2 2 31 11 5 14 12 9 2 2 32 13 5 13 14 10 2 2 32 13 14 11 4 11 2 2 32 13 13 11 14 12 2 2 32 13 13 3 11 13 2 2 30 15 1 7 18 14 2 2 30 15 3 17 7 15 2 2 30 15 12 17 13 16 2 2 30 15 7 17 18 17 2 2 30 15 12 18 17 18 2 2 30 15 3 13 17 19 2 2 30 15 1 18 12 20 2 2 30 15 13 5 12 21 2 2 31 17 8 19 10 22 2 2 31 17 6 19 1 23 2 2 31 17 1 19 8 24 2 2 31 17 6 10 19 25 2 2 31 17 10 6 2 26 2 2 31 17 4 8 10 27 2 2 32 19 10 11 4 28 2 2 32 19 10 9 11 29 2 2 32 19 9 3 11 30 2 2 32 19 2 9 10 31 2 2 30 21 7 20 9 32 2 2 30 21 6 20 1 33 2 2 30 21 1 20 7 34 2 2 30 21 6 9 20 35 2 2 30 21 2 9 6 36 2 2 30 21 7 9 3 37 4 2 28 25 11 14 13 24 38 4 2 28 25 22 15 4 14 39 4 2 28 25 15 22 4 8 40 4 2 28 25 23 11 8 21 41 4 2 28 25 24 15 16 22 42 4 2 28 25 22 16 8 15 43 4 2 28 25 23 17 7 18 44 4 2 28 25 11 25 13 3 45 4 2 28 25 23 17 18 12 46 4 2 28 25 1 23 21 7 47 4 2 28 25 23 8 1 21 48 4 2 28 25 25 11 7 3 49 4 2 28 25 24 15 22 14 50 4 2 28 25 23 11 21 7 51 4 2 28 25 25 11 13 24 52 4 2 28 25 23 17 25 7 53 4 2 28 25 23 17 24 25 54 4 2 28 25 17 25 13 24 55 4 2 28 25 23 16 12 1 56 4 2 28 25 11 22 4 14 57 4 2 28 25 22 11 4 8 58 4 2 28 25 23 11 24 22 59 4 2 28 25 11 23 8 22 60 4 2 28 25 11 22 14 24 61 4 2 28 25 1 18 23 7 62 4 2 28 25 23 25 24 11 63 4 2 28 25 12 23 1 18 64 4 2 28 25 23 25 11 7 65 4 2 28 25 17 24 13 12 66 4 2 28 25 23 16 24 12 67 4 2 28 25 24 15 14 12 68 4 2 28 25 24 15 12 16 69 4 2 28 25 23 17 12 24 70 4 2 28 25 17 25 7 3 71 4 2 28 25 23 8 16 1 72 4 2 28 25 25 17 13 3 73 4 2 28 25 16 23 24 22 74 4 2 28 25 23 16 8 22 75 4 2 28 25 13 14 12 24 76 4 2 28 25 12 14 13 5 77 4 2 29 27 27 29 19 10 78 4 2 29 27 28 21 1 8 79 4 2 29 27 10 11 29 4 80 4 2 29 27 27 20 6 1 81 4 2 29 27 6 27 19 10 82 4 2 29 27 29 21 28 8 83 4 2 29 27 8 10 29 4 84 4 2 29 27 6 27 9 20 85 4 2 29 27 9 11 29 10 86 4 2 29 27 7 9 26 20 87 4 2 29 27 9 26 29 11 88 4 2 29 27 7 21 26 11 89 4 2 29 27 7 26 1 20 90 4 2 29 27 29 21 8 11 91 4 2 29 27 11 8 29 4 92 4 2 29 27 7 26 21 1 93 4 2 29 27 26 28 21 1 94 4 2 29 27 29 19 8 28 95 4 2 29 27 19 27 6 1 96 4 2 29 27 28 27 29 19 97 4 2 29 27 19 28 1 8 98 4 2 29 27 29 21 11 26 99 4 2 29 27 29 21 26 28 100 4 2 29 27 28 27 19 1 101 4 2 29 27 29 8 19 10 102 4 2 29 27 9 29 27 10 103 4 2 29 27 10 9 6 27 104 4 2 29 27 6 9 10 2 105 4 2 29 27 9 11 7 26 106 4 2 29 27 7 11 9 3 107 4 2 29 27 29 9 20 26 108 4 2 29 27 29 20 9 27 109 4 2 29 27 1 28 20 26 110 4 2 29 27 1 20 28 27 111 4 2 29 27 28 29 20 26 112 4 2 29 27 28 20 29 27 $EndElements dune-grid-2.11.0/doc/grids/gmsh/twotets.msh.license000066400000000000000000000002501511655130300221240ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/unitcube.msh000066400000000000000000000004321511655130300206120ustar00rootroot00000000000000$MeshFormat 2.2 0 8 $EndMeshFormat $Nodes 8 1 0 0 0 2 1 0 0 3 1 1 0 4 0 1 0 5 0 0 1 6 1 0 1 7 1 1 1 8 0 1 1 $EndNodes $Elements 7 1 3 2 0 13 1 2 6 5 2 3 2 1 25 4 1 5 8 3 3 2 3 17 2 3 7 6 4 3 2 0 21 3 4 8 7 5 3 2 0 1 1 2 3 4 6 3 2 0 26 5 6 7 8 7 5 2 1 1 1 2 3 4 5 6 7 8 $EndElements dune-grid-2.11.0/doc/grids/gmsh/unitcube.msh.license000066400000000000000000000002501511655130300222310ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gmsh/unitsquare_quads_2x2.msh000066400000000000000000000007601511655130300230700ustar00rootroot00000000000000$MeshFormat 2 0 8 $EndMeshFormat $PhysicalNames 2 2 1 "Left" 2 2 "Right" $EndPhysicalNames $Nodes 9 1 0 0 0 2 1 0 0 3 0 1 0 4 1 1 0 5 0.5 0 0 6 0 0.5 0 7 0.5 0.5 0 8 1 0.5 0 9 0.5 1 0 $EndNodes $Elements 16 1 15 3 0 1 0 1 2 15 3 0 2 0 2 3 15 3 0 3 0 3 4 15 3 0 4 0 4 5 1 3 0 1 0 1 5 6 1 3 0 1 0 5 2 7 1 3 0 1 0 1 6 8 1 3 0 1 0 6 3 13 1 3 0 1 0 3 9 14 1 3 0 1 0 9 4 15 1 3 0 1 0 2 8 16 1 3 0 1 0 8 4 17 3 3 1 2 0 5 2 8 7 18 3 3 1 1 0 6 7 9 3 19 3 3 1 2 0 7 8 4 9 20 3 3 1 1 0 1 5 7 6 $EndElements dune-grid-2.11.0/doc/grids/gmsh/unitsquare_quads_2x2.msh.license000066400000000000000000000002501511655130300245030ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/gridfactory/000077500000000000000000000000001511655130300176435ustar00rootroot00000000000000dune-grid-2.11.0/doc/grids/gridfactory/CMakeLists.txt000066400000000000000000000004241511655130300224030ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception install(FILES hybridtestgrids.hh testgrids.hh DESTINATION ${CMAKE_INSTALL_DOCDIR}/grids/gridfactory) dune-grid-2.11.0/doc/grids/gridfactory/hybridtestgrids.hh000066400000000000000000000317451511655130300234100ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_HYBRID_TESTGRIDS_HH #define DUNE_HYBRID_TESTGRIDS_HH /** \file \author Oliver Sander \brief Provides C++ code that creates hybrid grids suitable for unit tests, using the GridFactory. */ #include #include namespace Dune { template std::unique_ptr make2DHybridTestGrid() { static_assert(GridType::dimension == 2, "Instantiate make2dHybridTestGrid only for 2d grids!"); // Start grid creation GridFactory factory; // The list of grid vertex positions int numVertices = 16; double vertices[16][2] = {{0, 0}, {0.5, 0}, {0.5, 0.5}, {0, 0.5}, {0.25, 0}, {0.5, 0.25}, {0.25, 0.5}, {0, 0.25}, {0.25, 0.25}, {1, 0}, {1, 0.5}, {0.75, 0.25}, {1, 1}, {0.5, 1}, {0, 1}, {0.25, 0.75}}; // Create the grid vertices for (int i=0; i pos; pos[0] = vertices[i][0]; pos[1] = vertices[i][1]; factory.insertVertex(pos); } // Create the triangle elements int numTriangles = 2; unsigned int triangles[2][3] = {{9, 10, 11}, {15, 13, 14}}; for (int i=0; i cornerIDs(3); for (int j=0; j<3; j++) cornerIDs[j] = triangles[i][j]; factory.insertElement(Dune::GeometryTypes::triangle,cornerIDs); } // Create the quadrilateral elements int numQuadrilaterals = 9; unsigned int quadrilaterals[9][4] = {{0, 4, 7, 8}, {4, 1, 8, 5}, {8, 5, 6, 2}, {7, 8, 3, 6}, {1, 9, 5, 11}, {5, 11, 2, 10}, {2, 10, 13, 12}, {3, 6, 14, 15}, {6, 2, 15, 13}}; for (int i=0; i cornerIDs(4); for (int j=0; j<4; j++) cornerIDs[j] = quadrilaterals[i][j]; factory.insertElement(Dune::GeometryTypes::quadrilateral,cornerIDs); } // Finish initialization return factory.createGrid(); } template std::unique_ptr make3DHybridTestGrid() { static_assert(GridType::dimension == 3, "Instantiate make3DHybridTestGrid only for 3d grids!"); // Start grid creation GridFactory factory; // The list of grid vertex positions int numVertices = 61; double vertices[61][3] = {{0, 0, 0}, {0.5, 0, 0}, {0.5, 0.5, 0}, {0, 0.5, 0}, {0, 0, 0.5}, {0.5, 0, 0.5}, {0.5, 0.5, 0.5}, {0, 0.5, 0.5}, {0.25, 0, 0}, {0.5, 0.25, 0}, {0.25, 0.5, 0}, {0, 0.25, 0}, {0, 0, 0.25}, {0.5, 0, 0.25}, {0.5, 0.5, 0.25}, {0, 0.5, 0.25}, {0.25, 0, 0.5}, {0.5, 0.25, 0.5}, {0.25, 0.5, 0.5}, {0, 0.25, 0.5}, {0.25, 0.25, 0}, {0.25, 0, 0.25}, {0.5, 0.25, 0.25}, {0.25, 0.5, 0.25}, {0, 0.25, 0.25}, {0.25, 0.25, 0.5}, {0.25, 0.25, 0.25}, {1, 0, 0}, {1, 0.5, 0}, {1, 0, 0.5}, {1, 0.5, 0.5}, {0.75, 0.25, 0.25}, {1, 1, 0}, {0.5, 1, 0}, {1, 1, 0.5}, {0.5, 1, 0.5}, {0.75, 0.75, 0.25}, {0, 1, 0}, {0, 1, 0.5}, {0.25, 0.75, 0.25}, {0, 0, 1}, {0.5, 0, 1}, {0.5, 0.5, 1}, {0, 0.5, 1}, {0.25, 0.25, 0.75}, {1, 0, 1}, {1, 0.5, 1}, {0.75, 0.25, 0.75}, {1, 1, 1}, {0.5, 1, 1}, {0, 1, 1}, {0.25, 0.75, 0.75}, {1.5, 0, 0}, {1.5, 0.5, 0}, {1.5, 1, 0}, {1.5, 0, 0.5}, {1.5, 0.5, 0.5}, {1.5, 1, 0.5}, {1.5, 0, 1}, {1.5, 0.5, 1}, {1.5, 1, 1}}; // Create the grid vertices for (int i=0; i pos; for (int j=0; j<3; j++) pos[j] = vertices[i][j]; factory.insertVertex(pos); } // Create the tetrahedron elements int numTetrahedra = 54; unsigned int tetrahedra[54][4] = {{10, 29, 3, 32}, {10, 2, 28, 32}, {10, 28, 29, 32}, {14, 28, 2, 32}, {14, 6, 30, 32}, {14, 30, 28, 32}, {15, 31, 7, 32}, {15, 3, 29, 32}, {15, 29, 31, 32}, {18, 30, 6, 32}, {18, 7, 31, 32}, {18, 31, 30, 32}, {15, 29, 3, 37}, {15, 7, 31, 37}, {15, 31, 29, 37}, {15, 36, 7, 37}, {15, 3, 34, 37}, {15, 34, 36, 37}, {11, 38, 4, 40}, {11, 3, 34, 40}, {11, 34, 38, 40}, {15, 34, 3, 40}, {15, 7, 36, 40}, {15, 36, 34, 40}, {16, 39, 8, 40}, {16, 4, 38, 40}, {16, 38, 39, 40}, {19, 36, 7, 40}, {19, 8, 39, 40}, {19, 39, 36, 40}, {17, 42, 6, 45}, {17, 5, 41, 45}, {17, 41, 42, 45}, {18, 43, 7, 45}, {18, 6, 42, 45}, {18, 42, 43, 45}, {19, 44, 8, 45}, {19, 7, 43, 45}, {19, 43, 44, 45}, {20, 41, 5, 45}, {20, 8, 44, 45}, {20, 44, 41, 45}, {18, 31, 7, 48}, {18, 6, 30, 48}, {18, 30, 31, 48}, {18, 42, 6, 48}, {18, 7, 43, 48}, {18, 43, 42, 48}, {19, 39, 8, 52}, {19, 7, 36, 52}, {19, 36, 39, 52}, {19, 43, 7, 52}, {19, 8, 44, 52}, {19, 44, 43, 52}}; for (int i=0; i cornerIDs(4); for (int j=0; j<4; j++) cornerIDs[j] = tetrahedra[i][j]-1; factory.insertElement(Dune::GeometryTypes::tetrahedron,cornerIDs); } // Create the pyramid elements int numPyramids = 27; unsigned int pyramids[27][5] = {{28, 30, 29, 31, 32}, {10, 23, 2, 14, 32}, {14, 23, 6, 18, 32}, {18, 23, 7, 15, 32}, {15, 23, 3, 10, 32}, {3, 29, 34, 33, 37}, {29, 31, 33, 35, 37}, {33, 35, 34, 36, 37}, {7, 36, 31, 35, 37}, {11, 24, 3, 15, 40}, {15, 24, 7, 19, 40}, {19, 24, 8, 16, 40}, {16, 24, 4, 11, 40}, {34, 36, 38, 39, 40}, {20, 26, 8, 19, 45}, {19, 26, 7, 18, 45}, {18, 26, 6, 17, 45}, {17, 26, 5, 20, 45}, {41, 44, 42, 43, 45}, {6, 42, 30, 46, 48}, {30, 46, 31, 47, 48}, {31, 47, 7, 43, 48}, {42, 43, 46, 47, 48}, {7, 43, 36, 50, 52}, {36, 50, 39, 51, 52}, {39, 51, 8, 44, 52}, {44, 51, 43, 50, 52}}; for (int i=0; i cornerIDs(5); for (int j=0; j<5; j++) cornerIDs[j] = pyramids[i][j]-1; factory.insertElement(Dune::GeometryTypes::pyramid,cornerIDs); } // Create the prism elements int numPrisms = 8; unsigned int prisms[8][6] = {{28, 53, 29, 30, 56, 31}, {53, 54, 29, 56, 57, 31}, {30, 56, 31, 46, 59, 47}, {56, 57, 31, 59, 60, 47}, {29, 54, 33, 31, 57, 35}, {54, 55, 33, 57, 58, 35}, {31, 57, 35, 47, 60, 49}, {57, 58, 35, 60, 61, 49}}; for (int i=0; i cornerIDs(6); for (int j=0; j<6; j++) cornerIDs[j] = prisms[i][j]-1; factory.insertElement(Dune::GeometryTypes::prism,cornerIDs); } // Create the hexahedron elements int numHexahedra = 9; unsigned int hexahedra[9][8] = {{1, 9, 12, 21, 13, 22, 25, 27}, {9, 2, 21, 10, 22, 14, 27, 23}, {21, 10, 11, 3, 27, 23, 24, 15}, {12, 21, 4, 11, 25, 27, 16, 24}, {13, 22, 25, 27, 5, 17, 20, 26}, {22, 14, 27, 23, 17, 6, 26, 18}, {27, 23, 24, 15, 26, 18, 19, 7}, {25, 27, 16, 24, 20, 26, 8, 19}, {7, 31, 36, 35, 43, 47, 50, 49}}; for (int i=0; i cornerIDs(8); for (int j=0; j<8; j++) cornerIDs[j] = hexahedra[i][j]-1; factory.insertElement(Dune::GeometryTypes::hexahedron,cornerIDs); } // Finish initialization return factory.createGrid(); } } #endif dune-grid-2.11.0/doc/grids/gridfactory/testgrids.hh000066400000000000000000000223721511655130300222020ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DOC_GRIDS_GRIDFACTORY_TESTGRIDS_HH #define DOC_GRIDS_GRIDFACTORY_TESTGRIDS_HH #include #include #include #include #include namespace Dune { // TestGrid // -------- template< int dimworld > struct TestGrid { typedef FieldVector< double, dimworld > Vertex; typedef std::pair< GeometryType, std::vector< unsigned int > > Element; typedef std::vector< unsigned int > BoundarySegment; TestGrid ( std::vector< Vertex > v, std::vector< Element > e, std::vector< BoundarySegment > b ) : vertices( std::move( v ) ), elements( std::move( e ) ), boundaries( std::move( b ) ) {} template< class Grid, class Projection > void addToGridFactory ( Dune::GridFactory< Grid > &factory, Projection &&projection ) const { for( const Vertex &v : vertices ) factory.insertVertex( projection( v ) ); for( const Element &e : elements ) factory.insertElement( e.first, e.second ); for( const BoundarySegment &b : boundaries ) factory.insertBoundarySegment( b ); } template< class Grid > void addToGridFactory ( Dune::GridFactory< Grid > &factory ) const { addToGridFactory( factory, [] ( const Vertex &v ) { return v; } ); } std::vector< Vertex > vertices; std::vector< Element > elements; std::vector< BoundarySegment > boundaries; }; namespace TestGrids { using namespace GeometryTypes; // line grids static const TestGrid< 1 > unitLine = { { { 0.0 }, { 1.0 } }, { { line, { 0, 1 } } }, { { 0 }, { 1 } } }; // cube grids static const TestGrid< 2 > unitSquare = { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 0.0, 1.0 }, { 1.0, 1.0 } }, { { quadrilateral, { 0, 1, 2, 3 } } }, { { 0, 1 }, { 1, 3 }, { 3, 2 }, { 2, 0 } } }; static const TestGrid< 3 > unitCube = { { { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 } }, { { hexahedron, { 0, 1, 2, 3, 4, 5, 6, 7 } } }, { { 0, 1, 2, 3 }, { 1, 3, 7, 5 }, { 0, 4, 5, 1 }, { 0, 4, 6, 2 }, { 2, 3, 7, 6 }, { 4, 5, 7, 6 } } }; // simplex grids static const TestGrid< 2 > kuhn2d = { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 0.0, 1.0 }, { 1.0, 1.0 } }, { { triangle, { 0, 1, 3 } }, { triangle, { 0, 2, 3 } } }, { { 0, 1 }, { 1, 3 }, { 3, 2 }, { 2, 0 } } }; static const TestGrid< 3 > kuhn3d = { { { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 } }, { { tetrahedron, { 0, 1, 3, 7 } }, { tetrahedron, { 0, 1, 5, 7 } }, { tetrahedron, { 0, 2, 3, 7 } }, { tetrahedron, { 0, 2, 6, 7 } }, { tetrahedron, { 0, 4, 5, 7 } }, { tetrahedron, { 0, 4, 6, 7 } } }, { { 0, 1, 3 }, { 1, 3, 7 }, { 0, 1, 5 }, { 1, 5, 7 }, { 0, 2, 3 }, { 2, 3, 7 }, { 0, 2, 6 }, { 2, 6, 7 }, { 0, 4, 5 }, { 4, 5, 7 }, { 0, 4, 6 }, { 4, 6, 7 } } }; // hybrid grids static const TestGrid< 2 > hybrid2d = { { {0, 0}, {0.5, 0}, {0.5, 0.5}, {0, 0.5}, {0.25, 0}, {0.5, 0.25}, {0.25, 0.5}, {0, 0.25}, {0.25, 0.25}, {1, 0}, {1, 0.5}, {0.75, 0.25}, {1, 1}, {0.5, 1}, {0, 1}, {0.25, 0.75} }, { { triangle, { 9, 10, 11} }, { triangle, { 15, 13, 14 } }, { quadrilateral, {0, 4, 7, 8} }, { quadrilateral, {4, 1, 8, 5} }, { quadrilateral, {8, 5, 6, 2} }, { quadrilateral,{7, 8, 3, 6} }, { quadrilateral, {1, 9, 5, 11} }, { quadrilateral, {5, 11, 2, 10} }, { quadrilateral, {2, 10, 13, 12} }, { quadrilateral, {3, 6, 14, 15} }, { quadrilateral, {6, 2, 15, 13} } }, {} }; static const TestGrid< 3 > hybrid3d = { { {0, 0, 0}, {0.5, 0, 0}, {0.5, 0.5, 0}, {0, 0.5, 0}, {0, 0, 0.5}, {0.5, 0, 0.5}, {0.5, 0.5, 0.5}, {0, 0.5, 0.5}, {0.25, 0, 0}, {0.5, 0.25, 0}, {0.25, 0.5, 0}, {0, 0.25, 0}, {0, 0, 0.25}, {0.5, 0, 0.25}, {0.5, 0.5, 0.25}, {0, 0.5, 0.25}, {0.25, 0, 0.5}, {0.5, 0.25, 0.5}, {0.25, 0.5, 0.5}, {0, 0.25, 0.5}, {0.25, 0.25, 0}, {0.25, 0, 0.25}, {0.5, 0.25, 0.25}, {0.25, 0.5, 0.25}, {0, 0.25, 0.25}, {0.25, 0.25, 0.5}, {0.25, 0.25, 0.25}, {1, 0, 0}, {1, 0.5, 0}, {1, 0, 0.5}, {1, 0.5, 0.5}, {0.75, 0.25, 0.25}, {1, 1, 0}, {0.5, 1, 0}, {1, 1, 0.5}, {0.5, 1, 0.5}, {0.75, 0.75, 0.25}, {0, 1, 0}, {0, 1, 0.5}, {0.25, 0.75, 0.25}, {0, 0, 1}, {0.5, 0, 1}, {0.5, 0.5, 1}, {0, 0.5, 1}, {0.25, 0.25, 0.75}, {1, 0, 1}, {1, 0.5, 1}, {0.75, 0.25, 0.75}, {1, 1, 1}, {0.5, 1, 1}, {0, 1, 1}, {0.25, 0.75, 0.75}, {1.5, 0, 0}, {1.5, 0.5, 0}, {1.5, 1, 0}, {1.5, 0, 0.5}, {1.5, 0.5, 0.5}, {1.5, 1, 0.5}, {1.5, 0, 1}, {1.5, 0.5, 1}, {1.5, 1, 1} }, { { tetrahedron,{10, 29, 3, 32} }, { tetrahedron,{10, 2, 28, 32}}, { tetrahedron,{10, 28, 29, 32}}, { tetrahedron,{14, 28, 2, 32}}, { tetrahedron,{14, 6, 30, 32}}, { tetrahedron,{14, 30, 28, 32}}, { tetrahedron,{15, 31, 7, 32}}, { tetrahedron,{15, 3, 29, 32}}, { tetrahedron,{15, 29, 31, 32}}, { tetrahedron,{18, 30, 6, 32}}, { tetrahedron,{18, 7, 31, 32}}, { tetrahedron,{18, 31, 30, 32}}, { tetrahedron,{15, 29, 3, 37}}, { tetrahedron,{15, 7, 31, 37}}, { tetrahedron,{15, 31, 29, 37}}, { tetrahedron,{15, 36, 7, 37}}, { tetrahedron,{15, 3, 34, 37}}, { tetrahedron,{15, 34, 36, 37}}, { tetrahedron,{11, 38, 4, 40}}, { tetrahedron,{11, 3, 34, 40}}, { tetrahedron,{11, 34, 38, 40}}, { tetrahedron,{15, 34, 3, 40}}, { tetrahedron,{15, 7, 36, 40}}, { tetrahedron,{15, 36, 34, 40}}, { tetrahedron,{16, 39, 8, 40}}, { tetrahedron,{16, 4, 38, 40}}, { tetrahedron,{16, 38, 39, 40}}, { tetrahedron,{19, 36, 7, 40}}, { tetrahedron,{19, 8, 39, 40}}, { tetrahedron,{19, 39, 36, 40}}, { tetrahedron,{17, 42, 6, 45}}, { tetrahedron,{17, 5, 41, 45}}, { tetrahedron,{17, 41, 42, 45}}, { tetrahedron,{18, 43, 7, 45}}, { tetrahedron,{18, 6, 42, 45}}, { tetrahedron,{18, 42, 43, 45}}, { tetrahedron,{19, 44, 8, 45}}, { tetrahedron,{19, 7, 43, 45}}, { tetrahedron,{19, 43, 44, 45}}, { tetrahedron,{20, 41, 5, 45}}, { tetrahedron,{20, 8, 44, 45}}, { tetrahedron,{20, 44, 41, 45}}, { tetrahedron,{18, 31, 7, 48}}, { tetrahedron,{18, 6, 30, 48}}, { tetrahedron,{18, 30, 31, 48}}, { tetrahedron,{18, 42, 6, 48}}, { tetrahedron,{18, 7, 43, 48}}, { tetrahedron,{18, 43, 42, 48}}, { tetrahedron,{19, 39, 8, 52}}, { tetrahedron,{19, 7, 36, 52}}, { tetrahedron,{19, 36, 39, 52}}, { tetrahedron,{19, 43, 7, 52}}, { tetrahedron,{19, 8, 44, 52}}, { tetrahedron,{19, 44, 43, 52}}, { pyramid, {28, 30, 29, 31, 32}}, { pyramid, {10, 23, 2, 14, 32}}, { pyramid, {14, 23, 6, 18, 32}}, { pyramid, {18, 23, 7, 15, 32}}, { pyramid, {15, 23, 3, 10, 32}}, { pyramid, {3, 29, 34, 33, 37}}, { pyramid, {29, 31, 33, 35, 37}}, { pyramid, {33, 35, 34, 36, 37}}, { pyramid, {7, 36, 31, 35, 37}}, { pyramid, {11, 24, 3, 15, 40}}, { pyramid, {15, 24, 7, 19, 40}}, { pyramid, {19, 24, 8, 16, 40}}, { pyramid, {16, 24, 4, 11, 40}}, { pyramid, {34, 36, 38, 39, 40}}, { pyramid, {20, 26, 8, 19, 45}}, { pyramid, {19, 26, 7, 18, 45}}, { pyramid, {18, 26, 6, 17, 45}}, { pyramid, {17, 26, 5, 20, 45}}, { pyramid, {41, 44, 42, 43, 45}}, { pyramid, {6, 42, 30, 46, 48}}, { pyramid, {30, 46, 31, 47, 48}}, { pyramid, {31, 47, 7, 43, 48}}, { pyramid, {42, 43, 46, 47, 48}}, { pyramid, {7, 43, 36, 50, 52}}, { pyramid, {36, 50, 39, 51, 52}}, { pyramid, {39, 51, 8, 44, 52}}, { pyramid, {44, 51, 43, 50, 52}}, { prism, {28, 53, 29, 30, 56, 31}}, { prism, {53, 54, 29, 56, 57, 31}}, { prism, {30, 56, 31, 46, 59, 47}}, { prism, {56, 57, 31, 59, 60, 47}}, { prism, {29, 54, 33, 31, 57, 35}}, { prism, {54, 55, 33, 57, 58, 35}}, { prism, {31, 57, 35, 47, 60, 49}}, { prism, {57, 58, 35, 60, 61, 49}}, { hexahedron, {1, 9, 12, 21, 13, 22, 25, 27}}, { hexahedron, {9, 2, 21, 10, 22, 14, 27, 23}}, { hexahedron, {21, 10, 11, 3, 27, 23, 24, 15}}, { hexahedron, {12, 21, 4, 11, 25, 27, 16, 24}}, { hexahedron, {13, 22, 25, 27, 5, 17, 20, 26}}, { hexahedron, {22, 14, 27, 23, 17, 6, 26, 18}}, { hexahedron, {27, 23, 24, 15, 26, 18, 19, 7}}, { hexahedron, {25, 27, 16, 24, 20, 26, 8, 19}}, { hexahedron, {7, 31, 36, 35, 43, 47, 50, 49}} }, {} }; } // namespace TestGrids } // namespace Dune #endif // #ifndef DOC_GRIDS_GRIDFACTORY_TESTGRIDS_HH dune-grid-2.11.0/doc/grids/starcd/000077500000000000000000000000001511655130300166065ustar00rootroot00000000000000dune-grid-2.11.0/doc/grids/starcd/CMakeLists.txt000066400000000000000000000005641511655130300213530ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(GRIDS star.vrt tets.vrt withprism.vrt withpyramid.vrt star.cel tets.cel withprism.cel withpyramid.cel) install(FILES ${GRIDS} DESTINATION ${CMAKE_INSTALL_DOCDIR}/grids/starcd) dune-grid-2.11.0/doc/grids/starcd/star.cel000066400000000000000000000065401511655130300202510ustar00rootroot00000000000000 1 1 2 4 3 5 6 8 7 7 1 1 2 5 6 8 7 9 10 12 11 7 1 1 3 3 4 14 13 7 8 16 15 7 1 1 4 7 8 16 15 11 12 18 17 7 1 1 5 2 19 20 4 6 21 22 8 7 1 1 6 6 21 22 8 10 23 24 12 7 1 1 7 4 20 25 14 8 22 26 16 7 1 1 8 8 22 26 16 12 24 27 18 7 1 1 9 1 3 7 5 0 0 0 0 2 4 4 10 5 7 11 9 0 0 0 0 2 4 4 11 3 13 15 7 0 0 0 0 2 4 4 12 7 15 17 11 0 0 0 0 2 4 4 13 1 5 6 2 0 0 0 0 2 4 4 14 5 9 10 6 0 0 0 0 2 4 4 15 2 6 21 19 0 0 0 0 2 4 4 16 6 10 23 21 0 0 0 0 2 4 4 17 1 2 4 3 0 0 0 0 1 4 4 18 3 4 14 13 0 0 0 0 1 4 4 19 2 19 20 4 0 0 0 0 1 4 4 20 4 20 25 14 0 0 0 0 1 4 4 21 19 21 22 20 0 0 0 0 2 4 4 22 21 23 24 22 0 0 0 0 2 4 4 23 20 22 26 25 0 0 0 0 2 4 4 24 22 24 27 26 0 0 0 0 2 4 4 25 13 14 16 15 0 0 0 0 2 4 4 26 15 16 18 17 0 0 0 0 2 4 4 27 14 25 26 16 0 0 0 0 2 4 4 28 16 26 27 18 0 0 0 0 2 4 4 29 9 11 12 10 0 0 0 0 3 4 4 30 11 17 18 12 0 0 0 0 3 4 4 31 10 12 24 23 0 0 0 0 3 4 4 32 12 18 27 24 0 0 0 0 3 4 4 dune-grid-2.11.0/doc/grids/starcd/star.cel.license000066400000000000000000000002501511655130300216620ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/star.vrt000066400000000000000000000033001511655130300203100ustar00rootroot00000000000000 1 0.000000000E+00 0.000000000E+00 0.000000000E+00 2 5.00000000 0.000000000E+00 0.000000000E+00 3 0.000000000E+00 5.00000000 0.000000000E+00 4 5.00000000 5.00000000 0.000000000E+00 5 0.000000000E+00 0.000000000E+00 5.00000000 6 5.00000000 0.000000000E+00 5.00000000 7 0.000000000E+00 5.00000000 5.00000000 8 5.00000000 5.00000000 5.00000000 9 0.000000000E+00 0.000000000E+00 10.0000000 10 5.00000000 0.000000000E+00 10.0000000 11 0.000000000E+00 5.00000000 10.0000000 12 5.00000000 5.00000000 10.0000000 13 0.000000000E+00 10.0000000 0.000000000E+00 14 5.00000000 10.0000000 0.000000000E+00 15 0.000000000E+00 10.0000000 5.00000000 16 5.00000000 10.0000000 5.00000000 17 0.000000000E+00 10.0000000 10.0000000 18 5.00000000 10.0000000 10.0000000 19 10.0000000 0.000000000E+00 0.000000000E+00 20 10.0000000 5.00000000 0.000000000E+00 21 10.0000000 0.000000000E+00 5.00000000 22 10.0000000 5.00000000 5.00000000 23 10.0000000 0.000000000E+00 10.0000000 24 10.0000000 5.00000000 10.0000000 25 10.0000000 10.0000000 0.000000000E+00 26 10.0000000 10.0000000 5.00000000 27 10.0000000 10.0000000 10.0000000 dune-grid-2.11.0/doc/grids/starcd/star.vrt.license000066400000000000000000000002501511655130300217320ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/tets.cel000066400000000000000000002717761511655130300202760ustar00rootroot00000000000000 1 138 101 159 159 147 147 147 147 7 1 1 2 35 77 146 146 58 58 58 58 7 1 1 3 3 7 151 151 178 178 178 178 7 1 1 4 53 147 49 49 46 46 46 46 7 1 1 5 29 76 63 63 167 167 167 167 7 1 1 6 91 25 164 164 175 175 175 175 7 1 1 7 63 79 167 167 65 65 65 65 7 1 1 8 39 89 148 148 103 103 103 103 7 1 1 9 75 111 146 146 73 73 73 73 7 1 1 10 46 136 147 147 171 171 171 171 7 1 1 11 146 102 115 115 112 112 112 112 7 1 1 12 136 49 147 147 171 171 171 171 7 1 1 13 151 134 142 142 3 3 3 3 7 1 1 14 91 141 164 164 88 88 88 88 7 1 1 15 151 152 130 130 7 7 7 7 7 1 1 16 11 125 155 155 177 177 177 177 7 1 1 17 11 105 155 155 107 107 107 107 7 1 1 18 113 122 155 155 110 110 110 110 7 1 1 19 18 94 161 161 95 95 95 95 7 1 1 20 185 179 165 165 161 161 161 161 7 1 1 21 25 22 164 164 175 175 175 175 7 1 1 22 16 176 124 124 14 14 14 14 7 1 1 23 156 121 181 181 155 155 155 155 7 1 1 24 63 72 76 76 71 71 71 71 7 1 1 25 90 67 148 148 81 81 81 81 7 1 1 26 64 56 148 148 62 62 62 62 7 1 1 27 77 145 180 180 146 146 146 146 7 1 1 28 167 67 168 168 65 65 65 65 7 1 1 29 185 161 95 95 162 162 162 162 7 1 1 30 79 185 95 95 162 162 162 162 7 1 1 31 185 79 167 167 162 162 162 162 7 1 1 32 185 79 65 65 167 167 167 167 7 1 1 33 107 130 184 184 152 152 152 152 7 1 1 34 151 129 138 138 150 150 150 150 7 1 1 35 138 184 129 129 151 151 151 151 7 1 1 36 129 184 130 130 151 151 151 151 7 1 1 37 142 141 183 183 149 149 149 149 7 1 1 38 134 183 135 135 150 150 150 150 7 1 1 39 183 134 151 151 150 150 150 150 7 1 1 40 151 142 149 149 3 3 3 3 7 1 1 41 111 155 110 110 154 154 154 154 7 1 1 42 155 161 123 123 153 153 153 153 7 1 1 43 155 123 122 122 153 153 153 153 7 1 1 44 182 122 110 110 155 155 155 155 7 1 1 45 181 126 161 161 153 153 153 153 7 1 1 46 181 164 160 160 100 100 100 100 7 1 1 47 181 99 100 100 160 160 160 160 7 1 1 48 99 181 126 126 161 161 161 161 7 1 1 49 161 99 160 160 16 16 16 16 7 1 1 50 167 77 166 166 72 72 72 72 7 1 1 51 61 180 62 62 168 168 168 168 7 1 1 52 63 168 180 180 61 61 61 61 7 1 1 53 61 72 180 180 63 63 63 63 7 1 1 54 30 73 111 111 75 75 75 75 7 1 1 55 18 124 176 176 13 13 13 13 7 1 1 56 9 110 122 122 113 113 113 113 7 1 1 57 76 29 174 174 28 28 28 28 7 1 1 58 38 103 89 89 39 39 39 39 7 1 1 59 3 178 151 151 6 6 6 6 7 1 1 60 20 88 141 141 91 91 91 91 7 1 1 61 46 104 147 147 135 135 135 135 7 1 1 62 25 22 175 175 23 23 23 23 7 1 1 63 11 125 177 177 120 120 120 120 7 1 1 64 18 16 176 176 124 124 124 124 7 1 1 65 3 7 178 178 4 4 4 4 7 1 1 66 52 47 53 53 49 49 49 49 7 1 1 67 29 76 174 174 63 63 63 63 7 1 1 68 35 173 146 146 75 75 75 75 7 1 1 69 64 172 148 148 39 39 39 39 7 1 1 70 106 107 105 105 11 11 11 11 7 1 1 71 91 25 175 175 85 85 85 85 7 1 1 72 19 95 94 94 18 18 18 18 7 1 1 73 112 173 146 146 35 35 35 35 7 1 1 74 80 65 79 79 63 63 63 63 7 1 1 75 136 51 101 101 49 49 49 49 7 1 1 76 7 129 130 130 151 151 151 151 7 1 1 77 90 172 148 148 64 64 64 64 7 1 1 78 154 113 155 155 110 110 110 110 7 1 1 79 182 179 146 146 157 157 157 157 7 1 1 80 111 157 182 182 146 146 146 146 7 1 1 81 182 110 111 111 155 155 155 155 7 1 1 82 111 146 155 155 154 154 154 154 7 1 1 83 182 161 155 155 179 179 179 179 7 1 1 84 162 29 167 167 98 98 98 98 7 1 1 85 161 167 179 179 157 157 157 157 7 1 1 86 157 161 162 162 97 97 97 97 7 1 1 87 167 157 162 162 98 98 98 98 7 1 1 88 157 98 97 97 162 162 162 162 7 1 1 89 162 157 167 167 161 161 161 161 7 1 1 90 95 96 69 69 18 18 18 18 7 1 1 91 153 124 161 161 123 123 123 123 7 1 1 92 182 161 179 179 157 157 157 157 7 1 1 93 182 179 155 155 146 146 146 146 7 1 1 94 155 161 182 182 123 123 123 123 7 1 1 95 122 182 123 123 155 155 155 155 7 1 1 96 123 182 157 157 161 161 161 161 7 1 1 97 118 122 127 127 153 153 153 153 7 1 1 98 166 75 146 146 73 73 73 73 7 1 1 99 167 146 179 179 157 157 157 157 7 1 1 100 157 167 166 166 74 74 74 74 7 1 1 101 146 157 166 166 73 73 73 73 7 1 1 102 157 73 74 74 166 166 166 166 7 1 1 103 166 157 146 146 167 167 167 167 7 1 1 104 163 91 164 164 88 88 88 88 7 1 1 105 148 164 179 179 158 158 158 158 7 1 1 106 158 148 163 163 89 89 89 89 7 1 1 107 164 158 163 163 88 88 88 88 7 1 1 108 158 88 89 89 163 163 163 163 7 1 1 109 163 158 164 164 148 148 148 148 7 1 1 110 150 136 147 147 135 135 135 135 7 1 1 111 183 164 158 158 179 179 179 179 7 1 1 112 183 179 158 158 147 147 147 147 7 1 1 113 183 147 150 150 151 151 151 151 7 1 1 114 183 135 150 150 147 147 147 147 7 1 1 115 135 183 158 158 147 147 147 147 7 1 1 116 133 136 150 150 135 135 135 135 7 1 1 117 142 183 134 134 151 151 151 151 7 1 1 118 183 164 179 179 151 151 151 151 7 1 1 119 141 158 183 183 164 164 164 164 7 1 1 120 183 151 149 149 164 164 164 164 7 1 1 121 142 134 2 2 3 3 3 3 7 1 1 122 183 179 147 147 151 151 151 151 7 1 1 123 143 3 149 149 142 142 142 142 7 1 1 124 170 39 148 148 103 103 103 103 7 1 1 125 147 148 179 179 158 158 158 158 7 1 1 126 158 147 170 170 104 104 104 104 7 1 1 127 148 158 170 170 103 103 103 103 7 1 1 128 158 103 104 104 170 170 170 170 7 1 1 129 170 158 148 148 147 147 147 147 7 1 1 130 16 14 124 124 126 126 126 126 7 1 1 131 181 179 155 155 161 161 161 161 7 1 1 132 181 164 179 179 161 161 161 161 7 1 1 133 164 161 181 181 160 160 160 160 7 1 1 134 100 144 181 181 164 164 164 164 7 1 1 135 144 156 181 181 164 164 164 164 7 1 1 136 152 7 151 151 132 132 132 132 7 1 1 137 155 151 179 179 156 156 156 156 7 1 1 138 156 155 152 152 119 119 119 119 7 1 1 139 151 156 152 152 132 132 132 132 7 1 1 140 156 132 119 119 152 152 152 152 7 1 1 141 152 156 151 151 155 155 155 155 7 1 1 142 128 119 132 132 152 152 152 152 7 1 1 143 153 125 155 155 121 121 121 121 7 1 1 144 126 181 121 121 153 153 153 153 7 1 1 145 181 153 155 155 121 121 121 121 7 1 1 146 181 164 156 156 179 179 179 179 7 1 1 147 181 179 156 156 155 155 155 155 7 1 1 148 127 126 121 121 153 153 153 153 7 1 1 149 149 22 164 164 144 144 144 144 7 1 1 150 151 164 179 179 156 156 156 156 7 1 1 151 139 156 144 144 149 149 149 149 7 1 1 152 156 149 164 164 144 144 144 144 7 1 1 153 156 149 151 151 164 164 164 164 7 1 1 154 156 139 151 151 149 149 149 149 7 1 1 155 169 35 146 146 58 58 58 58 7 1 1 156 147 146 179 179 145 145 145 145 7 1 1 157 145 147 169 169 52 52 52 52 7 1 1 158 146 145 169 169 58 58 58 58 7 1 1 159 145 58 52 52 169 169 169 169 7 1 1 160 169 145 146 146 147 147 147 147 7 1 1 161 168 64 148 148 62 62 62 62 7 1 1 162 180 179 167 167 146 146 146 146 7 1 1 163 148 167 168 168 180 180 180 180 7 1 1 164 180 148 167 167 179 179 179 179 7 1 1 165 56 62 180 180 148 148 148 148 7 1 1 166 145 56 180 180 148 148 148 148 7 1 1 167 60 62 66 66 168 168 168 168 7 1 1 168 166 76 167 167 72 72 72 72 7 1 1 169 180 146 167 167 77 77 77 77 7 1 1 170 180 179 146 146 145 145 145 145 7 1 1 171 180 148 179 179 145 145 145 145 7 1 1 172 77 146 167 167 166 166 166 166 7 1 1 173 74 78 70 70 76 76 76 76 7 1 1 174 170 46 147 147 53 53 53 53 7 1 1 175 148 147 179 179 145 145 145 145 7 1 1 176 145 53 56 56 147 147 147 147 7 1 1 177 147 56 170 170 53 53 53 53 7 1 1 178 147 148 170 170 56 56 56 56 7 1 1 179 147 148 56 56 145 145 145 145 7 1 1 180 146 115 159 159 154 154 154 154 7 1 1 181 155 146 179 179 159 159 159 159 7 1 1 182 159 155 154 154 105 105 105 105 7 1 1 183 115 159 102 102 146 146 146 146 7 1 1 184 159 115 105 105 154 154 154 154 7 1 1 185 154 159 146 146 155 155 155 155 7 1 1 186 163 90 148 148 81 81 81 81 7 1 1 187 164 148 179 179 165 165 165 165 7 1 1 188 165 164 163 163 83 83 83 83 7 1 1 189 148 165 163 163 81 81 81 81 7 1 1 190 165 81 83 83 163 163 163 163 7 1 1 191 163 165 148 148 164 164 164 164 7 1 1 192 160 25 164 164 84 84 84 84 7 1 1 193 161 164 179 179 165 165 165 165 7 1 1 194 165 161 160 160 94 94 94 94 7 1 1 195 164 165 160 160 84 84 84 84 7 1 1 196 165 84 94 94 160 160 160 160 7 1 1 197 160 165 164 164 161 161 161 161 7 1 1 198 169 49 147 147 101 101 101 101 7 1 1 199 146 147 179 179 159 159 159 159 7 1 1 200 159 146 169 169 102 102 102 102 7 1 1 201 147 159 169 169 101 101 101 101 7 1 1 202 159 101 102 102 169 169 169 169 7 1 1 203 169 159 147 147 146 146 146 146 7 1 1 204 162 18 161 161 95 95 95 95 7 1 1 205 185 148 165 165 179 179 179 179 7 1 1 206 185 165 94 94 161 161 161 161 7 1 1 207 94 95 185 185 161 161 161 161 7 1 1 208 161 185 167 167 162 162 162 162 7 1 1 209 185 67 148 148 167 167 167 167 7 1 1 210 150 6 151 151 129 129 129 129 7 1 1 211 147 151 179 179 159 159 159 159 7 1 1 212 151 138 147 147 150 150 150 150 7 1 1 213 184 138 159 159 147 147 147 147 7 1 1 214 184 151 138 138 147 147 147 147 7 1 1 215 152 11 155 155 107 107 107 107 7 1 1 216 151 155 179 179 159 159 159 159 7 1 1 217 184 151 155 155 152 152 152 152 7 1 1 218 159 107 184 184 155 155 155 155 7 1 1 219 7 8 129 129 6 6 6 6 7 1 1 220 184 151 159 159 155 155 155 155 7 1 1 221 168 63 167 167 65 65 65 65 7 1 1 222 185 67 165 165 148 148 148 148 7 1 1 223 185 148 179 179 167 167 167 167 7 1 1 224 185 179 161 161 167 167 167 167 7 1 1 225 67 148 167 167 168 168 168 168 7 1 1 226 12 13 96 96 176 176 176 176 7 1 1 227 1 2 5 5 178 178 178 178 7 1 1 228 116 120 10 10 177 177 177 177 7 1 1 229 27 71 59 59 174 174 174 174 7 1 1 230 33 30 34 34 173 173 173 173 7 1 1 231 42 38 43 43 172 172 172 172 7 1 1 232 24 23 26 26 175 175 175 175 7 1 1 233 48 47 50 50 171 171 171 171 7 1 1 234 12 19 17 17 176 176 176 176 7 1 1 235 116 106 109 109 177 177 177 177 7 1 1 236 27 80 68 68 174 174 174 174 7 1 1 237 116 9 117 117 177 177 177 177 7 1 1 238 113 110 154 154 108 108 108 108 7 1 1 239 109 9 177 177 113 113 113 113 7 1 1 240 9 108 110 110 113 113 113 113 7 1 1 241 9 109 108 108 113 113 113 113 7 1 1 242 111 112 154 154 114 114 114 114 7 1 1 243 30 34 173 173 112 112 112 112 7 1 1 244 30 114 34 34 112 112 112 112 7 1 1 245 30 111 114 114 112 112 112 112 7 1 1 246 114 110 108 108 154 154 154 154 7 1 1 247 27 28 70 70 174 174 174 174 7 1 1 248 69 97 162 162 18 18 18 18 7 1 1 249 13 96 176 176 18 18 18 18 7 1 1 250 96 13 97 97 18 18 18 18 7 1 1 251 69 29 162 162 98 98 98 98 7 1 1 252 68 28 174 174 29 29 29 29 7 1 1 253 98 68 69 69 29 29 29 29 7 1 1 254 28 68 98 98 29 29 29 29 7 1 1 255 98 69 97 97 162 162 162 162 7 1 1 256 109 9 116 116 177 177 177 177 7 1 1 257 15 13 12 12 176 176 176 176 7 1 1 258 125 118 153 153 122 122 122 122 7 1 1 259 9 117 177 177 125 125 125 125 7 1 1 260 117 122 118 118 125 125 125 125 7 1 1 261 117 9 122 122 125 125 125 125 7 1 1 262 127 124 153 153 123 123 123 123 7 1 1 263 15 13 176 176 124 124 124 124 7 1 1 264 13 127 123 123 124 124 124 124 7 1 1 265 13 15 127 127 124 124 124 124 7 1 1 266 122 123 127 127 153 153 153 153 7 1 1 267 32 30 33 33 173 173 173 173 7 1 1 268 68 28 27 27 174 174 174 174 7 1 1 269 75 73 166 166 78 78 78 78 7 1 1 270 32 30 173 173 75 75 75 75 7 1 1 271 73 32 78 78 75 75 75 75 7 1 1 272 30 32 73 73 75 75 75 75 7 1 1 273 78 74 166 166 76 76 76 76 7 1 1 274 28 70 174 174 76 76 76 76 7 1 1 275 28 74 70 70 76 76 76 76 7 1 1 276 78 74 73 73 166 166 166 166 7 1 1 277 24 20 21 21 175 175 175 175 7 1 1 278 91 88 163 163 86 86 86 86 7 1 1 279 87 20 175 175 91 91 91 91 7 1 1 280 88 20 86 86 91 91 91 91 7 1 1 281 20 87 86 86 91 91 91 91 7 1 1 282 89 90 163 163 92 92 92 92 7 1 1 283 38 43 172 172 90 90 90 90 7 1 1 284 89 43 38 38 90 90 90 90 7 1 1 285 92 43 89 89 90 90 90 90 7 1 1 286 92 88 86 86 163 163 163 163 7 1 1 287 48 45 55 55 171 171 171 171 7 1 1 288 6 133 150 150 134 134 134 134 7 1 1 289 2 5 178 178 6 6 6 6 7 1 1 290 134 5 2 2 6 6 6 6 7 1 1 291 133 5 134 134 6 6 6 6 7 1 1 292 133 138 150 150 136 136 136 136 7 1 1 293 137 45 171 171 136 136 136 136 7 1 1 294 45 137 135 135 136 136 136 136 7 1 1 295 134 135 133 133 150 150 150 150 7 1 1 296 87 20 24 24 175 175 175 175 7 1 1 297 140 2 1 1 178 178 178 178 7 1 1 298 22 143 149 149 141 141 141 141 7 1 1 299 20 21 175 175 22 22 22 22 7 1 1 300 141 21 20 20 22 22 22 22 7 1 1 301 143 21 141 141 22 22 22 22 7 1 1 302 143 139 149 149 3 3 3 3 7 1 1 303 140 2 178 178 3 3 3 3 7 1 1 304 142 2 140 140 3 3 3 3 7 1 1 305 141 142 143 143 149 149 149 149 7 1 1 306 40 38 42 42 172 172 172 172 7 1 1 307 137 45 48 48 171 171 171 171 7 1 1 308 39 103 170 170 57 57 57 57 7 1 1 309 40 38 172 172 39 39 39 39 7 1 1 310 103 40 57 57 39 39 39 39 7 1 1 311 38 40 103 103 39 39 39 39 7 1 1 312 53 55 57 57 46 46 46 46 7 1 1 313 45 55 171 171 46 46 46 46 7 1 1 314 55 45 104 104 46 46 46 46 7 1 1 315 57 104 103 103 170 170 170 170 7 1 1 316 12 14 15 15 176 176 176 176 7 1 1 317 16 99 160 160 93 93 93 93 7 1 1 318 17 14 176 176 16 16 16 16 7 1 1 319 99 17 93 93 16 16 16 16 7 1 1 320 14 17 99 99 16 16 16 16 7 1 1 321 84 26 93 93 25 25 25 25 7 1 1 322 23 26 175 175 25 25 25 25 7 1 1 323 100 26 23 23 25 25 25 25 7 1 1 324 93 25 160 160 84 84 84 84 7 1 1 325 1 4 140 140 178 178 178 178 7 1 1 326 11 128 152 152 119 119 119 119 7 1 1 327 120 10 177 177 11 11 11 11 7 1 1 328 119 10 120 120 11 11 11 11 7 1 1 329 128 10 119 119 11 11 11 11 7 1 1 330 128 7 152 152 132 132 132 132 7 1 1 331 131 4 178 178 7 7 7 7 7 1 1 332 132 4 131 131 7 7 7 7 7 1 1 333 130 128 131 131 7 7 7 7 7 1 1 334 17 14 12 12 176 176 176 176 7 1 1 335 117 120 116 116 177 177 177 177 7 1 1 336 124 127 153 153 126 126 126 126 7 1 1 337 14 15 176 176 124 124 124 124 7 1 1 338 15 126 127 127 124 124 124 124 7 1 1 339 15 14 126 126 124 124 124 124 7 1 1 340 118 125 153 153 121 121 121 121 7 1 1 341 117 120 177 177 125 125 125 125 7 1 1 342 120 118 121 121 125 125 125 125 7 1 1 343 120 117 118 118 125 125 125 125 7 1 1 344 118 127 121 121 153 153 153 153 7 1 1 345 21 23 24 24 175 175 175 175 7 1 1 346 131 4 1 1 178 178 178 178 7 1 1 347 22 144 149 149 143 143 143 143 7 1 1 348 21 23 175 175 22 22 22 22 7 1 1 349 144 21 143 143 22 22 22 22 7 1 1 350 23 21 144 144 22 22 22 22 7 1 1 351 142 140 143 143 3 3 3 3 7 1 1 352 4 140 178 178 3 3 3 3 7 1 1 353 139 140 4 4 3 3 3 3 7 1 1 354 143 139 144 144 149 149 149 149 7 1 1 355 33 31 32 32 173 173 173 173 7 1 1 356 37 54 58 58 35 35 35 35 7 1 1 357 37 31 173 173 35 35 35 35 7 1 1 358 31 37 58 58 35 35 35 35 7 1 1 359 52 49 169 169 54 54 54 54 7 1 1 360 47 50 171 171 49 49 49 49 7 1 1 361 52 50 47 47 49 49 49 49 7 1 1 362 54 50 52 52 49 49 49 49 7 1 1 363 37 102 54 54 35 35 35 35 7 1 1 364 42 41 40 40 172 172 172 172 7 1 1 365 63 60 168 168 61 61 61 61 7 1 1 366 71 59 174 174 63 63 63 63 7 1 1 367 59 61 60 60 63 63 63 63 7 1 1 368 59 71 61 61 63 63 63 63 7 1 1 369 66 64 168 168 62 62 62 62 7 1 1 370 44 41 172 172 64 64 64 64 7 1 1 371 62 41 66 66 64 64 64 64 7 1 1 372 41 44 66 66 64 64 64 64 7 1 1 373 61 62 60 60 168 168 168 168 7 1 1 374 37 31 33 33 173 173 173 173 7 1 1 375 70 71 27 27 174 174 174 174 7 1 1 376 75 78 166 166 77 77 77 77 7 1 1 377 31 32 173 173 75 75 75 75 7 1 1 378 32 77 78 78 75 75 75 75 7 1 1 379 32 31 77 77 75 75 75 75 7 1 1 380 78 76 166 166 72 72 72 72 7 1 1 381 70 71 174 174 76 76 76 76 7 1 1 382 70 72 71 71 76 76 76 76 7 1 1 383 77 72 78 78 166 166 166 166 7 1 1 384 55 47 48 48 171 171 171 171 7 1 1 385 44 41 42 42 172 172 172 172 7 1 1 386 57 104 170 170 46 46 46 46 7 1 1 387 55 47 171 171 46 46 46 46 7 1 1 388 53 47 55 55 46 46 46 46 7 1 1 389 56 39 170 170 57 57 57 57 7 1 1 390 41 40 172 172 39 39 39 39 7 1 1 391 56 40 41 41 39 39 39 39 7 1 1 392 57 40 56 56 39 39 39 39 7 1 1 393 57 46 170 170 53 53 53 53 7 1 1 394 112 115 154 154 114 114 114 114 7 1 1 395 34 36 173 173 112 112 112 112 7 1 1 396 34 115 36 36 112 112 112 112 7 1 1 397 34 114 115 115 112 112 112 112 7 1 1 398 105 113 154 154 108 108 108 108 7 1 1 399 106 109 177 177 113 113 113 113 7 1 1 400 109 105 108 108 113 113 113 113 7 1 1 401 109 106 105 105 113 113 113 113 7 1 1 402 108 115 114 114 154 154 154 154 7 1 1 403 33 36 37 37 173 173 173 173 7 1 1 404 90 81 163 163 92 92 92 92 7 1 1 405 43 82 172 172 90 90 90 90 7 1 1 406 82 92 81 81 90 90 90 90 7 1 1 407 82 43 92 92 90 90 90 90 7 1 1 408 83 91 163 163 86 86 86 86 7 1 1 409 85 87 175 175 91 91 91 91 7 1 1 410 85 86 87 87 91 91 91 91 7 1 1 411 85 83 86 86 91 91 91 91 7 1 1 412 86 81 92 92 163 163 163 163 7 1 1 413 82 44 43 43 172 172 172 172 7 1 1 414 24 85 87 87 175 175 175 175 7 1 1 415 100 93 26 26 25 25 25 25 7 1 1 416 26 85 175 175 25 25 25 25 7 1 1 417 93 100 160 160 25 25 25 25 7 1 1 418 85 26 84 84 25 25 25 25 7 1 1 419 94 16 160 160 93 93 93 93 7 1 1 420 19 17 176 176 16 16 16 16 7 1 1 421 94 17 19 19 16 16 16 16 7 1 1 422 93 17 94 94 16 16 16 16 7 1 1 423 26 85 24 24 175 175 175 175 7 1 1 424 49 101 169 169 54 54 54 54 7 1 1 425 50 51 171 171 49 49 49 49 7 1 1 426 101 50 54 54 49 49 49 49 7 1 1 427 51 50 101 101 49 49 49 49 7 1 1 428 35 54 169 169 102 102 102 102 7 1 1 429 36 37 173 173 35 35 35 35 7 1 1 430 37 36 102 102 35 35 35 35 7 1 1 431 101 54 102 102 169 169 169 169 7 1 1 432 48 51 137 137 171 171 171 171 7 1 1 433 34 36 33 33 173 173 173 173 7 1 1 434 96 19 12 12 176 176 176 176 7 1 1 435 69 18 162 162 95 95 95 95 7 1 1 436 96 19 176 176 18 18 18 18 7 1 1 437 96 95 19 19 18 18 18 18 7 1 1 438 79 29 162 162 69 69 69 69 7 1 1 439 80 68 174 174 29 29 29 29 7 1 1 440 79 68 80 80 29 29 29 29 7 1 1 441 69 68 79 79 29 29 29 29 7 1 1 442 97 69 96 96 18 18 18 18 7 1 1 443 1 8 131 131 178 178 178 178 7 1 1 444 50 51 48 48 171 171 171 171 7 1 1 445 6 129 150 150 133 133 133 133 7 1 1 446 5 8 178 178 6 6 6 6 7 1 1 447 129 5 133 133 6 6 6 6 7 1 1 448 8 5 129 129 6 6 6 6 7 1 1 449 135 137 133 133 136 136 136 136 7 1 1 450 51 137 171 171 136 136 136 136 7 1 1 451 51 138 137 137 136 136 136 136 7 1 1 452 133 138 129 129 150 150 150 150 7 1 1 453 10 106 116 116 177 177 177 177 7 1 1 454 5 8 1 1 178 178 178 178 7 1 1 455 11 107 152 152 128 128 128 128 7 1 1 456 10 106 177 177 11 11 11 11 7 1 1 457 107 10 128 128 11 11 11 11 7 1 1 458 106 10 107 107 11 11 11 11 7 1 1 459 128 130 152 152 7 7 7 7 7 1 1 460 8 131 178 178 7 7 7 7 7 1 1 461 130 131 8 8 7 7 7 7 7 1 1 462 128 130 107 107 152 152 152 152 7 1 1 463 59 80 27 27 174 174 174 174 7 1 1 464 44 42 43 43 172 172 172 172 7 1 1 465 63 65 168 168 60 60 60 60 7 1 1 466 59 80 174 174 63 63 63 63 7 1 1 467 80 60 65 65 63 63 63 63 7 1 1 468 80 59 60 60 63 63 63 63 7 1 1 469 67 64 168 168 66 66 66 66 7 1 1 470 82 44 172 172 64 64 64 64 7 1 1 471 66 82 67 67 64 64 64 64 7 1 1 472 44 82 66 66 64 64 64 64 7 1 1 473 66 65 60 60 168 168 168 168 7 1 1 474 111 110 114 114 154 154 154 154 7 1 1 475 72 70 78 78 76 76 76 76 7 1 1 476 89 88 92 92 163 163 163 163 7 1 1 477 104 57 55 55 46 46 46 46 7 1 1 478 100 99 93 93 160 160 160 160 7 1 1 479 139 143 140 140 3 3 3 3 7 1 1 480 52 58 54 54 169 169 169 169 7 1 1 481 56 53 57 57 170 170 170 170 7 1 1 482 105 115 108 108 154 154 154 154 7 1 1 483 83 81 86 86 163 163 163 163 7 1 1 484 94 84 93 93 160 160 160 160 7 1 1 485 35 58 169 169 54 54 54 54 7 1 1 486 79 95 69 69 162 162 162 162 7 1 1 487 138 133 137 137 136 136 136 136 7 1 1 488 132 131 128 128 7 7 7 7 7 1 1 489 67 65 66 66 168 168 168 168 7 1 1 490 112 154 146 146 111 111 111 111 7 1 1 491 75 173 146 146 112 112 112 112 7 1 1 492 18 123 161 161 124 124 124 124 7 1 1 493 18 162 161 161 97 97 97 97 7 1 1 494 18 97 161 161 123 123 123 123 7 1 1 495 125 153 155 155 122 122 122 122 7 1 1 496 113 177 155 155 125 125 125 125 7 1 1 497 76 166 167 167 74 74 74 74 7 1 1 498 76 74 167 167 98 98 98 98 7 1 1 499 90 163 148 148 89 89 89 89 7 1 1 500 39 172 148 148 90 90 90 90 7 1 1 501 3 178 6 6 2 2 2 2 7 1 1 502 6 150 151 151 134 134 134 134 7 1 1 503 3 6 151 151 134 134 134 134 7 1 1 504 22 149 164 164 141 141 141 141 7 1 1 505 91 175 164 164 22 22 22 22 7 1 1 506 46 170 147 147 104 104 104 104 7 1 1 507 46 135 147 147 136 136 136 136 7 1 1 508 25 144 164 164 22 22 22 22 7 1 1 509 25 160 164 164 100 100 100 100 7 1 1 510 25 100 164 164 144 144 144 144 7 1 1 511 11 121 155 155 125 125 125 125 7 1 1 512 11 152 155 155 119 119 119 119 7 1 1 513 11 119 155 155 121 121 121 121 7 1 1 514 124 153 161 161 126 126 126 126 7 1 1 515 16 126 161 161 99 99 99 99 7 1 1 516 3 149 151 151 139 139 139 139 7 1 1 517 7 139 4 4 3 3 3 3 7 1 1 518 49 169 147 147 52 52 52 52 7 1 1 519 46 171 147 147 49 49 49 49 7 1 1 520 61 71 72 72 63 63 63 63 7 1 1 521 63 180 167 167 72 72 72 72 7 1 1 522 63 168 167 167 180 180 180 180 7 1 1 523 75 166 146 146 77 77 77 77 7 1 1 524 35 75 146 146 77 77 77 77 7 1 1 525 39 170 148 148 56 56 56 56 7 1 1 526 64 39 148 148 56 56 56 56 7 1 1 527 113 154 155 155 105 105 105 105 7 1 1 528 11 177 155 155 113 113 113 113 7 1 1 529 91 163 164 164 83 83 83 83 7 1 1 530 25 83 91 91 164 164 164 164 7 1 1 531 16 160 161 161 94 94 94 94 7 1 1 532 18 16 124 124 161 161 161 161 7 1 1 533 35 169 146 146 102 102 102 102 7 1 1 534 112 35 146 146 102 102 102 102 7 1 1 535 63 29 167 167 79 79 79 79 7 1 1 536 29 162 167 167 79 79 79 79 7 1 1 537 136 150 147 147 138 138 138 138 7 1 1 538 101 138 51 51 136 136 136 136 7 1 1 539 151 152 184 184 130 130 130 130 7 1 1 540 129 130 8 8 7 7 7 7 7 1 1 541 64 168 148 148 67 67 67 67 7 1 1 542 90 64 148 148 67 67 67 67 7 1 1 543 113 125 122 122 9 9 9 9 7 1 1 544 113 125 155 155 122 122 122 122 7 1 1 545 113 177 125 125 9 9 9 9 7 1 1 546 75 112 146 146 111 111 111 111 7 1 1 547 111 146 182 182 155 155 155 155 7 1 1 548 76 98 29 29 28 28 28 28 7 1 1 549 76 98 167 167 29 29 29 29 7 1 1 550 28 98 74 74 76 76 76 76 7 1 1 551 97 123 157 157 161 161 161 161 7 1 1 552 74 98 157 157 167 167 167 167 7 1 1 553 18 123 124 124 13 13 13 13 7 1 1 554 13 123 97 97 18 18 18 18 7 1 1 555 75 112 111 111 30 30 30 30 7 1 1 556 75 173 112 112 30 30 30 30 7 1 1 557 73 157 111 111 146 146 146 146 7 1 1 558 91 22 141 141 20 20 20 20 7 1 1 559 91 22 164 164 141 141 141 141 7 1 1 560 91 175 22 22 20 20 20 20 7 1 1 561 39 90 148 148 89 89 89 89 7 1 1 562 141 88 158 158 164 164 164 164 7 1 1 563 46 136 171 171 45 45 45 45 7 1 1 564 46 135 136 136 45 45 45 45 7 1 1 565 183 164 149 149 141 141 141 141 7 1 1 566 45 135 104 104 46 46 46 46 7 1 1 567 3 6 134 134 2 2 2 2 7 1 1 568 151 142 183 183 149 149 149 149 7 1 1 569 39 90 89 89 38 38 38 38 7 1 1 570 39 172 90 90 38 38 38 38 7 1 1 571 158 104 135 135 147 147 147 147 7 1 1 572 103 158 89 89 148 148 148 148 7 1 1 573 16 126 124 124 161 161 161 161 7 1 1 574 99 126 14 14 16 16 16 16 7 1 1 575 161 99 181 181 160 160 160 160 7 1 1 576 181 153 161 161 155 155 155 155 7 1 1 577 4 132 139 139 7 7 7 7 7 1 1 578 7 151 139 139 3 3 3 3 7 1 1 579 7 151 132 132 139 139 139 139 7 1 1 580 119 121 156 156 155 155 155 155 7 1 1 581 139 132 156 156 151 151 151 151 7 1 1 582 11 121 125 125 120 120 120 120 7 1 1 583 120 121 119 119 11 11 11 11 7 1 1 584 25 144 22 22 23 23 23 23 7 1 1 585 23 144 100 100 25 25 25 25 7 1 1 586 31 58 77 77 35 35 35 35 7 1 1 587 35 75 77 77 31 31 31 31 7 1 1 588 53 49 47 47 46 46 46 46 7 1 1 589 35 173 75 75 31 31 31 31 7 1 1 590 41 62 56 56 64 64 64 64 7 1 1 591 64 39 56 56 41 41 41 41 7 1 1 592 180 72 77 77 167 167 167 167 7 1 1 593 64 172 39 39 41 41 41 41 7 1 1 594 63 72 167 167 76 76 76 76 7 1 1 595 63 76 174 174 71 71 71 71 7 1 1 596 145 77 58 58 146 146 146 146 7 1 1 597 53 147 52 52 49 49 49 49 7 1 1 598 46 171 49 49 47 47 47 47 7 1 1 599 148 180 168 168 62 62 62 62 7 1 1 600 53 145 52 52 147 147 147 147 7 1 1 601 112 35 102 102 36 36 36 36 7 1 1 602 112 173 35 35 36 36 36 36 7 1 1 603 11 113 155 155 105 105 105 105 7 1 1 604 146 115 154 154 112 112 112 112 7 1 1 605 82 81 67 67 90 90 90 90 7 1 1 606 90 64 67 67 82 82 82 82 7 1 1 607 84 83 85 85 25 25 25 25 7 1 1 608 90 172 64 64 82 82 82 82 7 1 1 609 25 83 164 164 84 84 84 84 7 1 1 610 25 85 91 91 83 83 83 83 7 1 1 611 18 16 161 161 94 94 94 94 7 1 1 612 84 165 83 83 164 164 164 164 7 1 1 613 136 49 171 171 51 51 51 51 7 1 1 614 136 101 138 138 147 147 147 147 7 1 1 615 115 102 36 36 112 112 112 112 7 1 1 616 136 101 147 147 49 49 49 49 7 1 1 617 18 16 94 94 19 19 19 19 7 1 1 618 18 176 16 16 19 19 19 19 7 1 1 619 185 65 67 67 167 167 167 167 7 1 1 620 7 178 6 6 151 151 151 151 7 1 1 621 7 129 151 151 6 6 6 6 7 1 1 622 184 151 147 147 159 159 159 159 7 1 1 623 7 178 8 8 6 6 6 6 7 1 1 624 11 113 105 105 106 106 106 106 7 1 1 625 11 177 113 113 106 106 106 106 7 1 1 626 184 155 107 107 152 152 152 152 7 1 1 627 107 159 105 105 155 155 155 155 7 1 1 628 63 29 79 79 80 80 80 80 7 1 1 629 63 174 29 29 80 80 80 80 7 1 1 630 165 67 81 81 148 148 148 148 7 1 1 631 185 95 94 94 0 0 0 0 1 4 4 632 185 65 79 79 0 0 0 0 1 4 4 633 159 138 101 101 0 0 0 0 3 4 4 634 184 130 107 107 0 0 0 0 3 4 4 635 158 183 135 135 0 0 0 0 2 4 4 636 183 142 141 141 0 0 0 0 2 4 4 637 157 182 123 123 0 0 0 0 2 4 4 638 182 110 122 122 0 0 0 0 2 4 4 639 181 100 144 144 0 0 0 0 2 4 4 640 181 126 121 121 0 0 0 0 2 4 4 641 180 62 56 56 0 0 0 0 2 4 4 642 180 72 77 77 0 0 0 0 2 4 4 643 165 81 83 83 0 0 0 0 1 4 4 644 165 84 94 94 0 0 0 0 1 4 4 645 185 79 95 95 0 0 0 0 1 4 4 646 67 185 165 165 0 0 0 0 1 4 4 647 165 83 84 84 0 0 0 0 1 4 4 648 185 94 165 165 0 0 0 0 1 4 4 649 165 67 81 81 0 0 0 0 1 4 4 650 67 65 185 185 0 0 0 0 1 4 4 651 159 105 115 115 0 0 0 0 3 4 4 652 159 101 102 102 0 0 0 0 3 4 4 653 184 129 138 138 0 0 0 0 3 4 4 654 184 107 159 159 0 0 0 0 3 4 4 655 159 105 107 107 0 0 0 0 3 4 4 656 159 102 115 115 0 0 0 0 3 4 4 657 159 184 138 138 0 0 0 0 3 4 4 658 184 129 130 130 0 0 0 0 3 4 4 659 158 88 89 89 0 0 0 0 2 4 4 660 183 134 135 135 0 0 0 0 2 4 4 661 183 141 158 158 0 0 0 0 2 4 4 662 158 103 104 104 0 0 0 0 2 4 4 663 158 89 103 103 0 0 0 0 2 4 4 664 158 88 141 141 0 0 0 0 2 4 4 665 158 104 135 135 0 0 0 0 2 4 4 666 183 134 142 142 0 0 0 0 2 4 4 667 111 182 157 157 0 0 0 0 2 4 4 668 157 97 98 98 0 0 0 0 2 4 4 669 182 122 123 123 0 0 0 0 2 4 4 670 157 73 74 74 0 0 0 0 2 4 4 671 157 73 111 111 0 0 0 0 2 4 4 672 111 110 182 182 0 0 0 0 2 4 4 673 157 74 98 98 0 0 0 0 2 4 4 674 157 97 123 123 0 0 0 0 2 4 4 675 181 99 100 100 0 0 0 0 2 4 4 676 156 119 132 132 0 0 0 0 2 4 4 677 181 121 156 156 0 0 0 0 2 4 4 678 156 139 144 144 0 0 0 0 2 4 4 679 181 99 126 126 0 0 0 0 2 4 4 680 156 132 139 139 0 0 0 0 2 4 4 681 181 144 156 156 0 0 0 0 2 4 4 682 156 119 121 121 0 0 0 0 2 4 4 683 145 52 58 58 0 0 0 0 2 4 4 684 180 61 62 62 0 0 0 0 2 4 4 685 180 77 145 145 0 0 0 0 2 4 4 686 145 53 56 56 0 0 0 0 2 4 4 687 145 52 53 53 0 0 0 0 2 4 4 688 145 58 77 77 0 0 0 0 2 4 4 689 180 56 145 145 0 0 0 0 2 4 4 690 180 61 72 72 0 0 0 0 2 4 4 691 141 142 143 143 0 0 0 0 2 4 4 692 140 142 143 143 0 0 0 0 2 4 4 693 139 140 143 143 0 0 0 0 2 4 4 694 139 143 144 144 0 0 0 0 2 4 4 695 133 135 137 137 0 0 0 0 2 4 4 696 133 134 135 135 0 0 0 0 2 4 4 697 133 137 138 138 0 0 0 0 3 4 4 698 129 133 138 138 0 0 0 0 3 4 4 699 128 130 131 131 0 0 0 0 3 4 4 700 122 123 127 127 0 0 0 0 2 4 4 701 132 128 131 131 0 0 0 0 2 4 4 702 132 119 128 128 0 0 0 0 2 4 4 703 119 120 121 121 0 0 0 0 2 4 4 704 122 127 118 118 0 0 0 0 2 4 4 705 121 127 118 118 0 0 0 0 2 4 4 706 121 126 127 127 0 0 0 0 2 4 4 707 118 120 121 121 0 0 0 0 2 4 4 708 117 118 122 122 0 0 0 0 2 4 4 709 117 118 120 120 0 0 0 0 2 4 4 710 116 117 120 120 0 0 0 0 2 4 4 711 110 111 114 114 0 0 0 0 2 4 4 712 108 110 114 114 0 0 0 0 2 4 4 713 108 114 115 115 0 0 0 0 3 4 4 714 107 128 130 130 0 0 0 0 3 4 4 715 106 109 116 116 0 0 0 0 3 4 4 716 105 108 115 115 0 0 0 0 3 4 4 717 105 108 109 109 0 0 0 0 3 4 4 718 105 106 109 109 0 0 0 0 3 4 4 719 105 106 107 107 0 0 0 0 3 4 4 720 93 99 100 100 0 0 0 0 2 4 4 721 88 89 92 92 0 0 0 0 2 4 4 722 86 88 92 92 0 0 0 0 2 4 4 723 86 20 87 87 0 0 0 0 2 4 4 724 85 86 87 87 0 0 0 0 1 4 4 725 84 94 93 93 0 0 0 0 1 4 4 726 83 85 86 86 0 0 0 0 1 4 4 727 83 84 85 85 0 0 0 0 1 4 4 728 81 83 86 86 0 0 0 0 1 4 4 729 81 86 92 92 0 0 0 0 1 4 4 730 81 82 92 92 0 0 0 0 1 4 4 731 73 74 78 78 0 0 0 0 2 4 4 732 72 77 78 78 0 0 0 0 2 4 4 733 70 74 78 78 0 0 0 0 2 4 4 734 70 72 78 78 0 0 0 0 2 4 4 735 70 71 72 72 0 0 0 0 2 4 4 736 69 96 97 97 0 0 0 0 2 4 4 737 69 97 98 98 0 0 0 0 2 4 4 738 69 79 95 95 0 0 0 0 1 4 4 739 69 95 96 96 0 0 0 0 1 4 4 740 68 69 98 98 0 0 0 0 2 4 4 741 68 79 80 80 0 0 0 0 1 4 4 742 68 69 79 79 0 0 0 0 1 4 4 743 67 81 82 82 0 0 0 0 1 4 4 744 66 67 82 82 0 0 0 0 1 4 4 745 65 66 67 67 0 0 0 0 1 4 4 746 65 79 80 80 0 0 0 0 1 4 4 747 61 71 72 72 0 0 0 0 2 4 4 748 60 62 66 66 0 0 0 0 2 4 4 749 60 61 62 62 0 0 0 0 2 4 4 750 60 65 66 66 0 0 0 0 1 4 4 751 60 65 80 80 0 0 0 0 1 4 4 752 59 60 61 61 0 0 0 0 2 4 4 753 59 61 71 71 0 0 0 0 2 4 4 754 59 60 80 80 0 0 0 0 1 4 4 755 102 54 37 37 0 0 0 0 3 4 4 756 57 103 104 104 0 0 0 0 2 4 4 757 55 57 104 104 0 0 0 0 2 4 4 758 54 37 58 58 0 0 0 0 2 4 4 759 102 101 54 54 0 0 0 0 3 4 4 760 53 56 57 57 0 0 0 0 2 4 4 761 53 55 57 57 0 0 0 0 2 4 4 762 52 54 58 58 0 0 0 0 2 4 4 763 51 137 138 138 0 0 0 0 3 4 4 764 51 101 138 138 0 0 0 0 3 4 4 765 50 52 54 54 0 0 0 0 2 4 4 766 50 54 101 101 0 0 0 0 3 4 4 767 50 51 101 101 0 0 0 0 3 4 4 768 48 137 51 51 0 0 0 0 3 4 4 769 48 50 51 51 0 0 0 0 3 4 4 770 47 48 50 50 0 0 0 0 2 4 4 771 47 50 52 52 0 0 0 0 2 4 4 772 47 53 55 55 0 0 0 0 2 4 4 773 47 52 53 53 0 0 0 0 2 4 4 774 55 47 48 48 0 0 0 0 2 4 4 775 45 48 137 137 0 0 0 0 2 4 4 776 45 55 48 48 0 0 0 0 2 4 4 777 45 135 137 137 0 0 0 0 2 4 4 778 45 55 104 104 0 0 0 0 2 4 4 779 45 104 135 135 0 0 0 0 2 4 4 780 66 41 44 44 0 0 0 0 2 4 4 781 44 66 82 82 0 0 0 0 1 4 4 782 43 89 92 92 0 0 0 0 2 4 4 783 43 82 92 92 0 0 0 0 1 4 4 784 43 44 42 42 0 0 0 0 1 4 4 785 43 82 44 44 0 0 0 0 1 4 4 786 41 42 44 44 0 0 0 0 2 4 4 787 66 62 41 41 0 0 0 0 2 4 4 788 41 56 62 62 0 0 0 0 2 4 4 789 40 41 42 42 0 0 0 0 2 4 4 790 40 57 103 103 0 0 0 0 2 4 4 791 40 41 56 56 0 0 0 0 2 4 4 792 40 56 57 57 0 0 0 0 2 4 4 793 38 40 42 42 0 0 0 0 2 4 4 794 38 42 43 43 0 0 0 0 2 4 4 795 38 43 89 89 0 0 0 0 2 4 4 796 38 40 103 103 0 0 0 0 2 4 4 797 38 89 103 103 0 0 0 0 2 4 4 798 36 37 102 102 0 0 0 0 3 4 4 799 36 102 115 115 0 0 0 0 3 4 4 800 34 36 115 115 0 0 0 0 3 4 4 801 34 114 115 115 0 0 0 0 3 4 4 802 33 36 37 37 0 0 0 0 3 4 4 803 33 34 36 36 0 0 0 0 3 4 4 804 32 73 78 78 0 0 0 0 2 4 4 805 32 77 78 78 0 0 0 0 2 4 4 806 31 32 33 33 0 0 0 0 2 4 4 807 31 33 37 37 0 0 0 0 2 4 4 808 31 37 58 58 0 0 0 0 2 4 4 809 31 32 77 77 0 0 0 0 2 4 4 810 31 58 77 77 0 0 0 0 2 4 4 811 30 32 33 33 0 0 0 0 2 4 4 812 30 33 34 34 0 0 0 0 2 4 4 813 30 34 114 114 0 0 0 0 2 4 4 814 30 111 114 114 0 0 0 0 2 4 4 815 30 32 73 73 0 0 0 0 2 4 4 816 30 73 111 111 0 0 0 0 2 4 4 817 28 68 98 98 0 0 0 0 2 4 4 818 28 70 74 74 0 0 0 0 2 4 4 819 28 74 98 98 0 0 0 0 2 4 4 820 27 70 71 71 0 0 0 0 2 4 4 821 27 28 68 68 0 0 0 0 2 4 4 822 27 28 70 70 0 0 0 0 2 4 4 823 27 59 71 71 0 0 0 0 2 4 4 824 27 59 80 80 0 0 0 0 1 4 4 825 27 68 80 80 0 0 0 0 1 4 4 826 26 93 100 100 0 0 0 0 2 4 4 827 26 84 93 93 0 0 0 0 1 4 4 828 26 84 85 85 0 0 0 0 1 4 4 829 24 26 85 85 0 0 0 0 1 4 4 830 24 85 87 87 0 0 0 0 1 4 4 831 23 24 26 26 0 0 0 0 2 4 4 832 23 26 100 100 0 0 0 0 2 4 4 833 23 100 144 144 0 0 0 0 2 4 4 834 21 23 24 24 0 0 0 0 2 4 4 835 21 141 143 143 0 0 0 0 2 4 4 836 21 143 144 144 0 0 0 0 2 4 4 837 21 23 144 144 0 0 0 0 2 4 4 838 20 21 24 24 0 0 0 0 2 4 4 839 20 24 87 87 0 0 0 0 2 4 4 840 86 88 20 20 0 0 0 0 2 4 4 841 20 21 141 141 0 0 0 0 2 4 4 842 20 88 141 141 0 0 0 0 2 4 4 843 19 94 95 95 0 0 0 0 1 4 4 844 19 95 96 96 0 0 0 0 1 4 4 845 17 93 99 99 0 0 0 0 2 4 4 846 17 19 94 94 0 0 0 0 1 4 4 847 17 94 93 93 0 0 0 0 1 4 4 848 15 126 127 127 0 0 0 0 2 4 4 849 14 17 99 99 0 0 0 0 2 4 4 850 14 15 126 126 0 0 0 0 2 4 4 851 14 99 126 126 0 0 0 0 2 4 4 852 13 96 97 97 0 0 0 0 2 4 4 853 13 123 127 127 0 0 0 0 2 4 4 854 13 15 127 127 0 0 0 0 2 4 4 855 13 97 123 123 0 0 0 0 2 4 4 856 12 13 15 15 0 0 0 0 2 4 4 857 12 14 15 15 0 0 0 0 2 4 4 858 12 13 96 96 0 0 0 0 2 4 4 859 12 96 19 19 0 0 0 0 1 4 4 860 12 14 17 17 0 0 0 0 2 4 4 861 12 17 19 19 0 0 0 0 1 4 4 862 10 116 120 120 0 0 0 0 2 4 4 863 10 106 116 116 0 0 0 0 3 4 4 864 10 119 120 120 0 0 0 0 2 4 4 865 10 119 128 128 0 0 0 0 2 4 4 866 10 107 128 128 0 0 0 0 3 4 4 867 10 106 107 107 0 0 0 0 3 4 4 868 9 116 117 117 0 0 0 0 2 4 4 869 9 109 116 116 0 0 0 0 2 4 4 870 9 108 110 110 0 0 0 0 2 4 4 871 9 108 109 109 0 0 0 0 2 4 4 872 9 117 122 122 0 0 0 0 2 4 4 873 9 110 122 122 0 0 0 0 2 4 4 874 8 129 130 130 0 0 0 0 3 4 4 875 131 8 130 130 0 0 0 0 3 4 4 876 5 133 134 134 0 0 0 0 2 4 4 877 5 129 133 133 0 0 0 0 3 4 4 878 5 8 129 129 0 0 0 0 3 4 4 879 4 131 132 132 0 0 0 0 2 4 4 880 4 132 139 139 0 0 0 0 2 4 4 881 140 4 139 139 0 0 0 0 2 4 4 882 2 5 134 134 0 0 0 0 2 4 4 883 2 140 142 142 0 0 0 0 2 4 4 884 2 134 142 142 0 0 0 0 2 4 4 885 1 2 140 140 0 0 0 0 2 4 4 886 1 2 5 5 0 0 0 0 2 4 4 887 1 4 131 131 0 0 0 0 2 4 4 888 1 140 4 4 0 0 0 0 2 4 4 889 1 131 8 8 0 0 0 0 3 4 4 890 1 5 8 8 0 0 0 0 3 4 4 dune-grid-2.11.0/doc/grids/starcd/tets.cel.license000066400000000000000000000002501511655130300216700ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/tets.vrt000066400000000000000000000271001511655130300203220ustar00rootroot00000000000000 1 0.000000000E+00 0.000000000E+00 10.0000000 2 0.000000000E+00 1.49654794 8.41558933 3 1.15857017 1.24117339 6.99171591 4 1.60551512 0.000000000E+00 8.43397713 5 0.000000000E+00 2.32225704 10.0000000 6 1.13024342 2.97605777 8.90089989 7 2.93301225 1.07788742 8.95551682 8 1.55966055 1.47966540 10.0000000 9 10.0000000 1.94282353 8.76041889 10 7.42684364 0.000000000E+00 10.0000000 11 6.96426249 1.19530904 8.88443565 12 10.0000000 0.000000000E+00 0.000000000E+00 13 10.0000000 1.58896255 2.07751179 14 8.41599083 0.000000000E+00 1.48142660 15 10.0000000 0.000000000E+00 2.03203130 16 6.99827528 1.20999467 1.07253337 17 7.48950672 0.000000000E+00 0.000000000E+00 18 8.82930851 3.05224919 1.26455879 19 8.32532024 1.81820035 0.000000000E+00 20 0.000000000E+00 1.67257524 1.62382591 21 0.000000000E+00 0.000000000E+00 2.57468581 22 1.20672870 1.24214709 3.08840489 23 1.78830504 0.000000000E+00 1.67532849 24 0.000000000E+00 0.000000000E+00 0.000000000E+00 25 2.75537205 1.10034990 1.12356722 26 2.48950648 0.000000000E+00 0.000000000E+00 27 10.0000000 10.0000000 0.000000000E+00 28 10.0000000 8.44137001 1.61406159 29 8.81998253 6.92112684 1.17901278 30 10.0000000 7.97260475 8.45784664 31 7.93431950 10.0000000 8.74523735 32 10.0000000 10.0000000 7.42326832 33 10.0000000 10.0000000 10.0000000 34 10.0000000 7.99323845 10.0000000 35 6.98649120 8.82458496 8.89939499 36 8.44958305 8.42397118 10.0000000 37 7.47357464 10.0000000 10.0000000 38 0.000000000E+00 8.58899403 1.53599942 39 1.20337498 8.94793034 2.97427988 40 0.000000000E+00 10.0000000 2.84223127 41 1.97584963 10.0000000 1.53409433 42 0.000000000E+00 10.0000000 0.000000000E+00 43 0.000000000E+00 8.35044956 0.000000000E+00 44 1.66123211 10.0000000 0.000000000E+00 45 0.000000000E+00 8.21871281 8.19205856 46 1.12787950 8.86521244 7.07907963 47 1.60769153 10.0000000 8.42316246 48 0.000000000E+00 10.0000000 10.0000000 49 3.23406506 8.83615112 8.84388638 50 2.47357440 10.0000000 10.0000000 51 1.59318435 8.33586979 10.0000000 52 4.00660086 10.0000000 7.78517056 53 1.89313138 10.0000000 6.54732418 54 4.98922300 10.0000000 10.0000000 55 0.000000000E+00 10.0000000 7.47816849 56 2.68002701 10.0000000 3.90251017 57 0.000000000E+00 10.0000000 4.96672058 58 5.80844593 10.0000000 7.94796276 59 8.07142925 10.0000000 0.000000000E+00 60 6.16204405 10.0000000 0.000000000E+00 61 6.74844837 10.0000000 1.60139418 62 4.07057714 10.0000000 2.02934551 63 6.88203573 8.68848515 1.42079759 64 3.00779009 8.80255795 1.09610403 65 6.19440031 7.64174604 0.000000000E+00 66 3.94601297 10.0000000 0.000000000E+00 67 3.92867708 6.97164011 0.000000000E+00 68 10.0000000 7.60696602 0.000000000E+00 69 10.0000000 5.20584869 0.000000000E+00 70 10.0000000 10.0000000 2.13407683 71 8.57629204 10.0000000 1.51681256 72 8.02047253 10.0000000 3.37849665 73 10.0000000 7.87377119 5.86426210 74 10.0000000 8.10535622 3.52292204 75 8.80000114 8.80000114 6.90000105 76 8.72433949 8.83987141 2.76590848 77 7.16869164 10.0000000 5.98282957 78 10.0000000 10.0000000 4.79882288 79 8.02823448 6.44250727 0.000000000E+00 80 8.04922581 8.65424728 0.000000000E+00 81 2.02731109 5.61833858 0.000000000E+00 82 1.95778430 8.13550282 0.000000000E+00 83 2.17145085 3.23269987 0.000000000E+00 84 3.50230122 2.00867105 0.000000000E+00 85 1.35888612 1.84810638 0.000000000E+00 86 0.000000000E+00 3.74978518 0.000000000E+00 87 0.000000000E+00 1.87489259 0.000000000E+00 88 0.000000000E+00 3.94941449 1.80813432 89 0.000000000E+00 6.65680599 1.96753502 90 1.17211449 7.08507013 1.11518502 91 1.20348549 2.98144245 0.944010556 92 0.000000000E+00 6.39392376 0.000000000E+00 93 4.97920370 0.000000000E+00 0.000000000E+00 94 6.04964590 2.48404908 0.000000000E+00 95 7.91456842 3.95645118 0.000000000E+00 96 10.0000000 2.60292435 0.000000000E+00 97 10.0000000 4.06607294 2.12958264 98 10.0000000 6.49966431 2.03808832 99 6.35103703 0.000000000E+00 1.86969745 100 3.93612862 0.000000000E+00 1.98314738 101 4.03501225 7.75156975 10.0000000 102 6.55409908 8.02587032 10.0000000 103 0.000000000E+00 7.90621138 3.52996778 104 0.000000000E+00 7.87890816 6.01767540 105 7.75575209 3.43535185 10.0000000 106 8.29084778 1.55309463 10.0000000 107 6.43232393 2.34896851 10.0000000 108 10.0000000 3.92183948 10.0000000 109 10.0000000 1.96091974 10.0000000 110 10.0000000 3.72795033 8.18437481 111 10.0000000 5.90519667 7.22368002 112 9.02934742 7.05062246 8.84568024 113 8.82636547 2.89779377 8.88405609 114 10.0000000 5.98440790 10.0000000 115 8.13744068 6.01869774 10.0000000 116 10.0000000 0.000000000E+00 10.0000000 117 10.0000000 0.000000000E+00 7.99969482 118 10.0000000 0.000000000E+00 6.12834740 119 5.97913551 0.000000000E+00 7.95006371 120 8.41434956 0.000000000E+00 7.98694372 121 7.67199850 0.000000000E+00 6.34847641 122 10.0000000 1.83562922 6.57133722 123 10.0000000 2.81703973 4.08338642 124 8.91795540 1.37191629 2.94239712 125 8.79729652 1.07926583 6.96087599 126 8.02214241 0.000000000E+00 3.57944870 127 10.0000000 0.000000000E+00 4.23809099 128 4.79789972 0.000000000E+00 10.0000000 129 1.88958800 3.16089773 10.0000000 130 3.73610783 2.04862523 10.0000000 131 2.39894986 0.000000000E+00 10.0000000 132 3.97427392 0.000000000E+00 8.08608532 133 0.000000000E+00 4.63806581 10.0000000 134 0.000000000E+00 3.32029295 8.17760944 135 0.000000000E+00 6.30901098 7.68137646 136 1.19473934 6.92839336 8.84245300 137 0.000000000E+00 7.31903267 10.0000000 138 2.52710199 5.77475309 10.0000000 139 2.25195789 0.000000000E+00 6.48607635 140 0.000000000E+00 0.000000000E+00 7.57468605 141 0.000000000E+00 2.62808752 3.52927375 142 0.000000000E+00 2.12409019 6.25725651 143 0.000000000E+00 0.000000000E+00 5.19546890 144 2.59649396 0.000000000E+00 3.53847337 145 4.55413008 10.0000000 6.06727791 146 6.90821218 6.77467299 6.85163260 147 3.31563687 6.98626804 7.01660728 148 3.21317530 6.87527180 2.91819477 149 1.48926103 1.58688402 4.87503242 150 1.36986363 5.17113209 8.59394360 151 3.10595846 3.36738420 6.95517015 152 5.09373188 1.55999589 8.66626072 153 8.41304111 1.39718020 4.82986069 154 8.69301414 5.06768513 8.86409283 155 6.93553448 3.17826939 6.92324018 156 4.45471382 0.000000000E+00 5.92565680 157 10.0000000 5.69262314 4.38867998 158 0.000000000E+00 5.65254879 4.39879990 159 5.75746298 5.31525564 10.0000000 160 4.66005993 1.47689533 1.22099698 161 6.94719696 3.20131588 3.26169825 162 8.39352798 4.96263790 1.74032128 163 1.37330735 4.79903316 1.49719834 164 2.88592362 3.05078816 2.97639489 165 4.13698626 4.27793026 0.000000000E+00 166 8.72076321 8.69751263 5.03059530 167 6.78730869 6.90066195 3.12485886 168 4.97662687 8.87991714 1.32755280 169 5.00493050 8.10273933 8.38723278 170 1.16007841 8.47624016 4.79141283 171 1.20041227 8.70730782 8.79639530 172 1.30768871 8.80207825 1.25076294 173 8.80751038 8.74936581 8.74693775 174 8.74072647 8.74072647 1.25758827 175 1.30563557 1.20799983 1.21795130 176 8.80000114 1.20000100 1.20000100 177 8.69338322 1.22799993 8.76845360 178 1.27107096 1.27107072 8.72684860 179 4.96773386 4.95511484 5.05163431 180 5.59149981 10.0000000 3.90475464 181 5.29026508 0.000000000E+00 3.83828521 182 10.0000000 4.17231035 5.92008829 183 0.000000000E+00 4.34811735 5.69604588 184 3.92856693 3.68189144 10.0000000 185 6.10314560 5.41362190 0.000000000E+00 dune-grid-2.11.0/doc/grids/starcd/tets.vrt.license000066400000000000000000000002501511655130300217400ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/withprism.cel000066400000000000000000000003261511655130300213220ustar00rootroot00000000000000 1 1 2 3 4 5 6 7 8 7 1 1 2 5 6 9 9 8 7 10 10 7 1 1 dune-grid-2.11.0/doc/grids/starcd/withprism.cel.license000066400000000000000000000002501511655130300227370ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/withprism.vrt000066400000000000000000000003511511655130300213700ustar00rootroot00000000000000 1 0 0 0 2 2 0 0 3 2 2 0 4 0 2 0 5 0 0 1 6 2 0 1 7 2 2 1 8 0 2 1 9 1 0 2 10 1 2 2 dune-grid-2.11.0/doc/grids/starcd/withprism.vrt.license000066400000000000000000000002501511655130300230070ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/withpyramid.cel000066400000000000000000000003261511655130300216350ustar00rootroot00000000000000 1 1 2 3 4 5 6 7 8 7 1 1 2 5 6 7 8 9 9 9 9 7 1 1 dune-grid-2.11.0/doc/grids/starcd/withpyramid.cel.license000066400000000000000000000002501511655130300232520ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/grids/starcd/withpyramid.vrt000066400000000000000000000003231511655130300217020ustar00rootroot00000000000000 1 0 0 0 2 2 0 0 3 2 2 0 4 0 2 0 5 0 0 1 6 2 0 1 7 2 2 1 8 0 2 1 9 1 1 2 dune-grid-2.11.0/doc/grids/starcd/withpyramid.vrt.license000066400000000000000000000002501511655130300233220ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/doc/recipes/000077500000000000000000000000001511655130300156505ustar00rootroot00000000000000dune-grid-2.11.0/doc/recipes/CMakeLists.txt000066400000000000000000000005021511655130300204050ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune_add_test(SOURCES recipe-iterate-over-grid.cc LINK_LIBRARIES Dune::Grid) dune_add_test(SOURCES recipe-integration.cc LINK_LIBRARIES Dune::Grid) dune-grid-2.11.0/doc/recipes/mainpage.txt000066400000000000000000000010051511655130300201660ustar00rootroot00000000000000// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /** * @defgroup grid_recipes dune-grid recipes * @{ * \page all_grid_recipes dune-grid recipes * These recipes are short examples on how to achieve common tasks in dune-grid. * * Some simple examples illustrating the grid interface * ============== * - \subpage recipe-iterate-over-grid * - \subpage recipe-integration * * @} */ dune-grid-2.11.0/doc/recipes/recipe-integration.cc000066400000000000000000000120761511655130300217550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file COPYING in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /** * \page recipe-integration Integrate a function on a grid * * A fundamental task in any PDE solver is integration of a function over a domain given by a grid: * \f[ * I = \int_\Omega u(x)\,dx = \sum_{e\in E^0} \int_e u(x)\,dx * \f] * Here we demonstrate how this can be done for a user-defined function in global coordinates. * * As always we need to set up a grid first. Here we use the \ref Dune::YaspGrid class in * four dimensions in order to demonstrate that even dimension larger than three * can be used. * \snippet recipe-integration.cc set up grid * * The Dune grid interface employs the class templates Dune::FieldVector and Dune::FieldMatrix to * for small vectors and matrices of compile-time known * size in many places, for example to represent positions and Jacobians of certain maps. * Here is a small tutorial in the usage of these classes: * \snippet recipe-integration.cc small vectors and matrices * * Next we define the function to integrate as a generic lambda function. We expect * the argument x to be an instance of type Dune::FieldVector: * \snippet recipe-integration.cc a function to integrate * * First we demonstrate how to compute an approximation to the * integral by using the simple midpoint rule. This means traversing all elements, * evaluate the function at the barycenter of the element, multiplying with the * volume of the element and summing up: * \snippet recipe-integration.cc integration with midpoint rule * * A more accurate approximation of the integral for sufficiently smooth functions * can be computed by quadrature rules. These are available in Dune for all the different * element types and various integration orders. This simply requires an additional * loop over the quadrature points within an element: * \snippet recipe-integration.cc integration with quadrature rule * * For integrating the divergence of a vector field \f$f\f$ we might use the following formula: * \f[ * I = \int_\Omega \nabla\cdot f(x)\,dx = \int_{\partial \Omega} f(x)\cdot n(x) \,ds = \sum_{e\in E^0} \int_{\partial e\cap \partial \Omega} f(x)\cdot n(x) \,ds. * \f] * This is implemented by the following snippet illustrating the use of intersections: * \snippet recipe-integration.cc integrating a flux * * Full example code: @ref recipe-integration.cc * \example recipe-integration.cc * See explanation at @ref recipe-integration */ // C++ includes #include #include // dune-common includes #include #include #include // dune-geometry includes #include #include // dune-grid includes #include int main(int argc, char** argv) { // Maybe initialize Mpi [[maybe_unused]] Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv); // [set up grid] const int dim = 4; using Grid = Dune::YaspGrid; Dune::FieldVector len; for (auto& l:len) l=1.0; std::array cells; for (auto& c : cells) c=5; Grid grid(len,cells); //! [set up grid] // [small vectors and matrices] Dune::FieldVector x({1,2,3,4}); // make a vector auto y(x); // copy constructor y *= 1.0/3.0; // scaling [[maybe_unused]] auto s = x*y; // scalar product [[maybe_unused]] auto norm = x.two_norm(); // Euclidean norm Dune::FieldMatrix A({{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}); // make a matrix A.mv(x,y); // matvec: y = Ax A.usmv(0.5,x,y); // axpy: y += 0.5*Ax //! [small vectors and matrices] // [a function to integrate] auto u = [](const auto& x){return std::exp(x.two_norm());}; //! [a function to integrate] // [integration with midpoint rule] double integral=0.0; auto gv = grid.leafGridView(); // extract the grid view for (const auto& e : elements(gv)) integral += u(e.geometry().center())*e.geometry().volume(); std::cout << "integral = " << integral << std::endl; //! [integration with midpoint rule] // [integration with quadrature rule] double integral2 = 0.0; using QR = Dune::QuadratureRules; for (const auto& e : elements(gv)) { auto geo = e.geometry(); auto quadrature = QR::rule(geo.type(),5); for (const auto& qp : quadrature) integral2 += u(geo.global(qp.position())) *geo.integrationElement(qp.position())*qp.weight(); } std::cout << "integral2 = " << integral2 << std::endl; //! [integration with quadrature rule] // [integrating a flux] auto f = [](const auto& x){return x;}; double divergence=0.0; for (const auto& i : elements(gv)) { for (const auto& I : intersections(gv,i)) if (!I.neighbor()) { auto geoI = I.geometry(); divergence += f(geoI.center())*I.centerUnitOuterNormal()*geoI.volume(); } } std::cout << "divergence = " << divergence << std::endl; //! [integrating a flux] } dune-grid-2.11.0/doc/recipes/recipe-iterate-over-grid.cc000066400000000000000000000065411511655130300227630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file COPYING in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /** * \page recipe-iterate-over-grid Iterating over a grid * * A fundamental task in many finite element-type discretizations is iterating * over the elements of a grid, for example in order to numerically compute integrals * on it. All DUNE grids provide a unified interface for this and related operations. * * First, we set up a simple structured grid. Here we use the \ref Dune::YaspGrid class in * four dimensions in order to demonstrate that even dimension larger than three * can be used. * \snippet recipe-iterate-over-grid.cc set up grid * * Grids in Dune are hierarchical, i.e. they are organized into levels * (originating from refinement) and entities that are not further refined. * Each of these subsets is accessible via Dune::GridView and iteration over * is possible only over grid views. So we extract the Dune::LeafGridView: * \snippet recipe-iterate-over-grid.cc extract gridview * * Now we can iterate over all the entities of a certain codimension in a grid view * using a range-based for loop: * \snippet recipe-iterate-over-grid.cc iterate over codim * As an example we extract the type of an element and test for it to be a cube. * * Instead of specifying the codimension explicitly you can also * use the following predefined names in the range-based for loop: * \snippet recipe-iterate-over-grid.cc iterate over grid view * * Finally, from entities of codimension 0 (aka elements) you can access * all subentities of all codimensions using the following code: * \snippet recipe-iterate-over-grid.cc access to subentities * * Full example code: @ref recipe-iterate-over-grid.cc * \example recipe-iterate-over-grid.cc * See explanation at @ref recipe-iterate-over-grid */ // C++ includes #include #include // dune-common includes #include #include #include // dune-grid includes #include int main(int argc, char** argv) { // Maybe initialize Mpi [[maybe_unused]] Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv); // [set up grid] const int dim = 4; using Grid = Dune::YaspGrid; Dune::FieldVector len; for (auto& l : len) l=1.0; std::array cells; for (auto& c : cells) c=4; Grid grid(len,cells); //! [set up grid] // [extract gridview] auto gv = grid.leafGridView(); //! [extract gridview] // [iterate over codim] const int codim = 2; for (const auto& e : entities(gv,Dune::Codim{})) if (!e.type().isCube()) std::cout << "not a cube" << std::endl; //! [iterate over codim] // [iterate over grid view] for ([[maybe_unused]] const auto& e : elements(gv)) ; // codim=0 for ([[maybe_unused]] const auto& e : vertices(gv)) ; // codim=dim for ([[maybe_unused]] const auto& e : edges(gv)) ; // codim=dim-1 for ([[maybe_unused]] const auto& e : facets(gv)) ; // codim=1 //! [iterate over grid view] // [access to subentities] const int mycodim = 2; for (const auto& e : elements(gv)) for (unsigned int i=0; i(i); //! [access to subentities] } dune-grid-2.11.0/dune-grid.pc.in000066400000000000000000000007071511655130300162640ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ CXX=@CXX@ CC=@CC@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ Description: @DESCRIPTION@ URL: @URL@ Requires: ${DEPENDENCIES} Libs: -L${libdir} -ldunegrid Cflags: -I${includedir} dune-grid-2.11.0/dune.module000066400000000000000000000010051511655130300156070ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception Module: dune-grid Version: 2.11 Author: The Dune Core developers Maintainer: dune-devel@lists.dune-project.org Description: module providing main interfaces for setting and traversing grids URL: https://gitlab.dune-project.org/core/dune-grid Python-Requires: Depends: dune-geometry (>= 2.11) Suggests: dune-uggrid (>=2.11) Whitespace-Hook: Yes dune-grid-2.11.0/dune/000077500000000000000000000000001511655130300144045ustar00rootroot00000000000000dune-grid-2.11.0/dune/CMakeLists.txt000066400000000000000000000005171511655130300171470ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(grid) # if Python bindings are enabled, include necessary sub directories. if( DUNE_ENABLE_PYTHONBINDINGS ) add_subdirectory("python") endif() dune-grid-2.11.0/dune/grid/000077500000000000000000000000001511655130300153315ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/CMakeLists.txt000066400000000000000000000012011511655130300200630ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(albertagrid) add_subdirectory(common) add_subdirectory(concepts) add_subdirectory(geometrygrid) add_subdirectory(identitygrid) add_subdirectory(io) add_subdirectory(onedgrid) add_subdirectory(test) add_subdirectory(uggrid) add_subdirectory(utility) add_subdirectory(yaspgrid) install(FILES albertagrid.hh concepts.hh geometrygrid.hh identitygrid.hh onedgrid.hh uggrid.hh yaspgrid.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid) dune-grid-2.11.0/dune/grid/albertagrid.hh000066400000000000000000000007621511655130300201370ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRID_HH #define DUNE_ALBERTAGRID_HH #include "albertagrid/agrid.hh" #include "albertagrid/gridfactory.hh" #include "albertagrid/structuredgridfactory.hh" #include "albertagrid/persistentcontainer.hh" #endif dune-grid-2.11.0/dune/grid/albertagrid/000077500000000000000000000000001511655130300176115ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/albertagrid/CMakeLists.txt000066400000000000000000000024261511655130300223550ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(test) if(Alberta_FOUND) foreach(_dim ${ALBERTA_WORLD_DIMS}) target_sources(dunealbertagrid${_dim}d PRIVATE dgfparser.cc elementinfo.cc indexsets.cc macrodata.cc meshpointer.cc) endforeach(_dim) endif() #install header set(HEADERS agrid.hh albertagrid.cc albertaheader.hh indexsets.hh indexstack.hh datahandle.hh misc.hh macroelement.hh elementinfo.hh geometrycache.hh meshpointer.hh macrodata.hh dofadmin.hh dofvector.hh refinement.hh coordcache.hh level.hh undefine-2.0.hh undefine-3.0.hh entity.hh entity.cc entityseed.hh hierarchiciterator.hh algebra.hh geometry.hh geometry.cc projection.hh transformation.hh leveliterator.hh leafiterator.hh treeiterator.hh intersection.hh intersection.cc intersectioniterator.hh capabilities.hh gridfactory.hh dgfparser.hh albertareader.hh gridfamily.hh gridview.hh persistentcontainer.hh backuprestore.hh structuredgridfactory.hh geometryreference.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/albertagrid/) dune-grid-2.11.0/dune/grid/albertagrid/agrid.hh000066400000000000000000000536151511655130300212320ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRID_IMP_HH #define DUNE_ALBERTAGRID_IMP_HH /** \file * \author Robert Kloefkorn and Martin Nolte * \brief provides the AlbertaGrid class */ #if HAVE_ALBERTA || DOXYGEN #include #include #include #include #include #include #include // Dune includes #include #include #include #include #include #include #include #include //- Local includes // some cpp defines and include of alberta.h #include "albertaheader.hh" #include #include #include #include #include #include #include #include #include #include #include "indexsets.hh" #include "geometry.hh" #include "entity.hh" #include "hierarchiciterator.hh" #include "treeiterator.hh" #include "leveliterator.hh" #include "leafiterator.hh" namespace Dune { // External Forward Declarations // ----------------------------- template< class Grid > struct DGFGridFactory; // AlbertaGrid // ----------- /** \class AlbertaGrid * \brief [ provides \ref Dune::Grid ] * \brief Simplicial grid implementation from the ALBERTA finite element * toolbox * \ingroup GridImplementations * \ingroup AlbertaGrid * * AlbertaGrid provides access to the grid from the ALBERTA finite element * toolbox through the %Dune interface. * * ALBERTA is a finite element toolbox written by Alfred Schmidt and * Kunibert G. Siebert (see http://www.alberta-fem.de). It contains a * simplicial mesh in 1, 2 and 3 space dimensions that can be dynamically * adapted by a bisection algorithm. * * Supported ALBERTA versions include 3.0 or higher. * It can be downloaded from the ALBERTA website * (https://gitlab.mathematik.uni-stuttgart.de/ians-nmh/alberta/alberta3). * * After installing ALBERTA, just configure DUNE with the cmake option * -DAlberta_ROOT=[path/to/alberta] and provide the path to ALBERTA. * * Each program linking to ALBERTA only supports a fixed dimension of world. * This is obtained from the ALBERTA_DIM preprocessor variable. This * variable and all other necessary link flags and libraries are set by the * cmake function add_dune_alberta_flags(WORLDDIM [N] [targets]...) * with N the world dimension. * * CMake sets the compile flag HAVE_ALBERTA that tells you whether * ALBERTA was found, and ALBERTA_DIM compile flags which tells you the * dimension of world for this program. */ template< int dim, int dimworld = Alberta::dimWorld > class AlbertaGrid : public GridDefaultImplementation < dim, dimworld, Alberta::Real, AlbertaGridFamily< dim, dimworld > > { typedef AlbertaGrid< dim, dimworld > This; typedef GridDefaultImplementation < dim, dimworld, Alberta::Real, AlbertaGridFamily< dim, dimworld > > Base; template< int, int, class > friend class AlbertaGridEntity; template< class > friend class AlbertaLevelGridView; template< class > friend class AlbertaLeafGridView; template< int, class, bool > friend class AlbertaGridTreeIterator; template< class > friend class AlbertaGridHierarchicIterator; friend class GridFactory< This >; friend struct DGFGridFactory< This >; friend class AlbertaGridIntersectionBase< const This >; friend class AlbertaGridLeafIntersection< const This >; friend class AlbertaMarkerVector< dim, dimworld >; #if (__GNUC__ < 4) && !(defined __ICC) // add additional friend decls for gcc 3.4 friend struct AlbertaMarkerVector< dim, dimworld >::MarkSubEntities; friend struct AlbertaMarkerVector< dim, dimworld >::MarkSubEntities; #endif friend class AlbertaGridIndexSet< dim, dimworld >; friend class AlbertaGridHierarchicIndexSet< dim, dimworld >; template< class, class > friend class Alberta::AdaptRestrictProlongHandler; public: //! the grid family of AlbertaGrid typedef AlbertaGridFamily< dim, dimworld > GridFamily; typedef typename GridFamily::ctype ctype; static const int dimension = GridFamily::dimension; static const int dimensionworld = GridFamily::dimensionworld; // the Traits typedef typename AlbertaGridFamily< dim, dimworld >::Traits Traits; //! type of leaf index set typedef typename Traits::LeafIndexSet LeafIndexSet; //! type of level index sets typedef typename Traits::LevelIndexSet LevelIndexSet; //! type of hierarchic index set typedef typename Traits::HierarchicIndexSet HierarchicIndexSet; //! type of global id set typedef typename Traits::GlobalIdSet GlobalIdSet; //! type of local id set typedef typename Traits::LocalIdSet LocalIdSet; //! type of communication typedef typename Traits::Communication Communication; private: //! type of LeafIterator typedef typename Traits::template Codim<0>::LeafIterator LeafIterator; //! id set impl typedef AlbertaGridIdSet IdSetImp; //! AdaptationState struct AdaptationState { enum Phase { ComputationPhase, PreAdaptationPhase, PostAdaptationPhase }; private: Phase phase_; int coarsenMarked_; int refineMarked_; public: AdaptationState () : phase_( ComputationPhase ), coarsenMarked_( 0 ), refineMarked_( 0 ) {} void mark ( int count ) { if( count < 0 ) ++coarsenMarked_; if( count > 0 ) refineMarked_ += (2 << count); } void unmark ( int count ) { if( count < 0 ) --coarsenMarked_; if( count > 0 ) refineMarked_ -= (2 << count); } bool coarsen () const { return (coarsenMarked_ > 0); } int refineMarked () const { return refineMarked_; } void preAdapt () { if( phase_ != ComputationPhase ) error( "preAdapt may only be called in computation phase." ); phase_ = PreAdaptationPhase; } void adapt () { if( phase_ != PreAdaptationPhase ) error( "adapt may only be called in preadapdation phase." ); phase_ = PostAdaptationPhase; } void postAdapt () { if( phase_ != PostAdaptationPhase ) error( "postAdapt may only be called in postadaptation phase." ); phase_ = ComputationPhase; coarsenMarked_ = 0; refineMarked_ = 0; } private: void error ( const std::string &message ) { DUNE_THROW( InvalidStateException, message ); } }; template< class DataHandler > struct AdaptationCallback; // max number of allowed levels is 64 static const int MAXL = 64; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef Alberta::MeshPointer< dimension > MeshPointer; typedef Alberta::HierarchyDofNumbering< dimension > DofNumbering; typedef AlbertaGridLevelProvider< dimension > LevelProvider; public: AlbertaGrid ( const This & ) = delete; This &operator= ( const This & ) = delete; /** \brief create an empty grid */ AlbertaGrid (); /** \brief create a grid from an ALBERTA macro data structure * * \param[in] macroData macro data to create grid from * \param[in] projection shared pointer to a global boundary projection (defaults to 0) */ AlbertaGrid ( const Alberta::MacroData< dimension > ¯oData, const std::shared_ptr< DuneBoundaryProjection< dimensionworld > > &projection = std::shared_ptr< DuneBoundaryProjection< dimensionworld > >() ); template< class Proj, class Impl > AlbertaGrid ( const Alberta::MacroData< dimension > ¯oData, const Alberta::ProjectionFactoryInterface< Proj, Impl > &projectionFactory ); /** \brief create a grid from an ALBERTA macro grid file * * \param[in] macroGridFileName name of the macro grid file */ AlbertaGrid ( const std::string ¯oGridFileName ); /** \brief destructor */ ~AlbertaGrid (); //! Return maximum level defined in this grid. Levels are numbered //! 0 ... maxLevel with 0 the coarsest level. int maxLevel () const; //! Iterator to first entity of given codim on level template typename Traits::template Codim::template Partition::LevelIterator lbegin (int level) const; //! one past the end on this level template typename Traits::template Codim::template Partition::LevelIterator lend (int level) const; //! Iterator to first entity of given codim on level template< int codim > typename Traits::template Codim< codim >::LevelIterator lbegin ( int level ) const; //! one past the end on this level template< int codim > typename Traits::template Codim< codim >::LevelIterator lend ( int level ) const; //! return LeafIterator which points to first leaf entity template< int codim, PartitionIteratorType pitype > typename Traits ::template Codim< codim >::template Partition< pitype >::LeafIterator leafbegin () const; //! return LeafIterator which points behind last leaf entity template< int codim, PartitionIteratorType pitype > typename Traits ::template Codim< codim >::template Partition< pitype >::LeafIterator leafend () const; //! return LeafIterator which points to first leaf entity template< int codim > typename Traits::template Codim< codim >::LeafIterator leafbegin () const; //! return LeafIterator which points behind last leaf entity template< int codim > typename Traits::template Codim< codim >::LeafIterator leafend () const; /** \brief Number of grid entities per level and codim * because lbegin and lend are none const, and we need this methods * counting the entities on each level, you know. */ int size (int level, int codim) const; //! number of entities per level and geometry type in this process int size (int level, GeometryType type) const; //! number of leaf entities per codim in this process int size (int codim) const; //! number of leaf entities per geometry type in this process int size (GeometryType type) const; //! number of boundary segments within the macro grid std::size_t numBoundarySegments () const { return numBoundarySegments_; } //! View for a grid level for All_Partition typename Traits::LevelGridView levelGridView ( int level ) const { typedef typename Traits::LevelGridView View; typedef typename View::GridViewImp ViewImp; return View( ViewImp( *this, level ) ); } //! View for the leaf grid for All_Partition typename Traits::LeafGridView leafGridView () const { typedef typename Traits::LeafGridView View; typedef typename View::GridViewImp ViewImp; return View( ViewImp( *this ) ); } public: //*************************************************************** // Interface for Adaptation //*************************************************************** using Base::getMark; using Base::mark; /** \copydoc Dune::Grid::getMark() */ int getMark ( const typename Traits::template Codim< 0 >::Entity &e ) const; /** \copydoc Dune::Grid::mark() */ bool mark ( int refCount, const typename Traits::template Codim< 0 >::Entity &e ); //! uses the interface, mark on entity and refineLocal void globalRefine ( int refCount ); template< class DataHandle > void globalRefine ( int refCount, AdaptDataHandleInterface< This, DataHandle > &handle ); /** \copydoc Dune::Grid::adapt() */ bool adapt (); //! callback adapt method with AdaptDataHandleInterface template< class DataHandle > bool adapt ( AdaptDataHandleInterface< This, DataHandle > &handle ); //! returns true, if a least one element is marked for coarsening bool preAdapt (); //! clean up some markers void postAdapt(); /** \brief return reference to communication, if MPI found * this is specialisation for MPI */ const Communication &comm () const { return comm_; } static std::string typeName () { std::ostringstream s; s << "AlbertaGrid< " << dim << ", " << dimworld << " >"; return s.str(); } /** \brief obtain Entity from EntitySeed. */ template< class EntitySeed > typename Traits::template Codim< EntitySeed::codimension >::Entity entity ( const EntitySeed &seed ) const { typedef typename Traits::template Codim< EntitySeed::codimension >::EntityImpl EntityImpl; return EntityImpl( *this, seed.impl().elementInfo( meshPointer() ), seed.impl().subEntity() ); } //********************************************************** // End of Interface Methods //********************************************************** /** \brief write Grid to file in Xdr */ bool writeGrid( const std::string &filename, ctype time ) const; /** \brief read Grid from file filename and store time of mesh in time */ bool readGrid( const std::string &filename, ctype &time ); // return hierarchic index set const HierarchicIndexSet & hierarchicIndexSet () const { return hIndexSet_; } //! return level index set for given level const typename Traits :: LevelIndexSet & levelIndexSet (int level) const; //! return leaf index set const typename Traits :: LeafIndexSet & leafIndexSet () const; //! return global IdSet const GlobalIdSet &globalIdSet () const { return idSet_; } //! return local IdSet const LocalIdSet &localIdSet () const { return idSet_; } // access to mesh pointer, needed by some methods ALBERTA MESH* getMesh () const { return mesh_; }; const MeshPointer &meshPointer () const { return mesh_; } const DofNumbering &dofNumbering () const { return dofNumbering_; } const LevelProvider &levelProvider () const { return levelProvider_; } int dune2alberta ( int codim, int i ) const { return numberingMap_.dune2alberta( codim, i ); } int alberta2dune ( int codim, int i ) const { return numberingMap_.alberta2dune( codim, i ); } int generic2alberta ( int codim, int i ) const { return genericNumberingMap_.dune2alberta( codim, i ); } int alberta2generic ( int codim, int i ) const { return genericNumberingMap_.alberta2dune( codim, i ); } private: typedef std::vector ArrayType; void setup (); // make the calculation of indexOnLevel and so on. // extra method because of Reihenfolge void calcExtras(); private: // delete mesh and all vectors void removeMesh(); //*********************************************************************** // MemoryManagement for Entities and Geometries //********************************************************************** typedef MakeableInterfaceObject< typename Traits::template Codim< 0 >::Entity > EntityObject; public: friend class AlbertaGridLeafIntersectionIterator< const This >; template< int codim > static int getTwist ( const typename Traits::template Codim< codim >::Entity &entity ) { return entity.impl().twist(); } template< int codim > static int getTwist ( const typename Traits::template Codim< 0 >::Entity &entity, int subEntity ) { return entity.impl().template twist< codim >( subEntity ); } static int getTwistInInside ( const typename Traits::LeafIntersection &intersection ) { return intersection.impl().twistInInside(); } static int getTwistInOutside ( const typename Traits::LeafIntersection &intersection ) { return intersection.impl().twistInOutside(); } public: // read global element number from elNumbers_ const Alberta::GlobalVector & getCoord ( const ElementInfo &elementInfo, int vertex ) const; private: // pointer to an Albert Mesh, which contains the data MeshPointer mesh_; // communication Communication comm_; // maximum level of the mesh int maxlevel_; // number of boundary segments within the macro grid size_t numBoundarySegments_; // map between ALBERTA and DUNE numbering Alberta::NumberingMap< dimension, Alberta::Dune2AlbertaNumbering > numberingMap_; Alberta::NumberingMap< dimension, Alberta::Generic2AlbertaNumbering > genericNumberingMap_; DofNumbering dofNumbering_; LevelProvider levelProvider_; // hierarchical numbering of AlbertaGrid, unique per codim HierarchicIndexSet hIndexSet_; // the id set of this grid IdSetImp idSet_; // the level index set, is generated from the HierarchicIndexSet // is generated, when accessed mutable std::vector< typename GridFamily::LevelIndexSetImp * > levelIndexVec_; // the leaf index set, is generated from the HierarchicIndexSet // is generated, when accessed mutable typename GridFamily::LeafIndexSetImp* leafIndexSet_; SizeCache< This > sizeCache_; typedef AlbertaMarkerVector< dim, dimworld > MarkerVector; // needed for VertexIterator, mark on which element a vertex is treated mutable MarkerVector leafMarkerVector_; // needed for VertexIterator, mark on which element a vertex is treated mutable std::vector< MarkerVector > levelMarkerVector_; #if DUNE_ALBERTA_CACHE_COORDINATES Alberta::CoordCache< dimension > coordCache_; #endif // current state of adaptation AdaptationState adaptationState_; }; } // namespace Dune #include "albertagrid.cc" // undef all dangerous defines #undef DIM #undef DIM_OF_WORLD #ifdef _ABS_NOT_DEFINED_ #undef ABS #endif #ifdef _MIN_NOT_DEFINED_ #undef MIN #endif #ifdef _MAX_NOT_DEFINED_ #undef MAX #endif #ifdef obstack_chunk_alloc #undef obstack_chunk_alloc #endif #ifdef obstack_chunk_free #undef obstack_chunk_free #endif #include // We use MEM_ALLOC, so undefine it here. #undef MEM_ALLOC // We use MEM_REALLOC, so undefine it here. #undef MEM_REALLOC // We use MEM_CALLOC, so undefine it here. #undef MEM_CALLOC // We use MEM_FREE, so undefine it here. #undef MEM_FREE // Macro ERROR may be defined by alberta_util.h. If so, undefine it. #ifdef ERROR #undef ERROR #endif // #ifdef ERROR // Macro ERROR_EXIT may be defined by alberta_util.h. If so, undefine it. #ifdef ERROR_EXIT #undef ERROR_EXIT #endif // #ifdef ERROR_EXIT // Macro WARNING may be defined by alberta_util.h. If so, undefine it. #ifdef WARNING #undef WARNING #endif // #ifdef WARNING // Macro TEST may be defined by alberta_util.h. If so, undefine it. #ifdef TEST #undef TEST #endif // #ifdef TEST // Macro TEST_EXIT may be defined by alberta_util.h. If so, undefine it. #ifdef TEST_EXIT #undef TEST_EXIT #endif // #ifdef TEST_EXIT // Macro DEBUG_TEST may be defined by alberta_util.h. If so, undefine it. #ifdef DEBUG_TEST #undef DEBUG_TEST #endif // #ifdef DEBUG_TEST // Macro DEBUG_TEST_EXIT may be defined by alberta_util.h. If so, undefine it. #ifdef DEBUG_TEST_EXIT #undef DEBUG_TEST_EXIT #endif // #ifdef DEBUG_TEST_EXIT // Macro INFO may be defined by alberta_util.h. If so, undefine it. #ifdef INFO #undef INFO #endif // #ifdef INFO // Macro PRINT_INFO may be defined by alberta_util.h. If so, undefine it. #ifdef PRINT_INFO #undef PRINT_INFO #endif // #ifdef PRINT_INFO // Macro PRINT_INT_VEC may be defined by alberta_util.h. If so, undefine it. #ifdef PRINT_INT_VEC #undef PRINT_INT_VEC #endif // #ifdef PRINT_INT_VEC // Macro PRINT_REAL_VEC may be defined by alberta_util.h. If so, undefine it. #ifdef PRINT_REAL_VEC #undef PRINT_REAL_VEC #endif // #ifdef PRINT_REAL_VEC // Macro WAIT may be defined by alberta_util.h. If so, undefine it. #ifdef WAIT #undef WAIT #endif // #ifdef WAIT // Macro WAIT_REALLY may be defined by alberta_util.h. If so, undefine it. #ifdef WAIT_REALLY #undef WAIT_REALLY #endif // #ifdef WAIT_REALLY // Macro GET_WORKSPACE may be defined by alberta_util.h. If so, undefine it. #ifdef GET_WORKSPACE #undef GET_WORKSPACE #endif // #ifdef GET_WORKSPACE // Macro FREE_WORKSPACE may be defined by alberta_util.h. If so, undefine it. #ifdef FREE_WORKSPACE #undef FREE_WORKSPACE #endif // #ifdef FREE_WORKSPACE // Macro MAT_ALLOC may be defined by alberta_util.h. If so, undefine it. #ifdef MAT_ALLOC #undef MAT_ALLOC #endif // #ifdef MAT_ALLOC // Macro MAT_FREE may be defined by alberta_util.h. If so, undefine it. #ifdef MAT_FREE #undef MAT_FREE #endif // #ifdef MAT_FREE // Macro NAME may be defined by alberta_util.h. If so, undefine it. #ifdef NAME #undef NAME #endif // #ifdef NAME // Macro GET_STRUCT may be defined by alberta_util.h. If so, undefine it. #ifdef GET_STRUCT #undef GET_STRUCT #endif // #ifdef GET_STRUCT // Macro ADD_PARAMETER may be defined by alberta_util.h. If so, undefine it. #ifdef ADD_PARAMETER #undef ADD_PARAMETER #endif // #ifdef ADD_PARAMETER // Macro GET_PARAMETER may be defined by alberta_util.h. If so, undefine it. #ifdef GET_PARAMETER #undef GET_PARAMETER #endif // #ifdef GET_PARAMETER #define _ALBERTA_H_ #endif // HAVE_ALBERTA || DOXYGEN #endif dune-grid-2.11.0/dune/grid/albertagrid/albertagrid.cc000066400000000000000000000443541511655130300224120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRID_CC #define DUNE_ALBERTAGRID_CC //************************************************************************ // // implementation of AlbertaGrid // // namespace Dune // //************************************************************************ #include "geometry.cc" #include "entity.cc" #include "intersection.cc" namespace Dune { namespace Alberta { static void *adaptationDataHandler_; } template< int dim, int dimworld > static void checkAlbertaDimensions () { // If this check fails, define ALBERTA_DIM accordingly static_assert((dimworld == Alberta::dimWorld), "Template Parameter dimworld does not match " "ALBERTA's DIM_OF_WORLD setting."); } // AlbertaGrid // ----------- template< int dim, int dimworld > inline AlbertaGrid < dim, dimworld >::AlbertaGrid () : mesh_(), maxlevel_( 0 ), numBoundarySegments_( 0 ), hIndexSet_( dofNumbering_ ), idSet_( hIndexSet_ ), levelIndexVec_( (size_t)MAXL, 0 ), leafIndexSet_( 0 ), sizeCache_( *this ), leafMarkerVector_( dofNumbering_ ), levelMarkerVector_( (size_t)MAXL, MarkerVector( dofNumbering_ ) ) { checkAlbertaDimensions< dim, dimworld>(); } template< int dim, int dimworld > template< class Proj, class Impl > inline AlbertaGrid< dim, dimworld > ::AlbertaGrid ( const Alberta::MacroData< dimension> ¯oData, const Alberta::ProjectionFactoryInterface< Proj, Impl > &projectionFactory ) : mesh_(), maxlevel_( 0 ), numBoundarySegments_( 0 ), hIndexSet_( dofNumbering_ ), idSet_( hIndexSet_ ), levelIndexVec_( (size_t)MAXL, 0 ), leafIndexSet_ ( 0 ), sizeCache_( *this ), leafMarkerVector_( dofNumbering_ ), levelMarkerVector_( (size_t)MAXL, MarkerVector( dofNumbering_ ) ) { checkAlbertaDimensions< dim, dimworld >(); numBoundarySegments_ = mesh_.create( macroData, projectionFactory ); if( !mesh_ ) DUNE_THROW( AlbertaError, "Invalid macro data structure." ); setup(); hIndexSet_.create(); calcExtras(); } template< int dim, int dimworld > inline AlbertaGrid< dim, dimworld > ::AlbertaGrid ( const Alberta::MacroData< dimension> ¯oData, const std::shared_ptr< DuneBoundaryProjection< dimensionworld > > &projection ) : mesh_(), maxlevel_( 0 ), numBoundarySegments_( 0 ), hIndexSet_( dofNumbering_ ), idSet_( hIndexSet_ ), levelIndexVec_( (size_t)MAXL, 0 ), leafIndexSet_ ( 0 ), sizeCache_( *this ), leafMarkerVector_( dofNumbering_ ), levelMarkerVector_( (size_t)MAXL, MarkerVector( dofNumbering_ ) ) { checkAlbertaDimensions< dim, dimworld >(); if( projection != 0 ) { Alberta::DuneGlobalBoundaryProjectionFactory< dimension > projectionFactory( projection ); numBoundarySegments_ = mesh_.create( macroData, projectionFactory ); } else numBoundarySegments_ = mesh_.create( macroData ); if( !mesh_ ) DUNE_THROW( AlbertaError, "Invalid macro data structure." ); setup(); hIndexSet_.create(); calcExtras(); } template < int dim, int dimworld > inline AlbertaGrid< dim, dimworld > ::AlbertaGrid ( const std::string ¯oGridFileName ) : mesh_(), maxlevel_( 0 ), hIndexSet_( dofNumbering_ ), idSet_( hIndexSet_ ), levelIndexVec_( (size_t)MAXL, 0 ), leafIndexSet_ ( 0 ), sizeCache_( *this ), leafMarkerVector_( dofNumbering_ ), levelMarkerVector_( (size_t)MAXL, MarkerVector( dofNumbering_ ) ) { checkAlbertaDimensions< dim, dimworld >(); numBoundarySegments_ = mesh_.create( macroGridFileName ); if( !mesh_ ) { DUNE_THROW( AlbertaIOError, "Grid file '" << macroGridFileName << "' is not in ALBERTA macro triangulation format." ); } setup(); hIndexSet_.create(); calcExtras(); std::cout << typeName() << " created from macro grid file '" << macroGridFileName << "'." << std::endl; } template< int dim, int dimworld > inline void AlbertaGrid< dim, dimworld >::setup () { dofNumbering_.create( mesh_ ); levelProvider_.create( dofNumbering_ ); #if DUNE_ALBERTA_CACHE_COORDINATES coordCache_.create( dofNumbering_ ); #endif } template< int dim, int dimworld > inline void AlbertaGrid< dim, dimworld >::removeMesh () { for( size_t i = 0; i < levelIndexVec_.size(); ++i ) { if( levelIndexVec_[ i ] != 0 ) delete levelIndexVec_[ i ]; levelIndexVec_[ i ] = 0; } if( leafIndexSet_ != 0 ) delete leafIndexSet_; leafIndexSet_ = 0; // release dof vectors hIndexSet_.release(); levelProvider_.release(); #if DUNE_ALBERTA_CACHE_COORDINATES coordCache_.release(); #endif dofNumbering_.release(); sizeCache_.reset(); mesh_.release(); } template< int dim, int dimworld > inline AlbertaGrid< dim, dimworld >::~AlbertaGrid () { removeMesh(); } template< int dim, int dimworld > template< int codim, PartitionIteratorType pitype > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::template Partition::LevelIterator AlbertaGrid< dim, dimworld >::lbegin ( int level ) const { typedef AlbertaGridLevelIterator< codim, pitype, const This > LevelIteratorImp; assert( level >= 0 ); if( level > maxlevel_ ) return lend< codim, pitype >( level ); MarkerVector &markerVector = levelMarkerVector_[ level ]; if( (codim > 0) && !markerVector.up2Date() ) markerVector.template markSubEntities< 1 >( lbegin< 0 >( level ), lend< 0 >( level ) ); return LevelIteratorImp( *this, &markerVector, level ); } template< int dim, int dimworld > template< int codim, PartitionIteratorType pitype > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::template Partition< pitype >::LevelIterator AlbertaGrid < dim, dimworld >::lend ( int level ) const { typedef AlbertaGridLevelIterator< codim, pitype, const This > LevelIteratorImp; assert( level >= 0 ); return LevelIteratorImp( *this, level ); } template< int dim, int dimworld > template< int codim > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::LevelIterator AlbertaGrid < dim, dimworld >::lbegin ( int level ) const { return lbegin< codim, All_Partition >( level ); } template< int dim, int dimworld > template< int codim > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::LevelIterator AlbertaGrid< dim, dimworld >::lend ( int level ) const { return lend< codim, All_Partition >( level ); } template< int dim, int dimworld > template< int codim, PartitionIteratorType pitype > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::template Partition< pitype >::LeafIterator AlbertaGrid< dim, dimworld >::leafbegin () const { typedef AlbertaGridLeafIterator< codim, pitype, const This > LeafIteratorImp; MarkerVector &markerVector = leafMarkerVector_; const int firstMarkedCodim = 2; if( (codim >= firstMarkedCodim) && !markerVector.up2Date() ) markerVector.template markSubEntities< firstMarkedCodim >( leafbegin< 0 >(), leafend< 0 >() ); return LeafIteratorImp( *this, &markerVector, maxlevel_ ); } template< int dim, int dimworld > template< int codim, PartitionIteratorType pitype > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::template Partition< pitype >::LeafIterator AlbertaGrid< dim, dimworld >::leafend () const { typedef AlbertaGridLeafIterator< codim, pitype, const This > LeafIteratorImp; return LeafIteratorImp( *this, maxlevel_ ); } template< int dim, int dimworld > template< int codim > inline typename AlbertaGrid::Traits ::template Codim< codim >::LeafIterator AlbertaGrid< dim, dimworld >::leafbegin () const { return leafbegin< codim, All_Partition >(); } template< int dim, int dimworld > template< int codim > inline typename AlbertaGrid< dim, dimworld >::Traits ::template Codim< codim >::LeafIterator AlbertaGrid < dim, dimworld >::leafend () const { return leafend< codim, All_Partition >(); } template< int dim, int dimworld > inline void AlbertaGrid< dim, dimworld >::globalRefine ( int refCount ) { typedef typename Traits::template Codim< 0 >::LeafIterator LeafIterator; // only MAXL levels allowed assert( (refCount >= 0) && (refCount + maxlevel_ < MAXL) ); for( int i = 0; i < refCount; ++i ) { // mark all interior elements const LeafIterator endit = leafend< 0 >(); for( LeafIterator it = leafbegin< 0 >(); it != endit; ++it ) mark( 1, *it ); preAdapt(); adapt(); postAdapt(); } } template< int dim, int dimworld > template< class DataHandle > inline void AlbertaGrid< dim, dimworld > ::globalRefine ( int refCount, AdaptDataHandleInterface< This, DataHandle > &handle ) { typedef typename Traits::template Codim< 0 >::LeafIterator LeafIterator; // only MAXL levels allowed assert( (refCount >= 0) && (refCount + maxlevel_ < MAXL) ); for( int i = 0; i < refCount; ++i ) { // mark all interior elements const LeafIterator endit = leafend< 0 >(); for( LeafIterator it = leafbegin< 0 >(); it != endit; ++it ) mark( 1, *it ); adapt( handle ); } } template< int dim, int dimworld > inline bool AlbertaGrid< dim, dimworld >::preAdapt () { adaptationState_.preAdapt(); return adaptationState_.coarsen(); } template < int dim, int dimworld > inline void AlbertaGrid < dim, dimworld >::postAdapt () { #ifndef NDEBUG if( leafIndexSet_ != 0 ) { bool consistent = true; for( int codim = 0; codim <= dimension; ++codim ) { if( int(leafIndexSet_->size( codim )) == mesh_.size( codim ) ) continue; std::cerr << "Incorrect size of leaf index set for codimension " << codim << "!" << std::endl; std::cerr << "DUNE index set reports: " << leafIndexSet_->size( codim ) << std::endl; std::cerr << "ALBERTA mesh reports: " << mesh_.size( codim ) << std::endl; consistent = false; } if( !consistent ) abort(); } #endif levelProvider_.markAllOld(); adaptationState_.postAdapt(); } template< int dim, int dimworld > inline bool AlbertaGrid< dim, dimworld > ::mark( int refCount, const typename Traits::template Codim< 0 >::Entity &e ) { // if not leaf entity, leave method if( !e.isLeaf() ) return false; // don't mark macro elements for coarsening if( refCount < -e.level() ) return false; // take back previous marking adaptationState_.unmark( getMark( e ) ); // set new marking adaptationState_.mark( refCount ); e.impl().elementInfo().setMark( refCount ); return true; } template< int dim, int dimworld > inline int AlbertaGrid< dim, dimworld > ::getMark( const typename Traits::template Codim< 0 >::Entity &e ) const { return e.impl().elementInfo().getMark(); } template< int dim, int dimworld > inline bool AlbertaGrid< dim, dimworld >::adapt () { // this is already done in postAdapt //levelProvider_.markAllOld(); // adapt mesh hIndexSet_.preAdapt(); const bool refined = mesh_.refine(); const bool coarsened = (adaptationState_.coarsen() ? mesh_.coarsen() : false); adaptationState_.adapt(); hIndexSet_.postAdapt(); if( refined || coarsened ) calcExtras(); // return true if elements were created return refined; } template< int dim, int dimworld > template< class DataHandle > inline bool AlbertaGrid < dim, dimworld > ::adapt ( AdaptDataHandleInterface< This, DataHandle > &handle ) { preAdapt(); typedef Alberta::AdaptRestrictProlongHandler < This, AdaptDataHandleInterface< This, DataHandle > > DataHandler; DataHandler dataHandler( *this, handle ); typedef AdaptationCallback< DataHandler > Callback; typename Callback::DofVectorPointer callbackVector; callbackVector.create( dofNumbering_.emptyDofSpace(), "Adaptation Callback" ); callbackVector.template setupInterpolation< Callback >(); callbackVector.template setupRestriction< Callback >(); if( Callback::DofVectorPointer::supportsAdaptationData ) callbackVector.setAdaptationData( &dataHandler ); else Alberta::adaptationDataHandler_ = &dataHandler; bool refined = adapt(); if( !Callback::DofVectorPointer::supportsAdaptationData ) Alberta::adaptationDataHandler_ = 0; callbackVector.release(); postAdapt(); return refined; } template< int dim, int dimworld > inline const Alberta::GlobalVector & AlbertaGrid< dim, dimworld > ::getCoord ( const ElementInfo &elementInfo, int vertex ) const { assert( (vertex >= 0) && (vertex <= dim) ); #if DUNE_ALBERTA_CACHE_COORDINATES return coordCache_( elementInfo, vertex ); #else return elementInfo.coordinate( vertex ); #endif } template < int dim, int dimworld > inline int AlbertaGrid < dim, dimworld >::maxLevel() const { return maxlevel_; } template< int dim, int dimworld > inline int AlbertaGrid< dim, dimworld >::size ( int level, int codim ) const { return ((level >= 0) && (level <= maxlevel_) ? sizeCache_.size( level, codim ) : 0); } template< int dim, int dimworld > inline int AlbertaGrid< dim, dimworld >::size ( int level, GeometryType type ) const { return ((level >= 0) && (level <= maxlevel_) ? sizeCache_.size( level, type ) : 0); } template< int dim, int dimworld > inline int AlbertaGrid< dim, dimworld >::size ( int codim ) const { assert( sizeCache_.size( codim ) == mesh_.size( codim ) ); return mesh_.size( codim ); } template< int dim, int dimworld > inline int AlbertaGrid< dim, dimworld >::size ( GeometryType type ) const { return sizeCache_.size( type ); } template < int dim, int dimworld > inline const typename AlbertaGrid < dim, dimworld > :: Traits :: LevelIndexSet & AlbertaGrid < dim, dimworld > :: levelIndexSet (int level) const { // assert that given level is in range assert( (level >= 0) && (level < (int)levelIndexVec_.size()) ); if( levelIndexVec_[ level ] == 0 ) { levelIndexVec_[ level ] = new typename GridFamily::LevelIndexSetImp ( dofNumbering_ ); levelIndexVec_[ level ]->update( lbegin< 0 >( level ), lend< 0 >( level ) ); } return *(levelIndexVec_[ level ]); } template < int dim, int dimworld > inline const typename AlbertaGrid < dim, dimworld > :: Traits :: LeafIndexSet & AlbertaGrid < dim, dimworld > :: leafIndexSet () const { if( leafIndexSet_ == 0 ) { leafIndexSet_ = new typename GridFamily::LeafIndexSetImp( dofNumbering_ ); leafIndexSet_->update( leafbegin< 0 >(), leafend< 0 >() ); } return *leafIndexSet_; } template < int dim, int dimworld > inline void AlbertaGrid < dim, dimworld >::calcExtras () { // determine new maxlevel maxlevel_ = levelProvider_.maxLevel(); assert( (maxlevel_ >= 0) && (maxlevel_ < MAXL) ); // unset up2Dat status, if lbegin is called then this status is updated for( int l = 0; l < MAXL; ++l ) levelMarkerVector_[ l ].clear(); // unset up2Dat status, if leafbegin is called then this status is updated leafMarkerVector_.clear(); sizeCache_.reset(); // update index sets (if they exist) if( leafIndexSet_ != 0 ) leafIndexSet_->update( leafbegin< 0 >(), leafend< 0 >() ); for( unsigned int level = 0; level < levelIndexVec_.size(); ++level ) { if( levelIndexVec_[ level ] ) levelIndexVec_[ level ]->update( lbegin< 0 >( level ), lend< 0 >( level ) ); } } template< int dim, int dimworld > inline bool AlbertaGrid< dim, dimworld > ::writeGrid ( const std::string &filename, ctype time ) const { if( filename.size() <= 0 ) DUNE_THROW( AlbertaIOError, "No filename given to writeGridXdr." ); return (mesh_.write( filename, time ) && hIndexSet_.write( filename )); } template< int dim, int dimworld > inline bool AlbertaGrid< dim, dimworld > ::readGrid ( const std::string &filename, ctype &time ) { //removeMesh(); if( filename.size() <= 0 ) return false; numBoundarySegments_ = mesh_.read( filename, time ); if( !mesh_ ) DUNE_THROW( AlbertaIOError, "Could not read grid file: " << filename << "." ); setup(); hIndexSet_.read( filename ); // calc maxlevel and indexOnLevel and so on calcExtras(); return true; } // AlbertaGrid::AdaptationCallback // ------------------------------- template< int dim, int dimworld > template< class DataHandler > struct AlbertaGrid< dim, dimworld >::AdaptationCallback { static const int dimension = dim; typedef Alberta::DofVectorPointer< Alberta::GlobalVector > DofVectorPointer; typedef Alberta::Patch< dimension > Patch; static DataHandler &getDataHandler ( const DofVectorPointer &dofVector ) { DataHandler *dataHandler; if( DofVectorPointer::supportsAdaptationData ) dataHandler = dofVector.getAdaptationData< DataHandler >(); else dataHandler = (DataHandler *)Alberta::adaptationDataHandler_; assert( dataHandler != 0 ); return *dataHandler; } static void interpolateVector ( const DofVectorPointer &dofVector, const Patch &patch ) { DataHandler &dataHandler = getDataHandler( dofVector ); for( int i = 0; i < patch.count(); ++i ) dataHandler.prolongLocal( patch, i ); } static void restrictVector ( const DofVectorPointer &dofVector, const Patch &patch ) { DataHandler &dataHandler = getDataHandler( dofVector ); for( int i = 0; i < patch.count(); ++i ) dataHandler.restrictLocal( patch, i ); } }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/albertagrid/albertaheader.hh000066400000000000000000000031761511655130300227240ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAHEADER_HH #define DUNE_ALBERTAHEADER_HH #if HAVE_ALBERTA #if not (ALBERTA_DIM > 0) #if HEADERCHECK #undef ALBERTA_DIM #define ALBERTA_DIM 2 #else #error ALBERTA_DIM should be 1, 2, or 3 #endif #endif // Set ALBERTA's DIM_OF_WORLD preprocessor variable #ifndef ALBERTA_DIM #error "ALBERTA_DIM needed to use AlbertaGrid." #endif #define DIM_OF_WORLD ALBERTA_DIM // if we have ALBERTA C++ lib define namespace for ALBERTA #ifdef __ALBERTApp__ #define ALBERTA Alberta:: #else #define ALBERTA :: #endif #ifndef ALBERTA_DEBUG #define ALBERTA_DEBUG 0 #endif // MAX, MIN, and ABS are defined macros of ALBERTA // if they are not defined elsewhere, they are undefined here #ifndef MAX #define _MAX_NOT_DEFINED_ #endif #ifndef MIN #define _MIN_NOT_DEFINED_ #endif #ifndef ABS #define _ABS_NOT_DEFINED_ #endif #ifndef DIM_OF_WORLD #error "DIM_OF_WORLD not defined." #endif #ifdef HAVE_CONFIG_H #define ALBERTASAVE_HAVE_CONFIG_H HAVE_CONFIG_H #undef HAVE_CONFIG_H #endif #include #ifdef ALBERTASAVE_HAVE_CONFIG_H #define HAVE_CONFIG_H ALBERTASAVE_HAVE_CONFIG_H #undef ALBERTASAVE_HAVE_CONFIG_H #endif #ifndef _ALBERTA_H_ #error "Unable to include alberta.h." #endif // Macro nil may be defined by alberta_util.h. If so, undefine it. #ifdef nil #undef nil #endif #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTAHEADER_HH dune-grid-2.11.0/dune/grid/albertagrid/albertareader.hh000066400000000000000000000044461511655130300227370ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_ALBERTAREADER_HH #define DUNE_ALBERTA_ALBERTAREADER_HH #include #include #include #include #if HAVE_ALBERTA namespace Dune { template< class Grid > class AlbertaReader { typedef AlbertaReader< Grid > This; public: typedef Dune::GridFactory< Grid > GridFactory; typedef typename Grid::ctype ctype; static const int dimension = Grid::dimension; static const int dimensionworld = Grid::dimensionworld; private: static_assert(dimensionworld == Alberta::dimWorld, "AlbertaReader: world dimension must match ALBERTA's world dimension."); typedef Alberta::MacroData< dimension > MacroData; MacroData macroData_; AlbertaReader ( const This & ); This &operator= ( const This & ); public: AlbertaReader () {} void readGrid ( const std::string &fileName, GridFactory &factory ) { // read ALBERTA macro triangulation macroData_.read( fileName, false ); // insert all vertices into the factory const int numVertices = macroData_.vertexCount(); for( int i = 0; i < numVertices; ++i ) { FieldVector< ctype, dimensionworld > v; const Alberta::GlobalVector &coords = macroData_.vertex( i ); for( int j = 0; j < dimensionworld; ++j ) v[ j ] = coords[ j ]; factory.insertVertex( v ); } // insert all elements into the factory std::vector< unsigned int > vertices( dimension+1 ); const int numElements = macroData_.elementCount(); for( int i = 0; i < numElements; ++i ) { const typename MacroData::ElementId &id = macroData_.element( i ); for( int j = 0; j <= dimension; ++j ) vertices[ j ] = id[ j ]; factory.insertElement( GeometryTypes::simplex( dimension ), vertices ); } // release ALBERTA macro data macroData_.release(); } }; } #endif // #if HAVE_ALBERTA #endif dune-grid-2.11.0/dune/grid/albertagrid/algebra.hh000066400000000000000000000107761511655130300215420ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_ALGEBRA_HH #define DUNE_ALBERTA_ALGEBRA_HH #include #include namespace Dune { namespace Alberta { template< class K > inline static FieldVector< K, 3 > vectorProduct ( const FieldVector< K, 3 > &u, const FieldVector< K, 3 > &v ) { FieldVector< K, 3 > w; w[ 0 ] = u[ 1 ] * v[ 2 ] - u[ 2 ] * v[ 1 ]; w[ 1 ] = u[ 2 ] * v[ 0 ] - u[ 0 ] * v[ 2 ]; w[ 2 ] = u[ 0 ] * v[ 1 ] - u[ 1 ] * v[ 0 ]; return w; } template< class K, int m > inline static K determinant ( [[maybe_unused]] const FieldMatrix< K, 0, m > &matrix ) { return K( 1 ); } template< class K > inline static K determinant ( const FieldMatrix< K, 1, 1 > &matrix ) { return matrix[ 0 ][ 0 ]; } template< class K, int m > inline static K determinant ( const FieldMatrix< K, 1, m > &matrix ) { using std::sqrt; K sum = matrix[ 0 ][ 0 ] * matrix[ 0 ][ 0 ]; for( int i = 1; i < m; ++i ) sum += matrix[ 0 ][ i ] * matrix[ 0 ][ i ]; return sqrt( sum ); } template< class K > inline static K determinant ( const FieldMatrix< K, 2, 2 > &matrix ) { return matrix[ 0 ][ 0 ] * matrix[ 1 ][ 1 ] - matrix[ 0 ][ 1 ] * matrix[ 1 ][ 0 ]; } template< class K > inline static K determinant ( const FieldMatrix< K, 2, 3 > &matrix ) { return vectorProduct( matrix[ 0 ], matrix[ 1 ] ).two_norm(); } template< class K, int m > inline static K determinant ( const FieldMatrix< K, 2, m > &matrix ) { using std::sqrt; const K tmpA = matrix[ 0 ].two_norm2(); const K tmpB = matrix[ 1 ].two_norm2(); const K tmpC = matrix[ 0 ] * matrix[ 1 ]; return sqrt( tmpA * tmpB - tmpC * tmpC ); } template< class K > inline static K determinant ( const FieldMatrix< K, 3, 3 > &matrix ) { return matrix[ 0 ] * vectorProduct( matrix[ 1 ], matrix[ 2 ] ); } template< class K, int m > inline static K invert ( [[maybe_unused]] const FieldMatrix< K, 0, m > &matrix, [[maybe_unused]] FieldMatrix< K, m, 0 > &inverse ) { return K( 1 ); } template< class K > inline static K invert ( const FieldMatrix< K, 1, 1 > &matrix, FieldMatrix< K, 1, 1 > &inverse ) { inverse[ 0 ][ 0 ] = K( 1 ) / matrix[ 0 ][ 0 ]; return matrix[ 0 ][ 0 ]; } template< class K, int m > inline static K invert ( const FieldMatrix< K, 1, m > &matrix, FieldMatrix< K, m, 1 > &inverse ) { using std::sqrt; K detSqr = matrix[ 0 ].two_norm2(); K invDetSqr = K( 1 ) / detSqr; for( int i = 0; i < m; ++i ) inverse[ i ][ 0 ] = invDetSqr * matrix[ 0 ][ i ]; return sqrt( detSqr ); } template< class K > inline static K invert ( const FieldMatrix< K, 2, 2 > &matrix, FieldMatrix< K, 2, 2 > &inverse ) { K det = determinant( matrix ); K invDet = K( 1 ) / det; inverse[ 0 ][ 0 ] = invDet * matrix[ 1 ][ 1 ]; inverse[ 0 ][ 1 ] = - invDet * matrix[ 0 ][ 1 ]; inverse[ 1 ][ 0 ] = - invDet * matrix[ 1 ][ 0 ]; inverse[ 1 ][ 1 ] = invDet * matrix[ 0 ][ 0 ]; return det; } template< class K, int m > inline static K invert ( const FieldMatrix< K, 2, m > &matrix, FieldMatrix< K, m, 2 > &inverse ) { using std::sqrt; const K tmpA = matrix[ 0 ].two_norm2(); const K tmpB = matrix[ 1 ].two_norm2(); const K tmpC = matrix[ 0 ] * matrix[ 1 ]; const K detSqr = tmpA * tmpB - tmpC * tmpC; const K invDetSqr = K( 1 ) / detSqr; for( int i = 0; i < m; ++i ) { inverse[ i ][ 0 ] = invDetSqr * (tmpB * matrix[ 0 ][ i ] - tmpC * matrix[ 1 ][ i ]); inverse[ i ][ 1 ] = invDetSqr * (tmpA * matrix[ 1 ][ i ] - tmpC * matrix[ 0 ][ i ]); } return sqrt( detSqr ); } template< class K > inline static K invert ( const FieldMatrix< K, 3, 3 > &matrix, FieldMatrix< K, 3, 3 > &inverse ) { return FMatrixHelp::invertMatrix( matrix, inverse ); } } } #endif // #ifndef DUNE_ALBERTA_ALGEBRA_HH dune-grid-2.11.0/dune/grid/albertagrid/backuprestore.hh000066400000000000000000000041221511655130300230020ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_ALBERTAGRID_BACKUPRESTORE_HH #define DUNE_GRID_ALBERTAGRID_BACKUPRESTORE_HH #include namespace Dune { // External Forward Declarations // ----------------------------- template< int, int > class AlbertaGrid; // BackupRestoreFacility for AlbertaGrid // ------------------------------------- template< int dim, int dimworld > struct BackupRestoreFacility< AlbertaGrid< dim, dimworld > > { typedef AlbertaGrid< dim, dimworld > Grid; /** \copydoc Dune::BackupRestoreFacility::backup() */ static void backup ( const Grid &grid, const std::string &filename ) { grid.writeGrid( filename, 0.0 ); } /** \copydoc Dune::BackupRestoreFacility::backup() \note This method is not available for AlbertGrid. Use try/catch to catch the NotImplemented exception and fall back to the other backup method. */ static void backup ( const Grid &/*grid*/, std::ostream &/*stream*/ ) { DUNE_THROW( NotImplemented, "backup / restore using streams not implemented." ); } /** \copydoc Dune::BackupRestoreFacility::restore(const std::string&) */ static Grid *restore ( const std::string &filename ) { Grid *grid = new Grid; double time; // ignore time grid->readGrid( filename, time ); return grid; } /** \copydoc Dune::BackupRestoreFacility::restore() \note This method is not available for AlbertGrid. Use try/catch to catch the NotImplemented exception and fall back to the other restore method. */ static Grid *restore ( std::istream &/*stream*/ ) { DUNE_THROW( NotImplemented, "backup / restore using streams not implemented." ); } }; } // namespace Dune #endif // #ifndef DUNE_GRID_ALBERTAGRID_BACKUPRESTORE_HH dune-grid-2.11.0/dune/grid/albertagrid/capabilities.hh000066400000000000000000000051731511655130300225710ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_CAPABILITIES_HH #define DUNE_ALBERTA_CAPABILITIES_HH #include #include #if HAVE_ALBERTA namespace Dune { // External Forward Declarations // ----------------------------- template< int dim, int dimworld > class AlbertaGrid; // Capabilities // ------------ namespace Capabilities { /** \brief AlbertaGrid has only one geometry type for codim 0 entities \ingroup AlbertaGrid */ template< int dim, int dimworld > struct hasSingleGeometryType< AlbertaGrid< dim, dimworld > > { static const bool v = true; static const unsigned int topologyId = GeometryTypes::simplex(dim).id(); }; /** \brief AlbertaGrid has entities for all codimensions * \ingroup AlbertaGrid */ template< int dim, int dimworld, int codim > struct hasEntity< AlbertaGrid< dim, dimworld >, codim > { static const bool v = true; }; /** * \brief AlbertaGrid can iterate over all codimensions * * \ingroup AlbertaGrid **/ template< int dim, int dimworld, int codim > struct hasEntityIterator< AlbertaGrid< dim, dimworld >, codim > { static const bool v = true; }; /** \brief AlbertaGrid is not levelwise conforming * (since it uses bisection) * \ingroup AlbertaGrid */ template< int dim, int dimworld > struct isLevelwiseConforming< AlbertaGrid< dim, dimworld > > { static const bool v = false; }; /** \brief AlbertaGrid is leafwise conforming * \ingroup AlbertaGrid */ template< int dim, int dimworld > struct isLeafwiseConforming< AlbertaGrid< dim, dimworld > > { static const bool v = true; }; /** \brief AlbertaGrid has backup and restore facilities * \ingroup AlbertaGrid */ template< int dim, int dimworld > struct hasBackupRestoreFacilities< AlbertaGrid< dim, dimworld > > { static const bool v = true; }; // non-standard capabilities // ------------------------- template< class Grid > struct hasHierarchicIndexSet; template< int dim, int dimworld > struct hasHierarchicIndexSet< AlbertaGrid< dim, dimworld > > { static const bool v = true; }; } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_CAPABILITIES_HH dune-grid-2.11.0/dune/grid/albertagrid/coordcache.hh000066400000000000000000000102031511655130300222200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_COORDCACHE_HH #define DUNE_ALBERTA_COORDCACHE_HH #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // CoordCache // ---------- template< int dim > class CoordCache { typedef DofVectorPointer< GlobalVector > CoordVectorPointer; typedef Alberta::DofAccess< dim, dim > DofAccess; class LocalCaching; struct Interpolation; public: static const int dimension = dim; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef Alberta::MeshPointer< dimension > MeshPointer; typedef HierarchyDofNumbering< dimension > DofNumbering; GlobalVector &operator() ( const Element *element, int vertex ) const { assert( !(!coords_) ); GlobalVector *array = (GlobalVector *)coords_; return array[ dofAccess_( element, vertex ) ]; } GlobalVector &operator() ( const ElementInfo &elementInfo, int vertex ) const { return (*this)( elementInfo.el(), vertex ); } void create ( const DofNumbering &dofNumbering ) { MeshPointer mesh = dofNumbering.mesh(); const DofSpace *dofSpace = dofNumbering.dofSpace( dimension ); coords_.create( dofSpace, "Coordinate Cache" ); LocalCaching localCaching( coords_ ); mesh.hierarchicTraverse( localCaching, FillFlags< dimension >::coords ); coords_.template setupInterpolation< Interpolation >(); dofAccess_ = DofAccess( dofSpace ); } void release () { coords_.release(); } private: CoordVectorPointer coords_; DofAccess dofAccess_; }; // CoordCache::LocalCaching // ------------------------ template< int dim > class CoordCache< dim >::LocalCaching { CoordVectorPointer coords_; DofAccess dofAccess_; public: explicit LocalCaching ( const CoordVectorPointer &coords ) : coords_( coords ), dofAccess_( coords.dofSpace() ) {} void operator() ( const ElementInfo &elementInfo ) const { GlobalVector *array = (GlobalVector *)coords_; for( int i = 0; i < DofAccess::numSubEntities; ++i ) { const GlobalVector &x = elementInfo.coordinate( i ); GlobalVector &y = array[ dofAccess_( elementInfo.el(), i ) ]; for( int i = 0; i < dimWorld; ++i ) y[ i ] = x[ i ]; } } }; // CoordCache::Interpolation // ------------------------- template< int dim > struct CoordCache< dim >::Interpolation { static const int dimension = dim; typedef Alberta::Patch< dimension > Patch; static void interpolateVector ( const CoordVectorPointer &dofVector, const Patch &patch ) { DofAccess dofAccess( dofVector.dofSpace() ); GlobalVector *array = (GlobalVector *)dofVector; const Element *element = patch[ 0 ]; // new vertex is always the last one assert( element->child[ 0 ] != NULL ); GlobalVector &newCoord = array[ dofAccess( element->child[ 0 ], dimension ) ]; if( element->new_coord != NULL ) { for( int j = 0; j < dimWorld; ++j ) newCoord[ j ] = element->new_coord[ j ]; } else { // new coordinate is the average of of old ones on the same edge // refinement edge is always between vertices 0 and 1 const GlobalVector &coord0 = array[ dofAccess( element, 0 ) ]; const GlobalVector &coord1 = array[ dofAccess( element, 1 ) ]; for( int j = 0; j < dimWorld; ++j ) newCoord[ j ] = 0.5 * (coord0[ j ] + coord1[ j ]); } } }; } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_COORDCACHE_HH dune-grid-2.11.0/dune/grid/albertagrid/datahandle.hh000066400000000000000000000036611511655130300222250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRIDDATAHANDLE_HH #define DUNE_ALBERTAGRIDDATAHANDLE_HH #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { template< class Grid, class RestrictProlongOperator > class AdaptRestrictProlongHandler { static const int dimension = Grid::dimension; typedef typename Grid::template Codim< 0 >::Entity Entity; typedef Dune::MakeableInterfaceObject< Entity > EntityObject; typedef typename EntityObject::ImplementationType EntityImp; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef Alberta::Patch< dimension > Patch; Grid &grid_; RestrictProlongOperator &rpOp_; EntityObject father_; public: AdaptRestrictProlongHandler ( Grid &grid, RestrictProlongOperator &rpOp ) : grid_( grid ), rpOp_( rpOp ), father_( EntityImp( grid_ ) ) {} void restrictLocal ( const Patch &patch, int i ) { ElementInfo fatherInfo = patch.elementInfo( i, grid_.levelProvider() ); father_.impl().setElement( fatherInfo, 0 ); rpOp_.preCoarsening( (const Entity &)father_ ); } void prolongLocal ( const Patch &patch, int i ) { ElementInfo fatherInfo = patch.elementInfo( i, grid_.levelProvider() ); father_.impl().setElement( fatherInfo, 0 ); rpOp_.postRefinement( (const Entity &)father_ ); } }; } } #endif // #if HAVE_ALBERTA #endif dune-grid-2.11.0/dune/grid/albertagrid/dgfparser.cc000066400000000000000000000110621511655130300220750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // compile surface grid support into the lib even for ALBERTA 2.0 #define DUNE_ALBERTA_SURFACE_GRID 1 #include #include #if HAVE_ALBERTA namespace Dune { // Implementation of DGFGridFactory for AlbertaGrid // ------------------------------------------------ template< int dim, int dimworld > bool DGFGridFactory< AlbertaGrid< dim, dimworld > >::generate( std::istream &input ) { dgf_.element = DuneGridFormatParser::Simplex; dgf_.dimgrid = dim; dgf_.dimw = dimworld; if( !dgf_.readDuneGrid( input, dim, dimworld ) ) return false; for( int n = 0; n < dgf_.nofvtx; ++n ) { typename GridFactory::WorldVector coord; for( int i = 0; i < dimworld; ++i ) coord[ i ] = dgf_.vtx[ n ][ i ]; factory_.insertVertex( coord ); } std::vector< unsigned int > elementId( dimension+1 ); for( int n = 0; n < dgf_.nofelements; ++n ) { // This is a nasty hack: The tetrahedrons generated by make6 are not // directly usable by ALBERTA. On every second tetrahedron we have to // switch the last 2 vertices (otherwise ALBERTA causes a segmentation // fault during refinement). if( (dimension == 3) && dgf_.cube2simplex && (n % 2 == 0) ) { const int flip[ 4 ] = { 0, 1, 3, 2 }; for( int i = 0; i <= dimension; ++i ) elementId[ i ] = dgf_.elements[ n ][ flip[ i ] ]; } else { for( int i = 0; i <= dimension; ++i ) elementId[ i ] = dgf_.elements[ n ][ i ]; } factory_.insertElement( GeometryTypes::simplex( dimension ), elementId ); // look for boundaries and insert them for( int face = 0; face <= dimension; ++face ) { typedef typename DuneGridFormatParser::facemap_t::key_type Key; typedef typename DuneGridFormatParser::facemap_t::iterator Iterator; const Key key( elementId, dimension, face+1 ); const Iterator it = dgf_.facemap.find( key ); if( it != dgf_.facemap.end() ) factory_.insertBoundary( n, face, it->second.first ); } } if( GridFactory::supportPeriodicity ) { typedef dgf::PeriodicFaceTransformationBlock::AffineTransformation Transformation; dgf::PeriodicFaceTransformationBlock block( input, dimworld ); const int size = block.numTransformations(); for( int k = 0; k < size; ++k ) { const Transformation &trafo = block.transformation( k ); typename GridFactory::WorldMatrix matrix; for( int i = 0; i < dimworld; ++i ) for( int j = 0; j < dimworld; ++j ) matrix[ i ][ j ] = trafo.matrix( i, j ); typename GridFactory::WorldVector shift; for( int i = 0; i < dimworld; ++i ) shift[ i ] = trafo.shift[ i ]; factory_.insertFaceTransformation( matrix, shift ); } } dgf::ProjectionBlock projectionBlock( input, dimworld ); const DuneBoundaryProjection< dimworld > *projection = projectionBlock.template defaultProjection< dimworld >(); if( projection != 0 ) factory_.insertBoundaryProjection( projection ); const size_t numBoundaryProjections = projectionBlock.numBoundaryProjections(); for( size_t i = 0; i < numBoundaryProjections; ++i ) { const std::vector< unsigned int > &vertices = projectionBlock.boundaryFace( i ); const DuneBoundaryProjection< dimworld > *projection = projectionBlock.template boundaryProjection< dimworld >( i ); factory_.insertBoundaryProjection( GeometryTypes::simplex( dimension-1 ), vertices, projection ); } dgf::GridParameterBlock parameter( input ); if( parameter.markLongestEdge() ) factory_.markLongestEdge(); const std::string &dumpFileName = parameter.dumpFileName(); if( !dumpFileName.empty() ) factory_.write( dumpFileName ); grid_ = factory_.createGrid().release(); return true; } // Instantiation // ------------- template struct DGFGridFactory< AlbertaGrid< 1, Alberta::dimWorld > >; #if ALBERTA_DIM >= 2 template struct DGFGridFactory< AlbertaGrid< 2, Alberta::dimWorld > >; #endif // #if ALBERTA_DIM >= 2 #if ALBERTA_DIM >= 3 template struct DGFGridFactory< AlbertaGrid< 3, Alberta::dimWorld > >; #endif // #if ALBERTA_DIM >= 3 } #endif // #if HAVE_ALBERTA dune-grid-2.11.0/dune/grid/albertagrid/dgfparser.hh000066400000000000000000000126451511655130300221170ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_DGFPARSER_HH #define DUNE_ALBERTA_DGFPARSER_HH #include #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { // External Forward Declarations // ----------------------------- template< class GridImp, class IntersectionImp > class Intersection; // DGFGridFactory for AlbertaGrid // ------------------------------ template< int dim, int dimworld > struct DGFGridFactory< AlbertaGrid< dim, dimworld > > { typedef AlbertaGrid Grid; const static int dimension = Grid::dimension; typedef MPIHelper::MPICommunicator MPICommunicatorType; typedef typename Grid::template Codim<0>::Entity Element; typedef typename Grid::template Codim::Entity Vertex; typedef Dune::GridFactory GridFactory; explicit DGFGridFactory ( std::istream &input, MPICommunicatorType comm = MPIHelper::getCommunicator() ); explicit DGFGridFactory ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ); Grid *grid () const { return grid_; } template< class Intersection > bool wasInserted ( const Intersection &intersection ) const { return factory_.wasInserted( intersection ); } template< class Intersection > int boundaryId ( const Intersection &intersection ) const { return intersection.impl().boundaryId(); } // return true if boundary parameters found bool haveBoundaryParameters () const { return dgf_.haveBndParameters; } template < class GG, class II > const DGFBoundaryParameter::type & boundaryParameter ( const Intersection< GG, II > & intersection ) const { typedef Dune::Intersection< GG, II > Intersection; typename Intersection::Entity entity = intersection.inside(); const int face = intersection.indexInInside(); auto refElem = referenceElement< double, dimension >( entity.type() ); int corners = refElem.size( face, 1, dimension ); std :: vector< unsigned int > bound( corners ); for( int i=0; i < corners; ++i ) { const int k = refElem.subEntity( face, 1, i, dimension ); bound[ i ] = factory_.insertionIndex( entity.template subEntity< dimension >( k ) ); } DuneGridFormatParser::facemap_t::key_type key( bound, false ); const DuneGridFormatParser::facemap_t::const_iterator pos = dgf_.facemap.find( key ); if( pos != dgf_.facemap.end() ) return dgf_.facemap.find( key )->second.second; else return DGFBoundaryParameter::defaultValue(); } template< int codim > int numParameters () const { if( codim == 0 ) return dgf_.nofelparams; else if( codim == dimension ) return dgf_.nofvtxparams; else return 0; } std::vector< double > ¶meter ( const Element &element ) { if( numParameters< 0 >() <= 0 ) { DUNE_THROW( InvalidStateException, "Calling DGFGridFactory::parameter is only allowed if there are parameters." ); } return dgf_.elParams[ factory_.insertionIndex( element ) ]; } std::vector< double > ¶meter ( const Vertex &vertex ) { if( numParameters< dimension >() <= 0 ) { DUNE_THROW( InvalidStateException, "Calling DGFGridFactory::parameter is only allowed if there are parameters." ); } return dgf_.vtxParams[ factory_.insertionIndex( vertex ) ]; } private: bool generate( std::istream &input ); Grid *grid_; GridFactory factory_; DuneGridFormatParser dgf_; }; // DGFGridInfo for AlbertaGrid // --------------------------- template< int dim, int dimworld > struct DGFGridInfo< AlbertaGrid< dim, dimworld > > { static int refineStepsForHalf () { return dim; } static double refineWeight () { return 0.5; } }; // Implementation of DGFGridFactory for AlbertaGrid // ------------------------------------------------ template< int dim, int dimworld > inline DGFGridFactory< AlbertaGrid< dim, dimworld > > ::DGFGridFactory ( std::istream &input, MPICommunicatorType /* comm */ ) : dgf_( 0, 1 ) { input.clear(); input.seekg( 0 ); if( !input ) DUNE_THROW(DGFException, "Error resetting input stream." ); generate( input ); } template< int dim, int dimworld > inline DGFGridFactory< AlbertaGrid< dim, dimworld > > ::DGFGridFactory ( const std::string &filename, MPICommunicatorType /* comm */ ) : dgf_( 0, 1 ) { std::ifstream input( filename.c_str() ); if( !input ) DUNE_THROW( DGFException, "Macrofile " << filename << " not found." ); if( !generate( input ) ) grid_ = new AlbertaGrid< dim, dimworld >( filename.c_str() ); input.close(); } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_DGFPARSER_HH dune-grid-2.11.0/dune/grid/albertagrid/doc/000077500000000000000000000000001511655130300203565ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/albertagrid/doc/alberta_tetrahedron.svg000066400000000000000000000244301511655130300251130ustar00rootroot00000000000000 image/svg+xml 2 3 bottom 1 left 0 right 2 front 1 0 3 dune-grid-2.11.0/dune/grid/albertagrid/doc/alberta_tetrahedron.svg.license000066400000000000000000000002501511655130300265260ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/albertagrid/doc/alberta_tetrahedron_edges.svg000066400000000000000000000246601511655130300262670ustar00rootroot00000000000000 image/svg+xml 3 1 5 2 1 0 3 0 4 2 dune-grid-2.11.0/dune/grid/albertagrid/doc/alberta_tetrahedron_edges.svg.license000066400000000000000000000002501511655130300276750ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/albertagrid/doc/alberta_triangle.svg000066400000000000000000000125541511655130300244050ustar00rootroot00000000000000 image/svg+xml 0 1 2 1 2 0 dune-grid-2.11.0/dune/grid/albertagrid/doc/alberta_triangle.svg.license000066400000000000000000000002501511655130300260140ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/albertagrid/dofadmin.hh000066400000000000000000000172761511655130300217300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_DOFADMIN_HH #define DUNE_ALBERTA_DOFADMIN_HH #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // External Forward Declarations // ----------------------------- template< int dim > class MeshPointer; // DofAccess // --------- template< int dim, int codim > class DofAccess { static const int codimtype = CodimType< dim, codim >::value; public: static const int numSubEntities = NumSubEntities< dim, codim >::value; static const int dimension = dim; static const int codimension = codim; typedef Alberta::ElementInfo< dimension > ElementInfo; DofAccess () : node_( -1 ) {} explicit DofAccess ( const DofSpace *dofSpace ) { assert( dofSpace ); node_ = dofSpace->admin->mesh->node[ codimtype ]; index_ = dofSpace->admin->n0_dof[ codimtype ]; } int operator() ( const Element *element, int subEntity, int i ) const { assert( element ); assert( node_ != -1 ); assert( subEntity < numSubEntities ); return element->dof[ node_ + subEntity ][ index_ + i ]; } int operator() ( const Element *element, int subEntity ) const { return (*this)( element, subEntity, 0 ); } int operator() ( const ElementInfo &elementInfo, int subEntity, int i ) const { return (*this)( elementInfo.el(), subEntity, i ); } int operator() ( const ElementInfo &elementInfo, int subEntity ) const { return (*this)( elementInfo.el(), subEntity ); } private: int node_; int index_; }; // HierarchyDofNumbering // --------------------- template< int dim > class HierarchyDofNumbering { typedef HierarchyDofNumbering< dim > This; public: static const int dimension = dim; typedef Alberta::MeshPointer< dimension > MeshPointer; typedef Alberta::ElementInfo< dimension > ElementInfo; private: static const int nNodeTypes = N_NODE_TYPES; template< int codim > struct CreateDofSpace; template< int codim > struct CacheDofSpace; typedef std::pair< int, int > Cache; public: HierarchyDofNumbering () {} private: HierarchyDofNumbering ( const This & ); This &operator= ( const This & ); public: ~HierarchyDofNumbering () { release(); } int operator() ( const Element *element, int codim, unsigned int subEntity ) const { assert( !(*this) == false ); assert( (codim >= 0) && (codim <= dimension) ); const Cache &cache = cache_[ codim ]; return element->dof[ cache.first + subEntity ][ cache.second ]; } int operator() ( const ElementInfo &element, int codim, unsigned int subEntity ) const { return (*this)( element.el(), codim, subEntity ); } explicit operator bool () const { return (bool)mesh_; } const DofSpace *dofSpace ( int codim ) const { assert( *this ); assert( (codim >= 0) && (codim <= dimension) ); return dofSpace_[ codim ]; } const DofSpace *emptyDofSpace () const { assert( *this ); return emptySpace_; } const MeshPointer &mesh () const { return mesh_; } int size ( int codim ) const { return dofSpace( codim )->admin->size; } void create ( const MeshPointer &mesh ); void release () { if( *this ) { for( int codim = 0; codim <= dimension; ++codim ) freeDofSpace( dofSpace_[ codim ] ); freeDofSpace( emptySpace_ ); mesh_ = MeshPointer(); } } private: static const DofSpace *createEmptyDofSpace ( const MeshPointer &mesh ); static const DofSpace *createDofSpace ( const MeshPointer &mesh, const std::string &name, const int (&ndof)[ nNodeTypes ], const bool periodic = false ); static void freeDofSpace ( const DofSpace *dofSpace ); MeshPointer mesh_; const DofSpace *emptySpace_; const DofSpace *dofSpace_[ dimension+1 ]; Cache cache_[ dimension+1 ]; }; template< int dim > inline void HierarchyDofNumbering< dim >::create ( const MeshPointer &mesh ) { release(); if( !mesh ) return; mesh_ = mesh; Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ CreateDofSpace< i >::apply( mesh_, dofSpace_ ); } ); Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ CacheDofSpace< i >::apply( dofSpace_, cache_ ); } ); emptySpace_ = createEmptyDofSpace( mesh_ ); for( int i = 0; i < nNodeTypes; ++i ) assert( emptySpace_->admin->n_dof[ i ] == 0 ); } template< int dim > inline const DofSpace * HierarchyDofNumbering< dim >::createEmptyDofSpace ( const MeshPointer &mesh ) { int ndof[ nNodeTypes ]; for( int i = 0; i < nNodeTypes; ++i ) ndof[ i ] = 0; std::string name = "Empty"; return createDofSpace( mesh, name, ndof ); } template< int dim > inline const DofSpace * HierarchyDofNumbering< dim >::createDofSpace ( const MeshPointer &mesh, const std::string &name, const int (&ndof)[ nNodeTypes ], const bool periodic ) { const ALBERTA FLAGS flags = ADM_PRESERVE_COARSE_DOFS | (periodic ? ADM_PERIODIC : 0); return ALBERTA get_dof_space ( mesh, name.c_str(), ndof, flags ); } template< int dim > inline void HierarchyDofNumbering< dim >::freeDofSpace ( const DofSpace *dofSpace ) { ALBERTA free_fe_space( dofSpace ); } // HierarchyDofNumbering::CreateDofSpace // ------------------------------------- template< int dim > template< int codim > struct HierarchyDofNumbering< dim >::CreateDofSpace { static void apply ( const MeshPointer &mesh, const DofSpace *(&dofSpace)[ dim+1 ] ) { int ndof[ nNodeTypes ]; for( int i = 0; i < nNodeTypes; ++i ) ndof[ i ] = 0; ndof[ CodimType< dim, codim >::value ] = 1; std::string name = "Codimension "; name += (char)(codim + '0'); dofSpace[ codim ] = createDofSpace( mesh, name, ndof ); assert( dofSpace[ codim ] ); } }; // HierarchyDofNumbering::CacheDofSpace // ------------------------------------ template< int dim > template< int codim > struct HierarchyDofNumbering< dim >::CacheDofSpace { static void apply ( const DofSpace *(&dofSpace)[ dim+1 ], Cache (&cache)[ dim+1 ] ) { assert( dofSpace[ codim ] ); const int codimtype = CodimType< dim, codim >::value; cache[ codim ].first = dofSpace[ codim ]->mesh->node[ codimtype ]; cache[ codim ].second = dofSpace[ codim ]->admin->n0_dof[ codimtype ]; } }; } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_DOFADMIN_HH dune-grid-2.11.0/dune/grid/albertagrid/dofvector.hh000066400000000000000000000231401511655130300221250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_DOFVECTOR_HH #define DUNE_ALBERTA_DOFVECTOR_HH #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // External Forward Declarations // ----------------------------- template< int dim > class MeshPointer; // DofVectorProvider // ----------------- template< class Dof > struct DofVectorProvider; template<> struct DofVectorProvider< int > { typedef ALBERTA DOF_INT_VEC DofVector; static DofVector *get ( const DofSpace *dofSpace, const std::string &name ) { return ALBERTA get_dof_int_vec( name.c_str(), dofSpace ); } static void free ( DofVector *dofVector ) { ALBERTA free_dof_int_vec( dofVector ); } static DofVector *read ( const std::string &filename, Mesh *mesh, DofSpace *dofSpace ) { return ALBERTA read_dof_int_vec_xdr( filename.c_str(), mesh, dofSpace ); } static bool write ( const DofVector *dofVector, const std::string &filename ) { int success = ALBERTA write_dof_int_vec_xdr( dofVector, filename.c_str() ); return (success == 0); } }; template<> struct DofVectorProvider< signed char > { typedef ALBERTA DOF_SCHAR_VEC DofVector; static DofVector *get ( const DofSpace *dofSpace, const std::string &name ) { return ALBERTA get_dof_schar_vec( name.c_str(), dofSpace ); } static void free ( DofVector *dofVector ) { ALBERTA free_dof_schar_vec( dofVector ); } static DofVector *read ( const std::string &filename, Mesh *mesh, DofSpace *dofSpace ) { return ALBERTA read_dof_schar_vec_xdr( filename.c_str(), mesh, dofSpace ); } static bool write ( const DofVector *dofVector, const std::string &filename ) { int success = ALBERTA write_dof_schar_vec_xdr( dofVector, filename.c_str() ); return (success == 0); } }; template<> struct DofVectorProvider< unsigned char > { typedef ALBERTA DOF_UCHAR_VEC DofVector; static DofVector *get ( const DofSpace *dofSpace, const std::string &name ) { return ALBERTA get_dof_uchar_vec( name.c_str(), dofSpace ); } static void free ( DofVector *dofVector ) { ALBERTA free_dof_uchar_vec( dofVector ); } static DofVector *read ( const std::string &filename, Mesh *mesh, DofSpace *dofSpace ) { return ALBERTA read_dof_uchar_vec_xdr( filename.c_str(), mesh, dofSpace ); } static bool write ( const DofVector *dofVector, const std::string &filename ) { int success = ALBERTA write_dof_uchar_vec_xdr( dofVector, filename.c_str() ); return (success == 0); } }; template<> struct DofVectorProvider< Real > { typedef ALBERTA DOF_REAL_VEC DofVector; static DofVector *get ( const DofSpace *dofSpace, const std::string &name ) { return ALBERTA get_dof_real_vec( name.c_str(), dofSpace ); } static void free ( DofVector *dofVector ) { ALBERTA free_dof_real_vec( dofVector ); } static DofVector *read ( const std::string &filename, Mesh *mesh, DofSpace *dofSpace ) { return ALBERTA read_dof_real_vec_xdr( filename.c_str(), mesh, dofSpace ); } static bool write ( const DofVector *dofVector, const std::string &filename ) { int success = ALBERTA write_dof_real_vec_xdr( dofVector, filename.c_str() ); return (success == 0); } }; template<> struct DofVectorProvider< GlobalVector > { typedef ALBERTA DOF_REAL_D_VEC DofVector; static DofVector *get ( const DofSpace *dofSpace, const std::string &name ) { return ALBERTA get_dof_real_d_vec( name.c_str(), dofSpace ); } static void free ( DofVector *dofVector ) { ALBERTA free_dof_real_d_vec( dofVector ); } static DofVector *read ( const std::string &filename, Mesh *mesh, DofSpace *dofSpace ) { return ALBERTA read_dof_real_d_vec_xdr( filename.c_str(), mesh, dofSpace ); } static bool write ( const DofVector *dofVector, const std::string &filename ) { int success = ALBERTA write_dof_real_d_vec_xdr( dofVector, filename.c_str() ); return (success == 0); } }; // DofVectorPointer // ---------------- template< class Dof > class DofVectorPointer { typedef DofVectorPointer< Dof > This; typedef Alberta::DofVectorProvider< Dof > DofVectorProvider; public: typedef typename DofVectorProvider::DofVector DofVector; static const bool supportsAdaptationData = true; private: DofVector *dofVector_; public: DofVectorPointer () : dofVector_( NULL ) {} explicit DofVectorPointer ( const DofSpace *dofSpace, const std::string &name = "" ) : dofVector_ ( DofVectorProvider::get( dofSpace, name ) ) {} explicit DofVectorPointer ( DofVector *dofVector ) : dofVector_( dofVector ) {} explicit operator bool () const { return (bool)dofVector_; } operator DofVector * () const { return dofVector_; } operator Dof * () const { Dof *ptr = NULL; GET_DOF_VEC( ptr, dofVector_ ); return ptr; } const DofSpace *dofSpace () const { return dofVector_->fe_space; } std::string name () const { if( dofVector_ ) return dofVector_->name; else return std::string(); } void create ( const DofSpace *dofSpace, const std::string &name = "" ) { release(); dofVector_ = DofVectorProvider::get( dofSpace, name ); } template< int dim > void read ( const std::string &filename, const MeshPointer< dim > &meshPointer ) { release(); dofVector_ = DofVectorProvider::read( filename, meshPointer, NULL ); } bool write ( const std::string &filename ) const { return DofVectorProvider::write( dofVector_, filename ); } void release () { if( dofVector_ ) { DofVectorProvider::free( dofVector_ ); dofVector_ = NULL; } } template< class Functor > void forEach ( Functor &functor ) const { Dof *array = (Dof *)(*this); FOR_ALL_DOFS( dofSpace()->admin, functor( array[ dof ] ) ); } void initialize ( const Dof &value ) { Dof *array = (Dof *)(*this); FOR_ALL_DOFS( dofSpace()->admin, array[ dof ] = value ); } template< class AdaptationData > AdaptationData *getAdaptationData () const { assert( dofVector_ ); assert( dofVector_->user_data ); return static_cast< AdaptationData * >( dofVector_->user_data ); } template< class AdaptationData > void setAdaptationData ( AdaptationData *adaptationData ) { assert( dofVector_ ); dofVector_->user_data = adaptationData; } template< class Interpolation > void setupInterpolation () { assert( dofVector_ ); dofVector_->refine_interpol = &refineInterpolate< Interpolation >; } template< class Restriction > void setupRestriction () { assert( dofVector_ ); dofVector_->coarse_restrict = &coarsenRestrict< Restriction >; } private: template< class Interpolation > static void refineInterpolate ( DofVector *dofVector, RC_LIST_EL *list, int n ) { const This dofVectorPointer( dofVector ); typename Interpolation::Patch patch( list, n ); Interpolation::interpolateVector( dofVectorPointer, patch ); } template< class Restriction > static void coarsenRestrict ( DofVector *dofVector, RC_LIST_EL *list, int n ) { const This dofVectorPointer( dofVector ); typename Restriction::Patch patch( list, n ); Restriction::restrictVector( dofVectorPointer, patch ); } }; // Auxiliary Functions // -------------------- inline void abs ( const DofVectorPointer< int > &dofVector ) { assert( !dofVector == false ); int *array = (int *)dofVector; FOR_ALL_DOFS( dofVector.dofSpace()->admin, array[ dof ] = std::abs( array[ dof ] ) ); } inline int max ( const DofVectorPointer< int > &dofVector ) { assert( !dofVector == false ); int *array = (int *)dofVector; int result = std::numeric_limits< int >::min(); FOR_ALL_DOFS( dofVector.dofSpace()->admin, result = std::max( result, array[ dof ] ) ); return result; } inline int min ( const DofVectorPointer< int > &dofVector ) { assert( !dofVector == false ); int *array = (int *)dofVector; int result = std::numeric_limits< int >::max(); FOR_ALL_DOFS( dofVector.dofSpace()->admin, result = std::min( result, array[ dof ] ) ); return result; } } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_DOFVECTOR_HH dune-grid-2.11.0/dune/grid/albertagrid/elementinfo.cc000066400000000000000000000321771511655130300224370ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \author Martin Nolte * \brief provides a wrapper for ALBERTA's el_info structure */ #if HAVE_ALBERTA #include #include namespace Dune { namespace Alberta { // Implementation of ElementInfo // ----------------------------- template< int dim > template< int dimWorld > inline int ElementInfo< dim >::Library< dimWorld > ::macroNeighbor ( const ElementInfo &element, int face, ElementInfo &neighbor ) { assert( (face >= 0) && (face < numFaces) ); const MacroElement ¯oElement = element.macroElement(); const MacroElement *macroNeighbor = macroElement.neighbor( face ); if( macroNeighbor != 0 ) { neighbor = ElementInfo( element.mesh(), *macroNeighbor, element.elInfo().fill_flag ); return macroElement.opp_vertex[ face ]; } else return -1; } template<> template<> int ElementInfo< 1 >::Library< dimWorld > ::leafNeighbor ( const ElementInfo &element, const int face, ElementInfo &neighbor ) { static const int neighborInFather[ 2 ][ numFaces ] = { {-1, 1}, {0, -1} }; assert( !!element ); int faceInNeighbor; if( element.level() > 0 ) { assert( (face >= 0) && (face < numFaces) ); const int myIndex = element.indexInFather(); const int nbInFather = neighborInFather[ myIndex ][ face ]; if( nbInFather >= 0 ) return leafNeighbor( element.father(), nbInFather, neighbor ); else { neighbor = element.father().child( 1-myIndex ); faceInNeighbor = 1-myIndex; } } else faceInNeighbor = macroNeighbor( element, face, neighbor ); if( faceInNeighbor >= 0 ) { // refine until we are on the leaf level (faceInNeighbor < 2 is always true) while( !neighbor.isLeaf() ) neighbor = neighbor.child( 1-faceInNeighbor ); assert( neighbor.el() == element.elInfo().neigh[ face ] ); } return faceInNeighbor; } template<> template<> int ElementInfo< 2 >::Library< dimWorld > ::leafNeighbor ( const ElementInfo &element, const int face, ElementInfo &neighbor ) { static const int neighborInFather[ 2 ][ numFaces ] = { {2, -1, 1}, {-1, 2, 0} }; assert( !!element ); int faceInNeighbor; if( element.level() > 0 ) { assert( (face >= 0) && (face < numFaces) ); const int myIndex = element.indexInFather(); const int nbInFather = neighborInFather[ myIndex ][ face ]; if( nbInFather >= 0 ) { faceInNeighbor = leafNeighbor( element.father(), nbInFather, neighbor ); // handle a common face of in refinement patch if( (faceInNeighbor >= 0) && (nbInFather >= 2) ) { assert( faceInNeighbor >= 2 ); int childIndex = myIndex; if( element.father().el()->dof[ 0 ][ 0 ] != neighbor.el()->dof[ 0 ][ 0 ] ) { assert( element.father().el()->dof[ 0 ][ 0 ] == neighbor.el()->dof[ 1 ][ 0 ] ); childIndex = 1-myIndex; } neighbor = neighbor.child( childIndex ); faceInNeighbor = childIndex; } } else { neighbor = element.father().child( 1-myIndex ); faceInNeighbor = myIndex; } } else faceInNeighbor = macroNeighbor( element, face, neighbor ); if( faceInNeighbor >= 0 ) { // refine until we share a refinement face of the neighbor if( !neighbor.isLeaf() && (faceInNeighbor < 2) ) { neighbor = neighbor.child( 1-faceInNeighbor ); faceInNeighbor = dimension; } assert( neighbor.el() == element.elInfo().neigh[ face ] ); } return faceInNeighbor; } template<> template<> int ElementInfo< 3 >::Library< dimWorld > ::leafNeighbor ( const ElementInfo &element, const int face, ElementInfo &neighbor ) { // father.neigh[ neighborInFather[ child[ i ].el_type ][ i ][ j ] == child[ i ].neigh[ j ] static const int neighborInFather[ 3 ][ 2 ][ numFaces ] = { { {-1, 2, 3, 1}, {-1, 2, 3, 0} }, { {-1, 2, 3, 1}, {-1, 3, 2, 0} }, { {-1, 2, 3, 1}, {-1, 2, 3, 0} } }; assert( !!element ); int faceInNeighbor; if( element.level() > 0 ) { assert( (face >= 0) && (face < numFaces) ); const int myIndex = element.indexInFather(); const int nbInFather = neighborInFather[ element.type() ][ myIndex ][ face ]; if( nbInFather >= 0 ) { faceInNeighbor = leafNeighbor( element.father(), nbInFather, neighbor ); // handle a common face of in refinement patch if( (faceInNeighbor >= 0) && (nbInFather >= 2) ) { assert( faceInNeighbor >= 2 ); int childIndex = myIndex; if( element.father().el()->dof[ 0 ][ 0 ] != neighbor.el()->dof[ 0 ][ 0 ] ) { assert( element.father().el()->dof[ 0 ][ 0 ] == neighbor.el()->dof[ 1 ][ 0 ] ); childIndex = 1-myIndex; } const int oppDof = neighbor.el()->dof[ faceInNeighbor ][ 0 ]; neighbor = neighbor.child( childIndex ); faceInNeighbor = (oppDof == neighbor.el()->dof[ 1 ][ 0 ] ? 1 : 2); assert( oppDof == neighbor.el()->dof[ faceInNeighbor ][ 0 ] ); } } else { neighbor = element.father().child( 1-myIndex ); faceInNeighbor = 0; } } else faceInNeighbor = macroNeighbor( element, face, neighbor ); if( faceInNeighbor >= 0 ) { // refine until we share a refinement face of the neighbor if( !neighbor.isLeaf() && (faceInNeighbor < 2) ) { neighbor = neighbor.child( 1-faceInNeighbor ); faceInNeighbor = dimension; } assert( neighbor.el() == element.elInfo().neigh[ face ] ); } return faceInNeighbor; } template<> template<> int ElementInfo< 1 >::Library< dimWorld > ::levelNeighbors ( const ElementInfo &element, const int face, ElementInfo (&neighbor)[ maxLevelNeighbors ], int (&faceInNeighbor)[ maxLevelNeighbors ] ) { static const int neighborInFather[ 2 ][ numFaces ] = { {-1, 1}, {0, -1} }; assert( !!element ); int numNeighbors; // number of neighbors if grid is sufficiently fine if( element.level() > 0 ) { assert( (face >= 0) && (face < numFaces) ); const int myIndex = element.indexInFather(); const int nbInFather = neighborInFather[ myIndex ][ face ]; if( nbInFather >= 0 ) { numNeighbors = levelNeighbors( element.father(), nbInFather, neighbor, faceInNeighbor ); if( numNeighbors >= 0 ) { if( !neighbor[ 0 ].isLeaf() ) neighbor[ 0 ] = neighbor[ 0 ].child( 1-faceInNeighbor[ 0 ] ); else { faceInNeighbor[ 0 ] = -1; numNeighbors = 0; } } } else { // the neighbor is the other child of our father neighbor[ 0 ] = element.father().child( 1-myIndex ); faceInNeighbor[ 0 ] = 1-myIndex; numNeighbors = 1; } } else { // find macro level neighbors faceInNeighbor[ 0 ] = macroNeighbor( element, face, neighbor[ 0 ] ); numNeighbors = (faceInNeighbor[ 0 ] >= 0); } return numNeighbors; } template<> template<> int ElementInfo< 2 >::Library< dimWorld > ::levelNeighbors ( const ElementInfo &element, const int face, ElementInfo (&neighbor)[ maxLevelNeighbors ], int (&faceInNeighbor)[ maxLevelNeighbors ] ) { static const int neighborInFather[ 2 ][ numFaces ] = { {2, -1, 1}, {-1, 2, 0} }; assert( !!element ); int numNeighbors; // number of neighbors if grid is sufficiently fine if( element.level() > 0 ) { assert( (face >= 0) && (face < numFaces) ); const int myIndex = element.indexInFather(); const int nbInFather = neighborInFather[ myIndex ][ face ]; if( nbInFather >= 0 ) { numNeighbors = levelNeighbors( element.father(), nbInFather, neighbor, faceInNeighbor ); if( numNeighbors >= 0 ) { if( nbInFather >= 2 ) { // handle a refinement edge in inside if( faceInNeighbor[ 0 ] >= 2 ) { // handle a refinement edge in outside (common refinement edge) assert( numNeighbors < 2 ); int childIndex = myIndex; if( element.father().el()->dof[ 0 ][ 0 ] != neighbor[ 0 ].el()->dof[ 0 ][ 0 ] ) { assert( element.father().el()->dof[ 0 ][ 0 ] != neighbor[ 0 ].el()->dof[ 1 ][ 0 ] ); childIndex = 1-myIndex; } neighbor[ 0 ] = neighbor[ 0 ].child( childIndex ); faceInNeighbor[ 0 ] = childIndex; } else { // handle a non-refinement edge in outside if( numNeighbors >= 2 ) { // drop the neighbor for the other child neighbor[ 0 ] = neighbor[ myIndex ]; faceInNeighbor[ 0 ] = faceInNeighbor[ myIndex ]; numNeighbors = 1; } neighbor[ 0 ] = neighbor[ 0 ].child( 1-faceInNeighbor[ 0 ] ); faceInNeighbor[ 0 ] = 2; } } else { // handle non-refinement edge in inside if( faceInNeighbor[ 0 ] >= 2 ) { // handle refinement edge in outside assert( numNeighbors < 2 ); if( !neighbor[ 0 ].isLeaf() ) { if( element.father().el()->dof[ 2 ][ 0 ] != neighbor[ 0 ].el()->dof[ faceInNeighbor[ 0 ] ][ 0 ] ) { assert( element.father().el()->dof[ 2 ][ 0 ] == neighbor[ 0 ].el()->dof[ 1-faceInNeighbor[ 0 ] ][ 0 ] ); faceInNeighbor[ 0 ] = 0; } else faceInNeighbor[ 0 ] = 1; faceInNeighbor[ 1 ] = 1 - faceInNeighbor[ 0 ]; neighbor[ 1 ] = neighbor[ 0 ].child( faceInNeighbor[ 1 ] ); neighbor[ 0 ] = neighbor[ 0 ].child( faceInNeighbor[ 0 ] ); numNeighbors = 2; } else numNeighbors = 0; } else { // handle non-refinement edge in outside int realNumNeighbors = 0; for( int i = 0; i < numNeighbors; ++i ) { assert( faceInNeighbor[ i ] < 2 ); if( faceInNeighbor[ i ] < 0 ) continue; if( !neighbor[ i ].isLeaf() ) { neighbor[ i ] = neighbor[ i ].child( 1-faceInNeighbor[ i ] ); faceInNeighbor[ i ] = 2; ++realNumNeighbors; } else faceInNeighbor[ i ] = -1; } numNeighbors = (realNumNeighbors > 0 ? numNeighbors : 0); } } } } else { // the neighbor is the other child of our father neighbor[ 0 ] = element.father().child( 1-myIndex ); faceInNeighbor[ 0 ] = myIndex; faceInNeighbor[ 1 ] = -1; numNeighbors = 1; } } else { // find macro level neighbors faceInNeighbor[ 0 ] = macroNeighbor( element, face, neighbor[ 0 ] ); faceInNeighbor[ 1 ] = -1; numNeighbors = (faceInNeighbor[ 0 ] >= 0); } return numNeighbors; } template<> template<> int ElementInfo< 3 >::Library< dimWorld > ::levelNeighbors ( const ElementInfo &element, const int face, ElementInfo (&neighbor)[ maxLevelNeighbors ], int (&faceInNeighbor)[ maxLevelNeighbors ] ) { assert( !!element ); int numNeighbors; if( element.level() > 0 ) { // we support level neighbors only on the macro level for now numNeighbors = 0; } else { // find macro level neighbors faceInNeighbor[ 0 ] = macroNeighbor( element, face, neighbor[ 0 ] ); numNeighbors = (faceInNeighbor[ 0 ] >= 0); } return numNeighbors; } } } #else #error "Library for AlbertaGrid can only be compiled if ALBERTA has been found by configure." #endif // #if HAVE_ALBERTA dune-grid-2.11.0/dune/grid/albertagrid/elementinfo.hh000066400000000000000000000570521511655130300224500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_ELEMENTINFO_HH #define DUNE_ALBERTA_ELEMENTINFO_HH /** \file * \author Martin Nolte * \brief provides a wrapper for ALBERTA's el_info structure */ #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // External Forward Declarations // ----------------------------- template< int dim > class MeshPointer; struct BasicNodeProjection; // ElementInfo // ----------- template< int dim > class ElementInfo { struct Instance; class Stack; template< int > struct Library; typedef Instance *InstancePtr; public: static const int dimension = dim; static const int numVertices = NumSubEntities< dimension, dimension >::value; static const int numFaces = NumSubEntities< dimension, 1 >::value; typedef Alberta::MacroElement< dimension > MacroElement; typedef Alberta::MeshPointer< dimension > MeshPointer; typedef Alberta::FillFlags< dimension > FillFlags; static const int maxNeighbors = N_NEIGH_MAX; static const int maxLevelNeighbors = Library< dimWorld >::maxLevelNeighbors; #if !DUNE_ALBERTA_CACHE_COORDINATES typedef GeometryCacheProxy< dim > GeometryCache; #endif struct Seed; private: explicit ElementInfo ( const InstancePtr &instance ); public: ElementInfo (); ElementInfo ( const MeshPointer &mesh, const MacroElement ¯oElement, typename FillFlags::Flags fillFlags = FillFlags::standard ); ElementInfo ( const MeshPointer &mesh, const Seed &seed, typename FillFlags::Flags fillFlags = FillFlags::standard ); ElementInfo ( const ElementInfo &other ); ElementInfo ( ElementInfo&& other ); ~ElementInfo (); ElementInfo &operator= ( const ElementInfo &other ); ElementInfo &operator= ( ElementInfo &&other ); explicit operator bool () const { return (instance_ != null()); } bool operator== ( const ElementInfo &other ) const; bool operator!= ( const ElementInfo &other ) const; const MacroElement ¯oElement () const; ElementInfo father () const; int indexInFather () const; ElementInfo child ( int i ) const; bool isLeaf () const; Seed seed () const; MeshPointer mesh () const; bool mightVanish () const; int level () const; // see ALBERTA documentation for definition of element type // values are 0, 1, 2 int type () const; int getMark () const; void setMark ( int refCount ) const; bool hasLeafNeighbor ( const int face ) const; ElementInfo leafNeighbor ( const int face ) const; /* obtain all level neighbors of a face * * param[in] face face for which the neighbors are desired * param[out] neighbor array storing the neighbors * param[out] faceInNeighbor array storing the faces in neighbor * (-1, if this neighbor does not exist) * * returns (potential) number of neighbors (i.e., the number of valid * entries in the output arrays */ int levelNeighbors ( const int face, ElementInfo (&neighbor)[ maxLevelNeighbors ], int (&faceInNeighbor)[ maxLevelNeighbors ] ) const; template< int codim > int twist ( int subEntity ) const; int twistInNeighbor ( int face ) const; bool isBoundary ( int face ) const; int boundaryId ( int face ) const; AffineTransformation *transformation ( int face ) const; BasicNodeProjection *boundaryProjection ( int face ) const; bool hasCoordinates () const; const GlobalVector &coordinate ( int vertex ) const; #if !DUNE_ALBERTA_CACHE_COORDINATES GeometryCache geometryCache () const { return GeometryCache( instance_->geometryCache, instance_->elInfo ); } #endif template< class Functor > void hierarchicTraverse ( Functor &functor ) const; template< class Functor > void leafTraverse ( Functor &functor ) const; const Element *element () const; const Element *neighbor ( int face ) const; Element *el () const; ALBERTA EL_INFO &elInfo () const; static ElementInfo createFake ( const MeshPointer &mesh, const Element *element, int level, int type = 0 ); static ElementInfo createFake ( const ALBERTA EL_INFO &elInfo ); private: static bool isLeaf ( Element *element ); static bool mightVanish ( Element *element, int depth ); static void fill ( Mesh *mesh, const ALBERTA MACRO_EL *mel, ALBERTA EL_INFO &elInfo ); static void fill ( int ichild, const ALBERTA EL_INFO &parentInfo, ALBERTA EL_INFO &elInfo ); void addReference () const; void removeReference () const; static InstancePtr null (); static Stack &stack (); InstancePtr instance_; }; // ElementInfo::Instance // --------------------- template< int dim > struct ElementInfo< dim >::Instance { ALBERTA EL_INFO elInfo; unsigned int refCount; InstancePtr &parent () { return parent_; } private: InstancePtr parent_; #if !DUNE_ALBERTA_CACHE_COORDINATES public: Alberta::GeometryCache< dim > geometryCache; #endif }; // ElementInfo::Stack // ------------------ template< int dim > class ElementInfo< dim >::Stack { InstancePtr top_; Instance null_; public: Stack (); ~Stack (); InstancePtr allocate (); void release ( InstancePtr &p ); InstancePtr null (); }; // ElementInfo::Library // -------------------- template< int dim > template< int > struct ElementInfo< dim >::Library { typedef Alberta::ElementInfo< dim > ElementInfo; static const int maxLevelNeighbors = (1 << (dim-1)); static int leafNeighbor ( const ElementInfo &element, const int face, ElementInfo &neighbor ); static int levelNeighbors ( const ElementInfo &element, const int face, ElementInfo (&neighbor)[ maxLevelNeighbors ], int (&faceInNeighbor)[ maxLevelNeighbors ] ); private: static int macroNeighbor ( const ElementInfo &element, const int face, ElementInfo &neighbor ); }; // ElementInfo::Seed // ----------------- template< int dim > struct ElementInfo< dim >::Seed { Seed () : macroIndex_( -1 ), level_( 0 ), path_( 0 ) {} Seed ( const int macroIndex, const int level, const unsigned long path ) : macroIndex_( macroIndex ), level_( level ), path_( path ) {} bool operator== ( const Seed &other ) const { return (macroIndex() == other.macroIndex()) && (level() == other.level()) && (path() == other.path()); } bool operator< ( const Seed &other ) const { const bool ml = (macroIndex() < other.macroIndex()); const bool me = (macroIndex() == other.macroIndex()); const bool ll = (level() < other.level()); const bool le = (level() == other.level()); const bool pl = (path() < other.path()); return ml | (me & (ll | (le & pl))); } bool operator!= ( const Seed &other ) const { return !(*this == other); } bool operator<= ( const Seed &other ) const { return !(other < *this); } bool operator> ( const Seed &other ) const { return (other < *this); } bool operator>= ( const Seed &other ) const { return !(*this < other); } bool isValid ( ) const { return macroIndex_ != -1; } int macroIndex () const { return macroIndex_; } int level () const { return level_; } unsigned long path () const { return path_; } private: int macroIndex_; int level_; unsigned long path_; }; // Implementation of ElementInfo // ----------------------------- template< int dim > inline ElementInfo< dim >::ElementInfo ( const InstancePtr &instance ) : instance_( instance ) { addReference(); } template< int dim > inline ElementInfo< dim >::ElementInfo () : instance_( null() ) { addReference(); } template< int dim > inline ElementInfo< dim > ::ElementInfo ( const MeshPointer &mesh, const MacroElement ¯oElement, typename FillFlags::Flags fillFlags ) { instance_ = stack().allocate(); instance_->parent() = null(); ++(instance_->parent()->refCount); addReference(); elInfo().fill_flag = fillFlags; // Alberta fills opp_vertex only if there is a neighbor for( int k = 0; k < maxNeighbors; ++k ) elInfo().opp_vertex[ k ] = -1; fill( mesh, ¯oElement, elInfo() ); } template< int dim > inline ElementInfo< dim > ::ElementInfo ( const MeshPointer &mesh, const Seed &seed, typename FillFlags::Flags fillFlags ) { instance_ = stack().allocate(); instance_->parent() = null(); ++(instance_->parent()->refCount); addReference(); // fill in macro element info elInfo().fill_flag = fillFlags; // Alberta fills opp_vertex only if there is a neighbor for( int k = 0; k < maxNeighbors; ++k ) elInfo().opp_vertex[ k ] = -1; fill( mesh, ((Mesh *)mesh)->macro_els + seed.macroIndex(), elInfo() ); // traverse the seed's path unsigned long path = seed.path(); for( int i = 0; i < seed.level(); ++i ) { InstancePtr child = stack().allocate(); child->parent() = instance_; // Alberta fills opp_vertex only if there is a neighbor for( int k = 0; k < maxNeighbors; ++k ) child->elInfo.opp_vertex[ k ] = -2; fill( path & 1, elInfo(), child->elInfo ); instance_ = child; addReference(); path = path >> 1; } assert( this->seed() == seed ); } template< int dim > inline ElementInfo< dim >::ElementInfo ( const ElementInfo &other ) : instance_( other.instance_ ) { addReference(); } template< int dim > inline ElementInfo< dim >::ElementInfo ( ElementInfo &&other ) : instance_( NULL ) { using std::swap; swap( instance_, other.instance_ ); } template< int dim > inline ElementInfo< dim >::~ElementInfo () { removeReference(); } template< int dim > inline ElementInfo< dim > & ElementInfo< dim >::operator= ( const ElementInfo< dim > &other ) { other.addReference(); removeReference(); instance_ = other.instance_; return *this; } template< int dim > inline ElementInfo< dim > & ElementInfo< dim >::operator= ( ElementInfo< dim > &&other ) { using std::swap; swap( instance_, other.instance_ ); return *this; } template< int dim > inline bool ElementInfo< dim >::operator== ( const ElementInfo< dim > &other ) const { return (instance_->elInfo.el == other.instance_->elInfo.el); } template< int dim > inline bool ElementInfo< dim >::operator!= ( const ElementInfo< dim > &other ) const { return (instance_->elInfo.el != other.instance_->elInfo.el); } template< int dim > inline const typename ElementInfo< dim >::MacroElement & ElementInfo< dim >::macroElement () const { assert( !!(*this) ); assert( elInfo().macro_el != NULL ); return static_cast< const MacroElement & >( *(elInfo().macro_el) ); } template< int dim > inline ElementInfo< dim > ElementInfo< dim >::father () const { assert( !!(*this) ); return ElementInfo< dim >( instance_->parent() ); } template< int dim > inline int ElementInfo< dim >::indexInFather () const { const Element *element = elInfo().el; const Element *father = elInfo().parent->el; assert( father != NULL ); const int index = (father->child[ 0 ] == element ? 0 : 1); assert( father->child[ index ] == element ); return index; } template< int dim > inline ElementInfo< dim > ElementInfo< dim >::child ( int i ) const { assert( !isLeaf() ); InstancePtr child = stack().allocate(); child->parent() = instance_; addReference(); // Alberta fills opp_vertex only if there is a neighbor for( int k = 0; k < maxNeighbors; ++k ) child->elInfo.opp_vertex[ k ] = -2; fill( i, elInfo(), child->elInfo ); return ElementInfo< dim >( child ); } template< int dim > inline bool ElementInfo< dim >::isLeaf () const { assert( !(*this) == false ); return isLeaf( el() ); } template< int dim > inline typename ElementInfo< dim >::Seed ElementInfo< dim >::seed () const { assert( !!(*this) ); int level = 0; unsigned long path = 0; for( InstancePtr p = instance_; p->parent() != null(); p = p->parent() ) { const Element *element = p->elInfo.el; const Element *father = p->parent()->elInfo.el; const unsigned long child = static_cast< unsigned long >( father->child[ 1 ] == element ); path = (path << 1) | child; ++level; } if( level != elInfo().level ) DUNE_THROW( NotImplemented, "Seed for fake elements not implemented." ); return Seed( macroElement().index, level, path ); } template< int dim > inline typename ElementInfo< dim >::MeshPointer ElementInfo< dim >::mesh () const { return MeshPointer( elInfo().mesh ); } template< int dim > inline bool ElementInfo< dim >::mightVanish () const { return mightVanish( el(), 0 ); } template< int dim > inline int ElementInfo< dim >::level () const { return elInfo().level; } template< int dim > inline int ElementInfo< dim >::type () const { return 0; } template<> inline int ElementInfo< 3 >::type () const { return instance_->elInfo.el_type; } template< int dim > inline int ElementInfo< dim >::getMark () const { return el()->mark; } template< int dim > inline void ElementInfo< dim >::setMark ( int refCount ) const { assert( isLeaf() ); assert( (refCount >= -128) && (refCount < 127) ); el()->mark = refCount; } template< int dim > inline bool ElementInfo< dim >::hasLeafNeighbor ( const int face ) const { assert( !!(*this) ); assert( (face >= 0) && (face < maxNeighbors) ); assert( (elInfo().fill_flag & FillFlags::boundaryId) != 0 ); const int macroFace = elInfo().macro_wall[ face ]; if( macroFace >= 0 ) return (macroElement().neighbor( macroFace ) != NULL); else return true; } template< int dim > inline ElementInfo< dim > ElementInfo< dim >::leafNeighbor ( const int face ) const { assert( (face >= 0) && (face < numFaces) ); ElementInfo neighbor; Library< dimWorld >::leafNeighbor( *this, face, neighbor ); return neighbor; } template< int dim > inline int ElementInfo< dim > ::levelNeighbors ( const int face, ElementInfo (&neighbor)[ maxLevelNeighbors ], int (&faceInNeighbor)[ maxLevelNeighbors ] ) const { assert( (face >= 0) && (face < numFaces) ); return Library< dimWorld >::levelNeighbors( *this, face, neighbor, faceInNeighbor ); } template< int dim > template< int codim > inline int ElementInfo< dim >::twist ( int subEntity ) const { return Twist< dim, dim-codim >::twist( element(), subEntity ); } template< int dim > inline int ElementInfo< dim >::twistInNeighbor ( const int face ) const { assert( neighbor( face ) != NULL ); return Twist< dim, dim-1 >::twist( neighbor( face ), elInfo().opp_vertex[ face ] ); } template< int dim > inline bool ElementInfo< dim >::isBoundary ( int face ) const { assert( !!(*this) ); assert( (face >= 0) && (face < maxNeighbors) ); assert( (elInfo().fill_flag & FillFlags::boundaryId) != 0 ); const int macroFace = elInfo().macro_wall[ face ]; if( macroFace >= 0 ) return macroElement().isBoundary( macroFace ); else return false; } template< int dim > inline int ElementInfo< dim >::boundaryId ( int face ) const { assert( !!(*this) ); assert( (face >= 0) && (face < N_WALLS_MAX) ); assert( (elInfo().fill_flag & FillFlags::boundaryId) != 0 ); const int macroFace = elInfo().macro_wall[ face ]; const int id = macroElement().boundaryId( macroFace ); // this assertion is only allowed, if FILL_BOUND is set // assert( id == elInfo().wall_bound[ face ] ); return id; } template< int dim > inline AffineTransformation * ElementInfo< dim >::transformation ( int face ) const { assert( !!(*this) ); assert( (face >= 0) && (face < N_WALLS_MAX) ); assert( (elInfo().fill_flag & FillFlags::boundaryId) != 0 ); const int macroFace = elInfo().macro_wall[ face ]; return (macroFace < 0 ? NULL : macroElement().wall_trafo[ macroFace ]); } template< int dim > inline BasicNodeProjection * ElementInfo< dim >::boundaryProjection ( int face ) const { assert( !!(*this) ); assert( (face >= 0) && (face < N_WALLS_MAX) ); assert( (elInfo().fill_flag & FillFlags::boundaryId) != 0 ); const int macroFace = elInfo().macro_wall[ face ]; if( macroFace >= 0 ) return static_cast< BasicNodeProjection * >( macroElement().projection[ macroFace+1 ] ); else return 0; } template< int dim > inline bool ElementInfo< dim >::hasCoordinates () const { return ((elInfo().fill_flag & FillFlags::coords) != 0); } template< int dim > inline const GlobalVector &ElementInfo< dim >::coordinate ( int vertex ) const { assert( hasCoordinates() ); assert( (vertex >= 0) && (vertex < numVertices) ); return elInfo().coord[ vertex ]; } template< int dim > template< class Functor > inline void ElementInfo< dim >::hierarchicTraverse ( Functor &functor ) const { functor( *this ); if( !isLeaf() ) { child( 0 ).hierarchicTraverse( functor ); child( 1 ).hierarchicTraverse( functor ); } } template< int dim > template< class Functor > inline void ElementInfo< dim >::leafTraverse ( Functor &functor ) const { if( !isLeaf() ) { child( 0 ).leafTraverse( functor ); child( 1 ).leafTraverse( functor ); } else functor( *this ); } template< int dim > inline const Element *ElementInfo< dim >::element () const { return elInfo().el; } template< int dim > inline const Element *ElementInfo< dim >::neighbor ( int face ) const { assert( (face >= 0) && (face < numFaces) ); assert( (elInfo().fill_flag & FillFlags::neighbor) != 0 ); return elInfo().neigh[ face ]; } template< int dim > inline Element *ElementInfo< dim >::el () const { return elInfo().el; } template< int dim > inline ALBERTA EL_INFO &ElementInfo< dim >::elInfo () const { return (instance_->elInfo); } template< int dim > inline ElementInfo< dim > ElementInfo< dim >::createFake ( const MeshPointer &mesh, const Element *element, int level, int type ) { InstancePtr instance = stack().allocate(); instance->parent() = null(); ++(instance->parent()->refCount); instance->elInfo.mesh = mesh; instance->elInfo.macro_el = NULL; instance->elInfo.el = const_cast< Element * >( element ); instance->elInfo.parent = NULL; instance->elInfo.fill_flag = FillFlags::nothing; instance->elInfo.level = level; instance->elInfo.el_type = type; return ElementInfo< dim >( instance ); } template< int dim > inline ElementInfo< dim > ElementInfo< dim >::createFake ( const ALBERTA EL_INFO &elInfo ) { InstancePtr instance = stack().allocate(); instance->parent() = null(); ++(instance->parent()->refCount); instance->elInfo = elInfo; return ElementInfo< dim >( instance ); } template< int dim > inline bool ElementInfo< dim >::isLeaf ( Element *element ) { return IS_LEAF_EL( element ); } template< int dim > inline bool ElementInfo< dim >::mightVanish ( Alberta::Element *element, int depth ) { if( isLeaf( element ) ) return (element->mark < depth); else return (mightVanish( element->child[ 0 ], depth-1 ) && mightVanish( element->child[ 1 ], depth-1 )); } template< int dim > inline void ElementInfo< dim > ::fill ( Mesh *mesh, const ALBERTA MACRO_EL *mel, ALBERTA EL_INFO &elInfo ) { ALBERTA fill_macro_info( mesh, mel, &elInfo ); } template< int dim > inline void ElementInfo< dim > ::fill ( int ichild, const ALBERTA EL_INFO &parentInfo, ALBERTA EL_INFO &elInfo ) { ALBERTA fill_elinfo( ichild, FILL_ANY, &parentInfo, &elInfo ); } template< int dim > inline void ElementInfo< dim >::addReference () const { ++(instance_->refCount); } template< int dim > inline void ElementInfo< dim >::removeReference () const { // short-circuit for rvalues that have been drained as argument to a move operation if ( !instance_ ) return; // this loop breaks when instance becomes null() for( InstancePtr instance = instance_; --(instance->refCount) == 0; ) { const InstancePtr parent = instance->parent(); stack().release( instance ); instance = parent; } } template< int dim > inline typename ElementInfo< dim >::InstancePtr ElementInfo< dim >::null () { return stack().null(); } template< int dim > inline typename ElementInfo< dim >::Stack & ElementInfo< dim >::stack () { static Stack s; return s; } // Implementation of ElementInfo::Stack // ------------------------------------ template< int dim > inline ElementInfo< dim >::Stack::Stack () : top_( 0 ) { null_.elInfo.el = NULL; null_.refCount = 1; null_.parent() = 0; } template< int dim > inline ElementInfo< dim >::Stack::~Stack () { while( top_ != 0 ) { InstancePtr p = top_; top_ = p->parent(); delete p; } } template< int dim > inline typename ElementInfo< dim >::InstancePtr ElementInfo< dim >::Stack::allocate () { InstancePtr p = top_; if( p != 0 ) top_ = p->parent(); else p = new Instance; p->refCount = 0; return p; } template< int dim > inline void ElementInfo< dim >::Stack::release ( InstancePtr &p ) { assert( (p != null()) && (p->refCount == 0) ); p->parent() = top_; top_ = p; } template< int dim > inline typename ElementInfo< dim >::InstancePtr ElementInfo< dim >::Stack::null () { return &null_; } } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_ELEMENTINFO_HH dune-grid-2.11.0/dune/grid/albertagrid/entity.cc000066400000000000000000000231021511655130300214320ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_ENTITY_CC #define DUNE_ALBERTA_ENTITY_CC namespace Dune { // AlbertaGridEntity (for codim > 0) // --------------------------------- template inline AlbertaGridEntity< codim, dim, Grid > ::AlbertaGridEntity ( const Grid &grid, const ElementInfo &elementInfo, int subEntity ) : grid_( &grid ), elementInfo_( elementInfo ), subEntity_( subEntity ) {} template inline AlbertaGridEntity< codim, dim, Grid > ::AlbertaGridEntity ( const Grid &grid ) : grid_( &grid ), elementInfo_(), subEntity_( -1 ) {} template inline AlbertaGridEntity< codim, dim, Grid > ::AlbertaGridEntity () : grid_( NULL ), elementInfo_(), subEntity_( -1 ) {} template< int codim, int dim, class Grid > inline PartitionType AlbertaGridEntity< codim,dim,Grid >::partitionType () const { return InteriorEntity; } template< int codim, int dim, class Grid > inline bool AlbertaGridEntity< codim, dim, Grid >::equals ( const This &other ) const { const Alberta::Element *e1 = elementInfo().el(); const Alberta::Element *e2 = other.elementInfo().el(); // if both element null then they are equal if( (e1 == NULL) && (e2 == NULL) ) return true; return ((e1 == e2) && (subEntity_ == other.subEntity_)); } template< int codim, int dim, class Grid > inline ALBERTA EL_INFO * AlbertaGridEntity< codim, dim, Grid >::getElInfo () const { return &(elementInfo_.elInfo()); } template< int codim, int dim, class Grid > inline void AlbertaGridEntity< codim, dim, Grid >::clearElement () { elementInfo_ = ElementInfo(); } template< int codim, int dim, class Grid > inline void AlbertaGridEntity< codim, dim, Grid > ::setElement ( const ElementInfo &elementInfo, int subEntity ) { elementInfo_ = elementInfo; subEntity_ = subEntity; } template< int codim, int dim, class Grid > inline void AlbertaGridEntity< codim, dim, Grid >::setEntity ( const This &other ) { setElement( other.elementInfo_, other.subEntity_ ); } template< int codim, int dim, class Grid > inline int AlbertaGridEntity< codim, dim, Grid >::level() const { assert( elementInfo_.level() == grid().levelProvider() ( elementInfo_ ) ); return elementInfo_.level(); } template< int codim, int dim, class Grid > inline typename AlbertaGridEntity< codim, dim, Grid >::Geometry AlbertaGridEntity< codim, dim, Grid >::geometry () const { typedef AlbertaGridCoordinateReader< codim, Grid > CoordReader; assert( elementInfo_ ); const CoordReader coordReader( grid(), elementInfo_, subEntity_ ); return Geometry( GeometryImpl( coordReader ) ); } template< int codim, int dim, class Grid > inline GeometryType AlbertaGridEntity< codim, dim, Grid >::type () const { return GeometryTypes::simplex( mydimension ); } // AlbertaGridEntity (for codim = 0) // --------------------------------- template< int dim, class Grid > inline AlbertaGridEntity< 0, dim, Grid > ::AlbertaGridEntity ( const Grid &grid, const ElementInfo &elementInfo, int subEntity ) : grid_( &grid ), elementInfo_( elementInfo ) { assert( subEntity == 0 ); } template< int dim, class Grid > inline AlbertaGridEntity< 0, dim, Grid > ::AlbertaGridEntity( const Grid &grid ) : grid_( &grid ), elementInfo_() {} template< int dim, class Grid > inline AlbertaGridEntity< 0, dim, Grid > ::AlbertaGridEntity () : grid_( NULL ), elementInfo_() {} template< int dim, class Grid > inline int AlbertaGridEntity< 0, dim, Grid >::boundaryId() const { // elements are always inside of our Domain return 0; } template< int dim, class Grid > inline bool AlbertaGridEntity< 0, dim, Grid >::isNew () const { return grid().levelProvider().isNew( elementInfo_ ); } template< int dim, class Grid > inline bool AlbertaGridEntity< 0, dim, Grid >::mightVanish () const { return elementInfo_.mightVanish(); } template< int dim, class Grid > inline bool AlbertaGridEntity< 0, dim, Grid >::hasBoundaryIntersections () const { assert( elementInfo_ ); bool isBoundary = false; for( int i = 0; i < dim+1; ++i ) isBoundary |= elementInfo_.isBoundary( i ); return isBoundary; } template< int dim, class Grid > inline PartitionType AlbertaGridEntity< 0, dim, Grid >::partitionType () const { return InteriorEntity; } template< int dim, class Grid > inline bool AlbertaGridEntity< 0, dim,Grid >::isLeaf () const { return elementInfo_.isLeaf(); } template< int dim, class Grid > inline bool AlbertaGridEntity< 0, dim, Grid >::equals ( const This &other ) const { // element pointers are unique return (elementInfo().el() == other.elementInfo().el()); } template< int dim, class Grid > template< int codim > inline typename Grid::template Codim< codim >::Entity AlbertaGridEntity< 0, dim, Grid >::subEntity ( int i ) const { typedef AlbertaGridEntity< codim, dim, Grid > EntityImpl; return EntityImpl( grid(), elementInfo_, grid().generic2alberta( codim, i ) ); } template< int dim, class Grid > inline ALBERTA EL_INFO * AlbertaGridEntity< 0, dim, Grid >::getElInfo () const { return &(elementInfo_.elInfo()); } template< int dim, class Grid > inline int AlbertaGridEntity< 0, dim, Grid >::level () const { assert( elementInfo_.level() == grid().levelProvider() ( elementInfo_ ) ); return elementInfo_.level(); } template< int dim, class Grid > inline void AlbertaGridEntity< 0, dim, Grid >::clearElement () { elementInfo_ = ElementInfo(); } template< int dim, class Grid > inline void AlbertaGridEntity< 0, dim, Grid > ::setElement ( const ElementInfo &elementInfo, int /* subEntity */ ) { elementInfo_ = elementInfo; } template< int dim, class Grid > inline void AlbertaGridEntity< 0, dim, Grid >::setEntity( const This &other ) { setElement( other.elementInfo_, 0 ); } template< int dim, class Grid > inline typename AlbertaGridEntity< 0, dim, Grid >::Geometry AlbertaGridEntity< 0, dim, Grid >::geometry () const { typedef AlbertaGridCoordinateReader< 0, Grid > CoordReader; assert( elementInfo_ ); const CoordReader coordReader( grid(), elementInfo_, 0 ); return Geometry( GeometryImpl( coordReader ) ); } template< int dim, class Grid > inline GeometryType AlbertaGridEntity< 0, dim, Grid>::type () const { return GeometryTypes::simplex( mydimension ); } template< int dim, class Grid > inline typename Grid::template Codim< 0 >::Entity AlbertaGridEntity< 0, dim, Grid >::father () const { typedef AlbertaGridEntity< 0, dim, Grid > EntityImpl; assert( elementInfo_ ); const ElementInfo fatherInfo = elementInfo_.father(); return EntityImpl( grid(), fatherInfo, 0 ); } template< int dim, class Grid > inline int AlbertaGridEntity< 0, dim, Grid >::nChild () const { return elementInfo_.indexInFather(); } template< int dim, class Grid > inline typename AlbertaGridEntity< 0, dim, Grid >::LocalGeometry AlbertaGridEntity< 0, dim, Grid >::geometryInFather() const { typedef AlbertaGridLocalGeometryProvider< Grid > LocalGeoProvider; const int indexInFather = elementInfo_.indexInFather(); const int orientation = (elementInfo_.type() == 1 ? -1 : 1); return LocalGeometry( LocalGeoProvider::instance().geometryInFather( indexInFather, orientation ) ); } template< int dim, class Grid > inline typename AlbertaGridEntity< 0, dim, Grid >::HierarchicIterator AlbertaGridEntity< 0, dim, Grid >::hbegin( int maxlevel ) const { assert( elementInfo_ ); typedef AlbertaGridHierarchicIterator< Grid > IteratorImp; return IteratorImp( grid(), elementInfo_, maxlevel ); } template< int dim, class Grid > inline typename AlbertaGridEntity< 0, dim, Grid >::HierarchicIterator AlbertaGridEntity< 0, dim, Grid>::hend( int maxlevel ) const { assert( elementInfo_ ); typedef AlbertaGridHierarchicIterator< Grid > IteratorImp; return IteratorImp( grid(), level(), maxlevel ); } template< int dim, class Grid > inline typename AlbertaGridEntity< 0, dim, Grid >::AlbertaGridLeafIntersectionIterator AlbertaGridEntity< 0, dim, Grid >::ileafbegin() const { assert( elementInfo_ ); #ifndef NDEBUG for( int i = 0; i <= dimension; ++i ) { // std::cout << "Opposite vertex " << i << ": " // << (int)(getElInfo()->opp_vertex[ i ]) << std::endl; if( getElInfo()->opp_vertex[ i ] == 127 ) { assert( false ); DUNE_THROW( NotImplemented, "AlbertaGrid: Intersections on outside " "entities are not fully implemented, yet." ); } } #endif // #ifndef NDEBUG typename AlbertaGridLeafIntersectionIterator::Begin begin; return AlbertaGridLeafIntersectionIterator( *this, begin ); } template< int dim, class Grid > inline typename AlbertaGridEntity< 0, dim, Grid >::AlbertaGridLeafIntersectionIterator AlbertaGridEntity< 0, dim, Grid >::ileafend() const { assert( elementInfo_ ); typename AlbertaGridLeafIntersectionIterator::End end; return AlbertaGridLeafIntersectionIterator( *this, end ); } } // namespace Dune #endif // #ifndef DUNE_ALBERTA_ENTITY_CC dune-grid-2.11.0/dune/grid/albertagrid/entity.hh000066400000000000000000000273311511655130300214540ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_ENTITY_HH #define DUNE_ALBERTA_ENTITY_HH #include #include #include #include #if HAVE_ALBERTA namespace Dune { // Forward Declarations // -------------------- template< int codim, class Grid, bool leafIterator > class AlbertaGridTreeIterator; template< class Grid > class AlbertaGridHierarchicIterator; template< class Grid > class AlbertaGridLeafIntersection; template< class Grid > class AlbertaGridLeafIntersectionIterator; // AlbertaGridEntity // ----------------- /*! A grid is a container of grid entities. An entity is parametrized by the codimension. An entity of codimension c in dimension d is a d-c dimensional object. */ template< int codim, int dim, class Grid > class AlbertaGridEntity : public EntityDefaultImplementation< codim, dim, Grid, AlbertaGridEntity > { typedef AlbertaGridEntity< codim, dim, Grid > This; constexpr static int dimworld = Grid::dimensionworld; friend class AlbertaGrid< dim, dimworld >; friend class AlbertaGridEntity< 0, dim, Grid >; friend class AlbertaGridHierarchicIterator< Grid >; template< int, class, bool > friend class AlbertaGridTreeIterator; public: static const int dimension = dim; static const int codimension = codim; static const int mydimension = dimension - codimension; template< int cd > struct Codim { typedef typename Grid::template Codim< cd >::Entity Entity; }; typedef typename Grid::template Codim< codim >::Entity Entity; typedef typename Grid::template Codim< codim >::EntitySeed EntitySeed; typedef typename Grid::template Codim< codim >::Geometry Geometry; typedef Alberta::ElementInfo< dimension > ElementInfo; private: typedef typename Grid::Traits::template Codim< codim >::GeometryImpl GeometryImpl; public: //! constructor explicit AlbertaGridEntity ( const Grid &grid ); AlbertaGridEntity (); //! constructor AlbertaGridEntity ( const Grid &grid, const ElementInfo &elementInfo, int subEntity ); //! level of this element int level () const; //! return partition type of this entity PartitionType partitionType() const; //! geometry of this entity Geometry geometry () const; //! type of geometry of this entity GeometryType type () const; //! obtain entity seed EntitySeed seed () const { return EntitySeed( AlbertaGridEntitySeed< codim, Grid >( elementInfo(), subEntity() ) ); } /** \brief Obtain the number of subentities of a given codimension * * That number is ((mydimension+1) over (dim-cd+1)) * * \param cd codimension * * \returns the number of subentities of the given codimension */ unsigned int subEntities ( unsigned int cd ) const { int n = mydimension+1; int k = dimension-cd+1; // binomial: n over k int binomial=1; for (int i=n-k+1; i<=n; i++) binomial *= i; for (long i=2; i<=k; i++) binomial /= i; return binomial; } //*********************************************** // end of interface methods //*********************************************** //! needed for the LevelIterator and LeafIterator ALBERTA EL_INFO *getElInfo () const; const ElementInfo &elementInfo () const { return elementInfo_; } //! equality of entities bool equals ( const This &other ) const; void clearElement (); void setElement ( const ElementInfo &elementInfo, int subEntity ); // same as setElInfo just with a entity given void setEntity ( const This &other ); //! obtain a reference to the grid const Grid &grid () const { return *grid_; } //! obtain number of the subentity within the element (in ALBERTA numbering) int subEntity () const { return subEntity_; } //! obtain twist int twist () const { return elementInfo().template twist< codimension >( subEntity() ); } private: // grid this entity belong to const Grid *grid_; // ALBERTA element info ElementInfo elementInfo_; // number of the subentity within the element (in ALBERTA numbering) int subEntity_; }; // AlbertaGridEntity for codimension 0 // ----------------------------------- /*! A grid is a container of grid entities. An entity is parametrized by the codimension. An entity of codimension c in dimension d is a d-c dimensional object. Entities of codimension 0 ("elements") are defined through template specialization. Note that this specialization has an extended interface compared to the general case */ template< int dim, class Grid > class AlbertaGridEntity< 0, dim, Grid > : public EntityDefaultImplementation< 0, dim, Grid, AlbertaGridEntity > { typedef AlbertaGridEntity< 0, dim, Grid > This; static const int dimworld = Grid::dimensionworld; friend class AlbertaGrid< dim, dimworld >; friend class AlbertaGridLeafIntersection< Grid >; friend class AlbertaGridHierarchicIterator< Grid >; template< int, class, bool > friend class AlbertaGridTreeIterator; public: static const int dimension = dim; static const int codimension = 0; static const int mydimension = dimension - codimension; template< int codim > struct Codim { typedef typename Grid::template Codim< codim >::Entity Entity; }; typedef typename Grid::template Codim< 0 >::Entity Entity; typedef typename Grid::template Codim< 0 >::EntitySeed EntitySeed; typedef typename Grid::template Codim< 0 >::Geometry Geometry; typedef typename Grid::template Codim< 0 >::LocalGeometry LocalGeometry; typedef typename Grid::Traits::template Codim< 0 >::GeometryImpl GeometryImpl; typedef typename Grid::HierarchicIterator HierarchicIterator; typedef Dune::AlbertaGridLeafIntersectionIterator< Grid > AlbertaGridLeafIntersectionIterator; typedef AlbertaGridLeafIntersectionIterator AlbertaGridLevelIntersectionIterator; typedef Alberta::ElementInfo< dimension > ElementInfo; //! constructor explicit AlbertaGridEntity ( const Grid &grid ); AlbertaGridEntity (); //! constructor AlbertaGridEntity ( const Grid &grid, const ElementInfo &elementInfo, int subEntity ); //! level of this element int level () const; //! index of the boundary which is associated with the entity, 0 for inner entities int boundaryId () const; //! geometry of this entity Geometry geometry () const; //! type of geometry of this entity GeometryType type () const; //! obtain entity seed EntitySeed seed () const { return EntitySeed( AlbertaGridEntitySeed< 0, Grid >(elementInfo() )); } /** \brief Obtain the number of subentities of a given codimension * * That number is ((mydimension+1) over (dim-cd+1)) * * \param cd codimension * * \returns the number of subentities of the given codimension */ unsigned int subEntities ( unsigned int cd ) const { int n = mydimension+1; int k = dimension-cd+1; // binomial: n over k int binomial=1; for (int i=n-k+1; i<=n; i++) binomial *= i; for (long i=2; i<=k; i++) binomial /= i; return binomial; } /** obtain a subentity * * \tparam codim codimension of the desired subentity * * \param[in] i number of the subentity (in generic numbering) * * \returns the subentity * * \note: The subentities are numbered 0, ..., subEntities(codim)-1 */ template< int codim > typename Grid::template Codim< codim >::Entity subEntity ( int i ) const; /*! Intra-level access to intersection with neighboring elements. A neighbor is an entity of codimension 0 which has an entity of codimension 1 in common with this entity. Access to neighbors is provided using iterators. This allows meshes to be nonmatching. Returns iterator referencing the first neighbor. */ AlbertaGridLeafIntersectionIterator ileafbegin () const; //! Reference to one past the last intersection with neighbor AlbertaGridLeafIntersectionIterator ileafend () const; AlbertaGridLevelIntersectionIterator ilevelbegin () const { if( grid().maxLevel() == 0 ) return ileafbegin(); else { DUNE_THROW( NotImplemented, "method ilevelbegin not implemented for AlbertaGrid." ); return ileafend(); } } AlbertaGridLevelIntersectionIterator ilevelend () const { return ileafend(); } //! returns true if entity is leaf entity, i.e. has no children bool isLeaf () const; //! Inter-level access to father element on coarser grid. //! Assumes that meshes are nested. Entity father () const; //! returns true if father entity exists bool hasFather () const { return (this->level()>0); } /** \brief Location of this element relative to the father's reference element * * This information is sufficient to interpolate all dofs in conforming case. * Nonconforming may require access to neighbors of father and computations * with local coordinates. * On the fly case is somewhat inefficient since dofs are visited several * times. If we store interpolation matrices, this is tolerable. */ LocalGeometry geometryInFather () const; /*! Inter-level access to son elements on higher levels<=maxlevel. This is provided for sparsely stored nested unstructured meshes. Returns iterator to first son. */ HierarchicIterator hbegin (int maxlevel) const; //! Returns iterator to one past the last son HierarchicIterator hend (int maxlevel) const; /** \brief Was the entity created during the last adaptation cycle? */ bool isNew () const; /**\brief Might the entity vanish during the next adaptation cycle? */ bool mightVanish () const; /**\brief Returns true, if entity has intersections with boundary */ bool hasBoundaryIntersections () const ; //! return partition type of this entity PartitionType partitionType() const; //! equality of entities bool equals ( const This &i ) const; // needed for LevelIterator to compare ALBERTA EL_INFO *getElInfo () const; const ElementInfo &elementInfo () const { return elementInfo_; } void clearElement (); void setElement ( const ElementInfo &elementInfo, int subEntity ); // same as setElInfo just with a entity given void setEntity ( const This &other ); //! obtain a reference to the grid const Grid &grid () const { return *grid_; } //! obtain number of the subentity within the element (in ALBERTA numbering) int subEntity () const { return 0; } //! obtain twist int twist () const { return elementInfo().template twist< codimension >( subEntity() ); } //! obtain twist of a subentity template< int codim > int twist ( int i ) const { return elementInfo().template twist< codim >( grid().generic2alberta( codim, i ) ); } private: //! return which number of child we are, i.e. 0 or 1 int nChild () const; //! the corresponding grid const Grid *grid_; // Alberta element info ElementInfo elementInfo_; }; } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_ENTITY_HH dune-grid-2.11.0/dune/grid/albertagrid/entityseed.hh000066400000000000000000000060501511655130300223100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_ENTITYSEED_HH #define DUNE_ALBERTA_ENTITYSEED_HH #include #include namespace Dune { // Internal Forward Declarations // ----------------------------- template< int codim, class Grid > class AlbertaGridEntitySeed; // External Forward Declarations // ----------------------------- template< int dim, int dimworld > class AlbertaGrid; #if HAVE_ALBERTA // AlbertaGridEntitySeed (for higher codimension) // ---------------------------------------------- template< int codim, int dim, int dimworld > class AlbertaGridEntitySeed< codim, const AlbertaGrid< dim, dimworld > > { public: typedef AlbertaGrid< dim, dimworld > Grid; static const int codimension = codim; static const int dimension = dim; static const int mydimension = dimension - codimension; static const int dimensionworld = dimworld; typedef Alberta::MeshPointer< dimension > MeshPointer; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef typename ElementInfo::Seed Seed; typedef typename Grid::template Codim< codimension >::Entity Entity; AlbertaGridEntitySeed ( ) {} AlbertaGridEntitySeed ( const ElementInfo &elementInfo, int subEntity ) : seed_( elementInfo.seed() ), subEntity_( subEntity ) {} bool isValid () const { return seed_.isValid(); } ElementInfo elementInfo ( const MeshPointer &mesh ) const { return ElementInfo( mesh, seed_ ); } int subEntity () const { return subEntity_; } private: Seed seed_; int subEntity_; }; // AlbertaGridEntitySeed (for codimension 0) // ----------------------------------------- template< int dim, int dimworld > class AlbertaGridEntitySeed< 0, const AlbertaGrid< dim, dimworld > > { public: typedef AlbertaGrid< dim, dimworld > Grid; static const int codimension = 0; static const int dimension = dim; static const int mydimension = dimension - codimension; static const int dimensionworld = dimworld; typedef Alberta::MeshPointer< dimension > MeshPointer; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef typename ElementInfo::Seed Seed; typedef typename Grid::template Codim< codimension >::Entity Entity; AlbertaGridEntitySeed ( ) {} explicit AlbertaGridEntitySeed ( const ElementInfo &elementInfo ) : seed_( elementInfo.seed() ) {} bool isValid () const { return seed_.isValid(); } ElementInfo elementInfo ( const MeshPointer &mesh ) const { return ElementInfo( mesh, seed_ ); } int subEntity () const { return 0; } private: Seed seed_; }; #endif // #if HAVE_ALBERTA } // end namespace Dune #endif // #ifndef DUNE_ALBERTA_ENTITYSEED_HH dune-grid-2.11.0/dune/grid/albertagrid/geometry.cc000066400000000000000000000156071511655130300217640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_GEOMETRY_CC #define DUNE_ALBERTA_GEOMETRY_CC #include #include #include namespace Dune { // AlbertaGridGeometry // ------------------- // print the GeometryInformation template inline void AlbertaGridGeometry::print (std::ostream& ss) const { ss << "AlbertaGridGeometry<" << mydim << "," << cdim << "> = { \n"; for(int i=0; i inline typename AlbertaGridGeometry< mydim, cdim, GridImp >::GlobalCoordinate AlbertaGridGeometry< mydim, cdim, GridImp >::global ( const LocalCoordinate &local ) const { GlobalCoordinate y = corner( 0 ); jacobianTransposed().umtv( local, y ); return y; } //local implementation for mydim < cdim template< int mydim, int cdim, class GridImp > inline typename AlbertaGridGeometry< mydim, cdim, GridImp >::LocalCoordinate AlbertaGridGeometry< mydim, cdim, GridImp >::local ( const GlobalCoordinate &global ) const { LocalCoordinate x; jacobianInverseTransposed().mtv( global - corner( 0 ), x ); return x; } template< int mydim, int cdim, class GridImp > inline const typename AlbertaGridGeometry< mydim, cdim, GridImp >::JacobianTransposed & AlbertaGridGeometry< mydim, cdim, GridImp >::jacobianTransposed () const { if( !builtJT_ ) { const FieldVector< ctype, coorddimension > &origin = coord_[ 0 ]; for( int i = 0; i < mydimension; ++i ) { jT_[ i ] = coord_[ i+1 ]; jT_[ i ] -= origin; } builtJT_ = true; } return jT_; } template< int mydim, int cdim, class GridImp > inline const typename AlbertaGridGeometry< mydim, cdim, GridImp >::JacobianInverseTransposed & AlbertaGridGeometry< mydim, cdim, GridImp >::jacobianInverseTransposed () const { if( !builtJTInv_ ) { elDet_ = std::abs( Alberta::invert( jacobianTransposed(), jTInv_ ) ); assert( elDet_ > 1.0e-25 ); calcedDet_ = true; builtJTInv_ = true; } return jTInv_; } // built Geometry template< int mydim, int cdim, class GridImp > template< class CoordReader > inline void AlbertaGridGeometry< mydim, cdim, GridImp > ::build ( const CoordReader &coordReader ) { builtJT_ = false; builtJTInv_ = false; // copy corners for( int i = 0; i < numCorners; ++i ) coordReader.coordinate( i, coord_[ i ] ); // calculate centroid centroid_ = coord_[ 0 ]; for( int i = 1; i < numCorners; ++i ) centroid_ += coord_[ i ]; centroid_ *= 1.0 / numCorners; elDet_ = (coordReader.hasDeterminant() ? coordReader.determinant() : elDeterminant()); assert( std::abs( elDet_ ) > 0.0 ); calcedDet_ = true; } #if !DUNE_ALBERTA_CACHE_COORDINATES template< int dim, int cdim > inline typename AlbertaGridGlobalGeometry< dim, cdim, const AlbertaGrid< dim, cdim > >::GlobalCoordinate AlbertaGridGlobalGeometry< dim, cdim, const AlbertaGrid< dim, cdim > >::global ( const LocalCoordinate &local ) const { GlobalCoordinate y = corner( 0 ); jacobianTransposed().umtv( local, y ); return y; } //local implementation for mydim < cdim template< int dim, int cdim > inline typename AlbertaGridGlobalGeometry< dim, cdim, const AlbertaGrid< dim, cdim > >::LocalCoordinate AlbertaGridGlobalGeometry< dim, cdim, const AlbertaGrid< dim, cdim > >::local ( const GlobalCoordinate &global ) const { LocalCoordinate x; jacobianInverseTransposed().mtv( global - corner( 0 ), x ); return x; } #endif // #if !DUNE_ALBERTA_CACHE_COORDINATES // AlbertaGridLocalGeometryProvider // -------------------------------- template< class Grid > void AlbertaGridLocalGeometryProvider< Grid >::buildGeometryInFather () { for( int child = 0; child < numChildren; ++child ) { for( int orientation = 0; orientation < 2; ++orientation ) { const GeoInFatherCoordReader coordReader( child, orientation ); geometryInFather_[ child ][ orientation ] = new LocalElementGeometry( coordReader ); } } } template< class Grid > void AlbertaGridLocalGeometryProvider< Grid >::buildFaceGeometry () { for( int face = 0; face < numFaces; ++face ) { for( int twist = minFaceTwist; twist <= maxFaceTwist; ++twist ) { const FaceCoordReader coordReader( face, twist ); faceGeometry_[ face ][ twist - minFaceTwist ] = new LocalFaceGeometry( coordReader ); } } } // AlbertaGridLocalGeometryProvider::GeoInFatherCoordReader // -------------------------------------------------------- template< class Grid > struct AlbertaGridLocalGeometryProvider< Grid >::GeoInFatherCoordReader { typedef Alberta::Real ctype; typedef FieldVector< ctype, dimension > Coordinate; private: typedef Alberta::GeometryInFather< dimension > GeoInFather; public: GeoInFatherCoordReader ( int child, int orientation ) : child_( child ), orientation_( orientation ) {} void coordinate ( int i, Coordinate &x ) const { const typename GeoInFather::LocalVector &coord = GeoInFather::coordinate( child_, orientation_, i ); for( int j = 0; j < dimension; ++j ) x[ j ] = coord[ j ]; } bool hasDeterminant () const { return false; } ctype determinant () const { return ctype( 0 ); } private: const int child_; const int orientation_; }; // AlbertaGridLocalGeometryProvider::FaceCoordReader // ------------------------------------------------- template< class Grid > struct AlbertaGridLocalGeometryProvider< Grid >::FaceCoordReader { typedef Alberta::Real ctype; typedef FieldVector< ctype, dimension > Coordinate; FaceCoordReader ( const int face, const int twist = 0 ) : face_( face ), twist_( twist ) {} void coordinate ( const int i, Coordinate &x ) const { const int ti = Alberta::applyInverseTwist< dimension-1 >( twist_, i ); const int j = mapVertices< 1 >( face_, ti ); refCorner( j, x ); } bool hasDeterminant () const { return false; } ctype determinant () const { return ctype( 0 ); } private: static void refCorner ( const int i, Coordinate &x ) { x = ctype( 0 ); if( i > 0 ) x[ i-1 ] = ctype( 1 ); } int face_; int twist_; }; } // namespace Dune #endif // #ifndef DUNE_ALBERTA_GEOMETRY_CC dune-grid-2.11.0/dune/grid/albertagrid/geometry.hh000066400000000000000000000416351511655130300217760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_GEOMETRY_HH #define DUNE_ALBERTA_GEOMETRY_HH #include #include #include #if HAVE_ALBERTA namespace Dune { // Forward Declarations // -------------------- template< int dim, int dimworld > class AlbertaGrid; // AlbertaGridCoordinateReader // --------------------------- template< int codim, class GridImp > struct AlbertaGridCoordinateReader { typedef typename std::remove_const< GridImp >::type Grid; static constexpr int dimension = Grid::dimension; static constexpr int codimension = codim; static constexpr int mydimension = dimension - codimension; static constexpr int coorddimension = Grid::dimensionworld; typedef Alberta::Real ctype; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef FieldVector< ctype, coorddimension > Coordinate; AlbertaGridCoordinateReader ( const GridImp &grid, const ElementInfo &elementInfo, int subEntity ) : grid_( grid ), elementInfo_( elementInfo ), subEntity_( subEntity ) {} const ElementInfo &elementInfo () const { return elementInfo_; } void coordinate ( int i, Coordinate &x ) const { assert( !elementInfo_ == false ); assert( (i >= 0) && (i <= mydimension) ); const int k = mapVertices( subEntity_, i ); const Alberta::GlobalVector &coord = grid_.getCoord( elementInfo_, k ); for( int j = 0; j < coorddimension; ++j ) x[ j ] = coord[ j ]; } bool hasDeterminant () const { return false; } ctype determinant () const { assert( hasDeterminant() ); return ctype( 0 ); } private: static int mapVertices ( int subEntity, int i ) { return Alberta::MapVertices< dimension, codimension >::apply( subEntity, i ); } const Grid &grid_; const ElementInfo &elementInfo_; const int subEntity_; }; // AlbertaGridGeometry // ------------------- /** \class AlbertaGridGeometry * \brief geometry implementation for AlbertaGrid * * Defines the geometry part of a mesh entity. Works for all dimensions, * element types and dim of world. Provides reference element and mapping * between local and global coordinates. * * \tparam mydim dimension of the element (0 <= dim <= 3) * \tparam cdim dimension of global coordinates * \tparam GridImp grid implementation * (always const AlbertaGrid< dim, dimworld >) */ template< int mydim, int cdim, class GridImp > class AlbertaGridGeometry { typedef AlbertaGridGeometry< mydim, cdim, GridImp > This; // remember type of the grid typedef GridImp Grid; // dimension of barycentric coordinates static constexpr int dimbary = mydim + 1; public: //! type of coordinates typedef Alberta::Real ctype; static constexpr int dimension = Grid :: dimension; static constexpr int mydimension = mydim; static constexpr int codimension = dimension - mydimension; static constexpr int coorddimension = cdim; typedef FieldVector< ctype, mydimension > LocalCoordinate; typedef FieldVector< ctype, coorddimension > GlobalCoordinate; typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed; typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed; typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian; typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianInverse; private: static constexpr int numCorners = mydimension + 1; typedef FieldMatrix< ctype, numCorners, coorddimension > CoordMatrix; public: AlbertaGridGeometry () { invalidate(); } template< class CoordReader > AlbertaGridGeometry ( const CoordReader &coordReader ) { build( coordReader ); } /** \brief obtain the type of reference element */ GeometryType type () const { return GeometryTypes::simplex( mydimension ); } //! returns always true since we only have simplices bool affine () const { return true; } /** \brief number of corner the geometry */ int corners () const { return numCorners; } /** \brief obtain the i-th corner of this geometry */ GlobalCoordinate corner ( const int i ) const { assert( (i >= 0) && (i < corners()) ); return coord_[ i ]; } /** \brief return center of geometry */ GlobalCoordinate center () const { return centroid_; } /** \brief map a point from the reference element to the geometry */ GlobalCoordinate global ( const LocalCoordinate &local ) const; /** \brief map a point from the geometry to the reference element */ LocalCoordinate local ( const GlobalCoordinate &global ) const; /** \brief integration element of the geometry mapping * * \note This method is not part of the geometry interface. It is used * internally only. */ ctype integrationElement () const { assert( calcedDet_ ); return elDet_; } /** \brief integration element of the geometry mapping */ ctype integrationElement ( [[maybe_unused]] const LocalCoordinate &local ) const { return integrationElement(); } /** \brief volume of geometry */ ctype volume () const { return integrationElement() / ctype( factorial(mydimension) ); } /** \brief transposed of the geometry mapping's Jacobian * * \note This method is not part of the geometry interface. It is used * internally only. */ const JacobianTransposed &jacobianTransposed () const; /** \brief transposed of the geometry mapping's Jacobian */ const JacobianTransposed & jacobianTransposed ( [[maybe_unused]] const LocalCoordinate &local ) const { return jacobianTransposed(); } /** \brief transposed inverse of the geometry mapping's Jacobian * * \note This method is not part of the geometry interface. It is used * internally only. */ const JacobianInverseTransposed &jacobianInverseTransposed () const; /** \brief transposed inverse of the geometry mapping's Jacobian */ const JacobianInverseTransposed & jacobianInverseTransposed ( [[maybe_unused]] const LocalCoordinate &local ) const { return jacobianInverseTransposed(); } /** \brief geometry mapping's Jacobian */ Jacobian jacobian ( const LocalCoordinate &local ) const { return jacobianTransposed(local).transposed(); } /** \brief inverse of the geometry mapping's Jacobian */ JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { return jacobianInverseTransposed(local).transposed(); } //*********************************************************************** // Methods that not belong to the Interface, but have to be public //*********************************************************************** /** \brief invalidate the geometry */ void invalidate () { builtJT_ = false; builtJTInv_ = false; calcedDet_ = false; } /** \brief build the geometry from a coordinate reader */ template< class CoordReader > void build ( const CoordReader &coordReader ); void print ( std::ostream &out ) const; private: // calculates the volume of the element ctype elDeterminant () const { return std::abs( Alberta::determinant( jacobianTransposed() ) ); } //! the vertex coordinates CoordMatrix coord_; //! the center/centroid GlobalCoordinate centroid_; // storage for the transposed of the jacobian mutable JacobianTransposed jT_; // storage for the transposed inverse of the jacboian mutable JacobianInverseTransposed jTInv_; // has jT_ been computed, yet? mutable bool builtJT_; // has jTInv_ been computed, yet? mutable bool builtJTInv_; mutable bool calcedDet_; //!< true if determinant was calculated mutable ctype elDet_; //!< storage of element determinant }; // AlbertaGridGlobalGeometry // ------------------------- template< int mydim, int cdim, class GridImp > class AlbertaGridGlobalGeometry : public AlbertaGridGeometry< mydim, cdim, GridImp > { typedef AlbertaGridGlobalGeometry< mydim, cdim, GridImp > This; typedef AlbertaGridGeometry< mydim, cdim, GridImp > Base; public: AlbertaGridGlobalGeometry () : Base() {} template< class CoordReader > AlbertaGridGlobalGeometry ( const CoordReader &coordReader ) : Base( coordReader ) {} }; #if !DUNE_ALBERTA_CACHE_COORDINATES template< int dim, int cdim > class AlbertaGridGlobalGeometry< dim, cdim, const AlbertaGrid< dim, cdim > > { typedef AlbertaGridGlobalGeometry< dim, cdim, const AlbertaGrid< dim, cdim > > This; // remember type of the grid typedef AlbertaGrid< dim, cdim > Grid; // dimension of barycentric coordinates static constexpr int dimbary = dim + 1; typedef Alberta::ElementInfo< dim > ElementInfo; public: //! type of coordinates typedef Alberta::Real ctype; static constexpr int dimension = Grid::dimension; static constexpr int mydimension = dimension; static constexpr int codimension = dimension - mydimension; static constexpr int coorddimension = cdim; typedef FieldVector< ctype, mydimension > LocalCoordinate; typedef FieldVector< ctype, coorddimension > GlobalCoordinate; typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed; typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed; typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian; typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianInverse; private: static constexpr int numCorners = mydimension + 1; typedef FieldMatrix< ctype, numCorners, coorddimension > CoordMatrix; public: AlbertaGridGlobalGeometry () { invalidate(); } template< class CoordReader > AlbertaGridGlobalGeometry ( const CoordReader &coordReader ) { build( coordReader ); } /** \brief obtain the type of reference element */ GeometryType type () const { return GeometryTypes::simplex( mydimension ); } /** \brief number of corner the geometry */ int corners () const { return numCorners; } /** \brief obtain the i-th corner of this geometry */ GlobalCoordinate corner ( const int i ) const { assert( (i >= 0) && (i < corners()) ); const Alberta::GlobalCoordinate &x = elementInfo_.coordinate( i ); GlobalCoordinate y; for( int j = 0; j < coorddimension; ++j ) y[ j ] = x[ j ]; return y; } /** \brief return center of geometry */ GlobalCoordinate center () const { GlobalCoordinate centroid_ = corner( 0 ); for( int i = 1; i < numCorners; ++i ) centroid_ += corner( i ); centroid_ *= ctype( 1 ) / ctype( numCorners ); return centroid_; } /** \brief map a point from the reference element to the geometry */ GlobalCoordinate global ( const LocalCoordinate &local ) const; /** \brief map a point from the geometry to the reference element */ LocalCoordinate local ( const GlobalCoordinate &global ) const; /** \brief integration element of the geometry mapping * * \note This method is not part of the geometry interface. It is used * internally only. */ ctype integrationElement () const { return elementInfo_.geometryCache().integrationElement(); } /** \brief integration element of the geometry mapping */ ctype integrationElement ( const LocalCoordinate &local ) const { return integrationElement(); } /** \brief volume of geometry */ ctype volume () const { return integrationElement() / ctype( factorial(mydimension) ); } /** \brief transposed of the geometry mapping's Jacobian * * \note This method is not part of the geometry interface. It is used * internally only. */ const JacobianTransposed &jacobianTransposed () const { return elementInfo_.geometryCache().jacobianTransposed(); } /** \brief transposed of the geometry mapping's Jacobian */ const JacobianTransposed & jacobianTransposed ( const LocalCoordinate &local ) const { return jacobianTransposed(); } /** \brief transposed inverse of the geometry mapping's Jacobian * * \note This method is not part of the geometry interface. It is used * internally only. */ const JacobianInverseTransposed &jacobianInverseTransposed () const { return elementInfo_.geometryCache().jacobianInverseTransposed(); } /** \brief transposed inverse of the geometry mapping's Jacobian */ const JacobianInverseTransposed & jacobianInverseTransposed ( const LocalCoordinate &local ) const { return jacobianInverseTransposed(); } /** \brief geometry mapping's Jacobian */ Jacobian jacobian ( const LocalCoordinate &local ) const { return jacobianTransposed(local).transposed(); } /** \brief inverse of the geometry mapping's Jacobian */ JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { return jacobianInverseTransposed(local).transposed(); } //*********************************************************************** // Methods that not belong to the Interface, but have to be public //*********************************************************************** /** \brief invalidate the geometry */ void invalidate () { elementInfo_ = ElementInfo(); } /** \brief build the geometry from a coordinate reader */ template< class CoordReader > void build ( const CoordReader &coordReader ) { elementInfo_ = coordReader.elementInfo(); } private: ElementInfo elementInfo_; }; #endif // #if !DUNE_ALBERTA_CACHE_COORDINATES // AlbertaGridLocalGeometryProvider // -------------------------------- template< class Grid > class AlbertaGridLocalGeometryProvider { typedef AlbertaGridLocalGeometryProvider< Grid > This; public: typedef typename Grid::ctype ctype; static constexpr int dimension = Grid::dimension; template< int codim > struct Codim { typedef AlbertaGridGeometry< dimension-codim, dimension, Grid > LocalGeometry; }; typedef typename Codim< 0 >::LocalGeometry LocalElementGeometry; typedef typename Codim< 1 >::LocalGeometry LocalFaceGeometry; static constexpr int numChildren = 2; static constexpr int numFaces = dimension + 1; static constexpr int minFaceTwist = Alberta::Twist< dimension, dimension-1 >::minTwist; static constexpr int maxFaceTwist = Alberta::Twist< dimension, dimension-1 >::maxTwist; static constexpr int numFaceTwists = maxFaceTwist - minFaceTwist + 1; private: struct GeoInFatherCoordReader; struct FaceCoordReader; AlbertaGridLocalGeometryProvider () { buildGeometryInFather(); buildFaceGeometry(); } ~AlbertaGridLocalGeometryProvider () { for( int child = 0; child < numChildren; ++child ) { delete geometryInFather_[ child ][ 0 ]; delete geometryInFather_[ child ][ 1 ]; } for( int i = 0; i < numFaces; ++i ) { for( int j = 0; j < numFaceTwists; ++j ) delete faceGeometry_[ i ][ j ]; } } void buildGeometryInFather(); void buildFaceGeometry(); public: const LocalElementGeometry & geometryInFather ( int child, const int orientation = 1 ) const { assert( (child >= 0) && (child < numChildren) ); assert( (orientation == 1) || (orientation == -1) ); return *geometryInFather_[ child ][ (orientation + 1) / 2 ]; } const LocalFaceGeometry & faceGeometry ( int face, int twist = 0 ) const { assert( (face >= 0) && (face < numFaces) ); assert( (twist >= minFaceTwist) && (twist <= maxFaceTwist) ); return *faceGeometry_[ face ][ twist - minFaceTwist ]; } static const This &instance () { static This theInstance; return theInstance; } private: template< int codim > static int mapVertices ( int subEntity, int i ) { return Alberta::MapVertices< dimension, codim >::apply( subEntity, i ); } const LocalElementGeometry *geometryInFather_[ numChildren ][ 2 ]; const LocalFaceGeometry *faceGeometry_[ numFaces ][ numFaceTwists ]; }; } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_GEOMETRY_HH dune-grid-2.11.0/dune/grid/albertagrid/geometrycache.hh000066400000000000000000000072671511655130300227650ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_GEOMETRYCACHE_HH #define DUNE_ALBERTA_GEOMETRYCACHE_HH #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // GeometryCache // ------------- template< int dim > class GeometryCache { static const unsigned int flagIntegrationElement = (1 << 0); static const unsigned int flagJacobianTransposed = (1 << 1); static const unsigned int flagJacobianInverseTransposed = (1 << 2); public: typedef FieldMatrix< Real, dimWorld, dim > JacobianInverseTransposed; typedef FieldMatrix< Real, dim, dimWorld > JacobianTransposed; GeometryCache () : flags_( 0 ) {} const Real &integrationElement ( const ALBERTA EL_INFO &elInfo ) { if( (flags_ & flagIntegrationElement) == 0 ) { integrationElement_ = std::abs( determinant( jacobianTransposed( elInfo ) ) ); assert( integrationElement_ > 1e-14 ); flags_ |= flagIntegrationElement; } return integrationElement_; } const JacobianTransposed &jacobianTransposed ( const ALBERTA EL_INFO &elInfo ) { if( (flags_ & flagJacobianTransposed) == 0 ) { assert( (elInfo.fill_flag & FillFlags< dim >::coords) != 0 ); const GlobalVector &x = elInfo.coord[ 0 ]; for( int i = 0; i < dim; ++i ) { const GlobalVector &y = elInfo.coord[ i+1 ]; for( int j = 0; j < dimWorld; ++j ) jacobianTransposed_[ i ][ j ] = y[ j ] - x[ j ]; } flags_ |= flagJacobianTransposed; } return jacobianTransposed_; } const JacobianInverseTransposed & jacobianInverseTransposed ( const ALBERTA EL_INFO &elInfo ) { if( (flags_ & flagJacobianInverseTransposed) == 0 ) { integrationElement_ = std::abs( invert( jacobianTransposed( elInfo ), jacobianInverseTransposed_ ) ); assert( integrationElement_ > 1e-14 ); flags_ |= flagIntegrationElement | flagJacobianInverseTransposed; } return jacobianInverseTransposed_; } private: unsigned int flags_; Real integrationElement_; FieldMatrix< Real, dim, dimWorld > jacobianTransposed_; FieldMatrix< Real, dimWorld, dim > jacobianInverseTransposed_; }; // GeometryCacheProxy // ------------------ template< int dim > struct GeometryCacheProxy { typedef FieldMatrix< Real, dimWorld, dim > JacobianInverseTransposed; typedef FieldMatrix< Real, dim, dimWorld > JacobianTransposed; GeometryCacheProxy ( GeometryCache< dim > &geometryCache, const ALBERTA EL_INFO &elInfo ) : geometryCache_( geometryCache ), elInfo_( elInfo ) {} const Real &integrationElement () { return geometryCache_.integrationElement( elInfo_ ); } const JacobianTransposed &jacobianTransposed () { return geometryCache_.jacobianTransposed( elInfo_ ); } const JacobianInverseTransposed &jacobianInverseTransposed () { return geometryCache_.jacobianInverseTransposed( elInfo_ ); } private: GeometryCache< dim > &geometryCache_; const ALBERTA EL_INFO &elInfo_; }; } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_GEOMETRYCACHE_HH dune-grid-2.11.0/dune/grid/albertagrid/geometryreference.hh000066400000000000000000000127071511655130300236530ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_ALBERTAGRID_GEOMETRYREFERENCE_HH #define DUNE_GRID_ALBERTAGRID_GEOMETRYREFERENCE_HH /** \file \brief Wrapper and interface classes for element geometries */ #include #include #include namespace Dune { // GeometryReference // ----------------- template< class Implementation > class GeometryReference { typedef GeometryReference< Implementation > This; public: static const int mydimension = Implementation::mydimension; static const int coorddimension = Implementation::coorddimension; typedef typename Implementation::ctype ctype; typedef typename Implementation::LocalCoordinate LocalCoordinate; typedef typename Implementation::GlobalCoordinate GlobalCoordinate; typedef typename Implementation::JacobianInverseTransposed JacobianInverseTransposed; typedef typename Implementation::JacobianTransposed JacobianTransposed; private: template using JacobianInverseOfImplementation = decltype(typename Implementation_T::JacobianInverse{std::declval().jacobianInverse(std::declval())}); using JacobianInverseDefault = decltype(transpose(std::declval())); template using JacobianOfImplementation = decltype(typename Implementation_T::Jacobian{std::declval().jacobian(std::declval())}); using JacobianDefault = decltype(transpose(std::declval())); template [[deprecated("Geometry implementatons are required to provide a jacobian(local) method. The default implementation is deprecated and will be removed after release 2.9")]] auto deprecatedDefaultJacobian ( const LocalCoordinate& local ) const { return transpose(jacobianTransposed(local)); } template [[deprecated("Geometry implementatons are required to provide a jacobianInverse(local) method. The default implementation is deprecated and will be removed after release 2.9")]] auto deprecatedDefaultJacobianInverse ( const LocalCoordinate& local ) const { return transpose(jacobianInverseTransposed(local)); } public: using Jacobian = Std::detected_or_t; using JacobianInverse = Std::detected_or_t; explicit GeometryReference ( const Implementation &impl ) : impl_( &impl ) {} GeometryType type () const { return impl().type(); } bool affine() const { return impl().affine(); } int corners () const { return impl().corners(); } GlobalCoordinate corner ( int i ) const { return impl().corner( i ); } GlobalCoordinate center () const { return impl().center(); } GlobalCoordinate global ( const LocalCoordinate &local ) const { return impl().global( local ); } LocalCoordinate local ( const GlobalCoordinate &global ) const { return impl().local( global ); } ctype integrationElement ( const LocalCoordinate &local ) const { return impl().integrationElement( local ); } ctype volume () const { return impl().volume(); } JacobianTransposed jacobianTransposed ( const LocalCoordinate &local ) const { return impl().jacobianTransposed( local ); } JacobianInverseTransposed jacobianInverseTransposed ( const LocalCoordinate &local ) const { return impl().jacobianInverseTransposed( local ); } Jacobian jacobian ( const LocalCoordinate& local ) const { if constexpr(Std::is_detected_v) return impl().jacobian(local); else return deprecatedDefaultJacobian(local); } JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { if constexpr(Std::is_detected_v) return impl().jacobianInverse(local); else return deprecatedDefaultJacobianInverse(local); } const Implementation &impl () const { return *impl_; } private: const Implementation *impl_; }; // LocalGeometryReference // ----------------------- template< int mydim, int cdim, class Grid > class LocalGeometryReference : public GeometryReference< typename std::remove_const< Grid >::type::Traits::template Codim< std::remove_const< Grid >::type::dimension - mydim >::LocalGeometryImpl > { typedef typename std::remove_const< Grid >::type::Traits::template Codim< std::remove_const< Grid >::type::dimension - mydim >::LocalGeometryImpl Implementation; public: LocalGeometryReference ( const Implementation &impl ) : GeometryReference< Implementation >( impl ) {} }; // Definitions of GeometryReference // -------------------------------- template< class Implementation > const int GeometryReference< Implementation >::mydimension; template< class Implementation > const int GeometryReference< Implementation >::coorddimension; } // namespace Dune #endif // #ifndef DUNE_GRID_ALBERTAGRID_GEOMETRYREFERENCE_HH dune-grid-2.11.0/dune/grid/albertagrid/gridfactory.hh000066400000000000000000000455261511655130300224630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_GRIDFACTORY_HH #define DUNE_ALBERTA_GRIDFACTORY_HH /** \file * \author Martin Nolte * \brief specialization of the generic GridFactory for AlbertaGrid */ #include #include #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { /** \brief specialization of the generic GridFactory for AlbertaGrid * * \ingroup GridFactory * * The GridFactory for AlbertaGrid adds some extensions to the standard * GridFactoryInterface. It provides the following additional features: * - It allows to set boundary ids via insertBoundary. For ALBERTA 1.2, * these boundary ids are ignored, though. * - For ALBERTA 3.0 and above, you can add face transformation to identify * faces. This allows the construction of periodic grids. * - The grid can be written in ALBERTA's native format for macro * triangulations via write (both ASCII and XDR format are supported). * - On grid creation, a name can be assigned to the grid. * - On grid creation, the grid can be reordered such that ALBERTA uses * the longest edge as refinement edge during recursive bisection. * . */ template< int dim, int dimworld > class GridFactory< AlbertaGrid< dim, dimworld > > : public GridFactoryInterface< AlbertaGrid< dim, dimworld > > { typedef GridFactory< AlbertaGrid< dim, dimworld > > This; public: //! type of grid this factory is for typedef AlbertaGrid< dim, dimworld > Grid; //! type of (scalar) coordinates typedef typename Grid::ctype ctype; //! dimension of the grid static const int dimension = Grid::dimension; //! dimension of the world static const int dimensionworld = Grid::dimensionworld; //! type of vector for world coordinates typedef FieldVector< ctype, dimensionworld > WorldVector; //! type of matrix from world coordinates to world coordinates typedef FieldMatrix< ctype, dimensionworld, dimensionworld > WorldMatrix; typedef DuneBoundaryProjection< dimensionworld > DuneProjection; typedef std::shared_ptr< const DuneProjection > DuneProjectionPtr; typedef Dune::BoundarySegment< dimension, dimensionworld > BoundarySegment; template< int codim > struct Codim { typedef typename Grid::template Codim< codim >::Entity Entity; }; private: typedef Dune::BoundarySegmentWrapper< dimension, dimensionworld > BoundarySegmentWrapper; static const int numVertices = Alberta::NumSubEntities< dimension, dimension >::value; typedef Alberta::MacroElement< dimension > MacroElement; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef Alberta::MacroData< dimension > MacroData; typedef Alberta::NumberingMap< dimension, Alberta::Dune2AlbertaNumbering > NumberingMap; typedef Alberta::DuneBoundaryProjection< dimension > Projection; typedef std::array< unsigned int, dimension > FaceId; typedef std::map< FaceId, size_t > BoundaryMap; class ProjectionFactory; public: //! are boundary ids supported by this factory? static const bool supportsBoundaryIds = true; //! is the factory able to create periodic meshes? static const bool supportPeriodicity = MacroData::supportPeriodicity; /** default constructor */ GridFactory () : globalProjection_( (const DuneProjection *) 0 ) { macroData_.create(); } virtual ~GridFactory (); /** \brief insert a vertex into the macro grid * * \param[in] pos position of the vertex (in world coordinates) */ virtual void insertVertex ( const WorldVector &pos ) { macroData_.insertVertex( pos ); } /** \brief insert an element into the macro grid * * \param[in] type GeometryType of the new element * \param[in] vertices indices of the element vertices (in DUNE numbering) */ virtual void insertElement ( const GeometryType &type, const std::vector< unsigned int > &vertices ) { if( (int)type.dim() != dimension ) DUNE_THROW( AlbertaError, "Inserting element of wrong dimension: " << type.dim() ); if( !type.isSimplex() ) DUNE_THROW( AlbertaError, "Alberta supports only simplices." ); if( vertices.size() != (size_t)numVertices ) DUNE_THROW( AlbertaError, "Wrong number of vertices passed: " << vertices.size() << "." ); int array[ numVertices ]; for( int i = 0; i < numVertices; ++i ) array[ i ] = vertices[ numberingMap_.alberta2dune( dimension, i ) ]; macroData_.insertElement( array ); } /** \brief mark a face as boundary (and assign a boundary id) * * \internal * * \param[in] element index of the element, the face belongs to * \param[in] face local number of the face within the element * \param[in] id boundary id to assign to the face * * \note ALBERTA supports only boundary id in the range 1,...,127. */ virtual void insertBoundary ( int element, int face, int id ) { if( (id <= 0) || (id > 127) ) DUNE_THROW( AlbertaError, "Invalid boundary id: " << id << "." ); macroData_.boundaryId( element, numberingMap_.dune2alberta( 1, face ) ) = id; } /** \brief insert a boundary projection into the macro grid * * \internal * * \param[in] type geometry type of boundary face * \param[in] vertices vertices of the boundary face * \param[in] projection boundary projection * * \note The grid takes control of the projection object. */ virtual void insertBoundaryProjection ( const GeometryType &type, const std::vector< unsigned int > &vertices, const DuneProjection *projection ) { if( (int)type.dim() != dimension-1 ) DUNE_THROW( AlbertaError, "Inserting boundary face of wrong dimension: " << type.dim() ); if( !type.isSimplex() ) DUNE_THROW( AlbertaError, "Alberta supports only simplices." ); FaceId faceId; if( vertices.size() != faceId.size() ) DUNE_THROW( AlbertaError, "Wrong number of face vertices passed: " << vertices.size() << "." ); for( size_t i = 0; i < faceId.size(); ++i ) faceId[ i ] = vertices[ i ]; std::sort( faceId.begin(), faceId.end() ); typedef std::pair< typename BoundaryMap::iterator, bool > InsertResult; const InsertResult result = boundaryMap_.insert( std::make_pair( faceId, boundaryProjections_.size() ) ); if( !result.second ) DUNE_THROW( GridError, "Only one boundary projection can be attached to a face." ); boundaryProjections_.push_back( DuneProjectionPtr( projection ) ); } /** \brief insert a global (boundary) projection into the macro grid * * \internal * * \param[in] projection global (boundary) projection * * \note The grid takes control of the projection object. */ virtual void insertBoundaryProjection ( const DuneProjection *projection ) { if( globalProjection_ ) DUNE_THROW( GridError, "Only one global boundary projection can be attached to a grid." ); globalProjection_ = DuneProjectionPtr( projection ); } /** \brief insert a boundary segment into the macro grid * * Only influences the ordering of the boundary segments * \param[in] vertices vertex indices of boundary face */ virtual void insertBoundarySegment ( const std::vector< unsigned int >& vertices ) { insertBoundaryProjection( GeometryTypes::simplex( dimension-1 ), vertices, 0 ); } /** \brief insert a shaped boundary segment into the macro grid * * \param[in] vertices vertex indices of boundary face * \param[in] boundarySegment geometric realization of shaped boundary */ virtual void insertBoundarySegment ( const std::vector< unsigned int > &vertices, const std::shared_ptr< BoundarySegment > &boundarySegment ) { auto refSimplex = ReferenceElements< ctype, dimension-1 >::simplex(); if( !boundarySegment ) DUNE_THROW( GridError, "Trying to insert null as a boundary segment." ); if( (int)vertices.size() != refSimplex.size( dimension-1 ) ) DUNE_THROW( GridError, "Wrong number of face vertices passed: " << vertices.size() << "." ); std::vector< WorldVector > coords( refSimplex.size( dimension-1 ) ); for( int i = 0; i < dimension; ++i ) { Alberta::GlobalVector &x = macroData_.vertex( vertices[ i ] ); for( int j = 0; j < dimensionworld; ++j ) coords[ i ][ j ] = x[ j ]; if( ((*boundarySegment)( refSimplex.position( i, dimension-1 ) ) - coords[ i ]).two_norm() > 1e-6 ) DUNE_THROW( GridError, "Boundary segment does not interpolate the corners." ); } const GeometryType gt = refSimplex.type( 0, 0 ); const DuneProjection *prj = new BoundarySegmentWrapper( gt, coords, boundarySegment ); insertBoundaryProjection( gt, vertices, prj ); } /** \brief add a face transformation (for periodic identification) * * A face transformation is an affine mapping T from world coordinates * to world coordinates. ALBERTA periodically identifies two faces f and g * if T( f ) = g or T( g ) = f. * * \param[in] matrix matrix describing the linear part of T * \param[in] shift vector describing T( 0 ) * * \note ALBERTA requires the matrix to be orthogonal. * * \note ALBERTA automatically adds the inverse transformation. */ void insertFaceTransformation ( const WorldMatrix &matrix, const WorldVector &shift ); /** \brief mark the longest edge as refinemet edge * * Marking the longest edge avoids cycles in the recursive bisection * algorithm, if the longest edge of each element is unique. It also * makes sure the angles degenerate least. It can, hoowever, produce * more nonlocal refinements than necessary. Therefore this feature is * disabled by default. */ void markLongestEdge () { macroData_.markLongestEdge(); } /** \brief finalize grid creation and hand over the grid * * This version of createGrid is original to the AlbertaGrid grid factroy, * allowing to specity a grid name. * * \returns a pointer to the newly created grid * * \note The caller takes responsibility of freeing the memory allocated * for the grid. * \note ALBERTA's grid factory provides a static method for freeing the * grid (destroyGrid). */ std::unique_ptr createGrid () { macroData_.finalize(); if( macroData_.elementCount() == 0 ) DUNE_THROW( GridError, "Cannot create empty AlbertaGrid." ); if( dimension < 3 ) macroData_.setOrientation( Alberta::Real( 1 ) ); assert( macroData_.checkNeighbors() ); macroData_.checkCycles(); ProjectionFactory projectionFactory( *this ); return std::make_unique( macroData_, projectionFactory ); } /** \brief destroy a grid previously obtain from this factory * * \param[in] grid pointer to the grid to destroy */ static void destroyGrid ( Grid *grid ) { delete grid; } /** \brief write out the macro triangulation in native grid file format * * \param[in] filename name of the file to write to * * \returns \c true on success */ bool write ( const std::string &filename ) { macroData_.finalize(); if( dimension < 3 ) macroData_.setOrientation( Alberta::Real( 1 ) ); assert( macroData_.checkNeighbors() ); return macroData_.write( filename, false ); } virtual unsigned int insertionIndex ( const typename Codim< 0 >::Entity &entity ) const { return insertionIndex( entity.impl().elementInfo() ); } virtual unsigned int insertionIndex ( const typename Codim< dimension >::Entity &entity ) const { const int elIndex = insertionIndex( entity.impl().elementInfo() ); const typename MacroData::ElementId &elementId = macroData_.element( elIndex ); return elementId[ entity.impl().subEntity() ]; } virtual unsigned int insertionIndex ( const typename Grid::LeafIntersection &intersection ) const { const Grid &grid = intersection.impl().grid(); const ElementInfo &elementInfo = intersection.impl().elementInfo(); const int face = grid.generic2alberta( 1, intersection.indexInInside() ); return insertionIndex( elementInfo, face ); } virtual bool wasInserted ( const typename Grid::LeafIntersection &intersection ) const { return (insertionIndex( intersection ) < std::numeric_limits< unsigned int >::max()); } private: unsigned int insertionIndex ( const ElementInfo &elementInfo ) const; unsigned int insertionIndex ( const ElementInfo &elementInfo, const int face ) const; FaceId faceId ( const ElementInfo &elementInfo, const int face ) const; MacroData macroData_; NumberingMap numberingMap_; DuneProjectionPtr globalProjection_; BoundaryMap boundaryMap_; std::vector< DuneProjectionPtr > boundaryProjections_; }; template< int dim, int dimworld > GridFactory< AlbertaGrid< dim, dimworld > >::~GridFactory () { macroData_.release(); } template< int dim, int dimworld > inline void GridFactory< AlbertaGrid< dim, dimworld > > ::insertFaceTransformation ( const WorldMatrix &matrix, const WorldVector &shift ) { // make sure the matrix is orthogonal for( int i = 0; i < dimworld; ++i ) for( int j = 0; j < dimworld; ++j ) { const ctype delta = (i == j ? ctype( 1 ) : ctype( 0 )); const ctype epsilon = (8*dimworld)*std::numeric_limits< ctype >::epsilon(); if( std::abs( matrix[ i ] * matrix[ j ] - delta ) > epsilon ) { DUNE_THROW( AlbertaError, "Matrix of face transformation is not orthogonal." ); } } // copy matrix Alberta::GlobalMatrix M; for( int i = 0; i < dimworld; ++i ) for( int j = 0; j < dimworld; ++j ) M[ i ][ j ] = matrix[ i ][ j ]; // copy shift Alberta::GlobalVector t; for( int i = 0; i < dimworld; ++i ) t[ i ] = shift[ i ]; // insert into ALBERTA macro data macroData_.insertWallTrafo( M, t ); } template< int dim, int dimworld > inline unsigned int GridFactory< AlbertaGrid< dim, dimworld > > ::insertionIndex ( const ElementInfo &elementInfo ) const { const MacroElement ¯oElement = elementInfo.macroElement(); const unsigned int index = macroElement.index; #ifndef NDEBUG const typename MacroData::ElementId &elementId = macroData_.element( index ); for( int i = 0; i <= dimension; ++i ) { const Alberta::GlobalVector &x = macroData_.vertex( elementId[ i ] ); const Alberta::GlobalVector &y = macroElement.coordinate( i ); for( int j = 0; j < dimensionworld; ++j ) { if( x[ j ] != y[ j ] ) DUNE_THROW( GridError, "Vertex in macro element does not coincide with same vertex in macro data structure." ); } } #endif // #ifndef NDEBUG return index; } template< int dim, int dimworld > inline unsigned int GridFactory< AlbertaGrid< dim, dimworld > > ::insertionIndex ( const ElementInfo &elementInfo, const int face ) const { typedef typename BoundaryMap::const_iterator Iterator; const Iterator it = boundaryMap_.find( faceId( elementInfo, face ) ); if( it != boundaryMap_.end() ) return it->second; else return std::numeric_limits< unsigned int >::max(); } template< int dim, int dimworld > inline typename GridFactory< AlbertaGrid< dim, dimworld > >::FaceId GridFactory< AlbertaGrid< dim, dimworld > > ::faceId ( const ElementInfo &elementInfo, const int face ) const { const unsigned int index = insertionIndex( elementInfo ); const typename MacroData::ElementId &elementId = macroData_.element( index ); FaceId faceId; for( size_t i = 0; i < faceId.size(); ++i ) { const int k = Alberta::MapVertices< dimension, 1 >::apply( face, i ); faceId[ i ] = elementId[ k ]; } std::sort( faceId.begin(), faceId.end() ); return faceId; } // GridFactory::ProjectionFactory // ------------------------------ template< int dim, int dimworld > class GridFactory< AlbertaGrid< dim, dimworld > >::ProjectionFactory : public Alberta::ProjectionFactory< Alberta::DuneBoundaryProjection< dim >, ProjectionFactory > { typedef ProjectionFactory This; typedef Alberta::ProjectionFactory< Alberta::DuneBoundaryProjection< dim >, ProjectionFactory > Base; typedef typename Dune::GridFactory< AlbertaGrid< dim, dimworld > > Factory; public: typedef typename Base::Projection Projection; typedef typename Base::ElementInfo ElementInfo; typedef typename Projection::Projection DuneProjection; ProjectionFactory( const GridFactory &gridFactory ) : gridFactory_( gridFactory ) {} bool hasProjection ( const ElementInfo &elementInfo, const int face ) const { if( gridFactory().globalProjection_ ) return true; const unsigned int index = gridFactory().insertionIndex( elementInfo, face ); if( index < std::numeric_limits< unsigned int >::max() ) return bool( gridFactory().boundaryProjections_[ index ] ); else return false; } bool hasProjection ( const ElementInfo & /* elementInfo */ ) const { return bool( gridFactory().globalProjection_ ); } Projection projection ( const ElementInfo &elementInfo, const int face ) const { const unsigned int index = gridFactory().insertionIndex( elementInfo, face ); if( index < std::numeric_limits< unsigned int >::max() ) { const DuneProjectionPtr &projection = gridFactory().boundaryProjections_[ index ]; if( projection ) return Projection( projection ); } assert( gridFactory().globalProjection_ ); return Projection( gridFactory().globalProjection_ ); }; Projection projection ( const ElementInfo & /* elementInfo */ ) const { assert( gridFactory().globalProjection_ ); return Projection( gridFactory().globalProjection_ ); }; const GridFactory &gridFactory () const { return gridFactory_; } private: const GridFactory &gridFactory_; }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_GRIDFACTORY_HH dune-grid-2.11.0/dune/grid/albertagrid/gridfamily.hh000066400000000000000000000123461511655130300222670ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRID_GRIDFAMILTY_HH #define DUNE_ALBERTAGRID_GRIDFAMILTY_HH /** \file * \author Martin Nolte * \brief provides the GridFamily for AlbertaGrid */ #include #include #include #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { // External Forward Declarations // ----------------------------- template< int dim, int dimworld > class AlbertaGrid; template< int codim, int dim, class GridImp > class AlbertaGridEntity; template< int codim, class GridImp > class AlbertaGridEntityPointer; template< int codim, class Grid > class AlbertaGridEntitySeed; template< int mydim, int cdim, class GridImp > class AlbertaGridGeometry; template< int mydim, int cdim, class GridImp > class AlbertaGridGlobalGeometry; template< int dim, int dimworld > class AlbertaGridHierarchicIndexSet; template< class GridImp > class AlbertaGridHierarchicIterator; template< class GridImp > class AlbertaGridLeafIntersection; template< class GridImp > class AlbertaGridLeafIntersectionIterator; template< int dim, int dimworld > class AlbertaGridIdSet; template< int dim, int dimworld > class AlbertaGridIndexSet; template< int codim, PartitionIteratorType pitype, class GridImp > class AlbertaGridLeafIterator; template< int codim, PartitionIteratorType pitype, class GridImp > class AlbertaGridLevelIterator; // AlbertaGridFamily // ----------------- template struct AlbertaGridFamily { typedef AlbertaGrid< dim, dimworld > GridImp; typedef Alberta::Real ctype; static const int dimension = dim; static const int dimensionworld = dimworld; typedef AlbertaGridIndexSet< dim, dimworld > LevelIndexSetImp; typedef AlbertaGridIndexSet< dim, dimworld > LeafIndexSetImp; typedef AlbertaGridIdSet< dim, dimworld > IdSetImp; typedef unsigned int IdType; struct Traits { typedef GridImp Grid; typedef Dune::Intersection< const GridImp, AlbertaGridLeafIntersection< const GridImp > > LeafIntersection; typedef Dune::Intersection< const GridImp, AlbertaGridLeafIntersection< const GridImp > > LevelIntersection; typedef Dune::IntersectionIterator < const GridImp, AlbertaGridLeafIntersectionIterator< const GridImp >, AlbertaGridLeafIntersection< const GridImp > > LeafIntersectionIterator; typedef Dune::IntersectionIterator < const GridImp, AlbertaGridLeafIntersectionIterator< const GridImp >, AlbertaGridLeafIntersection< const GridImp > > LevelIntersectionIterator; typedef Dune::EntityIterator< 0, const GridImp, AlbertaGridHierarchicIterator< const GridImp > > HierarchicIterator; typedef IdType GlobalIdType; typedef IdType LocalIdType; template< int cd > struct Codim { typedef AlbertaGridGlobalGeometry< dim-cd, dimworld, const Grid > GeometryImpl; typedef AlbertaGridGeometry< dim-cd, dim, const Grid > LocalGeometryImpl; typedef Dune::Geometry< dim-cd, dimworld, const Grid, AlbertaGridGlobalGeometry > Geometry; typedef Dune::Geometry< dim-cd, dim, const Grid, LocalGeometryReference > LocalGeometry; typedef AlbertaGridEntity< cd, dim, const GridImp > EntityImpl; typedef Dune::Entity< cd, dim, const GridImp, AlbertaGridEntity > Entity; typedef Dune::EntitySeed< const GridImp, AlbertaGridEntitySeed< cd, const GridImp > > EntitySeed; template struct Partition { typedef Dune::EntityIterator< cd, const GridImp, AlbertaGridLevelIterator< cd, pitype, const GridImp > > LevelIterator; typedef Dune::EntityIterator< cd, const GridImp, AlbertaGridLeafIterator< cd, pitype, const GridImp > > LeafIterator; }; typedef typename Partition< All_Partition >::LevelIterator LevelIterator; typedef typename Partition< All_Partition >::LeafIterator LeafIterator; }; typedef Dune::GridView< AlbertaLevelGridViewTraits< const GridImp > > LevelGridView; typedef Dune::GridView< AlbertaLeafGridViewTraits< const GridImp > > LeafGridView; typedef IndexSet< GridImp, LevelIndexSetImp, int, std::array< GeometryType, 1 > > LevelIndexSet; typedef IndexSet< GridImp, LeafIndexSetImp, int, std::array< GeometryType, 1 > > LeafIndexSet; typedef AlbertaGridHierarchicIndexSet< dim, dimworld > HierarchicIndexSet; typedef IdSet GlobalIdSet; typedef IdSet LocalIdSet; typedef Dune::Communication< No_Comm > Communication; }; }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTAGRID_GRIDFAMILTY_HH dune-grid-2.11.0/dune/grid/albertagrid/gridview.hh000066400000000000000000000331741511655130300217620ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRID_GRIDVIEW_HH #define DUNE_ALBERTAGRID_GRIDVIEW_HH #if HAVE_ALBERTA #include #include #include #include #include namespace Dune { template< class GridImp > class AlbertaLevelGridView; template< class GridImp > class AlbertaLeafGridView; template< class GridImp > struct AlbertaLevelGridViewTraits { typedef AlbertaLevelGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid::Traits::LevelIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid::Traits::LevelIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid::Traits::LevelIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid::Traits::Communication Communication; template< int cd > struct Codim { typedef typename Grid::Traits::template Codim< cd >::template Partition< All_Partition >::LevelIterator Iterator; typedef typename Grid::Traits::template Codim< cd >::Entity Entity; typedef typename Grid::template Codim< cd >::Geometry Geometry; typedef typename Grid::template Codim< cd >::LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template< PartitionIteratorType pit > struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid::template Codim< cd >::template Partition< pit >::LevelIterator Iterator; }; }; constexpr static bool conforming = Capabilities::isLevelwiseConforming< Grid >::v; }; template< class GridImp > class AlbertaLevelGridView { typedef AlbertaLevelGridView< GridImp > ThisType; public: typedef AlbertaLevelGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits::IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits::Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits::IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Traits::Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits::template Codim {}; constexpr static bool conforming = Traits::conforming; private: typedef Alberta::ElementInfo< Grid::dimension > ElementInfo; typedef Dune::AlbertaGridLeafIntersectionIterator< GridImp > IntersectionIteratorImpl; public: AlbertaLevelGridView ( const Grid &grid, int level ) : grid_( &grid ), indexSet_( &(grid.levelIndexSet( level )) ), level_( level ) {} // use default implementation of copy constructor and assignment operator #if 0 AlbertaLevelGridView ( const ThisType &other ) : grid_( other.grid_ ), indexSet_( other.indexSet_ ), level_( other.level_ ) {} /** \brief assignment from other GridView on the same grid */ ThisType &operator= ( const ThisType & other) { grid_ = other.grid_; indexSet_ = other.indexSet_; level_ = other.level_; } #endif /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return *indexSet_; } /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming() const { return bool(conforming); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( level_, codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( level_, type ); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd >::Iterator begin () const { return grid().template lbegin< cd, All_Partition >( level_ ); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd >::template Partition< pit >::Iterator begin () const { return grid().template lbegin< cd, pit >( level_ ); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd >::Iterator end () const { return grid().template lend< cd, All_Partition >( level_ ); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd >::template Partition< pit >::Iterator end () const { return grid().template lend< cd, pit >( level_ ); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 >::Entity &entity ) const { if( grid().maxLevel() == 0) { typename IntersectionIteratorImpl::Begin begin; return IntersectionIteratorImpl( entity.impl(), begin ); } else { DUNE_THROW( NotImplemented, "method ibegin not implemented on LevelGridView for AlbertaGrid." ); typename IntersectionIteratorImpl::End end; return IntersectionIteratorImpl( entity.impl(), end ); } } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 >::Entity &entity ) const { typename IntersectionIteratorImpl::End end; return IntersectionIteratorImpl( entity.impl(), end ); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize ( [[maybe_unused]] int codim ) const { return 0; } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize ( [[maybe_unused]] int codim ) const { return 0; } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( [[maybe_unused]] CommDataHandleIF< DataHandleImp, DataType > &data, [[maybe_unused]] InterfaceType iftype, [[maybe_unused]] CommunicationDirection dir ) const {} private: const Grid *grid_; const IndexSet *indexSet_; int level_; }; template< class GridImp > struct AlbertaLeafGridViewTraits { typedef AlbertaLeafGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid::Traits::LeafIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid::Traits::LeafIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid::Traits::LeafIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid::Traits::Communication Communication; template< int cd > struct Codim { typedef typename Grid::Traits::template Codim< cd >::template Partition< All_Partition >::LeafIterator Iterator; typedef typename Grid::Traits::template Codim< cd >::Entity Entity; typedef typename Grid::template Codim< cd >::Geometry Geometry; typedef typename Grid::template Codim< cd >::LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid::template Codim< cd >::template Partition< pit >::LeafIterator Iterator; }; }; constexpr static bool conforming = Capabilities::isLeafwiseConforming< Grid >::v; }; template< class GridImp > class AlbertaLeafGridView { typedef AlbertaLeafGridView< GridImp > ThisType; public: typedef AlbertaLeafGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits::IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits::Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits::IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Traits::Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits::template Codim {}; constexpr static bool conforming = Traits::conforming; private: typedef Alberta::ElementInfo< Grid::dimension > ElementInfo; typedef Dune::AlbertaGridLeafIntersectionIterator< GridImp > IntersectionIteratorImpl; public: AlbertaLeafGridView ( const Grid &grid ) : grid_( &grid ), indexSet_( &(grid.leafIndexSet()) ) {} // use default implementation of copy constructor and assignment operator #if 0 AlbertaLeafGridView ( const ThisType &other ) : grid_( other.grid_ ), indexSet_( other.indexSet_ ) {} /** \brief assignment from other GridView on the same grid */ ThisType &operator= ( const ThisType & other) { grid_ = other.grid_; indexSet_ = other.indexSet_; } #endif /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return *indexSet_; } /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming() const { return bool(conforming); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( type ); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd >::Iterator begin () const { return grid().template leafbegin< cd, All_Partition >(); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd >::template Partition< pit >::Iterator begin () const { return grid().template leafbegin< cd, pit >(); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd >::Iterator end () const { return grid().template leafend< cd, All_Partition >(); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd >::template Partition< pit >::Iterator end () const { return grid().template leafend< cd, pit >(); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 >::Entity &entity ) const { const ElementInfo elementInfo = entity.impl().elementInfo(); assert( !!elementInfo ); #ifndef NDEBUG for( int i = 0; i <= Grid::dimension; ++i ) { if( elementInfo.elInfo().opp_vertex[ i ] == 127 ) DUNE_THROW( NotImplemented, "AlbertaGrid: Intersections on outside entities are not fully implemented, yet." ); } #endif // #ifndef NDEBUG typename IntersectionIteratorImpl::Begin begin; return IntersectionIteratorImpl( entity.impl(), begin ); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 >::Entity &entity ) const { assert( !!entity.impl().elementInfo() ); typename IntersectionIteratorImpl::End end; return IntersectionIteratorImpl( entity.impl(), end ); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize ( [[maybe_unused]] int codim ) const { return 0; } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize ( [[maybe_unused]] int codim ) const { return 0; } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( [[maybe_unused]] CommDataHandleIF< DataHandleImp, DataType > &data, [[maybe_unused]] InterfaceType iftype, [[maybe_unused]] CommunicationDirection dir ) const {} private: const Grid *grid_; const IndexSet *indexSet_; }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTAGRID_GRIDVIEW_HH dune-grid-2.11.0/dune/grid/albertagrid/hierarchiciterator.hh000066400000000000000000000111661511655130300240120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_HIERARCHICITERATOR_HH #define DUNE_ALBERTA_HIERARCHICITERATOR_HH #include #include #if HAVE_ALBERTA namespace Dune { // AlbertaGridHierarchicIterator // ----------------------------- /*! Mesh entities of codimension 0 ("elements") allow to visit all entities of codimension 0 obtained through nested, hierarchic refinement of the entity. Iteration over this set of entities is provided by the HIerarchicIterator, starting from a given entity. This is redundant but important for memory efficient implementations of unstru hierarchically refined meshes. */ template< class GridImp > class AlbertaGridHierarchicIterator { typedef AlbertaGridHierarchicIterator< GridImp > This; public: typedef typename GridImp::template Codim<0>::Entity Entity; typedef typename GridImp::ctype ctype; typedef MakeableInterfaceObject< Entity > EntityObject; typedef typename EntityObject::ImplementationType EntityImp; typedef typename EntityImp::ElementInfo ElementInfo; AlbertaGridHierarchicIterator () {} //! the normal Constructor AlbertaGridHierarchicIterator ( const GridImp &grid, const ElementInfo &elementInfo, int maxLevel ); //! the default Constructor AlbertaGridHierarchicIterator ( const GridImp &grid, int actLevel, int maxLevel ); //! copy onstructor AlbertaGridHierarchicIterator ( const This &other ); //! assignment operator This &operator= ( const This &other ); //! increment void increment(); //! equality bool equals ( const This &other ) const { return entity_.impl().equals( other.entity_.impl() ); } //! dereferencing Entity &dereference () const { return entity_; } //! ask for level of entities int level () const { return entity_.impl().level(); } protected: //! obtain a reference to the grid const GridImp &grid () const { return entity_.impl().grid(); } private: void increment ( ElementInfo elementInfo ); mutable Entity entity_; // level on which the iterator was started int startLevel_; // maximal level to go down to int maxlevel_; }; template< class GridImp > inline AlbertaGridHierarchicIterator< GridImp > ::AlbertaGridHierarchicIterator( const GridImp &grid, int actLevel, int maxLevel ) : entity_( EntityImp( grid ) ), startLevel_( actLevel ), maxlevel_( maxLevel ) {} template< class GridImp > inline AlbertaGridHierarchicIterator< GridImp > ::AlbertaGridHierarchicIterator ( const GridImp &grid, const ElementInfo &elementInfo, int maxLevel ) : entity_( EntityImp( grid ) ), startLevel_( elementInfo.level() ), maxlevel_( maxLevel ) { increment( elementInfo ); } template< class GridImp > inline AlbertaGridHierarchicIterator< GridImp > ::AlbertaGridHierarchicIterator( const This &other ) : entity_( other.entity_ ), startLevel_( other.startLevel_ ), maxlevel_( other.maxlevel_ ) {} template< class GridImp > inline typename AlbertaGridHierarchicIterator< GridImp >::This & AlbertaGridHierarchicIterator< GridImp >::operator= ( const This &other ) { entity_ = other.entity_; startLevel_ = other.startLevel_; maxlevel_ = other.maxlevel_; return *this; } template< class GridImp > inline void AlbertaGridHierarchicIterator< GridImp >::increment () { increment( entity_.impl().elementInfo() ); } template< class GridImp > inline void AlbertaGridHierarchicIterator< GridImp > ::increment ( ElementInfo elementInfo ) { assert( !elementInfo == false ); if( (elementInfo.level() >= maxlevel_) || elementInfo.isLeaf() ) { while( (elementInfo.level() > startLevel_) && (elementInfo.indexInFather() == 1) ) elementInfo = elementInfo.father(); if( elementInfo.level() > startLevel_ ) entity_.impl().setElement( elementInfo.father().child( 1 ), 0 ); else entity_.impl().clearElement(); } else entity_.impl().setElement( elementInfo.child( 0 ), 0 ); } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_HIERARCHICITERATOR_HH dune-grid-2.11.0/dune/grid/albertagrid/indexsets.cc000066400000000000000000000131601511655130300221270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #if HAVE_ALBERTA #include // can we get rid of this? #include namespace Dune { // Implementation of AlbertaGridHierarchicIndexSet::CreateEntityNumbers // -------------------------------------------------------------------- template< int dim, int dimworld > template< int codim > inline void AlbertaGridHierarchicIndexSet< dim, dimworld >::CreateEntityNumbers< codim > ::setup ( AlbertaGridHierarchicIndexSet< dim, dimworld > &indexSet ) { IndexVectorPointer &entityNumbers = indexSet.entityNumbers_[ codim ]; entityNumbers.template setupInterpolation< RefineNumbering< codim > >(); entityNumbers.template setupRestriction< CoarsenNumbering< codim > >(); entityNumbers.setAdaptationData( &(indexSet.indexStack_[ codim ]) ); } template< int dim, int dimworld > template< int codim > inline void AlbertaGridHierarchicIndexSet< dim, dimworld >::CreateEntityNumbers< codim > ::apply ( const Alberta::HierarchyDofNumbering< dimension > &dofNumbering, AlbertaGridHierarchicIndexSet< dim, dimworld > &indexSet ) { const Alberta::DofSpace *dofSpace = dofNumbering.dofSpace( codim ); std::ostringstream s; s << "Numbering for codimension " << codim; indexSet.entityNumbers_[ codim ].create( dofSpace, s.str() ); InitEntityNumber init( indexSet.indexStack_[ codim ] ); indexSet.entityNumbers_[ codim ].forEach( init ); setup( indexSet ); } template< int dim, int dimworld > template< int codim > inline void AlbertaGridHierarchicIndexSet< dim, dimworld >::CreateEntityNumbers< codim > ::apply ( const std::string &filename, const Alberta::MeshPointer< dimension > &mesh, AlbertaGridHierarchicIndexSet< dim, dimworld > &indexSet ) { std::ostringstream s; s << filename << ".cd" << codim; indexSet.entityNumbers_[ codim ].read( s.str(), mesh ); const int maxIndex = max( indexSet.entityNumbers_[ codim ] ); indexSet.indexStack_[ codim ].setMaxIndex( maxIndex + 1 ); setup( indexSet ); } // Implementation of AlbertaGridHierarchicIndexSet::RefineNumbering // ---------------------------------------------------------------- template< int dim, int dimworld > template< int codim > void AlbertaGridHierarchicIndexSet< dim, dimworld >::RefineNumbering< codim > ::operator() ( const Alberta::Element *child, int subEntity ) { int *const array = (int *)dofVector_; const int dof = dofAccess_( child, subEntity ); array[ dof ] = indexStack_.getIndex(); } template< int dim, int dimworld > template< int codim > void AlbertaGridHierarchicIndexSet< dim, dimworld >::RefineNumbering< codim > ::interpolateVector ( const IndexVectorPointer &dofVector, const Alberta::Patch< dimension > &patch ) { RefineNumbering refineNumbering( dofVector ); patch.template forEachInteriorSubChild< codim >( refineNumbering ); } // Implementation of AlbertaGridHierarchicIndexSet::CoarsenNumbering // ----------------------------------------------------------------- template< int dim, int dimworld > template< int codim > void AlbertaGridHierarchicIndexSet< dim, dimworld >::CoarsenNumbering< codim > ::operator() ( const Alberta::Element *child, int subEntity ) { int *const array = (int *)dofVector_; const int dof = dofAccess_( child, subEntity ); indexStack_.freeIndex( array[ dof ] ); } template< int dim, int dimworld > template< int codim > void AlbertaGridHierarchicIndexSet< dim, dimworld >::CoarsenNumbering< codim > ::restrictVector ( const IndexVectorPointer &dofVector, const Patch &patch ) { CoarsenNumbering coarsenNumbering( dofVector ); patch.template forEachInteriorSubChild< codim >( coarsenNumbering ); } // Implementation of AlbertaGridHierarchicIndexSet // ----------------------------------------------- template< int dim, int dimworld > AlbertaGridHierarchicIndexSet< dim, dimworld > ::AlbertaGridHierarchicIndexSet ( const DofNumbering &dofNumbering ) : dofNumbering_( dofNumbering ) {} template< int dim, int dimworld > void AlbertaGridHierarchicIndexSet< dim, dimworld >::create () { Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ CreateEntityNumbers< i >::apply( dofNumbering_, *this ); } ); } template< int dim, int dimworld > void AlbertaGridHierarchicIndexSet< dim, dimworld >::read ( const std::string &filename ) { Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ CreateEntityNumbers< i >::apply( filename, dofNumbering_.mesh(), *this ); } ); } template< int dim, int dimworld > bool AlbertaGridHierarchicIndexSet< dim, dimworld >::write ( const std::string &filename ) const { bool success = true; for( int i = 0; i <= dimension; ++i ) { std::ostringstream s; s << filename << ".cd" << i; success &= entityNumbers_[ i ].write( s.str() ); } return success; } // Instantiation // ------------- template class AlbertaGridHierarchicIndexSet< 1, Alberta::dimWorld >; #if ALBERTA_DIM >= 2 template class AlbertaGridHierarchicIndexSet< 2, Alberta::dimWorld >; #endif // #if ALBERTA_DIM >= 2 #if ALBERTA_DIM >= 3 template class AlbertaGridHierarchicIndexSet< 3, Alberta::dimWorld >; #endif // #if ALBERTA_DIM >= 3 } // namespace Dune #endif // #if HAVE_ALBERTA dune-grid-2.11.0/dune/grid/albertagrid/indexsets.hh000066400000000000000000000427451511655130300221540ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRIDINDEXSETS_HH #define DUNE_ALBERTAGRIDINDEXSETS_HH #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { typedef Dune::IndexStack< int, 100000 > IndexStack; } // AlbertaGridHierarchicIndexSet // ----------------------------- template< int dim, int dimworld > class AlbertaGridHierarchicIndexSet : public IndexSet< AlbertaGridFamily< dim, dimworld >, AlbertaGridHierarchicIndexSet< dim,dimworld >, int, std::array< GeometryType, 1 > > { typedef AlbertaGridHierarchicIndexSet< dim, dimworld > This; typedef IndexSet< AlbertaGridFamily< dim, dimworld >, AlbertaGridHierarchicIndexSet< dim,dimworld >, int, std::array< GeometryType, 1 > > Base; friend class AlbertaGrid< dim, dimworld >; public: typedef AlbertaGrid< dim, dimworld > Grid; typedef AlbertaGridFamily< dim, dimworld > GridFamily; typedef typename Base::IndexType IndexType; typedef typename Base::Types Types; static const int dimension = GridFamily::dimension; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef Alberta::HierarchyDofNumbering< dimension > DofNumbering; private: typedef typename GridFamily::Traits Traits; typedef Alberta::DofVectorPointer< IndexType > IndexVectorPointer; class InitEntityNumber; template< int codim > struct CreateEntityNumbers; template< int codim > struct RefineNumbering; template< int codim > struct CoarsenNumbering; explicit AlbertaGridHierarchicIndexSet ( const DofNumbering &dofNumbering ); static Alberta::IndexStack *currentIndexStack; public: typedef Alberta::IndexStack IndexStack; //! return true if entity is contained in set template< class Entity > bool contains ( const Entity & ) const { return true; } using Base::index; using Base::subIndex; //! return hierarchic index of given entity template< int cc > IndexType index ( const typename Traits::template Codim< cc >::Entity &entity ) const { typedef AlbertaGridEntity< cc, dim, const Grid > EntityImp; const EntityImp &entityImp = entity.impl(); return subIndex( entityImp.elementInfo(), entityImp.subEntity(), cc ); } //! return subIndex of given enitiy's sub entity template< int cc > IndexType subIndex ( const typename Traits::template Codim< cc >::Entity &entity, int i, unsigned int codim ) const { typedef AlbertaGridEntity< cc, dim, const Grid > EntityImp; const EntityImp &entityImp = entity.impl(); int k = i; if( cc > 0 ) { auto refElement = ReferenceElements< Alberta::Real, dimension >::simplex(); k = refElement.subEntity( entityImp.subEntity(), cc, i, codim ); } const int j = entityImp.grid().generic2alberta( codim, k ); return subIndex( entityImp.elementInfo(), j, codim ); } //! return size of set for given GeometryType std::size_t size ( const GeometryType &type ) const { return (type.isSimplex() ? size( dimension - type.dim() ) : 0); } //! return size of set std::size_t size ( int codim ) const { assert( (codim >= 0) && (codim <= dimension) ); return indexStack_[ codim ].size(); } //! obtain all geometry types of entities in domain Types types ( int codim ) const { assert( (codim >= 0) && (codim <= dimension) ); return {{ GeometryTypes::simplex( dimension - codim ) }}; } IndexType subIndex ( const ElementInfo &elementInfo, int i, unsigned int codim ) const { assert( !elementInfo == false ); return subIndex( elementInfo.element(), i, codim ); } /** \brief obtain hierarchic subindex * * \param[in] element pointer to ALBERTA element * \param[in] i number of the subelement (in ALBERTA numbering) * \param[in] codim codimension */ IndexType subIndex ( const Alberta::Element *element, int i, unsigned int codim ) const { IndexType *array = (IndexType *)entityNumbers_[ codim ]; const IndexType subIndex = array[ dofNumbering_( element, codim, i ) ]; assert( (subIndex >= 0) && (subIndex < IndexType(size( codim ))) ); return subIndex; } void preAdapt () { // set global pointer to index stack if( !IndexVectorPointer::supportsAdaptationData ) { assert( currentIndexStack == nullptr ); currentIndexStack = indexStack_; } } void postAdapt () { // remove global pointer to index stack if( !IndexVectorPointer::supportsAdaptationData ) currentIndexStack = nullptr; } void create (); void read ( const std::string &filename ); bool write ( const std::string &filename ) const; void release () { for( int i = 0; i <= dimension; ++i ) entityNumbers_[ i ].release(); } private: template< int codim > static IndexStack &getIndexStack ( const IndexVectorPointer &dofVector ) { IndexStack *indexStack; if( IndexVectorPointer::supportsAdaptationData ) indexStack = dofVector.template getAdaptationData< IndexStack >(); else indexStack = ¤tIndexStack[ codim ]; assert( indexStack != 0 ); return *indexStack; } // access to the dof vectors const DofNumbering &dofNumbering_; // index stacks providing new numbers during adaptation IndexStack indexStack_[ dimension+1 ]; // dof vectors storing the (persistent) numbering IndexVectorPointer entityNumbers_[ dimension+1 ]; }; template< int dim, int dimworld > Alberta::IndexStack* AlbertaGridHierarchicIndexSet::currentIndexStack = nullptr; // AlbertaGridHierarchicIndexSet::InitEntityNumber // ----------------------------------------------- template< int dim, int dimworld > class AlbertaGridHierarchicIndexSet< dim, dimworld >::InitEntityNumber { IndexStack &indexStack_; public: InitEntityNumber ( IndexStack &indexStack ) : indexStack_( indexStack ) {} void operator() ( int &dof ) { dof = indexStack_.getIndex(); } }; // AlbertaGridHierarchicIndexSet::CreateEntityNumbers // -------------------------------------------------- template< int dim, int dimworld > template< int codim > struct AlbertaGridHierarchicIndexSet< dim, dimworld >::CreateEntityNumbers { static void setup ( AlbertaGridHierarchicIndexSet< dim, dimworld > &indexSet ); static void apply ( const Alberta::HierarchyDofNumbering< dimension > &dofNumbering, AlbertaGridHierarchicIndexSet< dim, dimworld > &indexSet ); static void apply ( const std::string &filename, const Alberta::MeshPointer< dimension > &mesh, AlbertaGridHierarchicIndexSet< dim, dimworld > &indexSet ); }; // AlbertaGridHierarchicIndexSet::RefineNumbering // ---------------------------------------------- template< int dim, int dimworld > template< int codim > struct AlbertaGridHierarchicIndexSet< dim, dimworld >::RefineNumbering { static const int dimension = dim; static const int codimension = codim; private: typedef Alberta::DofAccess< dimension, codimension > DofAccess; explicit RefineNumbering ( const IndexVectorPointer &dofVector ) : indexStack_( getIndexStack< codimension >( dofVector ) ), dofVector_( dofVector ), dofAccess_( dofVector.dofSpace() ) {} public: void operator() ( const Alberta::Element *child, int subEntity ); typedef Alberta::Patch< dimension > Patch; static void interpolateVector ( const IndexVectorPointer &dofVector, const Patch &patch ); private: IndexStack &indexStack_; IndexVectorPointer dofVector_; DofAccess dofAccess_; }; // AlbertaGridHierarchicIndexSet::CoarsenNumbering // ----------------------------------------------- template< int dim, int dimworld > template< int codim > struct AlbertaGridHierarchicIndexSet< dim, dimworld >::CoarsenNumbering { static const int dimension = dim; static const int codimension = codim; private: typedef Alberta::DofAccess< dimension, codimension > DofAccess; explicit CoarsenNumbering ( const IndexVectorPointer &dofVector ) : indexStack_( getIndexStack< codimension >( dofVector ) ), dofVector_( dofVector ), dofAccess_( dofVector.dofSpace() ) {} public: void operator() ( const Alberta::Element *child, int subEntity ); typedef Alberta::Patch< dimension > Patch; static void restrictVector ( const IndexVectorPointer &dofVector, const Patch &patch ); private: IndexStack &indexStack_; IndexVectorPointer dofVector_; DofAccess dofAccess_; }; // AlbertaGridIndexSet // ------------------- template< int dim, int dimworld > class AlbertaGridIndexSet : public IndexSet< AlbertaGrid< dim, dimworld >, AlbertaGridIndexSet< dim, dimworld >, int, std::array< GeometryType, 1 > > { typedef AlbertaGridIndexSet< dim, dimworld > This; typedef IndexSet< AlbertaGrid< dim, dimworld >, AlbertaGridIndexSet< dim, dimworld >, int, std::array< GeometryType, 1 > > Base; public: typedef AlbertaGrid< dim, dimworld > Grid; typedef typename Base::IndexType IndexType; typedef typename Base::Types Types; static const int dimension = Grid::dimension; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef Alberta::HierarchyDofNumbering< dimension > DofNumbering; private: typedef typename Grid::Traits Traits; template< int codim > struct Insert; public: explicit AlbertaGridIndexSet ( const DofNumbering &dofNumbering ) : dofNumbering_( dofNumbering ) { for( int codim = 0; codim <= dimension; ++codim ) { indices_[ codim ] = 0; } } ~AlbertaGridIndexSet () { for( int codim = 0; codim <= dimension; ++codim ) delete[] indices_[ codim ]; } template< class Entity > bool contains ( const Entity &entity ) const { const int codim = Entity::codimension; const AlbertaGridEntity< codim, dim, const Grid > &entityImp = entity.impl(); const Alberta::Element *element = entityImp.elementInfo().el(); const IndexType *const array = indices_[ codim ]; const IndexType subIndex = array[ dofNumbering_( element, codim, entityImp.subEntity() ) ]; return (subIndex >= 0); } using Base::index; using Base::subIndex; //! return hierarchic index of given entity template< int cc > IndexType index ( const typename Traits::template Codim< cc >::Entity &entity ) const { typedef AlbertaGridEntity< cc, dim, const Grid > EntityImp; const EntityImp &entityImp = entity.impl(); return subIndex( entityImp.elementInfo(), entityImp.subEntity(), cc ); } //! return subIndex of given enitiy's sub entity template< int cc > IndexType subIndex ( const typename Traits::template Codim< cc >::Entity &entity, int i, unsigned int codim ) const { typedef AlbertaGridEntity< cc, dim, const Grid > EntityImp; const EntityImp &entityImp = entity.impl(); int k = i; if( cc > 0 ) { auto refElement = ReferenceElements< Alberta::Real, dimension >::simplex(); k = refElement.subEntity( entityImp.subEntity(), cc, i, codim ); } const int j = entityImp.grid().generic2alberta( codim, k ); return subIndex( entityImp.elementInfo(), j, codim ); } std::size_t size ( const GeometryType &type ) const { return (type.isSimplex() ? size( dimension - type.dim() ) : 0); } std::size_t size ( int codim ) const { assert( (codim >= 0) && (codim <= dimension) ); return size_[ codim ]; } Types types ( int codim ) const { assert( (codim >= 0) && (codim <= dimension) ); return {{ GeometryTypes::simplex( dimension - codim ) }}; } template< class Iterator > void update ( const Iterator &begin, const Iterator &end ) { for( int codim = 0; codim <= dimension; ++codim ) { delete[] indices_[ codim ]; const unsigned int dofSize = dofNumbering_.size( codim ); indices_[ codim ] = new IndexType[ dofSize ]; for( unsigned int i = 0; i < dofSize; ++i ) indices_[ codim ][ i ] = -1; size_[ codim ] = 0; } for( Iterator it = begin; it != end; ++it ) { const AlbertaGridEntity< 0, dim, const Grid > &entityImp = it->impl(); const Alberta::Element *element = entityImp.elementInfo().el(); Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ Insert< i >::apply( element, *this ); } ); } } private: IndexType subIndex ( const ElementInfo &elementInfo, int i, unsigned int codim ) const { assert( !elementInfo == false ); return subIndex( elementInfo.element(), i, codim ); } /** \brief obtain subindex * * \param[in] element pointer to ALBERTA element * \param[in] i number of the subelement (in ALBERTA numbering) * \param[in] codim codimension */ IndexType subIndex ( const Alberta::Element *element, int i, unsigned int codim ) const { const IndexType *const array = indices_[ codim ]; const IndexType subIndex = array[ dofNumbering_( element, codim, i ) ]; assert( (subIndex >= 0) && (static_cast(subIndex) < size( codim )) ); return subIndex; } // access to the dof vectors const DofNumbering &dofNumbering_; // an array of indices for each codimension IndexType *indices_[ dimension+1 ]; // the size of each codimension IndexType size_[ dimension+1 ]; }; // AlbertaGridIndexSet::Insert // --------------------------- template< int dim, int dimworld > template< int codim > struct AlbertaGridIndexSet< dim, dimworld >::Insert { static void apply ( const Alberta::Element *const element, AlbertaGridIndexSet< dim, dimworld > &indexSet ) { int *const array = indexSet.indices_[ codim ]; IndexType &size = indexSet.size_[ codim ]; for( int i = 0; i < Alberta::NumSubEntities< dim, codim >::value; ++i ) { int &index = array[ indexSet.dofNumbering_( element, codim, i ) ]; if( index < 0 ) index = size++; } } }; // AlbertaGridIdSet // ---------------- //! hierarchic index set of AlbertaGrid template< int dim, int dimworld > class AlbertaGridIdSet : public IdSet< AlbertaGrid< dim, dimworld >, AlbertaGridIdSet< dim, dimworld >, unsigned int > { typedef AlbertaGridIdSet< dim, dimworld > This; typedef IdSet< AlbertaGrid< dim, dimworld >, This, unsigned int > Base; friend class AlbertaGrid< dim, dimworld >; public: //! export type of id typedef typename Base::IdType IdType; private: typedef AlbertaGrid< dim, dimworld > Grid; static const int dimension = Grid::dimension; typedef typename Grid::HierarchicIndexSet HierarchicIndexSet; // create id set, only allowed for AlbertaGrid AlbertaGridIdSet ( const HierarchicIndexSet &hIndexSet ) : hIndexSet_( hIndexSet ) {} public: /** \copydoc IdSet::id() */ template< class Entity > IdType id ( const Entity &e ) const { const int codim = Entity::codimension; return id< codim >( e ); } /** \copydoc IdSet::id() */ template< int codim > IdType id ( const typename Grid::template Codim< codim >::Entity &e ) const { assert( (codim >= 0) && (codim <= dimension) ); const IdType index = hIndexSet_.index( e ); return (index << 2) | IdType( codim ); } /** \copydoc IdSet::subId() */ IdType subId ( const typename Grid::template Codim< 0 >::Entity &e, int i, unsigned int subcodim ) const { assert( int( subcodim ) <= dimension ); const IdType index = hIndexSet_.subIndex( e, i, subcodim ); return (index << 2) | IdType( subcodim ); } /** \copydoc IdSet::subId() */ template< int codim > IdType subId ( const typename Grid::template Codim< codim >::Entity &e, int i, unsigned int subcodim ) const { assert( (codim >= 0) && (codim <= dimension) && (int( codim + subcodim ) <= dimension) ); const IdType index = hIndexSet_.subIndex( e, i, subcodim ); return (index << 2) | IdType( codim + subcodim ); } /** \copydoc IdSet::subId() */ template< class Entity > IdType subId ( const Entity &e, int i, unsigned int subcodim ) const { return subId< Entity::codimension >( e, i, subcodim ); } private: // prohibit copying AlbertaGridIdSet ( const This & ); const HierarchicIndexSet &hIndexSet_; }; } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTAGRIDINDEXSETS_HH dune-grid-2.11.0/dune/grid/albertagrid/indexstack.hh000066400000000000000000000135641511655130300223000ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTAGRID_INDEXSTACK_HH #define DUNE_ALBERTAGRID_INDEXSTACK_HH #include #include #include #include /** @file @author Robert Kloefkorn @brief Provides an index stack that supplies indices for element numbering for a grid (i.e. AlbertaGrid and ALUGrid) */ namespace Dune { //! IndexStack providing indices via getIndex and freeIndex //! indices that are freed, are put on a stack and get template class IndexStack { class MyFiniteStack : public ReservedVector { typedef ReservedVector BaseType ; public: //! Returns true if the stack is full bool full () const { return this->size() >= length; } //! standard push method void push( const T& t ) { BaseType :: push_back( t ); } //! Removes and returns the uppermost object from the stack T topAndPop () { assert( !this->empty() ); assert( this->size() <= length ); // This code is not slower than using the array structure directly. // The compiler removes the temporary completely. I measured this. // See the commit message for revision 7837 for more details. T tmp = this->back(); this->pop_back(); return tmp; } }; typedef MyFiniteStack StackType; typedef typename std::stack < StackType * > StackListType; StackListType fullStackList_; StackListType emptyStackList_; //typedef typename StackListType::Iterator DListIteratorType; StackType * stack_; // current maxIndex int maxIndex_; public: //! Constructor, create new IndexStack inline IndexStack(); //! Destructor, deleting all stacks inline ~IndexStack (); //! set index as maxIndex if index is bigger than maxIndex inline void checkAndSetMax(T index) { if(index > maxIndex_) maxIndex_ = index;} //! set index as maxIndex inline void setMaxIndex(T index) { maxIndex_ = index; } //! return maxIndex which is also the inline int getMaxIndex() const { return maxIndex_; } //! return maxIndex which is also the inline int size() const { return getMaxIndex(); } //! restore index from stack or create new index inline T getIndex (); //! store index on stack inline void freeIndex(T index); //! test stack functionality inline void test (); // backup set to out stream inline void backupIndexSet ( std::ostream & os ); // restore from in stream inline void restoreIndexSet ( std::istream & is ); private: // no copy constructor allowed IndexStack( const IndexStack & s) : maxIndex_ (0) , stack_(0) {} // no assignment operator allowed IndexStack & operator = ( const IndexStack & s) { DUNE_THROW(Exception, "IndexStack::operator = () not allowed!"); return *this; } // clear fullStacks void clearStack (); }; // end class IndexStack //**************************************************************** // Inline implementation // *************************************************************** template inline IndexStack::IndexStack() : stack_ ( new StackType () ) , maxIndex_ (0) {} template inline IndexStack::~IndexStack () { if(stack_) delete stack_; stack_ = 0; while( !fullStackList_.empty() ) { StackType * st = fullStackList_.top(); if(st) delete st; fullStackList_.pop(); } while( !emptyStackList_.empty() ) { StackType * st = emptyStackList_.top(); if(st) delete st; emptyStackList_.pop(); } } template inline T IndexStack::getIndex () { if((*stack_).empty()) { if( fullStackList_.size() <= 0) { return maxIndex_++; } else { emptyStackList_.push( stack_ ); stack_ = fullStackList_.top(); fullStackList_.pop(); } } return (*stack_).topAndPop(); } template inline void IndexStack::freeIndex ( T index ) { if((*stack_).full()) { fullStackList_.push( stack_ ); if(emptyStackList_.size() <= 0) { stack_ = new StackType (); } else { stack_ = emptyStackList_.top(); emptyStackList_.pop(); } } (*stack_).push(index); } template inline void IndexStack::test () { T vec[2*length]; for(int i=0; i<2*length; i++) vec[i] = getIndex(); for(int i=0; i<2*length; i++) freeIndex(vec[i]); for(int i=0; i<2*length; i++) vec[i] = getIndex(); for(int i=0; i<2*length; i++) printf(" index [%d] = %d \n",i,vec[i]); } template inline void IndexStack::backupIndexSet ( std::ostream & os ) { // holes are not stored at the moment os.write( ((const char *) &maxIndex_ ), sizeof(int) ) ; return ; } template inline void IndexStack::restoreIndexSet ( std::istream & is ) { is.read ( ((char *) &maxIndex_), sizeof(int) ); clearStack (); return ; } template inline void IndexStack::clearStack () { if(stack_) { delete stack_; stack_ = new StackType(); assert(stack_); } while( !fullStackList_.empty() ) { StackType * st = fullStackList_.top(); if(st) delete st; fullStackList_.pop(); } return; } } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/albertagrid/intersection.cc000066400000000000000000000313731511655130300226350ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_INTERSECTION_CC #define DUNE_ALBERTA_INTERSECTION_CC #include namespace Dune { // AlbertaGridIntersectionBase // --------------------------- template< class Grid > inline AlbertaGridIntersectionBase< Grid > ::AlbertaGridIntersectionBase () : grid_( nullptr ), elementInfo_(), oppVertex_( -1 ) // mark invalid intersection {} template< class Grid > inline AlbertaGridIntersectionBase< Grid > ::AlbertaGridIntersectionBase ( const EntityImp &entity, const int oppVertex ) : grid_( &entity.grid() ), elementInfo_( entity.elementInfo() ), oppVertex_( oppVertex ) {} template< class Grid > inline typename Grid::template Codim< 0 >::Entity AlbertaGridIntersectionBase< Grid >::inside () const { typedef AlbertaGridEntity< 0, Grid::dimension, Grid > EntityImp; return EntityImp( grid(), elementInfo(), 0 ); } template< class Grid > inline bool AlbertaGridIntersectionBase< Grid >::boundary () const { return elementInfo().isBoundary( oppVertex_ ); } template< class Grid > inline int AlbertaGridIntersectionBase< Grid >::boundaryId () const { if( boundary() ) { const int id = elementInfo().boundaryId( oppVertex_ ); assert( id != 0 ); return id; } else return 0; } template< class Grid > inline size_t AlbertaGridIntersectionBase< Grid >::boundarySegmentIndex () const { assert( boundary() ); const Alberta::BasicNodeProjection *projection = elementInfo().boundaryProjection( oppVertex_ ); assert( projection ); return projection->boundaryIndex(); } template< class Grid > inline int AlbertaGridIntersectionBase< Grid >::indexInInside () const { const int face = (dimension > 1 ? oppVertex_ : 1-oppVertex_); return grid().alberta2generic( 1, face ); } template< class Grid > inline GeometryType AlbertaGridIntersectionBase< Grid >::type () const { return GeometryTypes::simplex( dimension-1 ); } template< class Grid > inline typename AlbertaGridIntersectionBase< Grid >::NormalVector AlbertaGridIntersectionBase< Grid >::centerIntegrationOuterNormal () const { const typename Entity::Geometry geoInside = inside().geometry(); const int face = indexInInside(); auto refSimplex = ReferenceElements< ctype, dimension >::simplex(); FieldVector< ctype, dimension > refNormal = refSimplex.integrationOuterNormal( face ); const typename Entity::Geometry::JacobianInverseTransposed &jInvT = geoInside.impl().jacobianInverseTransposed(); NormalVector normal; jInvT.mv( refNormal, normal ); normal *= geoInside.impl().integrationElement(); return normal; } template<> inline AlbertaGridIntersectionBase< const AlbertaGrid< 1, 1 > >::NormalVector AlbertaGridIntersectionBase< const AlbertaGrid< 1, 1 > >::centerIntegrationOuterNormal () const { const Alberta::GlobalVector &oppCoord = grid().getCoord( elementInfo(), oppVertex_ ); const Alberta::GlobalVector &myCoord = grid().getCoord( elementInfo(), 1-oppVertex_ ); NormalVector n; n[ 0 ] = (myCoord[ 0 ] > oppCoord[ 0 ] ? ctype( 1 ) : -ctype( 1 )); return n; } #if defined GRIDDIM && GRIDDIM > 1 template<> inline AlbertaGridIntersectionBase< const AlbertaGrid< 2, 2 > >::NormalVector AlbertaGridIntersectionBase< const AlbertaGrid< 2, 2 > >::centerIntegrationOuterNormal () const { const Alberta::GlobalVector &coordOne = grid().getCoord( elementInfo(), (oppVertex_+1)%3 ); const Alberta::GlobalVector &coordTwo = grid().getCoord( elementInfo(), (oppVertex_+2)%3 ); NormalVector n; n[ 0 ] = -(coordOne[ 1 ] - coordTwo[ 1 ]); n[ 1 ] = coordOne[ 0 ] - coordTwo[ 0 ]; return n; } #endif // defined GRIDDIM && GRIDDIM > 1 template<> inline AlbertaGridIntersectionBase< const AlbertaGrid< 3, 3 > >::NormalVector AlbertaGridIntersectionBase< const AlbertaGrid< 3, 3 > >::centerIntegrationOuterNormal () const { // in this case the orientation is negative, multiply by -1 const ALBERTA EL_INFO &elInfo = elementInfo().elInfo(); const ctype val = (elInfo.orientation > 0) ? 1.0 : -1.0; static const int faceVertices[ 4 ][ 3 ] = { {1,3,2}, {0,2,3}, {0,3,1}, {0,1,2} }; const int *localFaces = faceVertices[ oppVertex_ ]; const Alberta::GlobalVector &coord0 = grid().getCoord( elementInfo(), localFaces[ 0 ] ); const Alberta::GlobalVector &coord1 = grid().getCoord( elementInfo(), localFaces[ 1 ] ); const Alberta::GlobalVector &coord2 = grid().getCoord( elementInfo(), localFaces[ 2 ] ); FieldVector< ctype, dimensionworld > u; FieldVector< ctype, dimensionworld > v; for( int i = 0; i < dimension; ++i ) { v[ i ] = coord1[ i ] - coord0[ i ]; u[ i ] = coord2[ i ] - coord1[ i ]; } NormalVector n; for( int i = 0; i < dimension; ++i ) { const int j = (i+1)%dimension; const int k = (i+2)%dimension; n[ i ] = val * (u[ j ] * v[ k ] - u[ k ] * v[ j ]); } return n; } template< class Grid > inline typename AlbertaGridIntersectionBase< Grid >::NormalVector AlbertaGridIntersectionBase< Grid >::centerOuterNormal() const { return centerIntegrationOuterNormal(); } template< class Grid > inline typename AlbertaGridIntersectionBase< Grid >::NormalVector AlbertaGridIntersectionBase< Grid >::centerUnitOuterNormal () const { NormalVector normal = centerOuterNormal(); normal *= (1.0 / normal.two_norm()); return normal; } template< class Grid > inline typename AlbertaGridIntersectionBase< Grid >::NormalVector AlbertaGridIntersectionBase< Grid >::integrationOuterNormal ( const LocalCoordType & ) const { return centerIntegrationOuterNormal(); } template< class Grid > inline typename AlbertaGridIntersectionBase< Grid >::NormalVector AlbertaGridIntersectionBase< Grid >::outerNormal( const LocalCoordType & ) const { return centerOuterNormal(); } template< class Grid > inline typename AlbertaGridIntersectionBase< Grid >::NormalVector AlbertaGridIntersectionBase< Grid >::unitOuterNormal ( const LocalCoordType & ) const { return centerUnitOuterNormal(); } template< class Grid > inline AlbertaTransformation AlbertaGridIntersectionBase< Grid >::transformation () const { return AlbertaTransformation( elementInfo().transformation( oppVertex_ ) ); } template< class Grid > inline const Grid &AlbertaGridIntersectionBase< Grid >::grid () const { return *grid_; } template< class Grid > inline const typename AlbertaGridIntersectionBase< Grid >::ElementInfo & AlbertaGridIntersectionBase< Grid >::elementInfo () const { assert( !!elementInfo_ ); return elementInfo_; } // AlbertaGridIntersectionBase::GlobalCoordReader // ---------------------------------------------- template< class GridImp > struct AlbertaGridIntersectionBase< GridImp >::GlobalCoordReader { typedef typename std::remove_const< GridImp >::type Grid; static const int dimension = Grid::dimension; static const int codimension = 1; static const int mydimension = dimension - codimension; static const int coorddimension = Grid::dimensionworld; typedef Alberta::Real ctype; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef FieldVector< ctype, coorddimension > Coordinate; private: const Grid &grid_; const ElementInfo &elementInfo_; const int subEntity_; const int twist_; public: GlobalCoordReader ( const GridImp &grid, const ElementInfo &elementInfo, int subEntity ) : grid_( grid ), elementInfo_( elementInfo ), subEntity_( subEntity ), twist_( elementInfo.template twist< codimension >( subEntity ) ) {} void coordinate ( int i, Coordinate &x ) const { assert( !elementInfo_ == false ); assert( (i >= 0) && (i <= mydimension) ); const int ti = Alberta::applyInverseTwist< mydimension >( twist_, i ); const int k = mapVertices( subEntity_, ti ); const Alberta::GlobalVector &coord = grid_.getCoord( elementInfo_, k ); for( int j = 0; j < coorddimension; ++j ) x[ j ] = coord[ j ]; } bool hasDeterminant () const { return false; } ctype determinant () const { assert( false ); return ctype( 0 ); } private: static int mapVertices ( int subEntity, int i ) { return Alberta::MapVertices< dimension, codimension >::apply( subEntity, i ); } }; // AlbertaGridIntersectionBase::LocalCoordReader // --------------------------------------------- template< class GridImp > struct AlbertaGridIntersectionBase< GridImp >::LocalCoordReader { typedef typename std::remove_const< GridImp >::type Grid; static const int dimension = Grid::dimension; static const int codimension = 1; static const int mydimension = dimension - codimension; static const int coorddimension = dimension; typedef Alberta::Real ctype; typedef FieldVector< ctype, coorddimension > Coordinate; typedef typename Grid::template Codim< 0 >::Geometry ElementGeometry; typedef typename Grid::template Codim< 1 >::Geometry FaceGeometry; private: const ElementGeometry &elementGeometry_; const FaceGeometry &faceGeometry_; public: LocalCoordReader ( const ElementGeometry &elementGeometry, const FaceGeometry &faceGeometry ) : elementGeometry_( elementGeometry ), faceGeometry_( faceGeometry ) {} void coordinate ( int i, Coordinate &x ) const { x = elementGeometry_.local( faceGeometry_.corner( i ) ); } bool hasDeterminant () const { return false; } ctype determinant () const { return ctype( 0 ); } }; // AlbertaGridLeafIntersection // --------------------------- template< class GridImp > inline void AlbertaGridLeafIntersection::next () { assert( oppVertex_ <= dimension ); ++oppVertex_; neighborInfo_ = ElementInfo(); } template< class GridImp > inline typename GridImp::template Codim< 0 >::Entity AlbertaGridLeafIntersection< GridImp >::outside () const { typedef AlbertaGridEntity< 0, GridImp::dimension, GridImp > EntityImp; if( !neighborInfo_ ) { assert( neighbor() ); neighborInfo_ = elementInfo().leafNeighbor( oppVertex_ ); } assert( !neighborInfo_ == false ); assert( neighborInfo_.el() != NULL ); return EntityImp( grid(), neighborInfo_, 0 ); } template< class GridImp > inline bool AlbertaGridLeafIntersection< GridImp >::neighbor () const { assert( oppVertex_ <= dimension ); return elementInfo().hasLeafNeighbor( oppVertex_ ); } template< class GridImp > inline typename AlbertaGridLeafIntersection< GridImp >::LocalGeometry AlbertaGridLeafIntersection< GridImp >::geometryInInside () const { typedef AlbertaGridLocalGeometryProvider< GridImp > LocalGeoProvider; const int twist = elementInfo().template twist< 1 >( oppVertex_ ); const int face = (dimension > 1 ? oppVertex_ : 1-oppVertex_); return LocalGeometry( LocalGeoProvider::instance().faceGeometry( face, twist ) ); } template< class GridImp > inline typename AlbertaGridLeafIntersection< GridImp >::LocalGeometry AlbertaGridLeafIntersection< GridImp >::geometryInOutside () const { assert( neighbor() ); typedef AlbertaGridLocalGeometryProvider< GridImp > LocalGeoProvider; const ALBERTA EL_INFO &elInfo = elementInfo().elInfo(); const int oppVertex = elInfo.opp_vertex[ oppVertex_ ]; const int twist = elementInfo().twistInNeighbor( oppVertex_ ); const int face = (dimension > 1 ? oppVertex : 1-oppVertex); return LocalGeometry( LocalGeoProvider::instance().faceGeometry( face, twist ) ); } template< class GridImp > inline typename AlbertaGridLeafIntersection< GridImp >::Geometry AlbertaGridLeafIntersection< GridImp >::geometry () const { const int face = (dimension > 1 ? oppVertex_ : 1-oppVertex_); const GlobalCoordReader coordReader( grid(), elementInfo(), face ); return Geometry( GeometryImpl( coordReader ) ); } template< class GridImp > inline int AlbertaGridLeafIntersection< GridImp >::indexInOutside () const { const ALBERTA EL_INFO &elInfo = elementInfo().elInfo(); const int oppVertex = elInfo.opp_vertex[ oppVertex_ ]; const int face = (dimension > 1 ? oppVertex : 1-oppVertex); return grid().alberta2generic( 1, face ); } } // namespace Dune #endif // #ifndef DUNE_ALBERTA_INTERSECTION_CC dune-grid-2.11.0/dune/grid/albertagrid/intersection.hh000066400000000000000000000125141511655130300226430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_INTERSECTION_HH #define DUNE_ALBERTA_INTERSECTION_HH #include #include #include #include #if HAVE_ALBERTA namespace Dune { // External Forward Declarations // ----------------------------- template< int codim, int dim, class GridImp > class AlbertaGridEntity; // AlbertaGridIntersectionBase // --------------------------- template< class Grid > class AlbertaGridIntersectionBase { typedef AlbertaGridIntersectionBase< Grid > This; public: typedef typename Grid::ctype ctype; static const int dimension = Grid::dimension; static const int dimensionworld = Grid::dimensionworld; typedef FieldVector< ctype, dimensionworld > NormalVector; typedef FieldVector< ctype, dimension-1 > LocalCoordType; typedef typename Grid::template Codim< 0 >::Entity Entity; typedef typename Grid::template Codim< 1 >::Geometry Geometry; typedef typename Grid::template Codim< 1 >::LocalGeometry LocalGeometry; typedef Alberta::ElementInfo< dimension > ElementInfo; protected: typedef AlbertaGridEntity< 0, dimension, Grid > EntityImp; typedef typename Grid::Traits::template Codim< 1 >::GeometryImpl GeometryImpl; typedef typename Grid::Traits::template Codim< 1 >::LocalGeometryImpl LocalGeometryImpl; struct GlobalCoordReader; struct LocalCoordReader; public: AlbertaGridIntersectionBase (); AlbertaGridIntersectionBase ( const EntityImp &entity, const int oppVertex ); Entity inside () const; bool boundary () const; int boundaryId () const; size_t boundarySegmentIndex () const; int indexInInside () const; GeometryType type () const; NormalVector centerIntegrationOuterNormal () const; NormalVector centerOuterNormal () const; NormalVector centerUnitOuterNormal () const; NormalVector integrationOuterNormal ( [[maybe_unused]] const LocalCoordType &local ) const; NormalVector outerNormal ( [[maybe_unused]] const LocalCoordType &local ) const; NormalVector unitOuterNormal ( [[maybe_unused]] const LocalCoordType &local ) const; AlbertaTransformation transformation () const; const Grid &grid () const; const ElementInfo &elementInfo () const; protected: const Grid *grid_; ElementInfo elementInfo_; int oppVertex_; }; // AlbertaGridLeafIntersection // --------------------------- template< class GridImp > class AlbertaGridLeafIntersection : public AlbertaGridIntersectionBase< GridImp > { typedef AlbertaGridLeafIntersection< GridImp > This; typedef AlbertaGridIntersectionBase< GridImp > Base; friend class AlbertaGridEntity< 0, GridImp::dimension, GridImp >; public: typedef This ImplementationType; static const int dimension = Base::dimension; static const int dimensionworld = Base::dimensionworld; typedef typename Base::NormalVector NormalVector; typedef typename Base::LocalCoordType LocalCoordType; typedef typename Base::Entity Entity; typedef typename Base::Geometry Geometry; typedef typename Base::LocalGeometry LocalGeometry; typedef typename Base::ElementInfo ElementInfo; protected: typedef typename Base::EntityImp EntityImp; typedef typename Base::GeometryImpl GeometryImpl; typedef typename Base::LocalGeometryImpl LocalGeometryImpl; typedef typename Base::GlobalCoordReader GlobalCoordReader; typedef typename Base::LocalCoordReader LocalCoordReader; public: using Base::grid; using Base::elementInfo; using Base::inside; AlbertaGridLeafIntersection () = default; AlbertaGridLeafIntersection ( const EntityImp &entity, int n ) : Base( entity, n ) {} AlbertaGridLeafIntersection ( const This &other ) : Base( other ) {} This &operator= ( const This &other ) { *static_cast< Base * >( this ) = other; neighborInfo_ = ElementInfo(); return *this; } bool operator== ( const This &other ) const { return (oppVertex_ == other.oppVertex_) && (elementInfo_ == other.elementInfo_); } bool operator!= ( const This &other ) const { return (oppVertex_ != other.oppVertex_) || (elementInfo_ != other.elementInfo_); } bool equals ( const AlbertaGridLeafIntersection& other ) const { return (*this) == other; } void next (); typename GridImp::template Codim< 0 >::Entity outside () const; bool neighbor () const; bool conforming () const { return true; } LocalGeometry geometryInInside () const; LocalGeometry geometryInOutside () const; Geometry geometry () const; int indexInOutside () const; int twistInInside () const { return elementInfo().template twist< 1 >( oppVertex_ ); } int twistInOutside () const { return elementInfo().twistInNeighbor( oppVertex_ ); } protected: using Base::elementInfo_; using Base::oppVertex_; private: mutable ElementInfo neighborInfo_; }; } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_INTERSECTION_HH dune-grid-2.11.0/dune/grid/albertagrid/intersectioniterator.hh000066400000000000000000000042401511655130300244120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_INTERSECTIONITERATOR_HH #define DUNE_ALBERTA_INTERSECTIONITERATOR_HH #include #include /** \file * \author Martin Nolte * \brief Implementation of the IntersectionIterator for AlbertaGrid */ #if HAVE_ALBERTA namespace Dune { // AlbertaGridLeafIntersectionIterator // ----------------------------------- template< class GridImp > class AlbertaGridLeafIntersectionIterator { typedef AlbertaGridLeafIntersectionIterator< GridImp > This; public: typedef Dune::Intersection< GridImp, AlbertaGridLeafIntersection< GridImp > > Intersection; static const int dimension = Intersection::Entity::dimension; struct Begin {}; struct End {}; private: typedef AlbertaGridLeafIntersection< GridImp > IntersectionImp; public: AlbertaGridLeafIntersectionIterator () {} template< class EntityImp > AlbertaGridLeafIntersectionIterator ( const EntityImp &entity, Begin ) : intersection_( IntersectionImp( entity, 0 ) ) {} template< class EntityImp > AlbertaGridLeafIntersectionIterator ( const EntityImp &entity, End ) : intersection_( IntersectionImp( entity, dimension+1 ) ) {} AlbertaGridLeafIntersectionIterator ( const This &other ) : intersection_( other.intersection_.impl() ) {} This &operator= ( const This &other ) { intersection_.impl() = other.intersection_.impl(); return *this; } const Intersection &dereference () const { return intersection_; } bool equals ( const This &other ) const { return (intersection_.impl() == other.intersection_.impl()); } void increment () { intersection_.impl().next(); } private: Intersection intersection_; }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_INTERSECTIONITERATOR_HH dune-grid-2.11.0/dune/grid/albertagrid/leafiterator.hh000066400000000000000000000046731511655130300226250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_LEAFITERATOR_HH #define DUNE_ALBERTA_LEAFITERATOR_HH #include #include #if HAVE_ALBERTA namespace Dune { // AlbertaGridLeafIterator // ----------------------- template< int codim, PartitionIteratorType pitype, class GridImp > class AlbertaGridLeafIterator : public AlbertaGridTreeIterator< codim, GridImp, true > { typedef AlbertaGridLeafIterator< codim, pitype, GridImp > This; typedef AlbertaGridTreeIterator< codim, GridImp, true > Base; public: typedef typename Base::Entity Entity; typedef typename Base::MarkerVector MarkerVector; AlbertaGridLeafIterator () {} //! Constructor making end iterator AlbertaGridLeafIterator ( const GridImp &grid, int level ) : Base( grid, level ) {} //! Constructor making begin iterator AlbertaGridLeafIterator ( const GridImp &grid, const MarkerVector *vec, int level ) : Base( grid, vec, level ) {} //! increment the iterator void increment () { Base::increment(); } }; template< int codim, class GridImp > class AlbertaGridLeafIterator< codim, Ghost_Partition, GridImp > : public AlbertaGridTreeIterator< codim, GridImp, true > { typedef AlbertaGridLeafIterator< codim, Ghost_Partition, GridImp > This; typedef AlbertaGridTreeIterator< codim, GridImp, true > Base; public: typedef typename Base::Entity Entity; typedef typename Base::MarkerVector MarkerVector; AlbertaGridLeafIterator () {} //! Constructor making end iterator AlbertaGridLeafIterator ( const GridImp &grid, int level ) : Base( grid, level ) {} //! Constructor making begin iterator (which is the end iterator in this case) AlbertaGridLeafIterator ( const GridImp &grid, const MarkerVector *, int level ) : Base( grid, level ) {} //! increment the iterator void increment () { Base::increment(); } }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_LEAFITERATOR_HH dune-grid-2.11.0/dune/grid/albertagrid/level.hh000066400000000000000000000126151511655130300212460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_LEVEL_HH #define DUNE_ALBERTA_LEVEL_HH #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { // AlbertaGridLevelProvider // ------------------------ template< int dim > class AlbertaGridLevelProvider { typedef AlbertaGridLevelProvider< dim > This; typedef unsigned char Level; typedef Alberta::DofVectorPointer< Level > DofVectorPointer; typedef Alberta::DofAccess< dim, 0 > DofAccess; typedef Alberta::FillFlags< dim > FillFlags; static const Level isNewFlag = (1 << 7); static const Level levelMask = (1 << 7) - 1; class SetLocal; class CalcMaxLevel; template< Level flags > struct ClearFlags; struct Interpolation; public: typedef Alberta::ElementInfo< dim > ElementInfo; typedef Alberta::MeshPointer< dim > MeshPointer; typedef Alberta::HierarchyDofNumbering< dim > DofNumbering; Level operator() ( const Alberta::Element *element ) const { const Level *array = (Level *)level_; return array[ dofAccess_( element, 0 ) ] & levelMask; } Level operator() ( const ElementInfo &elementInfo ) const { return (*this)( elementInfo.el() ); } bool isNew ( const Alberta::Element *element ) const { const Level *array = (Level *)level_; return ((array[ dofAccess_( element, 0 ) ] & isNewFlag) != 0); } bool isNew ( const ElementInfo &elementInfo ) const { return isNew( elementInfo.el() ); } Level maxLevel () const { CalcMaxLevel calcFromCache; level_.forEach( calcFromCache ); #ifndef NDEBUG CalcMaxLevel calcFromGrid; mesh().leafTraverse( calcFromGrid, FillFlags::nothing ); assert( calcFromCache.maxLevel() == calcFromGrid.maxLevel() ); #endif return calcFromCache.maxLevel();; } MeshPointer mesh () const { return MeshPointer( level_.dofSpace()->mesh ); } void markAllOld () { ClearFlags< isNewFlag > clearIsNew; level_.forEach( clearIsNew ); } void create ( const DofNumbering &dofNumbering ) { const Alberta::DofSpace *const dofSpace = dofNumbering.dofSpace( 0 ); dofAccess_ = DofAccess( dofSpace ); level_.create( dofSpace, "Element level" ); assert( level_ ); level_.template setupInterpolation< Interpolation >(); SetLocal setLocal( level_ ); mesh().hierarchicTraverse( setLocal, FillFlags::nothing ); } void release () { level_.release(); dofAccess_ = DofAccess(); } private: DofVectorPointer level_; DofAccess dofAccess_; }; // AlbertaGridLevelProvider::SetLocal // ---------------------------------- template< int dim > class AlbertaGridLevelProvider< dim >::SetLocal { DofVectorPointer level_; DofAccess dofAccess_; public: explicit SetLocal ( const DofVectorPointer &level ) : level_( level ), dofAccess_( level.dofSpace() ) {} void operator() ( const Alberta::ElementInfo< dim > &elementInfo ) const { Level *const array = (Level *)level_; array[ dofAccess_( elementInfo, 0 ) ] = elementInfo.level(); } }; // AlbertaGridLevelProvider::CalcMaxLevel // -------------------------------------- template< int dim > class AlbertaGridLevelProvider< dim >::CalcMaxLevel { Level maxLevel_; public: CalcMaxLevel () : maxLevel_( 0 ) {} void operator() ( const Level &dof ) { maxLevel_ = std::max( maxLevel_, Level( dof & levelMask ) ); } void operator() ( const Alberta::ElementInfo< dim > &elementInfo ) { maxLevel_ = std::max( maxLevel_, Level( elementInfo.level() ) ); } Level maxLevel () const { return maxLevel_; } }; // AlbertaGridLevelProvider::ClearFlags // ------------------------------------ template< int dim > template< typename AlbertaGridLevelProvider< dim >::Level flags > struct AlbertaGridLevelProvider< dim >::ClearFlags { void operator() ( Level &dof ) const { dof &= ~flags; } }; // AlbertaGridLevelProvider::Interpolation // --------------------------------------- template< int dim > struct AlbertaGridLevelProvider< dim >::Interpolation { static const int dimension = dim; typedef Alberta::Patch< dimension > Patch; static void interpolateVector ( const DofVectorPointer &dofVector, const Patch &patch ) { const DofAccess dofAccess( dofVector.dofSpace() ); Level *array = (Level *)dofVector; for( int i = 0; i < patch.count(); ++i ) { const Alberta::Element *const father = patch[ i ]; assert( (array[ dofAccess( father, 0 ) ] & levelMask) < levelMask ); const Level childLevel = (array[ dofAccess( father, 0 ) ] + 1) | isNewFlag; for( int i = 0; i < 2; ++i ) { const Alberta::Element *child = father->child[ i ]; array[ dofAccess( child, 0 ) ] = childLevel; } } } }; } #endif // #if HAVE_ALBERTA #endif dune-grid-2.11.0/dune/grid/albertagrid/leveliterator.hh000066400000000000000000000047201511655130300230160ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_LEVELITERATOR_HH #define DUNE_ALBERTA_LEVELITERATOR_HH #include #include #if HAVE_ALBERTA namespace Dune { // AlbertaGridLevelIterator // ------------------------ template< int codim, PartitionIteratorType pitype, class GridImp > class AlbertaGridLevelIterator : public AlbertaGridTreeIterator< codim, GridImp, false > { typedef AlbertaGridLevelIterator< codim, pitype, GridImp > This; typedef AlbertaGridTreeIterator< codim, GridImp, false > Base; public: typedef typename Base::Entity Entity; typedef typename Base::MarkerVector MarkerVector; AlbertaGridLevelIterator () {} //! Constructor making end iterator AlbertaGridLevelIterator ( const GridImp &grid, int level ) : Base( grid, level ) {} //! Constructor making begin iterator AlbertaGridLevelIterator ( const GridImp &grid, const MarkerVector *vec, int level ) : Base( grid, vec, level ) {} //! increment the iterator void increment () { Base::increment(); } }; template< int codim, class GridImp > class AlbertaGridLevelIterator< codim, Ghost_Partition, GridImp > : public AlbertaGridTreeIterator< codim, GridImp, false > { typedef AlbertaGridLevelIterator< codim, Ghost_Partition, GridImp > This; typedef AlbertaGridTreeIterator< codim, GridImp, false > Base; public: typedef typename Base::Entity Entity; typedef typename Base::MarkerVector MarkerVector; AlbertaGridLevelIterator () {} //! Constructor making end iterator AlbertaGridLevelIterator ( const GridImp &grid, int level ) : Base( grid, level ) {} //! Constructor making begin iterator (which is the end iterator in this case) AlbertaGridLevelIterator ( const GridImp &grid, const MarkerVector *, int level ) : Base( grid, level ) {} //! increment the iterator void increment () { Base::increment(); } }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_LEVELITERATOR_HH dune-grid-2.11.0/dune/grid/albertagrid/macrodata.cc000066400000000000000000000257071511655130300220660ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include /** \file * \author Martin Nolte * \brief provides a wrapper for ALBERTA's macro_data structure */ #include #if HAVE_ALBERTA #include namespace Dune { namespace Alberta { template< int dim > template< int dimWorld > bool MacroData< dim >::Library< dimWorld > ::checkNeighbors ( const MacroData ¯oData ) { assert( macroData.data_ ); if( !(macroData.data_->neigh) ) return true; const bool hasOppVertex = (bool)macroData.data_->opp_vertex; const int count = macroData.elementCount(); for( int i = 0; i < count; ++i ) { for( int j = 0; j <= dimension; ++j ) { const int nb = macroData.data_->neigh[ i*numVertices + j ]; if( nb < 0 ) continue; if( nb >= macroData.elementCount() ) return false; if( hasOppVertex ) { const int ov = macroData.data_->opp_vertex[ i*numVertices + j ]; if( ov > dimension ) return false; if( macroData.data_->neigh[ nb*numVertices + ov ] != i ) return false; if( macroData.data_->opp_vertex[ nb*numVertices + ov ] != j ) return false; } else { bool foundSelf = false; for( int k = 0; k <= dimension; ++k ) foundSelf |= (macroData.data_->neigh[ nb*numVertices + k ] == i); if( !foundSelf ) return false; } } } return true; } template<> template<> void MacroData< 1 >::Library< dimWorld >::markLongestEdge ( MacroData ¯oData ) { assert( macroData.data_ ); } template<> template<> void MacroData< 2 >::Library< dimWorld >::markLongestEdge ( MacroData ¯oData ) { assert( macroData.data_ ); std::cerr << "Marking longest edge for refinement..." << std::endl; const int count = macroData.elementCount(); for( int i = 0; i < count; ++i ) { const int refEdge = RefinementEdge< dimension >::value; const int edge = longestEdge( macroData, macroData.element( i ) ); if( edge != refEdge ) rotate( macroData, i, edge + (numVertices - refEdge) ); } } template<> template<> void MacroData< 3 >::Library< dimWorld >::markLongestEdge ( MacroData ¯oData ) { static const int shift[ 6 ] = { 0, 0, 3, 1, 0, 2 }; static const int swapSuccessor[ 6 ] = { -1, 1, -1, -1, 3, -1 }; static const int oldedge[ 6 ][ 6 ] = { { 0, 1, 2, 3, 4, 5 }, { 1, 0, 2, 3, 5, 4 }, { 2, 4, 5, 0, 1, 3 }, { 3, 4, 0, 5, 1, 2 }, { 4, 5, 2, 3, 0, 1 }, { 5, 1, 3, 2, 4, 0 } }; static const ElementType eltype[ 4 ] = { 1, 0, 0, 1 }; assert( macroData.data_ ); std::cerr << "Marking longest edge for refinement..." << std::endl; bool warnOpposedLongestEdges = false; const int count = macroData.elementCount(); for( int i = 0; i < count; ++i ) { const ElementId &element = macroData.element( i ); // calculate edge lengths std::array< Real, 6 > length; for( int j = 0; j < 6; ++j ) length[ j ] = edgeLength ( macroData, element, j ); // find longest edge int edge = 0; for( int k = 1; k < 6; ++k ) edge = (length[ k ] > length[ edge ] ? k : edge); // mark longest edge as refinement edge if( shift[ edge ] > 0 ) rotate( macroData, i, shift[ edge ] ); if( swapSuccessor[ edge ] > 0 ) swap( macroData, i, swapSuccessor[ edge ], (swapSuccessor[ edge ] + 1) % numVertices ); // make sure that the longest edge is the refinement edge (temporary assertion) const int refEdge = RefinementEdge< dimension >::value; if( longestEdge( macroData, macroData.element( i ) ) != refEdge ) DUNE_THROW( InvalidStateException, "Unable to mark longest edge." ); // improve second refinement edge int lengthFlags = 0; lengthFlags |= int( length[ oldedge[ edge ][ 2 ] ] > length[ oldedge[ edge ][ 1 ] ] ); lengthFlags |= int( length[ oldedge[ edge ][ 4 ] ] > length[ oldedge[ edge ][ 3 ] ] ) << 1; warnOpposedLongestEdges |= (length[ oldedge[ edge ][ 5 ] ] > length[ oldedge[ edge ][ (lengthFlags & 1) + 1 ] ]); warnOpposedLongestEdges |= (length[ oldedge[ edge ][ 5 ] ] > length[ oldedge[ edge ][ (lengthFlags >> 1) + 3 ] ]); if( (lengthFlags & 2) != 0 ) swap( macroData, i, 0, 1 ); macroData.data_->el_type[ i ] = eltype[ lengthFlags ]; } if( warnOpposedLongestEdges ) std::cerr << "Warning: There are elements whose longest edges don't share a vertex." << std::endl; } template< int dim > template< int dimWorld > void MacroData< dim >::Library< dimWorld > ::setOrientation ( MacroData ¯oData, const Real orientation ) {} #if ALBERTA_DIM <= 3 template<> template<> void MacroData< dimWorld >::Library< dimWorld > ::setOrientation ( MacroData ¯oData, const Real orientation ) { assert( macroData.data_ ); const int count = macroData.elementCount(); for( int i = 0; i < count; ++i ) { FieldMatrix< Real, dimWorld, dimWorld > jacobianTransposed; ElementId &id = macroData.element( i ); const GlobalVector &x = macroData.vertex( id[ 0 ] ); for( int j = 0; j < dimWorld; ++j ) { const GlobalVector &y = macroData.vertex( id[ j+1 ] ); for( int k = 0; k < dimWorld; ++k ) jacobianTransposed[ j ][ k ] = y[ k ] - x[ k ]; } if( determinant( jacobianTransposed ) * orientation < 0 ) swap( macroData, i, (dimWorld == 3 ? 2 : 0), (dimWorld == 3 ? 3 : 1) ); } } #endif // #if ALBERTA_DIM <= 3 template< int dim > template< int dimWorld > inline Real MacroData< dim >::Library< dimWorld > ::edgeLength ( const MacroData ¯oData, const ElementId &e, int edge ) { using std::sqrt; const int i = MapVertices< dim, dim-1 >::apply( edge, 0 ); assert( (macroData.vertexCount_ < 0) || (e[ i ] < macroData.vertexCount_) ); const GlobalVector &x = macroData.vertex( e[ i ] ); const int j = MapVertices< dim, dim-1 >::apply( edge, 1 ); assert( (macroData.vertexCount_ < 0) || (e[ j ] < macroData.vertexCount_) ); const GlobalVector &y = macroData.vertex( e[ j ] ); Real sum = (y[ 0 ] - x[ 0 ]) * (y[ 0 ] - x[ 0 ]); for( int i = 1; i < dimWorld; ++i ) sum += (y[ i ] - x[ i ]) * (y[ i ] - x[ i ]); return sqrt( sum ); } template< int dim > template< int dimWorld > inline int MacroData< dim >::Library< dimWorld > ::longestEdge ( const MacroData ¯oData, const ElementId &e ) { int maxEdge = 0; Real maxLength = edgeLength( macroData, e, 0 ); for( int i = 1; i < numEdges; ++i ) { const Real length = edgeLength( macroData, e, i ); if( length <= maxLength ) continue; maxEdge = i; maxLength = length; } return maxEdge; } template< int dim > template< int dimWorld > template< class Type > inline void MacroData< dim >::Library< dimWorld >::rotate ( Type *array, int i, int shift ) { if( array ) { const int offset = i*numVertices; Type old[ numVertices ]; for( int j = 0; j < numVertices; ++j ) old[ j ] = array[ offset + j ]; for( int j = 0; j < numVertices; ++j ) array[ offset + j ] = old[ (j+shift) % numVertices ]; } } template< int dim > template< int dimWorld > inline void MacroData< dim >::Library< dimWorld >::rotate ( MacroData ¯oData, int i, int shift ) { // rotate vertices rotate( macroData.data_->mel_vertices, i, shift ); // correct opposite vertices if( macroData.data_->opp_vertex ) { assert( macroData.data_->neigh ); const int shiftBack = numVertices - (shift % numVertices); for( int j = 0; j < numVertices; ++j ) { const int nb = macroData.data_->neigh[ i*numVertices + j ]; if( nb < 0 ) continue; const int ov = macroData.data_->opp_vertex[ i*numVertices + j ]; assert( macroData.data_->neigh[ nb*numVertices + ov ] == i ); assert( macroData.data_->opp_vertex[ nb*numVertices + ov ] == j ); macroData.data_->opp_vertex[ nb*numVertices + ov ] = (j+shiftBack) % numVertices; } rotate( macroData.data_->opp_vertex, i, shift ); } // correct neighbors and boundaries rotate( macroData.data_->neigh, i, shift ); rotate( macroData.data_->boundary, i, shift ); } template< int dim > template< int dimWorld > inline void MacroData< dim >::Library< dimWorld > ::swap ( MacroData ¯oData, int el, int v1, int v2 ) { std::swap( macroData.element( el )[ v1 ], macroData.element( el )[ v2 ] ); if( macroData.data_->opp_vertex ) { assert( macroData.data_->neigh ); const int nb1 = macroData.neighbor( el, v1 ); if( nb1 >= 0 ) { const int ov = macroData.data_->opp_vertex[ el*numVertices + v1 ]; assert( macroData.neighbor( nb1, ov ) == el ); assert( macroData.data_->opp_vertex[ nb1*numVertices + ov ] == v1 ); macroData.data_->opp_vertex[ nb1*numVertices + ov ] = v2; } const int nb2 = macroData.neighbor( el, v2 ); if( nb2 >= 0 ) { const int ov = macroData.data_->opp_vertex[ el*numVertices + v2 ]; assert( macroData.neighbor( nb2, ov ) == el ); assert( macroData.data_->opp_vertex[ nb2*numVertices + ov ] == v2 ); macroData.data_->opp_vertex[ nb2*numVertices + ov ] = v1; } std::swap( macroData.data_->opp_vertex[ el*numVertices + v1 ], macroData.data_->opp_vertex[ el*numVertices + v2 ] ); } if( macroData.data_->neigh ) std::swap( macroData.neighbor( el, v1 ), macroData.neighbor( el, v2 ) ); if( macroData.data_->boundary ) std::swap( macroData.boundaryId( el, v1 ), macroData.boundaryId( el, v2 ) ); } // Instantiation // ------------- template struct Dune::Alberta::MacroData< 1 >::Library< dimWorld >; #if ALBERTA_DIM >= 2 template struct Dune::Alberta::MacroData< 2 >::Library< dimWorld >; #endif // #if ALBERTA_DIM >= 2 #if ALBERTA_DIM >= 3 template struct Dune::Alberta::MacroData< 3 >::Library< dimWorld >; #endif // #if ALBERTA_DIM >= 3 } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA dune-grid-2.11.0/dune/grid/albertagrid/macrodata.hh000066400000000000000000000312741511655130300220740ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_MACRODATA_HH #define DUNE_ALBERTA_MACRODATA_HH /** \file * \author Martin Nolte * \brief provides a wrapper for ALBERTA's macro_data structure */ #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { template< int dim > class MacroData { typedef MacroData< dim > This; typedef ALBERTA MACRO_DATA Data; static const int dimension = dim; static const int numVertices = NumSubEntities< dimension, dimension >::value; static const int numEdges = NumSubEntities< dimension, dimension-1 >::value; static const int initialSize = 4096; public: template< int > struct Library; template< int > friend struct InstantiateMacroDataLibrary; public: typedef int ElementId[ numVertices ]; static const int supportPeriodicity = 1; MacroData () : data_( NULL ), vertexCount_( -1 ), elementCount_( -1 ) {} operator Data * () const { return data_; } int vertexCount () const { return (vertexCount_ < 0 ? data_->n_total_vertices : vertexCount_); } int elementCount () const { return (elementCount_ < 0 ? data_->n_macro_elements : elementCount_); } ElementId &element ( int i ) const; GlobalVector &vertex ( int i ) const; int &neighbor ( int element, int i ) const; BoundaryId &boundaryId ( int element, int i ) const; /** \brief create a new macro data structure * * A new macro data structure is created and put into insert mode. */ void create (); /** \brief compress macro data structure * * Compress the macro data structure to its minimum size and leave * insert mode. * * \note This method may always be called. It does nothing outside of * insert mode. */ void finalize (); /** \brief mark the longest edge of all elements as refinement edges * * This is a postprocessing step and should be done after finalizing * the triangulation. * * \note Though it is possible to call markLongestEdge in insert mode, * you must make sure that all required vertices have been set. */ void markLongestEdge (); /** \brief set the orientation of all elements * * This is a postprocessing step and should be done after finalizing * the triangulation. * * \note Though it is possible to call setOrientation in insert mode, * you must make sure that all required vertices have been set. */ void setOrientation ( const Real orientation ); /** \brief check the neighbor information * * This method allows the verification of neighbor information in a * finalized (and possibly postprecessed) macro triangulation. * * \note On unfinalized macro triangulations there is no neighbor * information. Hence this check will succeed in this case. * * \returns true, if all generated neighbor information is correct. */ bool checkNeighbors () const; /** \brief release the macro data structure */ void release () { if( data_ != NULL ) { ALBERTA free_macro_data( data_ ); data_ = NULL; } vertexCount_ = elementCount_ = -1; } /** \brief insert element * * Insert an element into the macro data structure. This may only be * done in insert mode. */ int insertElement ( const ElementId &id ); /** \brief insert vertex * * Insert a vertex into the macro data structure. This may only be * done in insert mode. */ int insertVertex ( const GlobalVector &coords ) { assert( vertexCount_ >= 0 ); if( vertexCount_ >= data_->n_total_vertices ) resizeVertices( 2*vertexCount_ ); copy( coords, vertex( vertexCount_ ) ); return vertexCount_++; } /** \brief insert vertex * * Insert a vertex into the macro data structure. This may only be * done in insert mode. */ int insertVertex ( const FieldVector< Real, dimWorld > &coords ) { assert( vertexCount_ >= 0 ); if( vertexCount_ >= data_->n_total_vertices ) resizeVertices( 2*vertexCount_ ); copy( coords, vertex( vertexCount_ ) ); return vertexCount_++; } void insertWallTrafo ( const GlobalMatrix &m, const GlobalVector &t ); void insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix, const FieldVector< Real, dimWorld > &shift ); void checkCycles (); void read ( const std::string &filename, bool binary = false ); bool write ( const std::string &filename, bool binary = false ) const { if( binary ) return ALBERTA write_macro_data_xdr( data_, filename.c_str() ); else return ALBERTA write_macro_data( data_, filename.c_str() ); } private: template< class Vector > void copy ( const Vector &x, GlobalVector &y ) { for( int i = 0; i < dimWorld; ++i ) y[ i ] = x[ i ]; } void resizeElements ( const int newSize ); void resizeVertices ( const int newSize ) { const int oldSize = data_->n_total_vertices; data_->n_total_vertices = newSize; data_->coords = memReAlloc< GlobalVector >( data_->coords, oldSize, newSize ); assert( (data_->coords != NULL) || (newSize == 0) ); } private: Data *data_; int vertexCount_; int elementCount_; }; // MacroData::Library // ------------------ template< int dim > template< int > struct MacroData< dim >::Library { typedef Alberta::MacroData< dim > MacroData; static bool checkNeighbors ( const MacroData ¯oData ); static void markLongestEdge ( MacroData ¯oData ); static void setOrientation ( [[maybe_unused]] MacroData ¯oData, [[maybe_unused]] const Real orientation ); private: static Real edgeLength ( const MacroData ¯oData, const ElementId &e, int edge ); static int longestEdge ( const MacroData ¯oData, const ElementId &e ); template< class Type > static void rotate ( Type *array, int i, int shift ); static void rotate ( MacroData ¯oData, int i, int shift ); static void swap ( MacroData ¯oData, int el, int v1, int v2 ); }; // Implementation of MacroData // --------------------------- template< int dim > inline typename MacroData< dim >::ElementId & MacroData< dim >::element ( int i ) const { assert( (i >= 0) && (i < data_->n_macro_elements) ); const int offset = i * numVertices; return *reinterpret_cast< ElementId * >( data_->mel_vertices + offset ); } template< int dim > inline GlobalVector &MacroData< dim >::vertex ( int i ) const { assert( (i >= 0) && (i < data_->n_total_vertices) ); return data_->coords[ i ]; } template< int dim > inline int &MacroData< dim >::neighbor ( int element, int i ) const { assert( (element >= 0) && (element < data_->n_macro_elements) ); assert( (i >= 0) && (i < numVertices) ); return data_->neigh[ element*numVertices + i ]; } template< int dim > inline BoundaryId &MacroData< dim >::boundaryId ( int element, int i ) const { assert( (element >= 0) && (element < data_->n_macro_elements) ); assert( (i >= 0) && (i < numVertices) ); return data_->boundary[ element*numVertices + i ]; } template< int dim > inline void MacroData< dim >::create () { release(); data_ = ALBERTA alloc_macro_data( dim, initialSize, initialSize ); data_->boundary = memAlloc< BoundaryId >( initialSize*numVertices ); if( dim == 3 ) data_->el_type = memAlloc< ElementType >( initialSize ); vertexCount_ = elementCount_ = 0; elementCount_ = 0; } template< int dim > inline void MacroData< dim >::finalize () { if( (vertexCount_ >= 0) && (elementCount_ >= 0) ) { resizeVertices( vertexCount_ ); resizeElements( elementCount_ ); ALBERTA compute_neigh_fast( data_ ); // assign default boundary id (if none is assigned) for( int element = 0; element < elementCount_; ++element ) { for( int i = 0; i < numVertices; ++i ) { BoundaryId &id = boundaryId( element, i ); if( neighbor( element, i ) >= 0 ) { assert( id == InteriorBoundary ); id = InteriorBoundary; } else id = (id == InteriorBoundary ? DirichletBoundary : id); } } vertexCount_ = elementCount_ = -1; } assert( (vertexCount_ < 0) && (elementCount_ < 0) ); } template< int dim > inline void MacroData< dim >::markLongestEdge () { Library< dimWorld >::markLongestEdge( *this ); } template< int dim > inline void MacroData< dim >::setOrientation ( const Real orientation ) { Library< dimWorld >::setOrientation( *this, orientation ); } template< int dim > inline bool MacroData< dim >::checkNeighbors () const { return Library< dimWorld >::checkNeighbors( *this ); } template< int dim > inline int MacroData< dim >::insertElement ( const ElementId &id ) { assert( elementCount_ >= 0 ); if( elementCount_ >= data_->n_macro_elements ) resizeElements( 2*elementCount_ ); ElementId &e = element( elementCount_ ); for( int i = 0; i < numVertices; ++i ) { e[ i ] = id[ i ]; boundaryId( elementCount_, i ) = InteriorBoundary; } if( dim == 3 ) data_->el_type[ elementCount_ ] = 0; return elementCount_++; } template< int dim > inline void MacroData< dim > ::insertWallTrafo ( const GlobalMatrix &matrix, const GlobalVector &shift ) { int &count = data_->n_wall_trafos; AffineTransformation *&array = data_->wall_trafos; // resize wall trafo array array = memReAlloc< AffineTransformation >( array, count, count+1 ); assert( data_->wall_trafos != NULL ); // copy matrix and shift for( int i = 0; i < dimWorld; ++i ) copy( matrix[ i ], array[ count ].M[ i ] ); copy( shift, array[ count ].t ); ++count; } template< int dim > inline void MacroData< dim > ::insertWallTrafo ( const FieldMatrix< Real, dimWorld, dimWorld > &matrix, const FieldVector< Real, dimWorld > &shift ) { int &count = data_->n_wall_trafos; AffineTransformation *&array = data_->wall_trafos; // resize wall trafo array array = memReAlloc< AffineTransformation >( array, count, count+1 ); assert( data_->wall_trafos != NULL ); // copy matrix and shift for( int i = 0; i < dimWorld; ++i ) copy( matrix[ i ], array[ count ].M[ i ] ); copy( shift, array[ count ].t ); ++count; } template< int dim > inline void MacroData< dim >::checkCycles () { // ensure that the macro data has been finalized finalize(); ALBERTA macro_test( data_, NULL ); } template< int dim > inline void MacroData< dim >::read ( const std::string &filename, bool binary ) { release(); if( binary ) data_ = ALBERTA read_macro_xdr( filename.c_str() ); else data_ = ALBERTA read_macro( filename.c_str() ); } template< int dim > inline void MacroData< dim >::resizeElements ( const int newSize ) { const int oldSize = data_->n_macro_elements; data_->n_macro_elements = newSize; data_->mel_vertices = memReAlloc( data_->mel_vertices, oldSize*numVertices, newSize*numVertices ); data_->boundary = memReAlloc( data_->boundary, oldSize*numVertices, newSize*numVertices ); if( dim == 3 ) data_->el_type = memReAlloc( data_->el_type, oldSize, newSize ); assert( (newSize == 0) || (data_->mel_vertices != NULL) ); } } } #endif // #if HAVE_ALBERTA #endif dune-grid-2.11.0/dune/grid/albertagrid/macroelement.hh000066400000000000000000000032041511655130300226040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_MACROELEMENT_HH #define DUNE_ALBERTA_MACROELEMENT_HH #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // MacroElement // ------------ template< int dim > struct MacroElement : public ALBERTA MACRO_EL { const GlobalVector &coordinate ( const int vertex ) const; int boundaryId ( const int face ) const; bool isBoundary ( const int face ) const; const MacroElement< dim > *neighbor ( const int face ) const; }; template< int dim > inline const GlobalVector &MacroElement< dim >::coordinate ( const int vertex ) const { assert( (vertex >= 0) && (vertex < N_VERTICES_MAX) ); return *coord[ vertex ]; } template< int dim > inline bool MacroElement< dim >::isBoundary ( const int face ) const { return (boundaryId( face ) != InteriorBoundary); } template< int dim > inline int MacroElement< dim >::boundaryId ( const int face ) const { return wall_bound[ face ]; } template< int dim > const MacroElement< dim > *MacroElement< dim >::neighbor ( const int face ) const { assert( (face >= 0) && (face < N_NEIGH_MAX) ); return static_cast< const MacroElement * >( neigh[ face ] ); } } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_MACROELEMENT_HH dune-grid-2.11.0/dune/grid/albertagrid/meshpointer.cc000066400000000000000000000047341511655130300224650ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #if HAVE_ALBERTA #include namespace Dune { namespace Alberta { // Implementation of MeshPointer // ----------------------------- template< int dim > template< int dimWorld > void MeshPointer< dim >::Library< dimWorld > ::create ( MeshPointer &ptr, const MacroData< dim > ¯oData, ALBERTA NODE_PROJECTION *(*initNodeProjection)( Mesh *, ALBERTA MACRO_EL *, int ) ) { ptr.mesh_ = GET_MESH( dim, "DUNE AlbertaGrid", macroData, initNodeProjection, NULL ); // The 1d grid does not create the face projections, so we do it here if( (dim == 1) && (ptr.mesh_ != NULL) ) { const MacroIterator eit = ptr.end(); for( MacroIterator it = ptr.begin(); it != eit; ++it ) { MacroElement ¯oEl = const_cast< MacroElement & >( it.macroElement() ); for( int i = 1; i <= dim+1; ++i ) macroEl.projection[ i ] = initNodeProjection( ptr.mesh_, ¯oEl, i ); } } } template< int dim > template< int dimWorld > void MeshPointer< dim >::Library< dimWorld >::release ( MeshPointer &ptr ) { if( ptr.mesh_ == NULL ) return; // free projections const MacroIterator eit = ptr.end(); for( MacroIterator it = ptr.begin(); it != eit; ++it ) { MacroElement ¯oEl = const_cast< MacroElement & >( it.macroElement() ); for( int i = 0; i <= dim+1; ++i ) { if( macroEl.projection[ i ] != NULL ) { delete static_cast< BasicNodeProjection * >( macroEl.projection[ i ] ); macroEl.projection[ i ] = NULL; } } } // free mesh ALBERTA free_mesh( ptr.mesh_ ); ptr.mesh_ = NULL; } // Instantiation // ------------- template struct Dune::Alberta::MeshPointer< 1 >::Library< dimWorld >; #if ALBERTA_DIM >= 2 template struct Dune::Alberta::MeshPointer< 2 >::Library< dimWorld >; #endif // #if ALBERTA_DIM >= 2 #if ALBERTA_DIM >= 3 template struct Dune::Alberta::MeshPointer< 3 >::Library< dimWorld >; #endif // #if ALBERTA_DIM >= 3 } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA dune-grid-2.11.0/dune/grid/albertagrid/meshpointer.hh000066400000000000000000000315441511655130300224760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_MESHPOINTER_HH #define DUNE_ALBERTA_MESHPOINTER_HH /** \file * \author Martin Nolte * \brief provides a wrapper for ALBERTA's mesh structure */ #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // External Forward Declarations // ----------------------------- template< int dim > class HierarchyDofNumbering; // MeshPointer // ----------- template< int dim > class MeshPointer { typedef Alberta::ElementInfo< dim > ElementInfo; typedef typename ElementInfo::MacroElement MacroElement; typedef typename ElementInfo::FillFlags FillFlags; class BoundaryProvider; template< int dimWorld > struct Library; public: class MacroIterator; MeshPointer () : mesh_( 0 ) {} explicit MeshPointer ( Mesh *mesh ) : mesh_( mesh ) {} operator Mesh * () const { return mesh_; } explicit operator bool () const { return (bool)mesh_; } MacroIterator begin () const { return MacroIterator( *this, false ); } MacroIterator end () const { return MacroIterator( *this, true ); } int numMacroElements () const; int size ( int codim ) const; // create a mesh from a macrodata structure // params: macroData - macro data structure // returns: number of boundary segments unsigned int create ( const MacroData< dim > ¯oData ); // create a mesh from a macrodata structure, adding projections // params: macroData - macro data structure // projectionFactory - factory for the projections // returns: number of boundary segments template< class Proj, class Impl > unsigned int create ( const MacroData< dim > ¯oData, const ProjectionFactoryInterface< Proj, Impl > &projectionFactory ); // create a mesh from a file // params: filename - file name of an Alberta macro triangulation // binary - read binary? // returns: number of boundary segments unsigned int create ( const std::string &filename, bool binary = false ); // read back a mesh from a file // params: filename - file name of an Alberta save file // time - variable to receive the time stored in the file // returns: number of boundary segments // // notes: - projections are not preserved // - we assume that projections are added in the same order they // inserted in when the grid was created (otherwise the boundary // indices change) unsigned int read ( const std::string &filename, Real &time ); bool write ( const std::string &filename, Real time ) const; void release (); template< class Functor > void hierarchicTraverse ( Functor &functor, typename FillFlags::Flags fillFlags = FillFlags::standard ) const; template< class Functor > void leafTraverse ( Functor &functor, typename FillFlags::Flags fillFlags = FillFlags::standard ) const; bool coarsen ( typename FillFlags::Flags fillFlags = FillFlags::nothing ); bool refine ( typename FillFlags::Flags fillFlags = FillFlags::nothing ); private: static ALBERTA NODE_PROJECTION * initNodeProjection ( [[maybe_unused]] Mesh *mesh, ALBERTA MACRO_EL *macroElement, int n ); template< class ProjectionProvider > static ALBERTA NODE_PROJECTION * initNodeProjection ( Mesh *mesh, ALBERTA MACRO_EL *macroElement, int n ); Mesh *mesh_; }; // MeshPointer::Library // -------------------- template< int dim > template< int dimWorld > struct MeshPointer< dim >::Library { typedef Alberta::MeshPointer< dim > MeshPointer; static inline unsigned int boundaryCount = 0; static inline const void *projectionFactory = nullptr; static void create ( MeshPointer &ptr, const MacroData< dim > ¯oData, ALBERTA NODE_PROJECTION *(*initNodeProjection)( Mesh *, ALBERTA MACRO_EL *, int ) ); static void release ( MeshPointer &ptr ); }; // MeshPointer::MacroIterator // -------------------------- template< int dim > class MeshPointer< dim >::MacroIterator { typedef MacroIterator This; friend class MeshPointer< dim >; public: typedef Alberta::MeshPointer< dim > MeshPointer; typedef Alberta::ElementInfo< dim > ElementInfo; MacroIterator () : mesh_(), index_( -1 ) {} private: explicit MacroIterator ( const MeshPointer &mesh, bool end = false ) : mesh_( mesh ), index_( end ? mesh.numMacroElements() : 0 ) {} public: bool done () const { return (index_ >= mesh().numMacroElements()); } bool equals ( const MacroIterator &other ) const { return (index_ == other.index_); } void increment () { assert( !done() ); ++index_; } const MacroElement ¯oElement () const { assert( !done() ); return static_cast< const MacroElement & >( mesh().mesh_->macro_els[ index_ ] ); } const MeshPointer &mesh () const { return mesh_; } This &operator++ () { increment(); return *this; } ElementInfo operator* () const { return elementInfo(); } bool operator== ( const MacroIterator &other ) const { return equals( other ); } bool operator!= ( const MacroIterator &other ) const { return !equals( other ); } ElementInfo elementInfo ( typename FillFlags::Flags fillFlags = FillFlags::standard ) const { if( done() ) return ElementInfo(); else return ElementInfo( mesh(), macroElement(), fillFlags ); } private: MeshPointer mesh_; int index_; }; // Implementation of MeshPointer // ----------------------------- template< int dim > inline int MeshPointer< dim >::numMacroElements () const { return (mesh_ ? mesh_->n_macro_el : 0); } template<> inline int MeshPointer< 1 >::size( int codim ) const { assert( (codim >= 0) && (codim <= 1) ); return (codim == 0 ? mesh_->n_elements : mesh_->n_vertices); } template<> inline int MeshPointer< 2 >::size( int codim ) const { assert( (codim >= 0) && (codim <= 2) ); if( codim == 0 ) return mesh_->n_elements; else if( codim == 2 ) return mesh_->n_vertices; else return mesh_->n_edges; } template<> inline int MeshPointer< 3 >::size( int codim ) const { assert( (codim >= 0) && (codim <= 3) ); if( codim == 0 ) return mesh_->n_elements; else if( codim == 3 ) return mesh_->n_vertices; else if( codim == 1 ) return mesh_->n_faces; else return mesh_->n_edges; } template< int dim > inline unsigned int MeshPointer< dim > ::create ( const MacroData< dim > ¯oData ) { release(); Library< dimWorld >::boundaryCount = 0; Library< dimWorld >::create( *this, macroData, &initNodeProjection ); return Library< dimWorld >::boundaryCount; } template< int dim > template< class Proj, class Impl > inline unsigned int MeshPointer< dim > ::create ( const MacroData< dim > ¯oData, const ProjectionFactoryInterface< Proj, Impl > &projectionFactory ) { typedef ProjectionFactoryInterface< Proj, Impl > ProjectionFactory; release(); Library< dimWorld >::boundaryCount = 0; Library< dimWorld >::projectionFactory = &projectionFactory; Library< dimWorld >::create( *this, macroData, &initNodeProjection< ProjectionFactory > ); Library< dimWorld >::projectionFactory = nullptr; return Library< dimWorld >::boundaryCount; } template< int dim > inline unsigned int MeshPointer< dim > ::create ( const std::string &filename, bool binary ) { MacroData< dim > macroData; macroData.read( filename, binary ); const unsigned int boundaryCount = create( macroData ); macroData.release(); return boundaryCount; } template< int dim > inline unsigned int MeshPointer< dim >::read ( const std::string &filename, Real &time ) { release(); Library< dimWorld >::boundaryCount = 0; mesh_ = ALBERTA read_mesh_xdr( filename.c_str(), &time, NULL, NULL ); return Library< dimWorld >::boundaryCount; } template< int dim > inline bool MeshPointer< dim >::write ( const std::string &filename, Real time ) const { int success = ALBERTA write_mesh_xdr( mesh_, filename.c_str(), time ); return (success == 0); } template< int dim > inline void MeshPointer< dim >::release () { Library< dimWorld >::release( *this ); } template< int dim > template< class Functor > inline void MeshPointer< dim > ::hierarchicTraverse ( Functor &functor, typename FillFlags::Flags fillFlags ) const { const MacroIterator eit = end(); for( MacroIterator it = begin(); it != eit; ++it ) { const ElementInfo info = it.elementInfo( fillFlags ); info.hierarchicTraverse( functor ); } } template< int dim > template< class Functor > inline void MeshPointer< dim > ::leafTraverse ( Functor &functor, typename FillFlags::Flags fillFlags ) const { const MacroIterator eit = end(); for( MacroIterator it = begin(); it != eit; ++it ) { const ElementInfo info = it.elementInfo( fillFlags ); info.leafTraverse( functor ); } } template< int dim > inline bool MeshPointer< dim >::coarsen ( typename FillFlags::Flags fillFlags ) { const bool coarsened = (ALBERTA coarsen( mesh_, fillFlags ) == meshCoarsened); if( coarsened ) ALBERTA dof_compress( mesh_ ); return coarsened; } template< int dim > inline bool MeshPointer< dim >::refine ( typename FillFlags::Flags fillFlags ) { return (ALBERTA refine( mesh_, fillFlags ) == meshRefined); } template< int dim > inline ALBERTA NODE_PROJECTION * MeshPointer< dim >::initNodeProjection ( Mesh *mesh, ALBERTA MACRO_EL *macroEl, int n ) { const MacroElement ¯oElement = static_cast< const MacroElement & >( *macroEl ); if( (n > 0) && macroElement.isBoundary( n-1 ) ) return new BasicNodeProjection( Library< dimWorld >::boundaryCount++ ); else return 0; } template< int dim > template< class ProjectionFactory > inline ALBERTA NODE_PROJECTION * MeshPointer< dim >::initNodeProjection ( Mesh *mesh, ALBERTA MACRO_EL *macroEl, int n ) { typedef typename ProjectionFactory::Projection Projection; const MacroElement ¯oElement = static_cast< const MacroElement & >( *macroEl ); MeshPointer< dim > meshPointer( mesh ); ElementInfo elementInfo( meshPointer, macroElement, FillFlags::standard ); const ProjectionFactory &projectionFactory = *static_cast< const ProjectionFactory * >( Library< dimWorld >::projectionFactory ); if( (n > 0) && macroElement.isBoundary( n-1 ) ) { const unsigned int boundaryIndex = Library< dimWorld >::boundaryCount++; if( projectionFactory.hasProjection( elementInfo, n-1 ) ) { Projection projection = projectionFactory.projection( elementInfo, n-1 ); return new NodeProjection< dim, Projection >( boundaryIndex, projection ); } else return new BasicNodeProjection( boundaryIndex ); } else if( (dim < dimWorld) && (n == 0) ) { const unsigned int boundaryIndex = std::numeric_limits< unsigned int >::max(); if( projectionFactory.hasProjection( elementInfo ) ) { Projection projection = projectionFactory.projection( elementInfo ); return new NodeProjection< dim, Projection >( boundaryIndex, projection ); } else return 0; } else return 0; } } // namespace Alberta } // namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_MESHPOINTER_HH dune-grid-2.11.0/dune/grid/albertagrid/misc.hh000066400000000000000000000366501511655130300210770ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_MISC_HH #define DUNE_ALBERTA_MISC_HH #include #include #include #include #include #include #if HAVE_ALBERTA // should the coordinates be cached in a vector (required for ALBERTA 2.0)? #ifndef DUNE_ALBERTA_CACHE_COORDINATES #define DUNE_ALBERTA_CACHE_COORDINATES 1 #endif namespace Dune { // Exceptions // ---------- class AlbertaError : public Exception {}; class AlbertaIOError : public IOError {}; namespace Alberta { // Import Types // ------------ static const int dimWorld = DIM_OF_WORLD; typedef ALBERTA REAL Real; typedef ALBERTA REAL_B LocalVector; // in barycentric coordinates typedef ALBERTA REAL_D GlobalVector; typedef ALBERTA REAL_DD GlobalMatrix; typedef ALBERTA AFF_TRAFO AffineTransformation; typedef ALBERTA MESH Mesh; typedef ALBERTA EL Element; static const int meshRefined = MESH_REFINED; static const int meshCoarsened = MESH_COARSENED; static const int InteriorBoundary = INTERIOR; static const int DirichletBoundary = DIRICHLET; typedef ALBERTA BNDRY_TYPE BoundaryId; typedef U_CHAR ElementType; typedef ALBERTA FE_SPACE DofSpace; // Memory Manipulation Functions // ----------------------------- template< class Data > inline Data *memAlloc ( size_t size ) { return MEM_ALLOC( size, Data ); } template< class Data > inline Data *memCAlloc ( size_t size ) { return MEM_CALLOC( size, Data ); } template< class Data > inline Data *memReAlloc ( Data *ptr, size_t oldSize, size_t newSize ) { return MEM_REALLOC( ptr, oldSize, newSize, Data ); } template< class Data > inline void memFree ( Data *ptr, size_t size ) { return MEM_FREE( ptr, size, Data ); } // GlobalSpace // ----------- class GlobalSpace { typedef GlobalSpace This; public: typedef GlobalMatrix Matrix; typedef GlobalVector Vector; private: Matrix identityMatrix_; Vector nullVector_; GlobalSpace () { for( int i = 0; i < dimWorld; ++i ) { for( int j = 0; j < dimWorld; ++j ) identityMatrix_[ i ][ j ] = Real( 0 ); identityMatrix_[ i ][ i ] = Real( 1 ); nullVector_[ i ] = Real( 0 ); } } static This &instance () { static This theInstance; return theInstance; } public: static const Matrix &identityMatrix () { return instance().identityMatrix_; } static const Vector &nullVector () { return instance().nullVector_; } }; // NumSubEntities // -------------- template< int dim, int codim > struct NumSubEntities; template< int dim > struct NumSubEntities< dim, 0 > { static const int value = 1; }; template< int dim > struct NumSubEntities< dim, dim > { static const int value = dim+1; }; template<> struct NumSubEntities< 0, 0 > { static const int value = 1; }; template<> struct NumSubEntities< 2, 1 > { static const int value = 3; }; template<> struct NumSubEntities< 3, 1 > { static const int value = 4; }; template<> struct NumSubEntities< 3, 2 > { static const int value = 6; }; // CodimType // --------- template< int dim, int codim > struct CodimType; template< int dim > struct CodimType< dim, 0 > { static const int value = CENTER; }; template< int dim > struct CodimType< dim, dim > { static const int value = VERTEX; }; template<> struct CodimType< 2, 1 > { static const int value = EDGE; }; template<> struct CodimType< 3, 1 > { static const int value = FACE; }; template<> struct CodimType< 3, 2 > { static const int value = EDGE; }; // FillFlags // --------- template< int dim > struct FillFlags { typedef ALBERTA FLAGS Flags; static const Flags nothing = FILL_NOTHING; static const Flags coords = FILL_COORDS; static const Flags neighbor = FILL_NEIGH; static const Flags orientation = (dim == 3 ? FILL_ORIENTATION : FILL_NOTHING); static const Flags projection = FILL_PROJECTION; static const Flags elementType = FILL_NOTHING; static const Flags boundaryId = FILL_MACRO_WALLS; static const Flags nonPeriodic = FILL_NON_PERIODIC; static const Flags all = coords | neighbor | boundaryId | nonPeriodic | orientation | projection | elementType; static const Flags standardWithCoords = all & ~nonPeriodic & ~projection; #if DUNE_ALBERTA_CACHE_COORDINATES static const Flags standard = standardWithCoords & ~coords; #else static const Flags standard = standardWithCoords; #endif }; // RefinementEdge // -------------- template< int dim > struct RefinementEdge { static const int value = 0; }; template<> struct RefinementEdge< 2 > { static const int value = 2; }; // Dune2AlbertaNumbering // --------------------- template< int dim, int codim > struct Dune2AlbertaNumbering { static int apply ( const int i ) { assert( (i >= 0) && (i < NumSubEntities< dim, codim >::value) ); return i; } }; template<> struct Dune2AlbertaNumbering< 3, 2 > { static const int numSubEntities = NumSubEntities< 3, 2 >::value; static int apply ( const int i ) { assert( (i >= 0) && (i < numSubEntities) ); static int dune2alberta[ numSubEntities ] = { 0, 3, 1, 2, 4, 5 }; return dune2alberta[ i ]; } }; // Generic2AlbertaNumbering // ------------------------ template< int dim, int codim > struct Generic2AlbertaNumbering { static int apply ( const int i ) { assert( (i >= 0) && (i < NumSubEntities< dim, codim >::value) ); return i; } }; template< int dim > struct Generic2AlbertaNumbering< dim, 1 > { static int apply ( const int i ) { assert( (i >= 0) && (i < NumSubEntities< dim, 1 >::value) ); return dim - i; } }; template<> struct Generic2AlbertaNumbering< 1, 1 > { static int apply ( const int i ) { assert( (i >= 0) && (i < NumSubEntities< 1, 1 >::value) ); return i; } }; template<> struct Generic2AlbertaNumbering< 3, 2 > { static const int numSubEntities = NumSubEntities< 3, 2 >::value; static int apply ( const int i ) { assert( (i >= 0) && (i < numSubEntities) ); static int generic2alberta[ numSubEntities ] = { 0, 1, 3, 2, 4, 5 }; return generic2alberta[ i ]; } }; // NumberingMap // ------------ template< int dim, template< int, int > class Numbering = Generic2AlbertaNumbering > class NumberingMap { typedef NumberingMap< dim, Numbering > This; template< int codim > struct Initialize; int *dune2alberta_[ dim+1 ]; int *alberta2dune_[ dim+1 ]; int numSubEntities_[ dim+1 ]; NumberingMap ( const This & ); This &operator= ( const This & ); public: NumberingMap () { Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( auto i ){ Initialize< i >::apply( *this ); } ); } ~NumberingMap () { for( int codim = 0; codim <= dim; ++codim ) { delete[]( dune2alberta_[ codim ] ); delete[]( alberta2dune_[ codim ] ); } } int dune2alberta ( int codim, int i ) const { assert( (codim >= 0) && (codim <= dim) ); assert( (i >= 0) && (i < numSubEntities( codim )) ); return dune2alberta_[ codim ][ i ]; } int alberta2dune ( int codim, int i ) const { assert( (codim >= 0) && (codim <= dim) ); assert( (i >= 0) && (i < numSubEntities( codim )) ); return alberta2dune_[ codim ][ i ]; } int numSubEntities ( int codim ) const { assert( (codim >= 0) && (codim <= dim) ); return numSubEntities_[ codim ]; } }; // NumberingMap::Initialize // ------------------------ template< int dim, template< int, int > class Numbering > template< int codim > struct NumberingMap< dim, Numbering >::Initialize { static const int numSubEntities = NumSubEntities< dim, codim >::value; static void apply ( NumberingMap< dim, Numbering > &map ) { map.numSubEntities_[ codim ] = numSubEntities; map.dune2alberta_[ codim ] = new int[ numSubEntities ]; map.alberta2dune_[ codim ] = new int[ numSubEntities ]; for( int i = 0; i < numSubEntities; ++i ) { const int j = Numbering< dim, codim >::apply( i ); map.dune2alberta_[ codim ][ i ] = j; map.alberta2dune_[ codim ][ j ] = i; } } }; // MapVertices // ----------- template< int dim, int codim > struct MapVertices; template< int dim > struct MapVertices< dim, 0 > { static int apply ( int subEntity, int vertex ) { assert( subEntity == 0 ); assert( (vertex >= 0) && (vertex <= NumSubEntities< dim, dim >::value) ); return vertex; } }; template<> struct MapVertices< 2, 1 > { static int apply ( int subEntity, int vertex ) { assert( (subEntity >= 0) && (subEntity < 3) ); assert( (vertex >= 0) && (vertex < 2) ); //static const int map[ 3 ][ 2 ] = { {1,2}, {2,0}, {0,1} }; static const int map[ 3 ][ 2 ] = { {1,2}, {0,2}, {0,1} }; return map[ subEntity ][ vertex ]; } }; template<> struct MapVertices< 3, 1 > { static int apply ( int subEntity, int vertex ) { assert( (subEntity >= 0) && (subEntity < 4) ); assert( (vertex >= 0) && (vertex < 3) ); //static const int map[ 4 ][ 3 ] = { {1,2,3}, {0,3,2}, {0,1,3}, {0,2,1} }; static const int map[ 4 ][ 3 ] = { {1,2,3}, {0,2,3}, {0,1,3}, {0,1,2} }; return map[ subEntity ][ vertex ]; } }; template<> struct MapVertices< 3, 2 > { static int apply ( int subEntity, int vertex ) { assert( (subEntity >= 0) && (subEntity < 6) ); assert( (vertex >= 0) && (vertex < 2) ); static const int map[ 6 ][ 2 ] = { {0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3} }; return map[ subEntity ][ vertex ]; } }; template< int dim > struct MapVertices< dim, dim > { static int apply ( int subEntity, int vertex ) { assert( (subEntity >= 0) && (subEntity < NumSubEntities< dim, 1 >::value) ); assert( vertex == 0 ); return subEntity; } }; // Twist // ----- // ****************************************************************** // Meaning of the twist (same as in ALU) // ------------------------------------- // // Consider a fixed ordering of the vertices v_1, ... v_n of a face // (here, we assume their indices to be increasing). Denote by k the // local number of a vertex v within the element and by t the twist. // Then, v = v_j, where j is computed by the following formula: // // / (2n + 1 - k + t) % n, if t < 0 // j = < // \ (k + t) % n, if t >= 0 // // Note: We use the order of the 0-th vertex dof to assign the twist. // This is ok for two reasons: // - ALBERTA preserves the relative order of the dofs during // dof compression. // - ALBERTA enforces the first vertex dof admin to be periodic. // ****************************************************************** template< int dim, int subdim > struct Twist { static const int numSubEntities = NumSubEntities< dim, dim-subdim >::value; static const int minTwist = 0; static const int maxTwist = 0; static int twist ( [[maybe_unused]] const Element *element, [[maybe_unused]] int subEntity ) { assert( (subEntity >= 0) && (subEntity < numSubEntities) ); return 0; } }; template< int dim > struct Twist< dim, 1 > { static const int numSubEntities = NumSubEntities< dim, dim-1 >::value; static const int minTwist = 0; static const int maxTwist = 1; static int twist ( const Element *element, int subEntity ) { assert( (subEntity >= 0) && (subEntity < numSubEntities) ); const int numVertices = NumSubEntities< 1, 1 >::value; int dof[ numVertices ]; for( int i = 0; i < numVertices; ++i ) { const int j = MapVertices< dim, dim-1 >::apply( subEntity, i ); dof[ i ] = element->dof[ j ][ 0 ]; } return (dof[ 0 ] < dof[ 1 ] ? 0 : 1); } }; template<> struct Twist< 1, 1 > { static const int minTwist = 0; static const int maxTwist = 0; static int twist ( [[maybe_unused]] const Element *element, [[maybe_unused]] int subEntity ) { assert( subEntity == 0 ); return 0; } }; template< int dim > struct Twist< dim, 2 > { static const int numSubEntities = NumSubEntities< dim, dim-2 >::value; static const int minTwist = -3; static const int maxTwist = 2; static int twist ( const Element *element, int subEntity ) { assert( (subEntity >= 0) && (subEntity < numSubEntities) ); const int numVertices = NumSubEntities< 2, 2 >::value; int dof[ numVertices ]; for( int i = 0; i < numVertices; ++i ) { const int j = MapVertices< dim, dim-2 >::apply( subEntity, i ); dof[ i ] = element->dof[ j ][ 0 ]; } const int twist[ 8 ] = { -2, 1, 666, -1, 2, 666, -3, 0 }; const int k = int( dof[ 0 ] < dof[ 1 ] ) | (int( dof[ 0 ] < dof[ 2 ] ) << 1) | (int( dof[ 1 ] < dof[ 2 ] ) << 2); assert( twist[ k ] != 666 ); return twist[ k ]; } }; template<> struct Twist< 2, 2 > { static const int minTwist = 0; static const int maxTwist = 0; static int twist ( [[maybe_unused]] const Element *element, [[maybe_unused]] int subEntity ) { assert( subEntity == 0 ); return 0; } }; template< int dim > inline int applyTwist ( int twist, int i ) { const int numCorners = NumSubEntities< dim, dim >::value; return (twist < 0 ? (2*numCorners + 1 - i + twist) : i + twist) % numCorners; } template< int dim > inline int applyInverseTwist ( int twist, int i ) { const int numCorners = NumSubEntities< dim, dim >::value; return (twist < 0 ? (2*numCorners + 1 - i + twist) : numCorners + i - twist) % numCorners; } } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_MISC_HH dune-grid-2.11.0/dune/grid/albertagrid/persistentcontainer.hh000066400000000000000000000025071511655130300242410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_PERSISTENTCONTAINER_HH #define DUNE_ALBERTA_PERSISTENTCONTAINER_HH #include #if HAVE_ALBERTA #include namespace Dune { // PersistentContainer for AlbertaGrid // ----------------------------------- template< int dim, int dimworld, class T > class PersistentContainer< AlbertaGrid< dim, dimworld >, T > : public PersistentContainerVector< AlbertaGrid< dim, dimworld >, typename AlbertaGrid< dim, dimworld >::HierarchicIndexSet, std::vector< T > > { typedef PersistentContainerVector< AlbertaGrid< dim, dimworld >, typename AlbertaGrid< dim, dimworld >::HierarchicIndexSet, std::vector< T > > Base; public: typedef typename Base::Grid Grid; typedef typename Base::Value Value; PersistentContainer ( const Grid &grid, int codim, const Value &value = Value() ) : Base( grid.hierarchicIndexSet(), codim, value ) {} }; } // end namespace Dune #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALU_PERSISTENTCONTAINER_HH dune-grid-2.11.0/dune/grid/albertagrid/projection.hh000066400000000000000000000156441511655130300223200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_NODEPROJECTION_HH #define DUNE_ALBERTA_NODEPROJECTION_HH #include #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // Internal Forward Declarations // ----------------------------- template< class Proj, class Impl > class ProjectionFactory; // DuneBoundaryProjection // ---------------------- template< int dim > class DuneBoundaryProjection { typedef DuneBoundaryProjection< dim > This; public: static const int dimension = dim; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef FieldVector< Real, dimWorld > GlobalCoordinate; typedef Dune::DuneBoundaryProjection< dimWorld > Projection; typedef std::shared_ptr< const Projection > ProjectionPtr; explicit DuneBoundaryProjection ( const ProjectionPtr &projection ) : projection_( projection ) {} // note: GlobalVector is an array type; global is the return value void operator() ( const ElementInfo & /* elementInfo */, const LocalVector /* local */, GlobalVector global ) const { GlobalCoordinate x; for( int i = 0; i < dimWorld; ++i ) x[ i ] = global[ i ]; GlobalCoordinate y = projection() ( x ); for( int i = 0; i < dimWorld; ++i ) global[ i ] = y[ i ]; } const Projection &projection () const { return *projection_; } private: ProjectionPtr projection_; }; // ProjectionFactoryInterface // -------------------------- template< class Proj, class Impl > class ProjectionFactoryInterface { typedef ProjectionFactoryInterface< Proj, Impl > This; friend class ProjectionFactory< Proj, Impl >; public: typedef Proj Projection; static const int dimension = Projection::dimension; typedef Alberta::ElementInfo< dimension > ElementInfo; private: ProjectionFactoryInterface () {} ProjectionFactoryInterface ( const This &other ); This &operator= ( const This &other ); public: bool hasProjection ( const ElementInfo &elementInfo, const int face ) const { return asImpl().hasProjection( elementInfo, face ); } bool hasProjection ( const ElementInfo &elementInfo ) const { return asImpl().hasProjection( elementInfo ); } Projection projection ( const ElementInfo &elementInfo, const int face ) const { return asImpl().projection( elementInfo, face ); }; Projection projection ( const ElementInfo &elementInfo ) const { return asImpl().projection( elementInfo ); }; protected: const Impl &asImpl () const { return static_cast< const Impl & >( *this ); } }; // ProjectionFactory // ----------------- template< class Proj, class Impl > class ProjectionFactory : public ProjectionFactoryInterface< Proj, Impl > { typedef ProjectionFactory< Proj, Impl > This; typedef ProjectionFactoryInterface< Proj, Impl > Base; public: typedef typename Base::Projection Projection; typedef typename Base::ElementInfo ElementInfo; protected: ProjectionFactory () {} private: bool hasProjection ( const ElementInfo &elementInfo, const int face ) const; bool hasProjection ( const ElementInfo &elementInfo ) const; Projection projection ( const ElementInfo &elementInfo, const int face ) const; Projection projection ( const ElementInfo &elementInfo ) const; }; // DuneGlobalBoundaryProjectionFactory // ----------------------------------- template< int dim > class DuneGlobalBoundaryProjectionFactory : public ProjectionFactory< DuneBoundaryProjection< dim >, DuneGlobalBoundaryProjectionFactory< dim > > { typedef DuneGlobalBoundaryProjectionFactory< dim > This; typedef ProjectionFactory< DuneBoundaryProjection< dim >, This > Base; public: typedef typename Base::Projection Projection; typedef typename Base::ElementInfo ElementInfo; typedef typename Projection::ProjectionPtr DuneProjectionPtr; DuneGlobalBoundaryProjectionFactory ( const DuneProjectionPtr &projection ) : projection_( projection ) {} bool hasProjection ( const ElementInfo &elementInfo, const int face ) const { return true; } bool hasProjection ( const ElementInfo &elementInfo ) const { return true; } Projection projection ( const ElementInfo &elementInfo, const int face ) const { return projection_; }; Projection projection ( const ElementInfo &elementInfo ) const { return projection_; }; private: const Projection projection_; }; // BasicNodeProjection // ------------------- struct BasicNodeProjection : public ALBERTA NODE_PROJECTION { explicit BasicNodeProjection ( unsigned int boundaryIndex ) : boundaryIndex_( boundaryIndex ) { func = 0; } virtual ~BasicNodeProjection () {} unsigned int boundaryIndex () const { return boundaryIndex_; } private: unsigned int boundaryIndex_; }; // NodeProjection // -------------- template< int dim, class Projection > class NodeProjection : public BasicNodeProjection { typedef NodeProjection< dim, Projection > This; typedef BasicNodeProjection Base; public: static const int dimension = dim; typedef Alberta::ElementInfo< dimension > ElementInfo; private: Projection projection_; public: NodeProjection ( unsigned int boundaryIndex, const Projection &projection ) : Base( boundaryIndex ), projection_( projection ) { func = apply; } private: // note: global is the return type (it is an array type and hence no // reference is needed) static void apply ( GlobalVector global, const EL_INFO *info, const LocalVector local ) { const ElementInfo elementInfo = ElementInfo::createFake( *info ); assert( (info->fill_flag & FillFlags< dimension >::projection) != 0 ); const This *nodeProjection = static_cast< const This * >( info->active_projection ); assert( nodeProjection != NULL ); nodeProjection->projection_( elementInfo, local, global ); } }; } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_NODEPROJECTION_HH dune-grid-2.11.0/dune/grid/albertagrid/refinement.hh000066400000000000000000000221301511655130300222640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_REFINEMENT_HH #define DUNE_ALBERTA_REFINEMENT_HH /** \file * \author Martin Nolte * \brief provides a wrapper for ALBERTA's refinement patches * and the corners for geometryInFather */ #include #include #include #if HAVE_ALBERTA namespace Dune { namespace Alberta { // Internal Forward Declarations // ----------------------------- template< int dim, int codim > struct ForEachInteriorSubChild; // Patch // ----- template< int dim > class Patch { typedef Patch< dim > This; static_assert(((dim >= 1) && (dim <= 3)), "Alberta supports only dimensions 1, 2, 3"); public: static const int dimension = dim; typedef Alberta::ElementInfo< dimension > ElementInfo; typedef ALBERTA RC_LIST_EL ElementList; private: ElementList *list_; int count_; public: Patch ( ElementList *list, int count ) : list_( list ), count_( count ) { assert( count > 0 ); } Element *operator[] ( int i ) const; int count () const { return count_; } template< class LevelProvider > ElementInfo elementInfo ( int i, const LevelProvider &levelProvider ) const; int elementType ( int i ) const; bool hasNeighbor ( int i, int neighbor ) const; int neighborIndex ( int i, int neighbor ) const; template< class Functor > void forEach ( Functor &functor ) const { for( int i = 0; i < count(); ++i ) functor( (*this)[ i ] ); } template< int codim, class Functor > void forEachInteriorSubChild ( Functor &functor ) const { ForEachInteriorSubChild< dim, codim >::apply( functor, *this ); } }; template< int dim > inline Element *Patch< dim >::operator[] ( int i ) const { assert( (i >= 0) && (i < count()) ); return list_[ i ].el_info.el; } template< int dim > template< class LevelProvider > inline typename Patch< dim >::ElementInfo Patch< dim >::elementInfo ( int i, const LevelProvider &levelProvider ) const { assert( (i >= 0) && (i < count()) ); return ElementInfo::createFake( list_[ i ].el_info ); } template<> template< class LevelProvider > inline typename Patch< 2 >::ElementInfo Patch< 2 >::elementInfo ( int i, const LevelProvider &levelProvider ) const { assert( (i >= 0) && (i < count()) ); const MeshPointer< 2 > &mesh = levelProvider.mesh(); const Element *element = (*this)[ i ]; const int level = levelProvider( element ); return ElementInfo::createFake( mesh, element, level ); } template< int dim > inline int Patch< dim >::elementType ( int i ) const { assert( (i >= 0) && (i < count()) ); return list_[ i ].el_info.el_type; } template< int dim > inline bool Patch< dim >::hasNeighbor ( int i, int neighbor ) const { return (list_[ i ].neigh[ neighbor ] != NULL); } template< int dim > inline int Patch< dim >::neighborIndex ( int i, int neighbor ) const { assert( hasNeighbor( i, neighbor ) ); return (list_[ i ].neigh[ neighbor ]->no); } // ForEachInteriorSubChild // ----------------------- template< int dim > struct ForEachInteriorSubChild< dim, 0 > { template< class Functor > static void apply ( Functor &functor, const Patch< dim > &patch ) { for( int i = 0; i < patch.count(); ++i ) { Element *const father = patch[ i ]; functor( father->child[ 0 ], 0 ); functor( father->child[ 1 ], 0 ); } } }; template< int dim > struct ForEachInteriorSubChild< dim, dim > { template< class Functor > static void apply ( Functor &functor, const Patch< dim > &patch ) { functor( patch[ 0 ]->child[ 0 ], dim ); } }; template<> struct ForEachInteriorSubChild< 2, 1 > { template< class Functor > static void apply ( Functor &functor, const Patch< 2 > &patch ) { // see alberta/src/2d/lagrange_2_2d.c for details Element *const firstFather = patch[ 0 ]; Element *const firstChild = firstFather->child[ 0 ]; functor( firstChild, 0 ); functor( firstChild, 1 ); functor( firstFather->child[ 1 ], 1 ); if( patch.count() > 1 ) { Element *const father = patch[ 1 ]; functor( father->child[ 0 ], 1 ); } } }; template<> struct ForEachInteriorSubChild< 3, 1 > { template< class Functor > static void apply ( Functor &functor, const Patch< 3 > &patch ) { // see alberta/src/3d/lagrange_3_3d.c for details Element *const firstFather = patch[ 0 ]; Element *const firstChild = firstFather->child[ 0 ]; functor( firstChild, 0 ); functor( firstChild, 1 ); functor( firstChild, 2 ); Element *const secondChild = firstFather->child[ 1 ]; functor( secondChild, 1 ); functor( secondChild, 2 ); for( int i = 1; i < patch.count(); ++i ) { Element *const father = patch[ i ]; const int type = patch.elementType( i ); int lr_set = 0; if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) ) lr_set |= 1; if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) ) lr_set |= 2; assert( lr_set != 0 ); functor( father->child[ 0 ], 0 ); switch( lr_set ) { case 1 : functor( father->child[ 0 ], 2 ); functor( father->child[ 1 ], (type == 0 ? 1 : 2) ); break; case 2 : functor( father->child[ 0 ], 1 ); functor( father->child[ 1 ], (type == 0 ? 2 : 1) ); break; } } } }; template<> struct ForEachInteriorSubChild< 3, 2 > { template< class Functor > static void apply ( Functor &functor, const Patch< 3 > &patch ) { // see alberta/src/3d/lagrange_2_3d.c for details Element *const firstFather = patch[ 0 ]; Element *const firstChild = firstFather->child[ 0 ]; functor( firstChild, 2 ); functor( firstChild, 4 ); functor( firstChild, 5 ); functor( firstFather->child[ 1 ], 2 ); for( int i = 1; i < patch.count(); ++i ) { Element *const father = patch[ i ]; int lr_set = 0; if( patch.hasNeighbor( i, 0 ) && (patch.neighborIndex( i, 0 ) < i) ) lr_set = 1; if( patch.hasNeighbor( i, 1 ) && (patch.neighborIndex( i, 1 ) < i) ) lr_set += 2; assert( lr_set != 0 ); switch( lr_set ) { case 1 : functor( father->child[ 0 ], 4 ); break; case 2 : functor( father->child[ 0 ], 5 ); break; } } } }; // GeometryInFather // ---------------- template< int dim > struct GeometryInFather; template<> struct GeometryInFather< 1 > { static const int dim = 1; typedef Real LocalVector[ dim ]; static const LocalVector & coordinate ( int child, int /* orientation */, int i ) { static const Real coords[ 2 ][ dim+1 ][ dim ] = { { {0.0}, {0.5} }, { {0.5}, {1.0} } }; assert( (i >= 0) && (i <= dim) ); return coords[ child ][ i ]; } }; template<> struct GeometryInFather< 2 > { static const int dim = 2; typedef Real LocalVector[ dim ]; static const LocalVector & coordinate ( int child, int /* orientation */, int i ) { static const Real coords[ 2 ][ dim+1 ][ dim ] = { { {0.0, 1.0}, {0.0, 0.0}, {0.5, 0.0} }, { {1.0, 0.0}, {0.0, 1.0}, {0.5, 0.0} } }; assert( (i >= 0) && (i <= dim) ); return coords[ child ][ i ]; } }; template<> struct GeometryInFather< 3 > { static const int dim = 3; typedef Real LocalVector[ dim ]; static const LocalVector & coordinate ( int child, int orientation, int i ) { static const Real coords[ 2 ][ dim+1 ][ dim ] = { { {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} }, { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {0.5, 0.0, 0.0} } }; static const int flip[ 2 ][ 2 ][ dim+1 ] = { { {0, 1, 2, 3}, {0, 1, 2, 3} }, { {0, 2, 1, 3}, {0, 1, 2, 3} } }; assert( (i >= 0) && (i <= dim) ); i = flip[ child ][ orientation ][ i ]; return coords[ child ][ i ]; } }; } } #endif // #if HAVE_ALBERTA #endif dune-grid-2.11.0/dune/grid/albertagrid/structuredgridfactory.hh000066400000000000000000000201341511655130300245740ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_STRUCTUREDGRIDFACTORY_HH #define DUNE_ALBERTA_STRUCTUREDGRIDFACTORY_HH /** \file * \author Simon Praetorius * \brief specialization of the generic StructuredGridFactory for AlbertaGrid */ #include #include #include #include #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { // Forward Declarations template class StructuredGridFactory; template class AlbertaGrid; /** \brief specialization of the generic StructuredGridFactory for AlbertaGrid * * The simplex grid generated by the default StructuredGridFactory is not compatible * with the Alberta vertex numbering. This might lead to infinite recursions when * refining such grid. This specialization of the StructuredGridFactory solves this issue * by * * 1. generating a structured cube grid * 2. subdividing each cube into 2 (2d) or 6 (3d) simplices following a compatible numbering * scheme for AlbertaGrid. * **/ template class StructuredGridFactory> { using GridType = AlbertaGrid; protected: using ctype = typename GridType::ctype; // Insert new elements into the grid by splitting the given cube with corners `vertices` into // a corresponding number of simplices. static void insertElement (GridFactory& factory, const GeometryType& type, const std::vector& vertices) { // triangulation of reference cube static const auto reference_cubes = std::make_tuple( /*1d*/ std::array,1>{ std::array{0,1}}, /*2d*/ std::array,2>{ std::array{3,0,1}, std::array{0,3,2}}, /*3d*/ std::array,6>{ std::array{0,7,3,1}, std::array{0,7,5,1}, std::array{0,7,5,4}, std::array{0,7,3,2}, std::array{0,7,6,2}, std::array{0,7,6,4}} ); const auto& simplices = std::get(reference_cubes); std::vector corners(dim+1); for (const auto& simplex : simplices) { for (std::size_t i = 0; i < simplex.size(); ++i) corners[i] = vertices[simplex[i]]; factory.insertElement(type, corners); } } // Insert a structured set of vertices into the factory static void insertVertices (GridFactory& factory, const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& vertices) { FactoryUtilities::MultiIndex index(vertices); // Compute the total number of vertices to be created int numVertices = index.cycle(); // Create vertices for (int i=0; i pos(0); for (int j=0; j computeUnitOffsets ( const std::array& vertices) { std::array unitOffsets; if (dim>0) // paranoia unitOffsets[0] = 1; for (int i=1; i& factory, const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { if (factory.comm().rank() == 0) { // Insert uniformly spaced vertices std::array vertices = elements; for (std::size_t i=0; i unitOffsets = computeUnitOffsets(vertices); // Compute an element template (the cube at (0,...,0). All // other cubes are constructed by moving this template around unsigned int nCorners = 1< cornersTemplate(nCorners,0); for (std::size_t i=0; i index(elements); // Compute the total number of elements to be created int numElements = index.cycle(); for (int i=0; i corners = cornersTemplate; for (std::size_t j=0; j createSimplexGrid ( const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { GridFactory factory; createSimplexGrid(factory, lowerLeft, upperRight, elements); return std::unique_ptr(factory.createGrid()); } static void createCubeGrid (GridFactory& factory, const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { DUNE_THROW(Dune::NotImplemented, "Cube grids are not supported by AlbertaGrid. Use createSimplexGrid instead."); } static std::unique_ptr createCubeGrid ( const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { DUNE_THROW(Dune::NotImplemented, "Cube grids are not supported by AlbertaGrid. Use createSimplexGrid instead."); return nullptr; } }; } // end namespace Dune #endif // HAVE_ALBERTA #endif // DUNE_ALBERTA_STRUCTUREDGRIDFACTORY_HH dune-grid-2.11.0/dune/grid/albertagrid/test/000077500000000000000000000000001511655130300205705ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/albertagrid/test/CMakeLists.txt000066400000000000000000000006631511655130300233350ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception if(Alberta_FOUND) add_executable(test-alberta3d-refine test-alberta3d-refine.cc) target_link_libraries(test-alberta3d-refine PRIVATE Dune::Grid) add_dune_alberta_flags(test-alberta3d-refine WORLDDIM 3) dune_add_test(TARGET test-alberta3d-refine) endif() dune-grid-2.11.0/dune/grid/albertagrid/test/test-alberta3d-refine.cc000066400000000000000000000155751511655130300252000ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 #ifdef HAVE_ALBERTA #include #include #endif // single unit tet template class UnitTetMaker { static_assert(Grid::dimension == 3, "Dimension of grid must be 3"); static_assert(Grid::dimensionworld == 3, "Dimension of world must be 3"); public: static std::shared_ptr create() { Dune::GridFactory gf; // insert vertices Dune::FieldVector pos; pos[0] = 0; pos[1] = 0; pos[2] = 0; gf.insertVertex(pos); pos[0] = 1; pos[1] = 0; pos[2] = 0; gf.insertVertex(pos); pos[0] = 0; pos[1] = 1; pos[2] = 0; gf.insertVertex(pos); pos[0] = 0; pos[1] = 0; pos[2] = 1; gf.insertVertex(pos); // insert elements std::vector vid(4); vid[0] = 0; vid[1] = 1; vid[2] = 2; vid[3] = 3; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); return std::shared_ptr(gf.createGrid()); } }; // kuhn triangulation with 6 tets template class KuhnTriangulatedUnitCubeMaker { static_assert(Grid::dimension == 3, "Dimension of grid must be 3"); static_assert(Grid::dimensionworld == 3, "Dimension of world must be 3"); public: static std::shared_ptr create() { Dune::GridFactory gf; Dune::FieldVector pos; pos[0] = 0; pos[1] = 0; pos[2] = 0; gf.insertVertex(pos); pos[0] = 1; pos[1] = 0; pos[2] = 0; gf.insertVertex(pos); pos[0] = 0; pos[1] = 1; pos[2] = 0; gf.insertVertex(pos); pos[0] = 1; pos[1] = 1; pos[2] = 0; gf.insertVertex(pos); pos[0] = 0; pos[1] = 0; pos[2] = 1; gf.insertVertex(pos); pos[0] = 1; pos[1] = 0; pos[2] = 1; gf.insertVertex(pos); pos[0] = 0; pos[1] = 1; pos[2] = 1; gf.insertVertex(pos); pos[0] = 1; pos[1] = 1; pos[2] = 1; gf.insertVertex(pos); std::vector vid(4); vid[0] = 0; vid[1] = 1; vid[2] = 3; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); vid[0] = 0; vid[1] = 2; vid[2] = 3; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); vid[0] = 0; vid[1] = 2; vid[2] = 6; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); vid[0] = 0; vid[1] = 4; vid[2] = 6; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); vid[0] = 0; vid[1] = 4; vid[2] = 5; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); vid[0] = 0; vid[1] = 1; vid[2] = 5; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); gf.markLongestEdge(); return std::shared_ptr(gf.createGrid()); } }; // minimal triangulation with 5 tets, contains unit tet template class MinTriangulatedUnitCubeMaker { static_assert(Grid::dimension == 3, "Dimension of grid must be 3"); static_assert(Grid::dimensionworld == 3, "Dimension of world must be 3"); public: static std::shared_ptr create() { Dune::GridFactory gf; Dune::FieldVector pos; pos[0] = 0; pos[1] = 0; pos[2] = 0; gf.insertVertex(pos); pos[0] = 1; pos[1] = 0; pos[2] = 0; gf.insertVertex(pos); pos[0] = 0; pos[1] = 1; pos[2] = 0; gf.insertVertex(pos); pos[0] = 1; pos[1] = 1; pos[2] = 0; gf.insertVertex(pos); pos[0] = 0; pos[1] = 0; pos[2] = 1; gf.insertVertex(pos); pos[0] = 1; pos[1] = 0; pos[2] = 1; gf.insertVertex(pos); pos[0] = 0; pos[1] = 1; pos[2] = 1; gf.insertVertex(pos); pos[0] = 1; pos[1] = 1; pos[2] = 1; gf.insertVertex(pos); std::vector vid(4); // tet at vertex 0 vid[0] = 0; vid[1] = 1; vid[2] = 2; vid[3] = 4; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); // tet at vertex 3 vid[0] = 1; vid[1] = 2; vid[2] = 3; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); // central tet vid[0] = 1; vid[1] = 2; vid[2] = 4; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); // tet at vertex 5 vid[0] = 1; vid[1] = 4; vid[2] = 5; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); // tet at vertex 6 vid[0] = 2; vid[1] = 4; vid[2] = 6; vid[3] = 7; gf.insertElement(Dune::GeometryTypes::tetrahedron, vid); gf.markLongestEdge(); return std::shared_ptr(gf.createGrid()); } }; int main(int /* argc */, char** /* argv*/) { try{ // default exitcode 77 (=skipped); returned in case none of the supported // Grids were found int result = 77; #ifdef HAVE_ALBERTA #if (ALBERTA_DIM != 3) #error ALBERTA_DIM is not set to 3 -- please check the Makefile.am #endif { typedef Dune::AlbertaGrid<3, 3> Grid; std::cout << "The recursive-bisection refinement algorithm of alberta " << "cannot be used on arbitrary meshes (see Flyspry#569 for a " << "more comprehensive explanation). However, the heuristic " << "used in the GridFactory can be tuned to support certain " << "types of meshes. This test makes sure that meshes that " << "worked at one time in the past continue to work in the " << "future. If a certain mesh does not work, this program " << "will usually generate a segmentation fault.\n" << std::endl; std::cout << "Checking unit tetrahedron..." << std::endl; std::cout << "Note: The unit tetrahdron check is a safety measure. If " << "this test already produces a segfault, the problem is " << "probably not Albertas recursive bisection algorithm but " << "something else." << std::endl; UnitTetMaker::create()->globalRefine(2); std::cout << "Checking unit tetrahedron: success\n" << std::endl; std::cout << "Checking 6-triangulation of unit cube..." << std::endl; KuhnTriangulatedUnitCubeMaker::create()->globalRefine(2); std::cout << "Checking 6-triangulation of unit cube: success\n" << std::endl; std::cout << "Checking 5-triangulation of unit cube..." << std::endl; MinTriangulatedUnitCubeMaker::create()->globalRefine(2); std::cout << "Checking 5-triangulation of unit cube: success\n" << std::endl; result = 0; } #endif return result; } catch (Dune::Exception &e) { std::cerr << "Dune reported error: " << e << std::endl; return 1; } catch (...) { std::cerr << "Unknown exception thrown!" << std::endl; return 1; } } dune-grid-2.11.0/dune/grid/albertagrid/transformation.hh000066400000000000000000000040311511655130300231760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_TRANSFORMATION_HH #define DUNE_ALBERTA_TRANSFORMATION_HH #include #include #if HAVE_ALBERTA namespace Dune { class AlbertaTransformation { typedef Alberta::GlobalSpace GlobalSpace; public: typedef Alberta::Real ctype; static const int dimension = Alberta::dimWorld; typedef FieldVector< ctype, dimension > WorldVector; explicit AlbertaTransformation ( const Alberta::AffineTransformation *trafo = NULL ) : matrix_( (trafo != NULL ? trafo->M : GlobalSpace::identityMatrix()) ), shift_( (trafo != NULL ? trafo->t : GlobalSpace::nullVector()) ) {} AlbertaTransformation ( const GlobalSpace::Matrix &matrix, const GlobalSpace::Vector &shift ) : matrix_( matrix ), shift_( shift ) {} WorldVector evaluate ( const WorldVector &x ) const { WorldVector y; for( int i = 0; i < dimension; ++i ) { const GlobalSpace::Vector &row = matrix_[ i ]; y[ i ] = shift_[ i ]; for( int j = 0; j < dimension; ++j ) y[ i ] += row[ j ] * x[ j ]; } return y; } WorldVector evaluateInverse ( const WorldVector &y ) const { // Note: ALBERTA requires the matrix to be orthogonal WorldVector x( ctype( 0 ) ); for( int i = 0; i < dimension; ++i ) { const GlobalSpace::Vector &row = matrix_[ i ]; const ctype v = y[ i ] - shift_[ i ]; for( int j = 0; j < dimension; ++j ) x[ j ] += row[ j ] * v; } return x; } private: const GlobalSpace::Matrix &matrix_; const GlobalSpace::Vector &shift_; }; } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_TRANSFORMATION_HH dune-grid-2.11.0/dune/grid/albertagrid/treeiterator.hh000066400000000000000000000401001511655130300226360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ALBERTA_TREEITERATOR_HH #define DUNE_ALBERTA_TREEITERATOR_HH #include #include #include #include #include #if HAVE_ALBERTA namespace Dune { // AlbertaMarkerVector // ------------------- /** \class AlbertaMarkerVector * \ingroup AlbertaGrid * \brief marker assigning subentities to one element containing them * * This Helper class is used for the level and leaf iterators of higher * codimension to visit each entity only once (on the element assigned to * it by this marker) */ template< int dim, int dimworld > class AlbertaMarkerVector { typedef AlbertaMarkerVector< dim, dimworld > This; typedef AlbertaGrid< dim, dimworld > Grid; //friend class AlbertaGrid< dim, dimworld >; static const int dimension = Grid::dimension; typedef Alberta::HierarchyDofNumbering< dimension > DofNumbering; typedef Alberta::ElementInfo< dimension > ElementInfo; template< bool > struct NoMarkSubEntities; template< bool > struct MarkSubEntities; public: //! create AlbertaMarkerVector with empty vectors explicit AlbertaMarkerVector ( const DofNumbering &dofNumbering ) : dofNumbering_( dofNumbering ) { for( int codim = 0; codim <= dimension; ++codim ) marker_[ codim ] = 0; } AlbertaMarkerVector ( const This &other ) : dofNumbering_( other.dofNumbering_ ) { for( int codim = 0; codim <= dimension; ++codim ) marker_[ codim ] = 0; } ~AlbertaMarkerVector () { clear(); } private: This &operator= ( const This & ); public: //! visit subentity on this element? template< int codim > bool subEntityOnElement ( const ElementInfo &elementInfo, int subEntity ) const; template< int firstCodim, class Iterator > void markSubEntities ( const Iterator &begin, const Iterator &end ); void clear () { for( int codim = 0; codim <= dimension; ++codim ) { if( marker_[ codim ] != 0 ) delete[] marker_[ codim ]; marker_[ codim ] = 0; } } //! return true if marking is up to date bool up2Date () const { return (marker_[ dimension ] != 0); } //! print for debugin' only void print ( std::ostream &out = std::cout ) const; private: const DofNumbering &dofNumbering_; int *marker_[ dimension+1 ]; }; // AlbertaMarkerVector::NoMarkSubEntities // -------------------------------------- template< int dim, int dimworld > template< bool > struct AlbertaMarkerVector< dim, dimworld >::NoMarkSubEntities { template< int firstCodim, class Iterator > static void mark ( [[maybe_unused]] const DofNumbering & dofNumbering, [[maybe_unused]] int *(&marker)[ dimension + 1 ], [[maybe_unused]] const Iterator &begin, [[maybe_unused]] const Iterator &end ) {} }; // AlbertaMarkerVector::MarkSubEntities // ------------------------------------ template< int dim, int dimworld > template< bool > struct AlbertaMarkerVector< dim, dimworld >::MarkSubEntities { template< int codim > struct Codim { static const int numSubEntities = Alberta::NumSubEntities< dimension, codim >::value; typedef Alberta::ElementInfo< dimension > ElementInfo; static void apply ( const DofNumbering &dofNumbering, int *(&marker)[ dimension + 1 ], const ElementInfo &elementInfo ) { int *array = marker[ codim ]; const int index = dofNumbering( elementInfo, 0, 0 ); for( int i = 0; i < numSubEntities; ++i ) { int &mark = array[ dofNumbering( elementInfo, codim, i ) ]; mark = std::max( index, mark ); } } }; template< int firstCodim, class Iterator > static void mark ( const DofNumbering &dofNumbering, int *(&marker)[ dimension + 1 ], const Iterator &begin, const Iterator &end ) { for( int codim = firstCodim; codim <= dimension; ++codim ) { const int size = dofNumbering.size( codim ); marker[ codim ] = new int[ size ]; int *array = marker[ codim ]; for( int i = 0; i < size; ++i ) array[ i ] = -1; } for( Iterator it = begin; it != end; ++it ) { const ElementInfo &elementInfo = it->impl().elementInfo(); Hybrid::forEach( std::make_index_sequence< dimension+1-firstCodim >{}, [ & ]( auto i ){ Codim< i+firstCodim >::apply( dofNumbering, marker, elementInfo ); } ); } } }; // AlbertaGridTreeIterator // ----------------------- /*! Enables iteration over all entities of a given codimension and level of a grid. */ template< int codim, class GridImp, bool leafIterator > class AlbertaGridTreeIterator { typedef AlbertaGridTreeIterator< codim, GridImp, leafIterator > This; public: static const int dimension = GridImp::dimension; static const int codimension = codim; static const int dimensionworld = GridImp::dimensionworld; private: friend class AlbertaGrid< dimension, dimensionworld >; static const int numSubEntities = Alberta::NumSubEntities< dimension, codimension >::value; public: typedef Alberta::MeshPointer< dimension > MeshPointer; typedef typename MeshPointer::MacroIterator MacroIterator; typedef typename GridImp::template Codim< codim >::Entity Entity; typedef MakeableInterfaceObject< Entity > EntityObject; typedef typename EntityObject::ImplementationType EntityImp; typedef typename EntityImp::ElementInfo ElementInfo; typedef AlbertaMarkerVector< dimension, dimensionworld > MarkerVector; AlbertaGridTreeIterator (); //! Constructor making end iterator AlbertaGridTreeIterator ( const This &other ); //! Constructor making end iterator This &operator= ( const This &other ); //! Constructor making end iterator AlbertaGridTreeIterator ( const GridImp &grid, int travLevel ); //! Constructor making begin iterator AlbertaGridTreeIterator ( const GridImp &grid, const MarkerVector *marker, int travLevel ); //! equality bool equals ( const This &other ) const { return entity_.impl().equals( other.entity_.impl() ); } //! dereferencing Entity &dereference () const { return entity_; } //! ask for level of entities int level () const { return entity_.impl().level(); } //! increment void increment(); protected: //! obtain a reference to the grid const GridImp &grid () const { return entity_.impl().grid(); } private: void nextElement ( ElementInfo &elementInfo ); void nextElementStop (ElementInfo &elementInfo ); bool stopAtElement ( const ElementInfo &elementInfo ) const; void goNext ( ElementInfo &elementInfo ); void goNext ( const std::integral_constant< int, 0 > cdVariable, ElementInfo &elementInfo ); void goNext ( const std::integral_constant< int, 1 > cdVariable, ElementInfo &elementInfo ); template< int cd > void goNext ( const std::integral_constant< int, cd > cdVariable, ElementInfo &elementInfo ); mutable Entity entity_; //! current level int level_; //! Number of the subentity within the element int subEntity_; MacroIterator macroIterator_; // knows on which element a point,edge,face is viewed const MarkerVector *marker_; }; // Implementation of AlbertaMarkerVector // ------------------------------------- template< int dim, int dimworld > template< int codim > inline bool AlbertaMarkerVector< dim, dimworld > ::subEntityOnElement ( const ElementInfo &elementInfo, int subEntity ) const { assert( marker_[ codim ] != 0 ); const int subIndex = dofNumbering_( elementInfo, codim, subEntity ); const int markIndex = marker_[ codim ][ subIndex ]; assert( (markIndex >= 0) ); const int index = dofNumbering_( elementInfo, 0, 0 ); return (markIndex == index); } template< int dim, int dimworld > template< int firstCodim, class Iterator > inline void AlbertaMarkerVector< dim, dimworld > ::markSubEntities ( const Iterator &begin, const Iterator &end ) { clear(); std::conditional< (firstCodim <= dimension), MarkSubEntities, NoMarkSubEntities >::type ::template mark< firstCodim, Iterator >( dofNumbering_, marker_, begin, end ); } template< int dim, int dimworld > inline void AlbertaMarkerVector< dim, dimworld >::print ( std::ostream &out ) const { for( int codim = 1; codim <= dimension; ++codim ) { int *marker = marker_[ codim ]; if( marker != 0 ) { const int size = dofNumbering_.size( codim ); out << std::endl; out << "Codimension " << codim << " (" << size << " entries)" << std::endl; for( int i = 0; i < size; ++i ) out << "subentity " << i << " visited on Element " << marker[ i ] << std::endl; } } } // Implementation of AlbertaGridTreeIterator // ----------------------------------------- template< int codim, class GridImp, bool leafIterator > inline AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::AlbertaGridTreeIterator () : entity_(), level_( -1 ), subEntity_( -1 ), macroIterator_(), marker_( NULL ) {} template< int codim, class GridImp, bool leafIterator > inline AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::AlbertaGridTreeIterator ( const GridImp &grid, const MarkerVector *marker, int travLevel ) : entity_( EntityImp( grid ) ), level_( travLevel ), subEntity_( (codim == 0 ? 0 : -1) ), macroIterator_( grid.meshPointer().begin() ), marker_( marker ) { ElementInfo elementInfo = *macroIterator_; nextElementStop( elementInfo ); if( codim > 0 ) goNext( elementInfo ); // it is ok to set the invalid ElementInfo entity_.impl().setElement( elementInfo, subEntity_ ); } // Make LevelIterator with point to element from previous iterations template< int codim, class GridImp, bool leafIterator > inline AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::AlbertaGridTreeIterator ( const GridImp &grid, int travLevel ) : entity_( EntityImp( grid ) ), level_( travLevel ), subEntity_( -1 ), macroIterator_( grid.meshPointer().end() ), marker_( 0 ) {} // Make LevelIterator with point to element from previous iterations template< int codim, class GridImp, bool leafIterator > inline AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::AlbertaGridTreeIterator( const This &other ) : entity_( other.entity_ ), level_( other.level_ ), subEntity_( other.subEntity_ ), macroIterator_( other.macroIterator_ ), marker_( other.marker_ ) {} // Make LevelIterator with point to element from previous iterations template< int codim, class GridImp, bool leafIterator > inline typename AlbertaGridTreeIterator< codim, GridImp, leafIterator >::This & AlbertaGridTreeIterator< codim, GridImp, leafIterator >::operator= ( const This &other ) { entity_ = other.entity_; level_ = other.level_; subEntity_ = other.subEntity_; macroIterator_ = other.macroIterator_; marker_ = other.marker_; return *this; } template< int codim, class GridImp, bool leafIterator > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator >::increment () { ElementInfo elementInfo = entity_.impl().elementInfo_; goNext ( elementInfo ); // it is ok to set the invalid ElementInfo entity_.impl().setElement( elementInfo, subEntity_ ); } template< int codim, class GridImp, bool leafIterator > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::nextElement ( ElementInfo &elementInfo ) { if( elementInfo.isLeaf() || (elementInfo.level() >= level_) ) { while( (elementInfo.level() > 0) && (elementInfo.indexInFather() == 1) ) elementInfo = elementInfo.father(); if( elementInfo.level() == 0 ) { ++macroIterator_; elementInfo = *macroIterator_; } else elementInfo = elementInfo.father().child( 1 ); } else elementInfo = elementInfo.child( 0 ); } template< int codim, class GridImp, bool leafIterator > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::nextElementStop ( ElementInfo &elementInfo ) { while( !(!elementInfo || stopAtElement( elementInfo )) ) nextElement( elementInfo ); } template< int codim, class GridImp, bool leafIterator > inline bool AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::stopAtElement ( const ElementInfo &elementInfo ) const { if( !elementInfo ) return true; return (leafIterator ? elementInfo.isLeaf() : (level_ == elementInfo.level())); } template< int codim, class GridImp, bool leafIterator > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::goNext ( ElementInfo &elementInfo ) { std::integral_constant< int, codim > codimVariable; goNext( codimVariable, elementInfo ); } template< int codim, class GridImp, bool leafIterator > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::goNext ( const std::integral_constant< int, 0 > /* cdVariable */, ElementInfo &elementInfo ) { assert( stopAtElement( elementInfo ) ); nextElement( elementInfo ); nextElementStop( elementInfo ); } template< int codim, class GridImp, bool leafIterator > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::goNext ( const std::integral_constant< int, 1 > cdVariable, ElementInfo &elementInfo ) { assert( stopAtElement( elementInfo ) ); ++subEntity_; if( subEntity_ >= numSubEntities ) { subEntity_ = 0; nextElement( elementInfo ); nextElementStop( elementInfo ); if( !elementInfo ) return; } if( leafIterator ) { const int face = (dimension == 1 ? (numSubEntities-1)-subEntity_ : subEntity_); const ALBERTA EL *neighbor = elementInfo.elInfo().neigh[ face ]; if( (neighbor != NULL) && !elementInfo.isBoundary( face ) ) { // face is reached from element with largest number const int elIndex = grid().dofNumbering() ( elementInfo, 0, 0 ); const int nbIndex = grid().dofNumbering() ( neighbor, 0, 0 ); if( elIndex < nbIndex ) goNext( cdVariable, elementInfo ); } // uncomment this assertion only if codimension 1 entities are marked // assert( marker_->template subEntityOnElement< 1 >( elementInfo, subEntity_ ) ); } else { assert( marker_ != 0 ); if( !marker_->template subEntityOnElement< 1 >( elementInfo, subEntity_ ) ) goNext( cdVariable, elementInfo ); } } template< int codim, class GridImp, bool leafIterator > template< int cd > inline void AlbertaGridTreeIterator< codim, GridImp, leafIterator > ::goNext ( const std::integral_constant< int, cd > cdVariable, ElementInfo &elementInfo ) { assert( stopAtElement( elementInfo ) ); ++subEntity_; if( subEntity_ >= numSubEntities ) { subEntity_ = 0; nextElement( elementInfo ); nextElementStop( elementInfo ); if( !elementInfo ) return; } assert( marker_ != 0 ); if( !marker_->template subEntityOnElement< cd >( elementInfo, subEntity_ ) ) goNext( cdVariable, elementInfo ); } } #endif // #if HAVE_ALBERTA #endif // #ifndef DUNE_ALBERTA_TREEITERATOR_HH dune-grid-2.11.0/dune/grid/albertagrid/undefAllMacros.pl000077500000000000000000000047371511655130300230630ustar00rootroot00000000000000#!/usr/bin/perl -w # SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception use strict; # configuration my $packagename = 'alberta'; my $outfilename = $packagename."_undefs.hh"; my $cppflagname = 'ALBERTA_CPPFLAGS'; # Detect location of Package open MAKEFILE, "> Makefile.undef"; print MAKEFILE <$outfilename") { die "Couldn't open $outfilename for writing!\n"; } # Loop over all the files given in the command line and # recursively parse them for macro definitions. foreach my $file (@ARGV) { # Write header comment print OUTFILE "/** \\file\n"; print OUTFILE "* \\brief Contains \#undefs for all preprocessor macros\n"; print OUTFILE "* defined by $packagename.\n"; print OUTFILE "*\n"; print OUTFILE "* This file is created automatically by the perl script undefAllMacros.pl.\n"; print OUTFILE "*/\n\n"; # Parse the file itself emitUndefs($file); # Makedepend recursively searches for more included headers. # Warnings appear because the system headers will not be found. # Those warnings get piped to /dev/null. foreach $_ (`makedepend -f- -w 20 $Yinclude $file 2>/dev/null`) { # The output of makedepend has the form # file.o: header.h # We look for the ".o:" Everything that follows must be a header file if (/\.o\:\s(\S+\.h)/) { emitUndefs($1); } } } print "Undef'ed $counter #defines!\n"; close(OUTFILE); ############################################################## # This subroutine reads the file given as the first argument # and issues an #undef for each macro found. ############################################################## sub emitUndefs { print "Parsing $_[0]\n"; unless (open INFILE, "$_[0]") { die "Couldn't open $_[0] for reading!\n"; } while() { # looks for lines that define a C macro if (/\#define\s+(\w+)/) { print OUTFILE "#ifdef $1\n"; print OUTFILE " #undef $1\n"; print OUTFILE "#endif // $1\n\n"; $counter = $counter + 1; } } close (INFILE); } dune-grid-2.11.0/dune/grid/albertagrid/undefine-2.0.hh000066400000000000000000000171721511655130300222340ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \brief Contains \#undefs for all preprocessor macros * defined by alberta. * * This file is created automatically by the perl script undefAllMacros.pl. */ #ifdef _ALBERTA_H_ #undef _ALBERTA_H_ #endif // _ALBERTA_H_ #ifdef ALBERTA_VERSION #undef ALBERTA_VERSION #endif // ALBERTA_VERSION #ifdef ALBERTA_DEBUG #undef ALBERTA_DEBUG #endif // ALBERTA_DEBUG #ifdef DIM_MAX #undef DIM_MAX #endif // DIM_MAX #ifdef N_VERTICES #undef N_VERTICES #endif // N_VERTICES #ifdef N_EDGES #undef N_EDGES #endif // N_EDGES #ifdef N_WALLS #undef N_WALLS #endif // N_WALLS #ifdef N_FACES #undef N_FACES #endif // N_FACES #ifdef N_NEIGH #undef N_NEIGH #endif // N_NEIGH #ifdef DIM_FAC #undef DIM_FAC #endif // DIM_FAC #ifdef N_VERTICES_0D #undef N_VERTICES_0D #endif // N_VERTICES_0D #ifdef N_EDGES_0D #undef N_EDGES_0D #endif // N_EDGES_0D #ifdef N_FACES_0D #undef N_FACES_0D #endif // N_FACES_0D #ifdef N_NEIGH_0D #undef N_NEIGH_0D #endif // N_NEIGH_0D #ifdef N_WALLS_0D #undef N_WALLS_0D #endif // N_WALLS_0D #ifdef N_VERTICES_1D #undef N_VERTICES_1D #endif // N_VERTICES_1D #ifdef N_EDGES_1D #undef N_EDGES_1D #endif // N_EDGES_1D #ifdef N_FACES_1D #undef N_FACES_1D #endif // N_FACES_1D #ifdef N_NEIGH_1D #undef N_NEIGH_1D #endif // N_NEIGH_1D #ifdef N_WALLS_1D #undef N_WALLS_1D #endif // N_WALLS_1D #ifdef N_VERTICES_2D #undef N_VERTICES_2D #endif // N_VERTICES_2D #ifdef N_EDGES_2D #undef N_EDGES_2D #endif // N_EDGES_2D #ifdef N_FACES_2D #undef N_FACES_2D #endif // N_FACES_2D #ifdef N_NEIGH_2D #undef N_NEIGH_2D #endif // N_NEIGH_2D #ifdef N_WALLS_2D #undef N_WALLS_2D #endif // N_WALLS_2D #ifdef N_VERTICES_3D #undef N_VERTICES_3D #endif // N_VERTICES_3D #ifdef N_EDGES_3D #undef N_EDGES_3D #endif // N_EDGES_3D #ifdef N_FACES_3D #undef N_FACES_3D #endif // N_FACES_3D #ifdef N_NEIGH_3D #undef N_NEIGH_3D #endif // N_NEIGH_3D #ifdef N_WALLS_3D #undef N_WALLS_3D #endif // N_WALLS_3D #ifdef N_VERTICES_MAX #undef N_VERTICES_MAX #endif // N_VERTICES_MAX #ifdef N_EDGES_MAX #undef N_EDGES_MAX #endif // N_EDGES_MAX #ifdef N_FACES_MAX #undef N_FACES_MAX #endif // N_FACES_MAX #ifdef N_NEIGH_MAX #undef N_NEIGH_MAX #endif // N_NEIGH_MAX #ifdef N_WALLS_MAX #undef N_WALLS_MAX #endif // N_WALLS_MAX #ifdef N_LAMBDA #undef N_LAMBDA #endif // N_LAMBDA #ifdef LAMBDA_MAX #undef LAMBDA_MAX #endif // LAMBDA_MAX #ifdef INDEX #undef INDEX #endif // INDEX #ifdef INDEX #undef INDEX #endif // INDEX #ifdef IS_LEAF_EL #undef IS_LEAF_EL #endif // IS_LEAF_EL #ifdef LEAF_DATA #undef LEAF_DATA #endif // LEAF_DATA #ifdef INTERIOR #undef INTERIOR #endif // INTERIOR #ifdef DIRICHLET #undef DIRICHLET #endif // DIRICHLET #ifdef NEUMANN #undef NEUMANN #endif // NEUMANN #ifdef IS_NEUMANN #undef IS_NEUMANN #endif // IS_NEUMANN #ifdef IS_DIRICHLET #undef IS_DIRICHLET #endif // IS_DIRICHLET #ifdef IS_INTERIOR #undef IS_INTERIOR #endif // IS_INTERIOR #ifdef N_NODE_TYPES #undef N_NODE_TYPES #endif // N_NODE_TYPES #ifdef VERTEX #undef VERTEX #endif // VERTEX #ifdef CENTER #undef CENTER #endif // CENTER #ifdef EDGE #undef EDGE #endif // EDGE #ifdef FACE #undef FACE #endif // FACE #ifdef LIST_ENTRY #undef LIST_ENTRY #endif // LIST_ENTRY #ifdef WALL_BOUND #undef WALL_BOUND #endif // WALL_BOUND #ifdef FILL_NOTHING #undef FILL_NOTHING #endif // FILL_NOTHING #ifdef FILL_COORDS #undef FILL_COORDS #endif // FILL_COORDS #ifdef FILL_BOUND #undef FILL_BOUND #endif // FILL_BOUND #ifdef FILL_NEIGH #undef FILL_NEIGH #endif // FILL_NEIGH #ifdef FILL_OPP_COORDS #undef FILL_OPP_COORDS #endif // FILL_OPP_COORDS #ifdef FILL_ORIENTATION #undef FILL_ORIENTATION #endif // FILL_ORIENTATION #ifdef FILL_EL_TYPE #undef FILL_EL_TYPE #endif // FILL_EL_TYPE #ifdef FILL_PROJECTION #undef FILL_PROJECTION #endif // FILL_PROJECTION #ifdef FILL_ANY #undef FILL_ANY #endif // FILL_ANY #ifdef HOOK_QUEUE_OFFSET #undef HOOK_QUEUE_OFFSET #endif // HOOK_QUEUE_OFFSET #ifdef RUN_HOOKS_0 #undef RUN_HOOKS_0 #endif // RUN_HOOKS_0 #ifdef RUN_BAS_FCTS_HOOKS #undef RUN_BAS_FCTS_HOOKS #endif // RUN_BAS_FCTS_HOOKS #ifdef RUN_HOOKS_1 #undef RUN_HOOKS_1 #endif // RUN_HOOKS_1 #ifdef RUN_HOOKS_2 #undef RUN_HOOKS_2 #endif // RUN_HOOKS_2 #ifdef RUN_HOOKS_3 #undef RUN_HOOKS_3 #endif // RUN_HOOKS_3 #ifdef RUN_HOOKS_4 #undef RUN_HOOKS_4 #endif // RUN_HOOKS_4 #ifdef RUN_HOOKS_5 #undef RUN_HOOKS_5 #endif // RUN_HOOKS_5 #ifdef RUN_HOOKS_6 #undef RUN_HOOKS_6 #endif // RUN_HOOKS_6 #ifdef RUN_HOOKS_7 #undef RUN_HOOKS_7 #endif // RUN_HOOKS_7 #ifdef CALL_EVERY_EL_PREORDER #undef CALL_EVERY_EL_PREORDER #endif // CALL_EVERY_EL_PREORDER #ifdef CALL_EVERY_EL_INORDER #undef CALL_EVERY_EL_INORDER #endif // CALL_EVERY_EL_INORDER #ifdef CALL_EVERY_EL_POSTORDER #undef CALL_EVERY_EL_POSTORDER #endif // CALL_EVERY_EL_POSTORDER #ifdef CALL_LEAF_EL #undef CALL_LEAF_EL #endif // CALL_LEAF_EL #ifdef CALL_LEAF_EL_LEVEL #undef CALL_LEAF_EL_LEVEL #endif // CALL_LEAF_EL_LEVEL #ifdef CALL_EL_LEVEL #undef CALL_EL_LEVEL #endif // CALL_EL_LEVEL #ifdef CALL_MG_LEVEL #undef CALL_MG_LEVEL #endif // CALL_MG_LEVEL #ifdef TEST_FLAG #undef TEST_FLAG #endif // TEST_FLAG #ifdef DOF_ADMIN_DEF #undef DOF_ADMIN_DEF #endif // DOF_ADMIN_DEF #ifdef DOF_FREE_SIZE #undef DOF_FREE_SIZE #endif // DOF_FREE_SIZE #ifdef DOF_UNIT_ALL_FREE #undef DOF_UNIT_ALL_FREE #endif // DOF_UNIT_ALL_FREE #ifdef FOR_ALL_DOFS #undef FOR_ALL_DOFS #endif // FOR_ALL_DOFS #ifdef FOR_ALL_FREE_DOFS #undef FOR_ALL_FREE_DOFS #endif // FOR_ALL_FREE_DOFS #ifdef DOWBM_FULL #undef DOWBM_FULL #endif // DOWBM_FULL #ifdef DOWBM_SYMM #undef DOWBM_SYMM #endif // DOWBM_SYMM #ifdef DOWBM_DIAG #undef DOWBM_DIAG #endif // DOWBM_DIAG #ifdef ROW_LENGTH #undef ROW_LENGTH #endif // ROW_LENGTH #ifdef ENTRY_USED #undef ENTRY_USED #endif // ENTRY_USED #ifdef ENTRY_NOT_USED #undef ENTRY_NOT_USED #endif // ENTRY_NOT_USED #ifdef UNUSED_ENTRY #undef UNUSED_ENTRY #endif // UNUSED_ENTRY #ifdef NO_MORE_ENTRIES #undef NO_MORE_ENTRIES #endif // NO_MORE_ENTRIES #ifdef LAGRANGE_NODES #undef LAGRANGE_NODES #endif // LAGRANGE_NODES #ifdef MAX_N_QUAD_POINTS #undef MAX_N_QUAD_POINTS #endif // MAX_N_QUAD_POINTS #ifdef INIT_PHI #undef INIT_PHI #endif // INIT_PHI #ifdef INIT_GRD_PHI #undef INIT_GRD_PHI #endif // INIT_GRD_PHI #ifdef INIT_D2_PHI #undef INIT_D2_PHI #endif // INIT_D2_PHI #ifdef MESH_REFINED #undef MESH_REFINED #endif // MESH_REFINED #ifdef MESH_COARSENED #undef MESH_COARSENED #endif // MESH_COARSENED #ifdef H1_NORM #undef H1_NORM #endif // H1_NORM #ifdef L2_NORM #undef L2_NORM #endif // L2_NORM #ifdef GRAPH_MESH_BOUNDARY #undef GRAPH_MESH_BOUNDARY #endif // GRAPH_MESH_BOUNDARY #ifdef GRAPH_MESH_ELEMENT_MARK #undef GRAPH_MESH_ELEMENT_MARK #endif // GRAPH_MESH_ELEMENT_MARK #ifdef GRAPH_MESH_VERTEX_DOF #undef GRAPH_MESH_VERTEX_DOF #endif // GRAPH_MESH_VERTEX_DOF #ifdef GRAPH_MESH_ELEMENT_INDEX #undef GRAPH_MESH_ELEMENT_INDEX #endif // GRAPH_MESH_ELEMENT_INDEX #ifdef GET_MESH #undef GET_MESH #endif // GET_MESH #ifdef GET_DOF_VEC #undef GET_DOF_VEC #endif // GET_DOF_VEC #ifdef CARD_SN_MAX #undef CARD_SN_MAX #endif // CARD_SN_MAX #ifdef INIT_UH #undef INIT_UH #endif // INIT_UH #ifdef INIT_GRD_UH #undef INIT_GRD_UH #endif // INIT_GRD_UH #ifdef TRAVERSE_START #undef TRAVERSE_START #endif // TRAVERSE_START #ifdef TRAVERSE_STOP #undef TRAVERSE_STOP #endif // TRAVERSE_STOP dune-grid-2.11.0/dune/grid/albertagrid/undefine-3.0.hh000066400000000000000000000375311511655130300222360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \brief Contains \#undefs for all preprocessor macros * defined by alberta. * * This file is created automatically by the perl script undefAllMacros.pl. */ #ifdef _ALBERTA_H_ #undef _ALBERTA_H_ #endif // _ALBERTA_H_ #ifdef ALBERTA_MAGIC #undef ALBERTA_MAGIC #endif // ALBERTA_MAGIC #ifdef ALBERTA_VERSION #undef ALBERTA_VERSION #endif // ALBERTA_VERSION #ifdef DIM_LIMIT #undef DIM_LIMIT #endif // DIM_LIMIT #ifdef DIM_MAX #undef DIM_MAX #endif // DIM_MAX #ifdef N_VERTICES #undef N_VERTICES #endif // N_VERTICES #ifdef N_EDGES #undef N_EDGES #endif // N_EDGES #ifdef N_WALLS #undef N_WALLS #endif // N_WALLS #ifdef N_FACES #undef N_FACES #endif // N_FACES #ifdef N_NEIGH #undef N_NEIGH #endif // N_NEIGH #ifdef N_LAMBDA #undef N_LAMBDA #endif // N_LAMBDA #ifdef DIM_FAC #undef DIM_FAC #endif // DIM_FAC #ifdef VERTEX_OF_EDGE #undef VERTEX_OF_EDGE #endif // VERTEX_OF_EDGE #ifdef VERTEX_OF_WALL #undef VERTEX_OF_WALL #endif // VERTEX_OF_WALL #ifdef N_VERTICES_0D #undef N_VERTICES_0D #endif // N_VERTICES_0D #ifdef N_EDGES_0D #undef N_EDGES_0D #endif // N_EDGES_0D #ifdef N_FACES_0D #undef N_FACES_0D #endif // N_FACES_0D #ifdef N_NEIGH_0D #undef N_NEIGH_0D #endif // N_NEIGH_0D #ifdef N_WALLS_0D #undef N_WALLS_0D #endif // N_WALLS_0D #ifdef N_LAMBDA_0D #undef N_LAMBDA_0D #endif // N_LAMBDA_0D #ifdef DIM_FAC_0D #undef DIM_FAC_0D #endif // DIM_FAC_0D #ifdef VERTEX_OF_EDGE_0D #undef VERTEX_OF_EDGE_0D #endif // VERTEX_OF_EDGE_0D #ifdef VERTEX_OF_WALL_0D #undef VERTEX_OF_WALL_0D #endif // VERTEX_OF_WALL_0D #ifdef N_VERTICES_1D #undef N_VERTICES_1D #endif // N_VERTICES_1D #ifdef N_EDGES_1D #undef N_EDGES_1D #endif // N_EDGES_1D #ifdef N_FACES_1D #undef N_FACES_1D #endif // N_FACES_1D #ifdef N_NEIGH_1D #undef N_NEIGH_1D #endif // N_NEIGH_1D #ifdef N_WALLS_1D #undef N_WALLS_1D #endif // N_WALLS_1D #ifdef N_LAMBDA_1D #undef N_LAMBDA_1D #endif // N_LAMBDA_1D #ifdef DIM_FAC_1D #undef DIM_FAC_1D #endif // DIM_FAC_1D #ifdef VERTEX_OF_EDGE_1D #undef VERTEX_OF_EDGE_1D #endif // VERTEX_OF_EDGE_1D #ifdef VERTEX_OF_WALL_1D #undef VERTEX_OF_WALL_1D #endif // VERTEX_OF_WALL_1D #ifdef N_VERTICES_2D #undef N_VERTICES_2D #endif // N_VERTICES_2D #ifdef N_EDGES_2D #undef N_EDGES_2D #endif // N_EDGES_2D #ifdef N_FACES_2D #undef N_FACES_2D #endif // N_FACES_2D #ifdef N_NEIGH_2D #undef N_NEIGH_2D #endif // N_NEIGH_2D #ifdef N_WALLS_2D #undef N_WALLS_2D #endif // N_WALLS_2D #ifdef N_LAMBDA_2D #undef N_LAMBDA_2D #endif // N_LAMBDA_2D #ifdef DIM_FAC_2D #undef DIM_FAC_2D #endif // DIM_FAC_2D #ifdef VERTEX_OF_EDGE_2D #undef VERTEX_OF_EDGE_2D #endif // VERTEX_OF_EDGE_2D #ifdef VERTEX_OF_WALL_2D #undef VERTEX_OF_WALL_2D #endif // VERTEX_OF_WALL_2D #ifdef N_VERTICES_3D #undef N_VERTICES_3D #endif // N_VERTICES_3D #ifdef N_EDGES_3D #undef N_EDGES_3D #endif // N_EDGES_3D #ifdef N_FACES_3D #undef N_FACES_3D #endif // N_FACES_3D #ifdef N_NEIGH_3D #undef N_NEIGH_3D #endif // N_NEIGH_3D #ifdef N_WALLS_3D #undef N_WALLS_3D #endif // N_WALLS_3D #ifdef N_LAMBDA_3D #undef N_LAMBDA_3D #endif // N_LAMBDA_3D #ifdef DIM_FAC_3D #undef DIM_FAC_3D #endif // DIM_FAC_3D #ifdef VERTEX_OF_EDGE_3D #undef VERTEX_OF_EDGE_3D #endif // VERTEX_OF_EDGE_3D #ifdef VERTEX_OF_WALL_3D #undef VERTEX_OF_WALL_3D #endif // VERTEX_OF_WALL_3D #ifdef N_LAMBDA_MAX #undef N_LAMBDA_MAX #endif // N_LAMBDA_MAX #ifdef N_VERTICES_MAX #undef N_VERTICES_MAX #endif // N_VERTICES_MAX #ifdef N_EDGES_MAX #undef N_EDGES_MAX #endif // N_EDGES_MAX #ifdef N_FACES_MAX #undef N_FACES_MAX #endif // N_FACES_MAX #ifdef N_NEIGH_MAX #undef N_NEIGH_MAX #endif // N_NEIGH_MAX #ifdef N_WALLS_MAX #undef N_WALLS_MAX #endif // N_WALLS_MAX #ifdef DIM_FAC_MAX #undef DIM_FAC_MAX #endif // DIM_FAC_MAX #ifdef N_LAMBDA_LIMIT #undef N_LAMBDA_LIMIT #endif // N_LAMBDA_LIMIT #ifdef N_VERTICES_LIMIT #undef N_VERTICES_LIMIT #endif // N_VERTICES_LIMIT #ifdef N_EDGES_LIMIT #undef N_EDGES_LIMIT #endif // N_EDGES_LIMIT #ifdef N_FACES_LIMIT #undef N_FACES_LIMIT #endif // N_FACES_LIMIT #ifdef N_NEIGH_LIMIT #undef N_NEIGH_LIMIT #endif // N_NEIGH_LIMIT #ifdef N_WALLS_LIMIT #undef N_WALLS_LIMIT #endif // N_WALLS_LIMIT #ifdef DIM_FAC_LIMIT #undef DIM_FAC_LIMIT #endif // DIM_FAC_LIMIT #ifdef INDEX #undef INDEX #endif // INDEX #ifdef INDEX #undef INDEX #endif // INDEX #ifdef IS_LEAF_EL #undef IS_LEAF_EL #endif // IS_LEAF_EL #ifdef LEAF_DATA #undef LEAF_DATA #endif // LEAF_DATA #ifdef INTERIOR #undef INTERIOR #endif // INTERIOR #ifdef DIRICHLET #undef DIRICHLET #endif // DIRICHLET #ifdef NEUMANN #undef NEUMANN #endif // NEUMANN #ifdef IS_NEUMANN #undef IS_NEUMANN #endif // IS_NEUMANN #ifdef IS_DIRICHLET #undef IS_DIRICHLET #endif // IS_DIRICHLET #ifdef IS_INTERIOR #undef IS_INTERIOR #endif // IS_INTERIOR #ifdef N_BNDRY_TYPES #undef N_BNDRY_TYPES #endif // N_BNDRY_TYPES #ifdef LIST_ENTRY #undef LIST_ENTRY #endif // LIST_ENTRY #ifdef INIT_EL_TAG_CTX_INIT #undef INIT_EL_TAG_CTX_INIT #endif // INIT_EL_TAG_CTX_INIT #ifdef INIT_EL_TAG_CTX_UNIQ #undef INIT_EL_TAG_CTX_UNIQ #endif // INIT_EL_TAG_CTX_UNIQ #ifdef INIT_EL_TAG_CTX_NULL #undef INIT_EL_TAG_CTX_NULL #endif // INIT_EL_TAG_CTX_NULL #ifdef INIT_EL_TAG_CTX_DFLT #undef INIT_EL_TAG_CTX_DFLT #endif // INIT_EL_TAG_CTX_DFLT #ifdef INIT_EL_TAG_CTX_TAG #undef INIT_EL_TAG_CTX_TAG #endif // INIT_EL_TAG_CTX_TAG #ifdef INIT_ELEMENT_METHOD #undef INIT_ELEMENT_METHOD #endif // INIT_ELEMENT_METHOD #ifdef INIT_ELEMENT_FLAGS #undef INIT_ELEMENT_FLAGS #endif // INIT_ELEMENT_FLAGS #ifdef INIT_ELEMENT_DEFUN #undef INIT_ELEMENT_DEFUN #endif // INIT_ELEMENT_DEFUN #ifdef INIT_OBJECT #undef INIT_OBJECT #endif // INIT_OBJECT #ifdef INIT_ELEMENT_DECL #undef INIT_ELEMENT_DECL #endif // INIT_ELEMENT_DECL #ifdef INIT_ELEMENT_INITIALIZER #undef INIT_ELEMENT_INITIALIZER #endif // INIT_ELEMENT_INITIALIZER #ifdef INIT_ELEMENT #undef INIT_ELEMENT #endif // INIT_ELEMENT #ifdef INIT_ELEMENT_NEEDED #undef INIT_ELEMENT_NEEDED #endif // INIT_ELEMENT_NEEDED #ifdef INIT_ELEMENT_SETUP #undef INIT_ELEMENT_SETUP #endif // INIT_ELEMENT_SETUP #ifdef INIT_OBJECT_SINGLE #undef INIT_OBJECT_SINGLE #endif // INIT_OBJECT_SINGLE #ifdef INIT_ELEMENT_SINGLE #undef INIT_ELEMENT_SINGLE #endif // INIT_ELEMENT_SINGLE #ifdef vertex_of_wall_2d #undef vertex_of_wall_2d #endif // vertex_of_wall_2d #ifdef PARAM_STRATEGY_MASK #undef PARAM_STRATEGY_MASK #endif // PARAM_STRATEGY_MASK #ifdef PARAM_PERIODIC_COORDS #undef PARAM_PERIODIC_COORDS #endif // PARAM_PERIODIC_COORDS #ifdef FILL_EL_DET #undef FILL_EL_DET #endif // FILL_EL_DET #ifdef FILL_EL_LAMBDA #undef FILL_EL_LAMBDA #endif // FILL_EL_LAMBDA #ifdef FILL_EL_WALL_SHIFT #undef FILL_EL_WALL_SHIFT #endif // FILL_EL_WALL_SHIFT #ifdef FILL_EL_WALL_MASK #undef FILL_EL_WALL_MASK #endif // FILL_EL_WALL_MASK #ifdef FILL_EL_WALL_DET #undef FILL_EL_WALL_DET #endif // FILL_EL_WALL_DET #ifdef FILL_EL_WALL_NORMAL #undef FILL_EL_WALL_NORMAL #endif // FILL_EL_WALL_NORMAL #ifdef FILL_EL_WALL_ORIENTATION #undef FILL_EL_WALL_ORIENTATION #endif // FILL_EL_WALL_ORIENTATION #ifdef FILL_EL_WALL_REL_ORIENTATION #undef FILL_EL_WALL_REL_ORIENTATION #endif // FILL_EL_WALL_REL_ORIENTATION #ifdef FILL_EL_WALL_DETS #undef FILL_EL_WALL_DETS #endif // FILL_EL_WALL_DETS #ifdef FILL_EL_WALL_NORMALS #undef FILL_EL_WALL_NORMALS #endif // FILL_EL_WALL_NORMALS #ifdef FILL_EL_WALL_ORIENTATIONS #undef FILL_EL_WALL_ORIENTATIONS #endif // FILL_EL_WALL_ORIENTATIONS #ifdef FILL_EL_WALL_REL_ORIENTATIONS #undef FILL_EL_WALL_REL_ORIENTATIONS #endif // FILL_EL_WALL_REL_ORIENTATIONS #ifdef BNDRY_FLAGS_INIT #undef BNDRY_FLAGS_INIT #endif // BNDRY_FLAGS_INIT #ifdef BNDRY_FLAGS_ALL #undef BNDRY_FLAGS_ALL #endif // BNDRY_FLAGS_ALL #ifdef BNDRY_FLAGS_CPY #undef BNDRY_FLAGS_CPY #endif // BNDRY_FLAGS_CPY #ifdef BNDRY_FLAGS_AND #undef BNDRY_FLAGS_AND #endif // BNDRY_FLAGS_AND #ifdef BNDRY_FLAGS_OR #undef BNDRY_FLAGS_OR #endif // BNDRY_FLAGS_OR #ifdef BNDRY_FLAGS_XOR #undef BNDRY_FLAGS_XOR #endif // BNDRY_FLAGS_XOR #ifdef BNDRY_FLAGS_IS_INTERIOR #undef BNDRY_FLAGS_IS_INTERIOR #endif // BNDRY_FLAGS_IS_INTERIOR #ifdef BNDRY_FLAGS_IS_AT_BNDRY #undef BNDRY_FLAGS_IS_AT_BNDRY #endif // BNDRY_FLAGS_IS_AT_BNDRY #ifdef BNDRY_FLAGS_SET #undef BNDRY_FLAGS_SET #endif // BNDRY_FLAGS_SET #ifdef BNDRY_FLAGS_IS_PARTOF #undef BNDRY_FLAGS_IS_PARTOF #endif // BNDRY_FLAGS_IS_PARTOF #ifdef BNDRY_FLAGS_FFBB #undef BNDRY_FLAGS_FFBB #endif // BNDRY_FLAGS_FFBB #ifdef RCLE_NONE #undef RCLE_NONE #endif // RCLE_NONE #ifdef RCLE_COARSE_EDGE_COMPAT #undef RCLE_COARSE_EDGE_COMPAT #endif // RCLE_COARSE_EDGE_COMPAT #ifdef FILL_NOTHING #undef FILL_NOTHING #endif // FILL_NOTHING #ifdef FILL_COORDS #undef FILL_COORDS #endif // FILL_COORDS #ifdef FILL_BOUND #undef FILL_BOUND #endif // FILL_BOUND #ifdef FILL_NEIGH #undef FILL_NEIGH #endif // FILL_NEIGH #ifdef FILL_OPP_COORDS #undef FILL_OPP_COORDS #endif // FILL_OPP_COORDS #ifdef FILL_ORIENTATION #undef FILL_ORIENTATION #endif // FILL_ORIENTATION #ifdef FILL_PROJECTION #undef FILL_PROJECTION #endif // FILL_PROJECTION #ifdef FILL_MACRO_WALLS #undef FILL_MACRO_WALLS #endif // FILL_MACRO_WALLS #ifdef FILL_WALL_MAP #undef FILL_WALL_MAP #endif // FILL_WALL_MAP #ifdef FILL_NON_PERIODIC #undef FILL_NON_PERIODIC #endif // FILL_NON_PERIODIC #ifdef FILL_MASTER_INFO #undef FILL_MASTER_INFO #endif // FILL_MASTER_INFO #ifdef FILL_ANY #undef FILL_ANY #endif // FILL_ANY #ifdef CALL_EVERY_EL_PREORDER #undef CALL_EVERY_EL_PREORDER #endif // CALL_EVERY_EL_PREORDER #ifdef CALL_EVERY_EL_INORDER #undef CALL_EVERY_EL_INORDER #endif // CALL_EVERY_EL_INORDER #ifdef CALL_EVERY_EL_POSTORDER #undef CALL_EVERY_EL_POSTORDER #endif // CALL_EVERY_EL_POSTORDER #ifdef CALL_LEAF_EL #undef CALL_LEAF_EL #endif // CALL_LEAF_EL #ifdef CALL_LEAF_EL_LEVEL #undef CALL_LEAF_EL_LEVEL #endif // CALL_LEAF_EL_LEVEL #ifdef CALL_EL_LEVEL #undef CALL_EL_LEVEL #endif // CALL_EL_LEVEL #ifdef CALL_MG_LEVEL #undef CALL_MG_LEVEL #endif // CALL_MG_LEVEL #ifdef TEST_FLAG #undef TEST_FLAG #endif // TEST_FLAG #ifdef ADM_FLAGS_MASK #undef ADM_FLAGS_MASK #endif // ADM_FLAGS_MASK #ifdef UCHAR_name #undef UCHAR_name #endif // UCHAR_name #ifdef uchar_VECNAME #undef uchar_VECNAME #endif // uchar_VECNAME #ifdef SCHAR_name #undef SCHAR_name #endif // SCHAR_name #ifdef schar_VECNAME #undef schar_VECNAME #endif // schar_VECNAME #ifdef INT_name #undef INT_name #endif // INT_name #ifdef int_VECNAME #undef int_VECNAME #endif // int_VECNAME #ifdef DOF_name #undef DOF_name #endif // DOF_name #ifdef dof_VECNAME #undef dof_VECNAME #endif // dof_VECNAME #ifdef PTR_name #undef PTR_name #endif // PTR_name #ifdef ptr_VECNAME #undef ptr_VECNAME #endif // ptr_VECNAME #ifdef REAL_name #undef REAL_name #endif // REAL_name #ifdef real_VECNAME #undef real_VECNAME #endif // real_VECNAME #ifdef REAL_D_name #undef REAL_D_name #endif // REAL_D_name #ifdef real_d_VECNAME #undef real_d_VECNAME #endif // real_d_VECNAME #ifdef BNDRY_name #undef BNDRY_name #endif // BNDRY_name #ifdef bndry_VECNAME #undef bndry_VECNAME #endif // bndry_VECNAME #ifdef DECL_DOF_EL_VEC #undef DECL_DOF_EL_VEC #endif // DECL_DOF_EL_VEC #ifdef PHI #undef PHI #endif // PHI #ifdef GRD_PHI #undef GRD_PHI #endif // GRD_PHI #ifdef D2_PHI #undef D2_PHI #endif // D2_PHI #ifdef D3_PHI #undef D3_PHI #endif // D3_PHI #ifdef D4_PHI #undef D4_PHI #endif // D4_PHI #ifdef PHI_D #undef PHI_D #endif // PHI_D #ifdef GRD_PHI_D #undef GRD_PHI_D #endif // GRD_PHI_D #ifdef D2_PHI_D #undef D2_PHI_D #endif // D2_PHI_D #ifdef GET_DOF_INDICES #undef GET_DOF_INDICES #endif // GET_DOF_INDICES #ifdef INTERPOL #undef INTERPOL #endif // INTERPOL #ifdef INTERPOL_D #undef INTERPOL_D #endif // INTERPOL_D #ifdef INTERPOL_DOW #undef INTERPOL_DOW #endif // INTERPOL_DOW #ifdef GET_BOUND #undef GET_BOUND #endif // GET_BOUND #ifdef LAGRANGE_NODES #undef LAGRANGE_NODES #endif // LAGRANGE_NODES #ifdef FILL_EL_QUAD_WORLD #undef FILL_EL_QUAD_WORLD #endif // FILL_EL_QUAD_WORLD #ifdef FILL_EL_QUAD_DET #undef FILL_EL_QUAD_DET #endif // FILL_EL_QUAD_DET #ifdef FILL_EL_QUAD_LAMBDA #undef FILL_EL_QUAD_LAMBDA #endif // FILL_EL_QUAD_LAMBDA #ifdef FILL_EL_QUAD_DLAMBDA #undef FILL_EL_QUAD_DLAMBDA #endif // FILL_EL_QUAD_DLAMBDA #ifdef FILL_EL_QUAD_GRD_WORLD #undef FILL_EL_QUAD_GRD_WORLD #endif // FILL_EL_QUAD_GRD_WORLD #ifdef FILL_EL_QUAD_D2_WORLD #undef FILL_EL_QUAD_D2_WORLD #endif // FILL_EL_QUAD_D2_WORLD #ifdef FILL_EL_QUAD_D3_WORLD #undef FILL_EL_QUAD_D3_WORLD #endif // FILL_EL_QUAD_D3_WORLD #ifdef FILL_EL_QUAD_WALL_DET #undef FILL_EL_QUAD_WALL_DET #endif // FILL_EL_QUAD_WALL_DET #ifdef FILL_EL_QUAD_WALL_NORMAL #undef FILL_EL_QUAD_WALL_NORMAL #endif // FILL_EL_QUAD_WALL_NORMAL #ifdef FILL_EL_QUAD_GRD_NORMAL #undef FILL_EL_QUAD_GRD_NORMAL #endif // FILL_EL_QUAD_GRD_NORMAL #ifdef FILL_EL_QUAD_D2_NORMAL #undef FILL_EL_QUAD_D2_NORMAL #endif // FILL_EL_QUAD_D2_NORMAL #ifdef INIT_PHI #undef INIT_PHI #endif // INIT_PHI #ifdef INIT_GRD_PHI #undef INIT_GRD_PHI #endif // INIT_GRD_PHI #ifdef INIT_D2_PHI #undef INIT_D2_PHI #endif // INIT_D2_PHI #ifdef INIT_D3_PHI #undef INIT_D3_PHI #endif // INIT_D3_PHI #ifdef INIT_D4_PHI #undef INIT_D4_PHI #endif // INIT_D4_PHI #ifdef INIT_TANGENTIAL #undef INIT_TANGENTIAL #endif // INIT_TANGENTIAL #ifdef MESH_REFINED #undef MESH_REFINED #endif // MESH_REFINED #ifdef MESH_COARSENED #undef MESH_COARSENED #endif // MESH_COARSENED #ifdef GRAPH_MESH_BOUNDARY #undef GRAPH_MESH_BOUNDARY #endif // GRAPH_MESH_BOUNDARY #ifdef GRAPH_MESH_ELEMENT_MARK #undef GRAPH_MESH_ELEMENT_MARK #endif // GRAPH_MESH_ELEMENT_MARK #ifdef GRAPH_MESH_VERTEX_DOF #undef GRAPH_MESH_VERTEX_DOF #endif // GRAPH_MESH_VERTEX_DOF #ifdef GRAPH_MESH_ELEMENT_INDEX #undef GRAPH_MESH_ELEMENT_INDEX #endif // GRAPH_MESH_ELEMENT_INDEX #ifdef GET_MESH #undef GET_MESH #endif // GET_MESH #ifdef GET_DOF_VEC #undef GET_DOF_VEC #endif // GET_DOF_VEC #ifdef TRACE_DOF_VEC_PROTO #undef TRACE_DOF_VEC_PROTO #endif // TRACE_DOF_VEC_PROTO #ifdef INIT_UH #undef INIT_UH #endif // INIT_UH #ifdef INIT_GRD_UH #undef INIT_GRD_UH #endif // INIT_GRD_UH #ifdef ellipt_est_d_init #undef ellipt_est_d_init #endif // ellipt_est_d_init #ifdef head_est_d_init #undef head_est_d_init #endif // head_est_d_init #ifdef element_est_d #undef element_est_d #endif // element_est_d #ifdef element_est_d_finish #undef element_est_d_finish #endif // element_est_d_finish #ifdef element_est_uh_d #undef element_est_uh_d #endif // element_est_uh_d #ifdef element_est_grd_uh_d #undef element_est_grd_uh_d #endif // element_est_grd_uh_d #ifdef ellipt_est_d_finish #undef ellipt_est_d_finish #endif // ellipt_est_d_finish #ifdef heat_est_d_finish #undef heat_est_d_finish #endif // heat_est_d_finish #ifdef TRAVERSE_FIRST #undef TRAVERSE_FIRST #endif // TRAVERSE_FIRST #ifdef TRAVERSE_NEXT #undef TRAVERSE_NEXT #endif // TRAVERSE_NEXT #ifdef TRAVERSE_START #undef TRAVERSE_START #endif // TRAVERSE_START #ifdef TRAVERSE_STOP #undef TRAVERSE_STOP #endif // TRAVERSE_STOP #ifdef TRAVERSE_NEIGHBOUR #undef TRAVERSE_NEIGHBOUR #endif // TRAVERSE_NEIGHBOUR #ifdef IFF_TAG_ALBERTA #undef IFF_TAG_ALBERTA #endif // IFF_TAG_ALBERTA #ifdef IFF_TAG_MESH #undef IFF_TAG_MESH #endif // IFF_TAG_MESH #ifdef IFF_TAG_REAL_VEC #undef IFF_TAG_REAL_VEC #endif // IFF_TAG_REAL_VEC #ifdef IFF_TAG_REAL_D_VEC #undef IFF_TAG_REAL_D_VEC #endif // IFF_TAG_REAL_D_VEC #ifdef IFF_TAG_INT_VEC #undef IFF_TAG_INT_VEC #endif // IFF_TAG_INT_VEC #ifdef IFF_TAG_UCHAR_VEC #undef IFF_TAG_UCHAR_VEC #endif // IFF_TAG_UCHAR_VEC #ifdef IFF_TAG_SCHAR_VEC #undef IFF_TAG_SCHAR_VEC #endif // IFF_TAG_SCHAR_VEC dune-grid-2.11.0/dune/grid/common/000077500000000000000000000000001511655130300166215ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/common/CMakeLists.txt000066400000000000000000000013441511655130300213630ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS adaptcallback.hh backuprestore.hh boundaryprojection.hh boundarysegment.hh capabilities.hh datahandleif.hh defaultgridview.hh entity.hh entityiterator.hh entityseed.hh exceptions.hh geometry.hh grid.hh gridenums.hh gridfactory.hh gridinfo.hh gridview.hh indexidset.hh intersection.hh intersectioniterator.hh mcmgmapper.hh mapper.hh partitionset.hh rangegenerators.hh sizecache.hh scsgmapper.hh) add_subdirectory(test) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/common) dune-grid-2.11.0/dune/grid/common/adaptcallback.hh000066400000000000000000000073601511655130300217160ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_ADAPTCALLBACK_HH #define DUNE_GRID_COMMON_ADAPTCALLBACK_HH /** \file * \author Martin Nolte * \brief interfaces and wrappers needed for the callback adaptation provided * by AlbertaGrid and dune-ALUGrid */ namespace Dune { // Internal Forward Declarations // ----------------------------- template< class Grid, class Impl > class AdaptDataHandle; // AdaptDataHandleInterface // ------------------------ /** \brief Interface class for the Grid's adapt method where the parameter is a AdaptDataHandleInterface. */ template< class Grid, class Impl > class AdaptDataHandleInterface { typedef AdaptDataHandleInterface< Grid, Impl > This; friend class AdaptDataHandle< Grid, Impl >; public: typedef typename Grid::template Codim< 0 >::Entity Entity; private: AdaptDataHandleInterface () {} AdaptDataHandleInterface ( const This & ); This &operator= ( const This & ); public: /** \brief call back for activity to take place on father and all descendants before the descendants are removed \param father entity where all descendants are going to be removed */ void preCoarsening ( const Entity &father ) { asImp().preCoarsening( father ); } /** \brief call back for activity to take place on newly created elements below the father element. \param father entity where all descendants were newly created */ void postRefinement ( const Entity &father ) { asImp().postRefinement( father ); } void restrictLocal( const Entity &father, const Entity& son, bool initialize ) { asImp().restrictLocal( father, son, initialize ); } void prolongLocal( const Entity &father, const Entity& son, bool initialize ) { asImp().prolongLocal( father, son, initialize ); } protected: const Impl &asImp () const { return static_cast< const Impl & >( *this ); } Impl &asImp () { return static_cast< Impl & >( *this ); } }; // AdaptDataHandle // --------------- template< class Grid, class Impl > class AdaptDataHandle : public AdaptDataHandleInterface< Grid, Impl > { typedef AdaptDataHandle< Grid, Impl > This; typedef AdaptDataHandleInterface< Grid, Impl > Base; public: typedef typename Base::Entity Entity; protected: AdaptDataHandle () {} private: AdaptDataHandle ( const This & ); This &operator= ( const This & ); void preCoarsening ( const Entity &father ); void postRefinement ( const Entity &father ); }; // CombinedAdaptProlongRestrict // ---------------------------- //! class for combining 2 index sets together for adaptation process template class CombinedAdaptProlongRestrict { //! space A and B A& _a; B& _b; public: //! constructor storing the two references CombinedAdaptProlongRestrict ( A& a, B& b ) : _a ( a ) , _b ( b ) {} //! restrict data to father template void restrictLocal ( const Entity &father, const Entity &son, bool initialize ) { _a.restrictLocal(father,son,initialize); _b.restrictLocal(father,son,initialize); } //! prolong data to children template void prolongLocal ( const Entity &father, const Entity &son, bool initialize ) { _a.prolongLocal(father,son,initialize); _b.prolongLocal(father,son,initialize); } }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/common/backuprestore.hh000066400000000000000000000075561511655130300220300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_BACKUPRESTORE_HH #define DUNE_GRID_COMMON_BACKUPRESTORE_HH #include namespace Dune { /** \class BackupRestoreFacility * \brief facility for writing and reading grids * * The BackupRestoreFacility allows writing hierarchic grids to disk and * reading them back into another program. * * It is guaranteed that all index sets and id sets are preserved by the * backup / restore process. * The result of restore is undefined, if the number of processes in a * parallel program differs from the number of processes used on backup. * * There are two pairs of backup / restore methods: * - methods writing into one or more dedicated files, * - methods operating on a std::stream. * . * * These techniques may not be mixed, i.e., you cannot write the grid into * files and read it back from a stream or vice versa. * While operating on a std::stream might be convenient, a grid written in * another language than C++ might need to emulate this method by writing * through a temporary file. * * \note The backup and restore methods might not be implemented for each grid. * In this case one can catch the Dune::NotImplemented exception and do * something else. * * \tparam Grid type of grid */ template< class Grid > struct BackupRestoreFacility { /** \brief write a hierarchic grid to disk * * \param[in] grid grid to write * \param[in] filename filename of the file to create * * \note This method might create multiple files based on the filename plus internal extension. */ static void backup ( const Grid &/*grid*/, const std::string &/*filename*/ ) { DUNE_THROW( NotImplemented, "backup / restore not implemented." ); } /** \brief write a hierarchic grid into a stream * * \param[in] grid grid to write * \param[in] stream std::stream to write the grid to * * \note While operating on a std::ostream might be convenient, a grid * written in another language than C++ might need to emulate this * method by writing through a temporary file. */ static void backup ( const Grid &/*grid*/, std::ostream &/*stream*/ ) { DUNE_THROW( NotImplemented, "backup / restore not implemented." ); } /** \brief read a hierarchic grid from disk * * \param[in] filename filename of the file to read * * \returns a pointer to the grid (allocated by new) * * \note This method might require multiple files based on the filename plus some extension. */ static Grid *restore ( const std::string &/*filename*/ ) { DUNE_THROW( NotImplemented, "backup / restore not implemented." ); } /** \brief read a hierarchic grid from a stream * * \param[in] stream std::stream to read the grid from * * \note While operating on a std::istream might be convenient, a grid * written in another language than C++ might need to emulate this * method by writing through a temporary file. */ static Grid *restore ( std::istream &/*stream*/ ) { DUNE_THROW( NotImplemented, "backup / restore not implemented." ); } }; /** \brief BackupRestoreFacility taking const Grid as type and deriving from the version with the const. */ template< class Grid > struct BackupRestoreFacility< const Grid > : public BackupRestoreFacility< Grid > {}; } // namespace Dune #endif // #ifndef DUNE_GRID_COMMON_BACKUPRESTORE_HH dune-grid-2.11.0/dune/grid/common/boundaryprojection.hh000066400000000000000000000177521511655130300230760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_BOUNDARYPROJECTION_HH #define DUNE_GRID_COMMON_BOUNDARYPROJECTION_HH //- system includes #include #include //- Dune includes #include #include #include #include namespace Dune { /** \brief Interface class for vertex projection at the boundary. */ template struct DuneBoundaryProjection; /** \brief Interface class for vertex projection at the boundary. */ template struct DuneBoundaryProjection : public BoundarySegmentBackupRestore< DuneBoundaryProjection< dimworld > > { typedef DuneBoundaryProjection< dimworld > ThisType; typedef BoundarySegmentBackupRestore< DuneBoundaryProjection< dimworld > > BaseType; typedef typename BaseType :: ObjectStreamType ObjectStreamType; using BaseType :: restore; using BaseType :: registerFactory; //! \brief type of coordinate vector typedef FieldVector< double, dimworld> CoordinateType; //! \brief destructor virtual ~DuneBoundaryProjection() {} //! \brief projection operator projection a global coordinate virtual CoordinateType operator() (const CoordinateType& global) const = 0; /** \brief write DuneBoundaryProjection's data to stream buffer * \param buffer buffer to store data */ virtual void backup( [[maybe_unused]] ObjectStreamType& buffer ) const { DUNE_THROW(NotImplemented,"DuneBoundaryProjection::backup not overloaded!"); } template void toBuffer( BufferImp& buffer ) const { MessageBufferIF< BufferImp > buf( buffer ); toBuffer( buf ); } template void toBuffer( MessageBufferIF< BufferImp > & buffer ) const { ObjectStreamType str; // call virtual interface backup backup( str ); std::string data = str.str(); const size_t size = data.size(); buffer.write( size ); for( size_t i=0; i static std::unique_ptr< ThisType > restoreFromBuffer( BufferImp & buffer ) { MessageBufferIF< BufferImp > buf( buffer ); return restoreFromBuffer( buf ); } template static std::unique_ptr< ThisType > restoreFromBuffer( MessageBufferIF< BufferImp > & buffer ) { std::string data; size_t size = 0; buffer.read( size ); data.resize( size ); for( size_t i=0; i class BoundaryProjectionWrapper : public DuneBoundaryProjection< dimworld > { protected: typedef DuneBoundaryProjection< dimworld > BaseType; const BaseType& proj_; public: //! \brief type of coordinate vector typedef typename BaseType :: CoordinateType CoordinateType; // constructor taking other projection BoundaryProjectionWrapper( const BaseType& proje ) : proj_( proje ) {} //! destructor ~BoundaryProjectionWrapper () {} //! \brief projection operator projection a global coordinate CoordinateType operator() (const CoordinateType& global) const { return proj_( global ); } }; // BoundarySegmentWrapper // ---------------------- /** \tparam dim Dimension of the grid */ template< int dim, int dimworld > class BoundarySegmentWrapper : public DuneBoundaryProjection< dimworld > { typedef BoundarySegmentWrapper< dim, dimworld > ThisType; typedef DuneBoundaryProjection< dimworld > Base; typedef typename Base :: ObjectStreamType ObjectStreamType; typedef MultiLinearGeometry FaceMapping; public: typedef typename Base::CoordinateType CoordinateType; typedef Dune::BoundarySegment< dim, dimworld > BoundarySegment; /** constructor * * \param[in] type geometry type of the boundary face * \param[in] vertices vertices of the boundary face * \param[in] boundarySegment geometric realization of the shaped boundary * * \note The BoundarySegmentWrapper takes control of the boundary segment. */ BoundarySegmentWrapper ( const GeometryType &type, const std::vector< CoordinateType > &vertices, const std::shared_ptr< BoundarySegment > &boundarySegment ) : faceMapping_( FaceMapping( type, vertices ) ), boundarySegment_( boundarySegment ) {} BoundarySegmentWrapper( ObjectStreamType& buffer ) : faceMapping_( readFaceMapping( buffer ) ), boundarySegment_( BoundarySegment::restore( buffer ).release() ) { } CoordinateType operator() ( const CoordinateType &global ) const { return boundarySegment() ( faceMapping_.local( global ) ); } const BoundarySegment &boundarySegment () const { return *boundarySegment_; } void backup( ObjectStreamType& buffer ) const { // write identifier key first buffer.write( (const char *) &key(), sizeof(int)); // now all data GeometryType type = faceMapping_.type(); buffer.write( (const char *) &type, sizeof(GeometryType) ); int corners = faceMapping_.corners() ; buffer.write( (const char *) &corners, sizeof(int) ); CoordinateType corner( 0 ); for( int i=0; ibackup( buffer ); } static void registerFactory() { if( key() < 0 ) { key() = Base::template registerFactory< ThisType >(); } } protected: static int& key() { static int k = -1; return k; } FaceMapping readFaceMapping( ObjectStreamType& buffer ) { GeometryType type; buffer.read( (char *) &type, sizeof(GeometryType) ); int corners = 0; buffer.read( (char *) &corners, sizeof(int) ); std::vector< CoordinateType > vertices( corners, CoordinateType(0) ); for( int i=0; i boundarySegment_; }; ////////////////////////////////////////////////////////////////////// // // Example of boundary projection projection to a circle // ////////////////////////////////////////////////////////////////////// template struct CircleBoundaryProjection : public DuneBoundaryProjection< dimworld > { //! \brief type of coordinate vector typedef FieldVector< double, dimworld> CoordinateType; //! constructor taking radius of circle (default = sqrt( dimworld ) ) CircleBoundaryProjection(const double radius = std::sqrt( (double)dimworld )) : radius_( radius ) {} //! \brief destructor virtual ~CircleBoundaryProjection() {} //! \brief projection operator projection a global coordinate virtual CoordinateType operator() (const CoordinateType& global) const { CoordinateType prj( global ); // get adjustment factor const double factor = radius_ / global.two_norm(); // adjust prj *= factor; return prj; } protected: //! radius of circ const double radius_; }; } // end namespace #endif // #ifndef DUNE_GRID_COMMON_BOUNDARYPROJECTION_HH dune-grid-2.11.0/dune/grid/common/boundarysegment.hh000066400000000000000000000100371511655130300223510ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_BOUNDARY_SEGMENT_HH #define DUNE_GRID_COMMON_BOUNDARY_SEGMENT_HH #include #include #include #include #include /** \file \brief Base class for grid boundary segments of arbitrary geometry */ namespace Dune { /** \brief Base class for classes implementing geometries of boundary segments Some grid implementations, as for example UGGrid, allow to use boundary segments of arbitrary geometry. That means that you can have grid boundaries approach smooth shapes when refining the grid. Such curved boundary segments are specified by giving classes that implement them. Each boundary segment is implemented by an object of a class derived from BoundarySegment. The set of these objects is handed over to the grid upon grid construction. \tparam dim Dimension of the grid \tparam dimworld Dimension of the Euclidean space the grid is embedded in \tparam ctype type of coordinate storage (default is double) */ template< int dim, int dimworld = dim, class ctype = double > struct BoundarySegment; template class BoundarySegmentBackupRestore { public: // type of object stream used for storing boundary segment information typedef std::stringstream ObjectStreamType ; protected: //! type of BoundarySegment interface class typedef BndSeg BoundarySegment; //! type of factory creating a unique_ptr from an ObjectStreamType typedef Dune::ParameterizedObjectFactory< std::unique_ptr< BoundarySegment > ( ObjectStreamType& ), int > FactoryType; /** \brief create an object of BoundarySegment type from a previously * registered factory linked to key. * \param in stream buffer previously written with backup containing key and object data * * \return Object derived from BoundarySegment. */ static std::unique_ptr< BoundarySegment > restore( ObjectStreamType& in ) { int key = -1; // read class key for restore in.read( (char *) &key, sizeof( int ) ); // factory creates a unique_ptr which can be released later on return factory().create( key, in ); } template static int registerFactory() { const int key = createKey(); // create factory method that produces unique_ptr factory().template define< DerivedType >( key ); // return key for storage in derived class return key; } private: static int createKey() { static int key = 0; return key++; } static FactoryType& factory() { return Dune::Singleton< FactoryType > :: instance(); } }; template< int dim, int dimworld, class ctype > struct BoundarySegment : public BoundarySegmentBackupRestore< BoundarySegment< dim, dimworld, ctype > > { typedef BoundarySegment< dim, dimworld, ctype > ThisType; typedef BoundarySegmentBackupRestore< BoundarySegment< dim, dimworld, ctype > > BaseType; typedef typename BaseType :: ObjectStreamType ObjectStreamType; using BaseType :: restore; using BaseType :: registerFactory; /** \brief Dummy virtual destructor */ virtual ~BoundarySegment() {} /** \brief A function mapping local coordinates on a boundary segment to world coordinates */ virtual FieldVector< ctype, dimworld > operator() ( const FieldVector< ctype, dim-1> &local ) const = 0; /** \brief write BoundarySegment's data to stream buffer * \param buffer buffer to store data */ virtual void backup( [[maybe_unused]] ObjectStreamType& buffer ) const { DUNE_THROW(NotImplemented,"BoundarySegment::backup needs to be overloaded!"); } }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/common/capabilities.hh000066400000000000000000000166341511655130300216050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_CAPABILITIES_HH #define DUNE_GRID_COMMON_CAPABILITIES_HH /** \file \brief A set of traits classes to store static information about grid implementation */ namespace Dune { /** \brief Contains all capabilities classes */ namespace Capabilities { /** \brief Specialize with 'true' for if the codimension 0 entity of the grid has only one possible geometry type. In this case the topologyId of this geometry type has also to be specified. (default=false, topologyId=undefined) \ingroup GICapabilities */ template struct hasSingleGeometryType { static const bool v = false; // this value will be initialized with something big // since it is invalid static const unsigned int topologyId = ~0u; }; /** \brief Specialize with 'true' if the grid is a Cartesian grid. Cartesian grids satisfy the following properties: - all geometries are axis-aligned hypercubes - The unit outer normal for the i-th intersection can be computed by the following code: \code FieldVector< ctype, dim > n( 0 ); n[ i / 2 ] = ctype( 2*(i % 2) - 1 ); \endcode (default=false). \ingroup GICapabilities */ template struct isCartesian { // default value is false static const bool v = false; }; /** \brief Specialize with 'true' for all codims that a grid implements entities for. (default=false) \ingroup GICapabilities */ template struct hasEntity { static const bool v = false; }; /** * \brief specialize with 'true' for all codims that a grid provides an iterator for (default=hasEntity::v) * * \note Being able to iterate over a codimension implies that the grid * provides entities for that codimension. * \note Any fully conforming DUNE grid implementation must be able to * iterate over all codim 0 entities (i.e., elements). * * \ingroup GICapabilities **/ template< class Grid, int codim > struct hasEntityIterator { static const bool v = hasEntity::v; }; /** \brief Specialize with 'false' for all codims that a grid does not implement geometries for. (default=true) \ingroup GICapabilities */ template struct hasGeometry { static const bool v = true; }; /** \brief specialize with 'true' for all codims that a grid can communicate data on (default=false) * * \note Being able to communicate data on a codimension implies that the * grid provides entities for that codimension. * * \ingroup GICapabilities */ template< class Grid, int codim > struct canCommunicate { static const bool v = false; }; /** \brief Specialize with 'true' if implementation guarantees conforming level grids. (default=false) \ingroup GICapabilities */ template struct isLevelwiseConforming { static const bool v = false; }; /** \brief Specialize with 'true' if implementation guarantees a conforming leaf grid. (default=false) \ingroup GICapabilities */ template struct isLeafwiseConforming { static const bool v = false; }; /** \brief Specialize with 'true' if implementation provides backup and restore facilities. (default=false) \ingroup GICapabilities */ template struct hasBackupRestoreFacilities { static const bool v = false; }; /** \brief Specialize with 'true' if the grid implementation is thread safe. (default=false) This capability is 'true' if the grid is always thread safe. This means especially that all grid modification, like load balancing and grid adaption are also thread safe. \sa viewThreadSafe \note that the communicate method can only be called by one individual thread, as the whole Dune parallel components are not (i.e. cannot be) thread safe. \ingroup GICapabilities */ template struct threadSafe { static const bool v = false; }; /** \brief Specialize with 'true' if the grid implementation is thread safe, while it is not modified. (default=false) This capability is 'true' if the grid is thread safe, at least while working on a GridView. This means especially that all grid modification, like load balancing and grid adaption are not necessarily thread safe. \sa threadSafe \note that the communicate method can only be called by one individual thread, as the whole Dune parallel components are (i.e. cannot be) not thread safe. \note the methods leafGridView(), levelGridView(level) on the Grid can only be called single-threaded \note calling the methods indexSet(), idSet(), globalIdSet() on the Grid or the GridView is only allowed, if they were called once before starting the threads. \code \endcode \ingroup GICapabilities */ template struct viewThreadSafe { static const bool v = false; }; /* forward Capabilities::Something to Capabilities::Something */ template struct hasSingleGeometryType< const Grid > { static const bool v = Dune::Capabilities::hasSingleGeometryType::v; static const unsigned int topologyId = Dune::Capabilities::hasSingleGeometryType::topologyId; }; template struct isCartesian< const Grid > { static const bool v = Dune::Capabilities::isCartesian::v; }; template struct hasEntity { static const bool v = Dune::Capabilities::hasEntity::v; }; template< class Grid, int codim > struct hasEntityIterator< const Grid, codim > { static const bool v = Dune::Capabilities::hasEntityIterator< Grid, codim >::v; }; template< class Grid, int codim > struct canCommunicate< const Grid, codim > { static const bool v = Dune::Capabilities::canCommunicate< Grid, codim >::v; }; template struct isLevelwiseConforming { static const bool v = Dune::Capabilities::isLevelwiseConforming::v; }; template struct isLeafwiseConforming { static const bool v = Dune::Capabilities::isLeafwiseConforming::v; }; template struct hasBackupRestoreFacilities { static const bool v = Dune::Capabilities::hasBackupRestoreFacilities::v; }; template struct threadSafe { static const bool v = Dune::Capabilities::threadSafe::v; }; template struct viewThreadSafe { static const bool v = Dune::Capabilities::viewThreadSafe::v; }; } } #endif // DUNE_GRID_COMMON_CAPABILITIES_HH dune-grid-2.11.0/dune/grid/common/cube-to-tet-6.png000066400000000000000000000422571511655130300216340ustar00rootroot00000000000000PNG  IHDRSasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATxwスKE D4Qc9FcxLbcJh&'b jT0"RDz[138 3Sw2纸e!2ygRJ)RnRJ) RJ)\EU)RJRJ)r<RJ)f"C,1o:qlRJ)M`]m5M4PRJ)v1a-9J)RUD__)R*6Y큯YƘtWJ)O"8 LvP~*RJ%ADn5Ƭt<~AUJ)JK:y?@UJ)JΔ=sPRJ)b1Y@#砞0Ƭvl~RJ)VDwU)thu8PIe#<2o5Mgr%r9̩tl~39r39 t}hp}RJ)eG1>h'2LWl5p4PRJ)ˉYN%DD)yVD8}PR0}G}OY8 TRR"R \iwyτy0~L8PXaZIew8/)h*RV t "Ddpw! өeAx-\6S4T+^x9NAU){zgطU5c ʦm^V4PRJ)Kccf6_}XFPDtDO"{9_Dr>RJ)_X |fN-L#iUa S@ p P  xM#U)T17c,ߚ0Ʉ)+NA5$c0cco;|.Rj?{4S S_~Ƙ#nz h8RJ)ūi$ LI%Lq ~PJ)՜ HvI5Lq QH_anc2gOA"c_DHRJt#L#iZ%0)hDDzs>j4;π"OPJy;4j SQ3XoiuH Ƙcc1Ɯt.phJ)oi$ DYq H'`1#lb;(U4Tc*L!{4Pý ~iEKEDJEd\8|,a)zOP2L!@1NDu ʇ5<$!h3Ƽ쩔R*E`GҧO |[w:홹mg{OɨY:vCVmo{9̩}ʧgq{wAQ8F/˾ )N|GRJ ӐLj'WZ^* Uwr\a SPgVcnį|Sk yR :'wOd}Pt:\>vUo΍q*"Efo@XZy?WDH`WJ)h,CcB0ixN*x<'Λ@U&"Eb9ID#;|4T0mC0widOҝ2xME,RSʁ1뀞^^jpOVBȽ6[ZOkri*]uU"<Ǵ(5J @~aw?s.wsTCz/. ?5I<ȋ/X!nsL`TX{xfMPmg~0 >yGʁQ@`;p&pPc~FݣGP 跳ws#z`_P9v-'}ɲCzckh z&g|gܿ`; q+L2 ԹX%0x=-* Cmug2y~{8џfeid= &3i=02\>WhZϭZO}5\3yݯq/L!q Ysd&0(#2\l#k'""yA9Y)qɬ7?ڡq;c/VZQ<zTCh O7>sL^%c*s'w.;ўcdBhTaICa$#/V԰ǡgt; sCfvK4z:_;)8E)_)O4A\anGC;p>BA㓌X6C|N/pibDȧ[ 71Ł]C~ :U> oфOD5s*N! Uu4L}ʪ0Xa q: 7G9~N=:f~ѡGFO+bi=2st&lUu4L}ʮ0xa 2lɝ<EN)5;sJ/Y[@ J݆Zi84yَG4Åy{ꯝ8M6L8hT4jtm)h˘Eσu_3)'Na:>0hƩS pŭ-OJ|%]Uzuڷ;N SpWUu4L}ʭa)[B50S;ԟy^t@0u SJFk&qj/3Ӿ]qjE;<aS^ H~ T4NSfx}ڷ#N SpoUu4L}/aɫjio?/OVǩa SH PEXd'xiO5L#y%T S8aSjUƩ;oNƩa ފS?gDd|)"?\+X|)ߧuOV+pS5:vM#PE$EQ lNtPu4L}J45va ncLԯRi?8->+Lq 1&~cLWc PDFW'{G:廎N>S5iNⴟ# |; V[8A], idc0u S0GjWƩ Ƌ/ȟfMI߂erB砾 !cUĩNSO锟NvL4NOymO|  +`%0&DzB@}( "r0C/a:>aX%v)hzKe0铸]hڟ}_VL\?<=n/gCCB:Zwk1Lj1{@QFyMq"}y>:S\֖1UgpJ3sgHN{G AGk.hrq-:'kӾq`5zS_xScb$D#tQKS/45s t: |صdVeo|7e-Д:YT KӾ/>G~NX2 ̀w~Sh#PST lfRm{4n+t0flqAg&g5;_{{SK/oQF#O 64PIQR5OQI N/,0GIe*v?4ybӽSU;v߾]cmʴoEBi?R2W5N_H$;O3|&]=c6dzSӳs h )SWޛqn͇|G:SiX #'gwTD.fv2r[lNtR[$3Tyȯ24I#5谻#ݮ]sZxxߙKgڷ*N#%29NAKzxٮpK5UU'NMt"ln:ġͅy9_:;~tE﫛4܇iM#:puӥv[i8.W^};7j}_9_cDj|]F; ,vnQҘ׾u:uҁdMջͯ>7峅I} 4i?R[W=NAK";ӛ@~YL4/W'XSn_ϽlXC_57_SGSl2}orP.~+mϦzhzlŘJ ׋ҾbG$zӊڜֽ]~{`m>tE߭_δoUBr~XWgC>ˎ6x}S"6qiyS'ޏqn5EX78uPIf󖽓OLgM~݋RSQIS} ى#wwÿc?z :45mȊ:[^?Y/-q ^U F=UBS^o8cʍøDžD8u3|/SU^F|i[N:"]ЕzwVj-卡[?z-K̩߬k0O7N?+UiJ~:LȖ8 T (ѫ-%S7,gQ~D8u:/K|vnujڷ#Nc]yUizK7` (Щ?)4i?R⼖-73SRXtꏯ.z д?zkTUᇫV,)w%{7~QG95M^J*~/M"QD}"rD{gx'X< H":'$ZB~-{Knɣ:ݯlSlc{#*w!B 0yx//q[Z>%95`ݴzm.`qJNqŊS}{7uZκcBʧ¸tN 'OϢEr˒vKiO}Ԫi?5Pd%p08?@Ut)VZ9֞ƻ.cY([ԟi+fѢj} ڷonXi8dO<6O6c/ҩ`#4tcYw0j't￿8ٳfNLv)X3{_Fe4P:/NcikXSGԟдʋ5),Ri87_Ǹ 8j}>ϴ6; {LJe qjմV1:yk-K8 NgϮbΜnG7܊Jtڷ9NcNja318OL@y~ ;tOF)e,)X3'!:{Nmy=ʲei}}W\q*ͯRژ$:{گiL9~ ;iLVi~c6xp݀~R&KԊi?8 ѩCt?ؖ=ٰ+W_|w1xf^;p[X!. Tx-h TMNmũU~q :{Nhmen TTd4i?SqS}MOyEΚ|ti?n>\6r$g-PʴziI!D0ѾN@UJxtO&NS3Su,e[=򵃦/(Ĵ7N4 8QԴ}$V6O6B]?JV%%Dִ {K0M2q MNiNǩ?]BݿѾ`A~s?f7N?d& E1{4r֏Fy9PvYcJTDNUXQ۾kiqʴd!~4݋F'woso3NQvjO6NCtˁ1GJ֏;(bs[hq3;6v?vn|˭ IDATNY獈ĝl2!NA~*ZaQٳ3Si8J/3ɩi?8 ѩ?6O2Z3`dmG)R*(rcu+h-`ߎ4֕ұ%/d!:{ק8mߩ-o:퇮on~h~qړgS~q :@X ` 'R/§f}7vlFIY %t4iӾ4D~ukKcN1ƒ0T95[!:G@~vDJE_m=t15]!I%NSxmꏌS"q}O(Nqjڷ2NCt?QE) ˻mŘ}:fʺl1RSHnws!^#hsڷpjڷ#NAh 'm|R*Yy;ҡL]j&3{!NCt/L4iߎS}4D!P .u,JO_(G";ؔN5NSyM ǩCӾqS7\y$uz>R>(+7SPlQ)$>{-NCtNώJ(NiSЩ?58Q*kZK&.8Mtj!n]y8u`_Ҋԁi#(T@5Yʝ fG=hVh]N^SЩs2?rV,(:(N;y{qht$k R.Gp9oK'N!iqSajV,(Ƕi}־{E )d|d8ہrB [(8MdS!NN^J|P'~-+XQpfxыvASqSR*9/ot4iߏq :{S?9qi;Kocqi/tdC(<&;8 ѩC2=\+rsNC249_ fc cSm_]N"7)dԯJS;Ot_N5=NCt$"?E;}dj#>v[dԯJNKrNo!xQM!>c~hos>p Ω?={6D?sAڌSش?&ˊCRg}!~oJ);M&;?'J(le)VvLq& NH(N-h x.f現7ɶZVY򷧟6vu[2Sx^6.p7gsN"R*"E oxcf+N᛫k߫LMS} S"0~! 'n`E!4!P t ~gQʿ֮-gbM&2[{8 + =US8 0Jrk(ɭPӾON3`z~yۙF++izV۔RV{IgxMii_@:cVc/9Ξ Ni it~qj*q 4osil2([~n`A۔RV\|_ms^9㱦~ 4ִqzl1Ƙ\{NMNi,6N ǩ~39/2s;K`ګy|okaz@s[}6:th]0eekw,9[}8-˧~Dq-RS,sʀyoi?R6L^TۄoleF5NۖMSLE$ x#LOnoEm~Rqjô/_p1MP}<1-ѽzfrKA~5PSSL#|gTUe˖̸3?NJ86k&&˦'$dyS%#ߪ8iO*Nmu|[(o<SjJˀaRp4p䡔rn_GԯQb1OK\ sPJm ⷿ:_]oG-)]z.r8MM6Mk*Ni?8q߳Z* ٔ-2/~$N| 4 TW#WQHUZNscn*_2r8M]M9[6LIǩ~6z4RQޗOv(۴ɏSjʀjl!եk)ʭe۪>k/[~_'M`Y1sJRq M]( iN.-(A~#q@MNS(qrXqrx'LӾƩut  |0Kq:(8iKq ԴP֡?H~5P rUxuZ[q 2O\S!'g.4}zOYYqjӴ?}tujÄ ?M ]vG"q(h8Nz{=ر%X<|F{6Lh׵8m5GԳ3튲 |4k&opXm|AӐдZSbD%X8pAT2qjǴ q d+;tNe/hNLmxj>z'?/B'T|iNq MiܖZSROcpOj;Y\?., uE e;2=/M/.xp`+D䡲1 dY|Ϭڤ4t-[mU]nphگԒqjDzn{toj>ϓ⽔TU7ZN))X>>U[h].5M~^OWђMd~M.|./hdUg_S55_)Lo T;v u2lM)NC/jeצ2J$%4{hfkXLmfܽZ Yb??z'kѴVx03`$[;ȃ|FUshУ}9'OC+vVʊihWٳ: tagw?d4USaRr%57gYf@U^7xIDӇsNg㫻BS[QT^L oxq7Jɼg~˗/gq?7475 Mxiũ~~l;ߗS\y킯yCS^"?7E 0PEu55?˒c១ˣMO3{(.knk}4c:c&kD,w| ~e 8uB8dd!*|wUE~Zq O4 SWɽ y7:lkL&"3grfI >7S; cVa!ESJj*bKjDc 8j:g5,-5f$*R}D`O;Nj?9 ;*G~=5ksaVM ￟Kv9L^='wjfϒ OtT=@Z #!uS—Jc}I2X]O;5s_.0d,^\dDqo`O(NWQVz)#zTϑVrchy?ϐilm8'|z*n=p ,aQGjnHxm(ȳ^5PQIj`>O~:$4#}'u `6w@jM7>ݵC^CyIS'H0`)p,ɪ'Y 3^q `o3NWQ\Ʊj1?/1Tq/r /pcY"-G2%UURBM~|oxwi-gs ,&'Ƙ_!  ~蓴T  7!RviD2g9,-̨ 8y06:/;kc$jnro#x[[c>v\gED?i?nFy@I?/SZrZ~aTYXVA󀱬 m_$t);wsoΏy)ή`3/38?4*.Ϟa+Wr3piK6ԋ4L8842/w2kQ 2NC§Igڏ){~T >J3_$ϝ5(B,(yGyi/MVHwN"`1f';40j S⋓TqLxHim-~:3:vGvM̯GK 'yiϦ@0u1緃_*(+40j S+NCD#T40{^?tOUI MgAopQ|uQyLboYhѲUqjUFPMKsTrDztiZ[惡O~ⴑvI:L~6@0u}Yvi$ Մh]qz`CssJ=!~?hUq0)㴂sݼ))~+O~ b` nafis3;34T SW:N- S)Qs ϥӾǹyCVh:MRӺ\`6R(%i, U S2N Si 4, ?:ҟ{xrinS`90e7 S/H%Nç|#&n2|eIjUqj#%/c24.P i:{1P=xGO4L"8ӣ G8m|.gEZSR`,[Q߾4Y:~/^.^LƻiW-=='aia*"G/G1S"oRNO}<Dt7N^T Sw0DԩP0t4GL#':g/_'1E,Nu%MnT Sw0Dԯa#a!iS1  "ˀsχɲ8i41P5LEԫڊl H. U SI%Nӿ*?x .6|޾*:~7hzY80P0dԺGcb}mq~Vp@0u S9LZ{UqƘ-1?Ϯ8i?aw2P5LEũib2hZO"'*w@Nc̢gWNY Sa.~)T5L=.88Lô,YIF:CI˵%.P+J2}Vjm%v >g2P5LEO 0MEamũ}a 1f60;mLN}Л?\w6u>/[BX?e Zy̶̛hL߯.;tom2'Α@0u S M6Я{fajCU'ũa[27b S[[`Os\eOv ڊļ0,׏m66n`GmW1&گWv^@1"ғf:d? ޫs*2}KV:cEŽ.Pq3'gi#^8Ma 6i0 )IhzW4GP1,L'n!x1feO4ƴ^m`Gs}a"h>nv-͔ʰ"6>3+N>OƘ3tN ߟm:Rϖ-pS qHFhg)zH.YpcLJm""""eCb<[y܀]Fsn8 SXfRK>o09URKhc\l{IfMʉO=#0 4.7 @ /߷ZI`E[G"Ƙ]y2S~0/#!2~hYE~T3#c?q_:,S+4CNY43bP}73 TiH,6ZDdpZ?/frG SI1Eco_CK0=//|j4c̋ |Y^k7oc m2'ӿj 562ib=4~P_4$V. njK_4=.-BcL ,cʝHo(T~?i&"} ƘE~TҎLi$j~ӐjYMD.!0ψca .ODS4l5xO :szkު,%a $sixVMeԉ0jl ӐI"w{1{/DS. #c G2.JƯav>4]N?Gu*'4ocna)ڜkCf[$aTfh*)ũ4SFXVjiHoujlrZ6MJyAq)?Y:',4@0U*34LrԋaIC5& 9JeRp!L#ia*"퀁Ƙ0U&"r1?k*R ũ4RUa*"9@` x$A&A+72UJDDx})4LrRIDAT644R  Tx? xD;D܁R ފ 54Lrqaǡj?xIDLiH8PEH_i1fJ/%P0ܛ)2"2(D1fqo#N` JK80=BcY$*n oUHW:EuVD#PvcLM9pP6s{J@8:-QMuP:!7?A )P&J$53&ƣJ);(N5LSlf(PCB*M*?UD $cLSJ|xly(s@6N"j5$x]Ƙ ߯o5'rGk*e9ܠqgy>BjFԏ T88Ş#)D"1/NG)){\nb7oqM\*u\2t.4,pJeK"rb 1{9R*R(q%B>0YPmKt$)c:t%s|h1GJ,'"Q>c>R*1"2P^^D Jiu\jyEDFW1wfs*yJ)RUr>RJ)RRy)RJ#>Cc.gONJ)BD v*P`/p1eNNJ)h (7 |dUGPRJ)1_9|ETRJ2w *h*R "2sc(RJ)u K")QJ)ODO1Ie! TRJ "] ԙƘFRJ)r a^cs`*+i*R +ƇcyTv@UJ)R/3RJ)\EU)RJRJ)r TRJ)*vT;IENDB`dune-grid-2.11.0/dune/grid/common/cube-to-tet-6.png.license000066400000000000000000000002501511655130300232400ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/cube-to-tet-6.svg000066400000000000000000001205361511655130300216440ustar00rootroot00000000000000 image/svg+xml x y z x y z 0 1 2 3 4 5 x y z 0 1 2 3 4 5 6 7 dune-grid-2.11.0/dune/grid/common/cube-to-tet-6.svg.license000066400000000000000000000002501511655130300232530ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/datahandleif.hh000066400000000000000000000133461511655130300215550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_DATAHANDLEIF_HH #define DUNE_GRID_COMMON_DATAHANDLEIF_HH /** @file @author Robert Kloefkorn @brief Describes the parallel communication interface class for MessageBuffers and DataHandles */ #include namespace Dune { /** @brief Communication message buffer interface. This class describes the interface for reading and writing data to the communication message buffer. As message buffers might be deeply implemented in various packages the message buffers implementations cannot be derived from this interface class. Therefore we just apply the engine concept to wrap the message buffer call and make sure that the interface is fulfilled. \tparam MessageBufferImp Implementation of message buffer used by the grids' communication method \ingroup GICommunication */ template class MessageBufferIF { MessageBufferImp & buff_; public: //! stores reference to original buffer \c buff MessageBufferIF(MessageBufferImp & buff) : buff_(buff) {} /** @brief just wraps the call of the internal buffer method write which writes the data of type T from the buffer by using the assignment operator of T @param val reference to object that is written */ template void write(const T & val) { buff_.write(val); } /** @brief just wraps the call of the internal buffer method read which reads the data of type T from the buffer by using the assignment operator of T @param val reference to object that is read The method is not const, because calling it advances the iterator to the current data of the MessageBufferImp member. */ template void read(T & val) { buff_.read(val); } }; // end class MessageBufferIF /** @brief CommDataHandleIF describes the features of a data handle for communication in parallel runs using the Grid::communicate methods. Here the Barton-Nackman trick is used to interpret data handle objects as its interface. Therefore usable data handle classes need to be derived from this class. \tparam DataHandleImp implementation of the users data handle \tparam DataTypeImp type of data that are going to be communicated which is exported as \c DataType (for example double) \ingroup GICommunication */ template class CommDataHandleIF { public: //! data type of data to communicate typedef DataTypeImp DataType; protected: // one should not create an explicit instance of this interface object CommDataHandleIF() {} public: /** @brief returns true if data for given valid codim should be communicated @param dim valid dimension (i.e. the grids dimension) @param codim valid codimension of the entity set for which data should be communicated */ bool contains (int dim, int codim) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().contains(dim,codim))); return asImp().contains(dim,codim); } /** @brief returns true if size of data per entity of given dim and codim is a constant @param dim valid dimension (i.e. the grids dimension) @param codim valid codimension of the entity set for which data should be communicated This method calls 'fixedSize' of the derived class. */ bool fixedSize (int dim, int codim) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().fixedSize(dim, codim))); return asImp().fixedSize(dim, codim); } /** @brief how many objects of type DataType have to be sent for a given entity @note Only the sender side needs to know this size. @param e entity for which the size should be determined */ template size_t size (const EntityType& e) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().size(e))); return asImp().size(e); } /** @brief pack data from user to message buffer @param buff message buffer provided by the grid @param e entity for which date should be packed to buffer */ template void gather (MessageBufferImp& buff, const EntityType& e) const { MessageBufferIF buffIF(buff); CHECK_AND_CALL_INTERFACE_IMPLEMENTATION((asImp().gather(buffIF,e))); } /*! \brief unpack data from message buffer to user. @param buff message buffer provided by the grid. This is not const, because the buffer has an internal iterator that gets advanced when reading from the buffer. @param e entity for which date should be unpacked from buffer @param n number of data written to buffer for this entity before */ template void scatter (MessageBufferImp& buff, const EntityType& e, size_t n) { MessageBufferIF buffIF(buff); CHECK_AND_CALL_INTERFACE_IMPLEMENTATION((asImp().scatter(buffIF,e,n))); } private: //! Barton-Nackman trick DataHandleImp& asImp () {return static_cast (*this);} //! Barton-Nackman trick const DataHandleImp& asImp () const { return static_cast(*this); } }; // end class CommDataHandleIF #undef CHECK_INTERFACE_IMPLEMENTATION #undef CHECK_AND_CALL_INTERFACE_IMPLEMENTATION } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/common/defaultgridview.hh000066400000000000000000000270341511655130300223350ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_DEFAULTGRIDVIEW_HH #define DUNE_GRID_COMMON_DEFAULTGRIDVIEW_HH #include #include #include #include namespace Dune { template< class GridImp > class DefaultLevelGridView; template< class GridImp > class DefaultLeafGridView; template< class GridImp > struct DefaultLevelGridViewTraits { typedef DefaultLevelGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid :: Traits :: LevelIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid :: Traits :: LevelIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid :: Traits :: LevelIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; template< int cd > struct Codim { typedef typename Grid :: Traits :: template Codim< cd > :: template Partition< All_Partition > :: LevelIterator Iterator; typedef typename Grid :: Traits :: template Codim< cd > :: Entity Entity; typedef typename Grid :: template Codim< cd > :: Geometry Geometry; typedef typename Grid :: template Codim< cd > :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template< PartitionIteratorType pit > struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid :: template Codim< cd > :: template Partition< pit > :: LevelIterator Iterator; }; }; constexpr static bool conforming = Capabilities :: isLevelwiseConforming< Grid > :: v; }; template< class GridImp > class DefaultLevelGridView { typedef DefaultLevelGridView< GridImp > ThisType; public: typedef DefaultLevelGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits :: template Codim {}; constexpr static bool conforming = Traits :: conforming; DefaultLevelGridView ( const Grid &grid, int level ) : grid_( &grid ), level_( level ) {} /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { assert( grid_ ); return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return grid().levelIndexSet( level_ ); } /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming() const { return bool(Traits::conforming); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( level_, codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( level_, type ); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { return grid().template lbegin< cd, All_Partition >( level_ ); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator begin () const { return grid().template lbegin< cd, pit >( level_ ); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return grid().template lend< cd, All_Partition >( level_ ); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator end () const { return grid().template lend< cd, pit >( level_ ); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return grid().ilevelbegin(entity); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return grid().ilevelend(entity); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize(int codim) const { return grid().overlapSize(level_, codim); } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize(int codim) const { return grid().ghostSize(level_, codim); } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( CommDataHandleIF< DataHandleImp, DataType > &data, InterfaceType iftype, CommunicationDirection dir ) const { return grid().communicate( data, iftype, dir, level_ ); } private: const Grid *grid_; int level_; }; template< class GridImp > struct DefaultLeafGridViewTraits { typedef DefaultLeafGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid :: Traits :: LeafIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid :: Traits :: LeafIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid :: Traits :: LeafIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; template< int cd > struct Codim { typedef typename Grid :: Traits :: template Codim< cd > :: template Partition< All_Partition > :: LeafIterator Iterator; typedef typename Grid :: Traits :: template Codim< cd > :: Entity Entity; typedef typename Grid :: template Codim< cd > :: Geometry Geometry; typedef typename Grid :: template Codim< cd > :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid :: template Codim< cd > :: template Partition< pit > :: LeafIterator Iterator; }; }; constexpr static bool conforming = Capabilities :: isLeafwiseConforming< Grid > :: v; }; template< class GridImp > class DefaultLeafGridView { typedef DefaultLeafGridView< GridImp > ThisType; public: typedef DefaultLeafGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits :: template Codim {}; constexpr static bool conforming = Traits :: conforming; public: DefaultLeafGridView ( const Grid &grid ) : grid_( &grid ) {} /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { assert( grid_ ); return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return grid().leafIndexSet(); } /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming() const { return bool(Traits::conforming); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( type ); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { return grid().template leafbegin< cd, All_Partition >(); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator begin () const { return grid().template leafbegin< cd, pit >(); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return grid().template leafend< cd, All_Partition >(); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator end () const { return grid().template leafend< cd, pit >(); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return grid().ileafbegin(entity); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return grid().ileafend(entity); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize(int codim) const { return grid().overlapSize(codim); } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize(int codim) const { return grid().ghostSize(codim); } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( CommDataHandleIF< DataHandleImp, DataType > &data, InterfaceType iftype, CommunicationDirection dir ) const { return grid().communicate( data, iftype, dir ); } private: const Grid *grid_; }; } #endif dune-grid-2.11.0/dune/grid/common/entity.hh000066400000000000000000000560661511655130300204730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_ENTITY_HH #define DUNE_GRID_COMMON_ENTITY_HH #include #include #include #include #include #include "grid.hh" #include "rangegenerators.hh" namespace Dune { /** @brief Wrapper class for entities \tparam cd Codimension of the entity \tparam dim Dimension of the grid \tparam GridImp Type that is a model of Dune::Grid \tparam EntityImp Class template that is a model of Dune::Entity

Engine Concept

This class wraps a object of type EntityImp and forwards all member function calls to corresponding members of this class. In that sense Entity defines the interface and EntityImp supplies the implementation. For various reasons we do not use an inheritance hierarchy and the Barton-Nackman trick here.

Specialization

The Entity class template is specialized for cd=0 (elements, Dune::Entity<0,dim,GridImp,EntityImp>). This case has an extended interface. The methods defined in the general template are provided by the specialization as well. We did not use inheritance because different implementations for different codimensions may be required and virtual functions had to be avoided.

View concept

Entities can not be created, assigned or otherwise modified outside the interface in the user code. They are only accessible by immutable iterators provided on the corresponding grid class. The only way to modify the entities of a grid is through grid adaptation which consists of tagging entities (of codimension 0) for refinement and then calling the adapt() method on the grid. \ingroup GIEntity \nosubgrouping */ template class EntityImp> class Entity { public: /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef EntityImp< cd, dim, GridImp > Implementation; /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation &impl () { return realEntity; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation &impl () const { return realEntity; } protected: Implementation realEntity; public: //=========================================================== /** @name Exported types and constants */ //@{ //=========================================================== //! \brief The corresponding geometry type typedef typename GridImp::template Codim::Geometry Geometry; //! \brief The corresponding entity seed (for storage of entities) typedef typename GridImp::template Codim::EntitySeed EntitySeed; //! \brief Know your own codimension. constexpr static int codimension = cd; //! \brief Know the grid dimension. constexpr static int dimension = dim; //! \brief Dimensionality of the reference element of the entity. constexpr static int mydimension = dim - cd; //@} //=========================================================== /** @name Methods shared by entities of all codimensions */ //@{ //=========================================================== //! The level of this entity int level () const { return realEntity.level(); } //! Partition type of this entity PartitionType partitionType () const { return realEntity.partitionType(); } /** \brief obtain geometric realization of the entity * * Each entity provides an object of type * Dune::Geometry< dimension-codimension, dimensionworld, ... > that * represents the map from a reference element to world coordinates. * * \note Previously, the geometry was encapsulated in the entity object and * a const reference was returned. * * \note The returned geometry object is guaranteed to remain valid until the * grid is modified (or deleted). */ Geometry geometry () const { return realEntity.geometry(); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ GeometryType type () const { return realEntity.type(); } /** * \brief Number of subentities for a given codimension * * \param codim codimension to obtain number of subentities for * * \note The codimension is specified with respect to the grid dimension. * * \note Unless the geometry type is None, this method is redundant and * the same information can be obtained from the corresponding * reference element. **/ unsigned int subEntities ( unsigned int codim ) const { return realEntity.subEntities(codim); } /** \brief Return the entity seed which contains sufficient information * to generate the entity again and uses as little memory as possible */ EntitySeed seed () const { return realEntity.seed(); } //! Compares two entities for equality. bool operator==(const Entity& other) const { return realEntity.equals(other.realEntity); } //! Compares two entities for inequality. bool operator!=(const Entity& other) const { return !realEntity.equals(other.realEntity); } Entity() {} //! Copy constructor from an existing entity. Entity(const Entity& other) : realEntity(other.realEntity) {} //! Move constructor from an existing entity. Entity(Entity&& other) : realEntity(std::move(other.realEntity)) {} //! Copy assignment operator from an existing entity. Entity& operator=(const Entity& other) { realEntity = other.realEntity; return *this; } //! Move assignment operator from an existing entity. Entity& operator=(Entity&& other) { realEntity = std::move(other.realEntity); return *this; } //@} //=========================================================== /** @name Interface for the implementor */ //@{ //=========================================================== //! Copy constructor from EntityImp Entity(const EntityImp & e) : realEntity(e) {} //! Move constructor from EntityImp Entity(EntityImp && e) : realEntity(std::move(e)) {} //@} }; /** @brief Template specialization of Dune::Entity for Elements (codim==0) \tparam dim Dimension of the grid \tparam GridImp Type that is a model of Dune::Grid \tparam EntityImp Class template that is a model of Dune::Entity @see Dune::Entity (general version) for the full documentation \extends Entity class EntityImp> \ingroup GIEntity \nosubgrouping */ template class EntityImp> class Entity <0,dim,GridImp,EntityImp> { public: /** * \brief Type of underlying implementation * * \note This code may change without prior warning * **/ typedef EntityImp< 0, dim, GridImp > Implementation; //! Return reference to the real implementation Implementation &impl () { return realEntity; } //! Return const reference to the real implementation const Implementation &impl () const { return realEntity; } protected: Implementation realEntity; public: //=========================================================== /** @name Exported types and constants */ //@{ //=========================================================== /** \brief The geometry type of this entity */ typedef typename GridImp::template Codim<0>::Geometry Geometry; //! \brief The corresponding entity seed (for storage of entities) typedef typename GridImp::template Codim<0>::EntitySeed EntitySeed; /** \brief The geometry type of this entity when the geometry is expressed embedded in the father element. This differs from Geometry in particular when dim != dimworld, but even when dim == dimworld the implementation may choose to use a different type here. */ typedef typename GridImp::template Codim<0>::LocalGeometry LocalGeometry; /** \brief Entity types of the different codimensions */ template struct Codim { typedef typename GridImp::template Codim::Entity Entity; }; /** \brief The HierarchicIterator type*/ typedef typename GridImp::HierarchicIterator HierarchicIterator; //! Know your own codimension constexpr static int codimension = 0; //! Know the grid's dimension constexpr static int dimension = dim; /** \brief Know dimension of the entity */ constexpr static int mydimension = dim; //@} //=========================================================== /** @name Methods shared by entities of all codimensions */ //@{ //=========================================================== //! @copydoc Dune::Entity::level() int level () const { return realEntity.level(); } //! @copydoc Dune::Entity::partitionType() PartitionType partitionType () const { return realEntity.partitionType(); } //! @copydoc Dune::Entity::geometry() Geometry geometry () const { return realEntity.geometry(); } /** * \brief Number of subentities for a given codimension * * \param codim codimension to obtain number of subentities for * * \note The codimension is specified with respect to the grid dimension. * * \note Unless the geometry type is None, this method is redundant and * the same information can be obtained from the corresponding * reference element. **/ unsigned int subEntities ( unsigned int codim ) const { return realEntity.subEntities(codim); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ GeometryType type () const { return realEntity.type(); } /** \brief Return the entity seed which contains sufficient information * to generate the entity again and uses as little memory as possible */ EntitySeed seed () const { return realEntity.seed(); } //! Compares two entities for equality. bool operator==(const Entity& other) const { return realEntity.equals(other.realEntity); } //! Compares two entities for inequality. bool operator!=(const Entity& other) const { return !realEntity.equals(other.realEntity); } Entity() {} //! Copy constructor from an existing entity. Entity(const Entity& other) : realEntity(other.realEntity) {} //! Move constructor from an existing entity. Entity(Entity&& other) : realEntity(std::move(other.realEntity)) {} //! Copy assignment operator from an existing entity. Entity& operator=(const Entity& other) { realEntity = other.realEntity; return *this; } //! Move assignment operator from an existing entity. Entity& operator=(Entity&& other) { realEntity = std::move(other.realEntity); return *this; } //@} //=========================================================== /** @name Extended interface of entities of codimension 0 */ //@{ //=========================================================== /** \brief Obtain a subentity * * \tparam codim codimension of the desired subentity * * \param[in] i number of the subentity (in generic numbering) * * \returns the specified subentity * * \note The subentities are numbered 0, ..., subEntities( codim )-1 */ template< int codim > typename Codim< codim >::Entity subEntity ( int i ) const { return realEntity.template subEntity< codim >( i ); } /**\brief Inter-level access to father entity on the next-coarser grid. The given entity resulted directly from a subdivision of its father entity. The behaviour for elements on the macro grid, that is when \ref hasFather() is false, is undefined. \note If the partitionType of the Entity is GhostEntity, it is not guaranteed that this method is working or implemented in general. For some grids it might be available, though. */ Entity father () const { return realEntity.father(); } /**\brief Return true if entity has a father entity which can be accessed using the father() method. */ bool hasFather () const { return realEntity.hasFather(); } //! Returns true if the entity is contained in the leaf grid bool isLeaf () const { return realEntity.isLeaf(); } /** @brief Returns true if element is of regular type in red/green type refinement. In bisection or hanging node refinement this is always true. */ bool isRegular() const { return realEntity.isRegular(); } /** \brief Provides information how this element has been subdivided from its * father element. * * The returned LocalGeometry is a model of * Dune::Geometry, mapping the reference element of * the given entity to the reference element of its father. * * This information is sufficient to interpolate all degrees of freedom in * the conforming case. * Nonconforming may require access to neighbors of the father and * calculations with local coordinates. * The on-the-fly case is somewhat inefficient since degrees of freedom may be * visited several times. * If we store interpolation matrices, this is tolerable. * We assume that on-the-fly implementation of interpolation is only done for * simple discretizations. * * \note For ghost entities, this method is not guaranteed to be implemented. * * \note Previously, the geometry was encapsulated in the entity object and * a const reference was returned. * * \note The returned geometry object is guaranteed to remain valid until the * grid is modified (or deleted). */ LocalGeometry geometryInFather () const { return realEntity.geometryInFather(); } /**\brief Inter-level access to elements that resulted from (recursive) subdivision of this element. \param[in] maxLevel Iterator does not stop at elements with level greater than maxlevel. \return Iterator to the first son (level is not greater than maxlevel) \note If the partitionType of the Entity is GhostEntity, it is not guaranteed that this method is working or implemented in general. For some grids it might be available, though. */ HierarchicIterator hbegin (int maxLevel) const { return realEntity.hbegin(maxLevel); } /** \brief Returns iterator to one past the last son element \note If the partitionType of the Entity is GhostEntity, it is not guaranteed that this method is working or implemented in general. For some grids it might be available, though. */ HierarchicIterator hend (int maxLevel) const { return realEntity.hend(maxLevel); } /**\brief Returns true, if the entity has been created during the last call to adapt() */ bool isNew () const { return realEntity.isNew(); } /**\brief Returns true, if entity might disappear during the next call to adapt(). * If the method returns false, the entity is guaranteed to still be present after * adaptation. */ bool mightVanish () const { return realEntity.mightVanish(); } /**\brief Returns true, if entity has intersections with boundary */ bool hasBoundaryIntersections () const { return realEntity.hasBoundaryIntersections(); } //=========================================================== /** @name Interface for the implementor */ //@{ //=========================================================== //! Copy constructor from EntityImp Entity(const EntityImp<0,dim,GridImp> & e) : realEntity(e) {} //! Move constructor from EntityImp Entity(EntityImp<0,dim,GridImp> && e) : realEntity(std::move(e)) {} //@} }; //******************************************************************** /** @brief Default Implementations for EntityImp EntityDefaultImplementation provides default implementations for Entity which uses the implemented interface which has to be done by the user. @note this is the general version, but there is a specialization for cd=0 @ingroup GridDevel */ template class EntityImp> class EntityDefaultImplementation { public: //! know your own codimension constexpr static int codimension = cd; //! Dimension of the grid constexpr static int dimension = dim; /** \brief Know dimension of the entity */ constexpr static int mydimension = dim - cd; //! \brief The corresponding entity seed (for storage of entities) typedef typename GridImp::template Codim::EntitySeed EntitySeed; /** * \brief Number of subentities for a given codimension * * \param codim codimension to obtain number of subentities for * * \note The codimension is specified with respect to the grid dimension. * * \note Unless the geometry type is None, this method is redundant and * the same information can be obtained from the corresponding * reference element. **/ unsigned int subEntities ( unsigned int codim ) const { typedef typename std::remove_const< GridImp >::type::ctype ctype; return ReferenceElements< ctype, mydimension >::general( asImp().type() ).size( codim - codimension ); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ GeometryType type () const { return asImp().geometry().type(); } private: //! Barton-Nackman trick EntityImp& asImp () { return static_cast&>(*this); } const EntityImp& asImp () const { return static_cast&>(*this); } }; // end EntityDefaultImplementation //******************************************************************** /** @brief Default Implementations for EntityImp (Elements [cd=0]) EntityDefaultImplementation provides default implementations for Entity which uses the implemented interface which has to be done by the user. \extends EntityDefaultImplementation class EntityImp> @ingroup GridDevel */ template class EntityImp> class EntityDefaultImplementation <0,dim,GridImp,EntityImp> { public: //! know your own codimension constexpr static int codimension = 0; //! Dimension of the grid constexpr static int dimension = dim; /** \brief Know dimension of the entity */ constexpr static int mydimension = dim; //! \brief The corresponding entity seed (for storage of entities) typedef typename GridImp::template Codim<0>::EntitySeed EntitySeed; /** @brief Returns true if element is of regular type in red/green type refinement. In bisection or hanging node refinement this is always true. */ bool isRegular() const { return true; } /** * \brief Number of subentities for a given codimension * * \param codim codimension to obtain number of subentities for * * \note The codimension is specified with respect to the grid dimension. * * \note Unless the geometry type is None, this method is redundant and * the same information can be obtained from the corresponding * reference element. **/ unsigned int subEntities ( unsigned int codim ) const { typedef typename std::remove_const< GridImp >::type::ctype ctype; return ReferenceElements< ctype, mydimension >::general( asImp().type() ).size( codim - codimension ); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ GeometryType type () const { return asImp().geometry().type(); } /**\brief Returns true, if the entity has been created during the last call to adapt() */ bool isNew () const { return false; } /**\brief Returns true, if entity might disappear during the next call to adapt() */ bool mightVanish () const { return false; } /**\brief Returns true, if entity has intersections with boundary, this implementation uses the Level- and LeafIntersectionIterator to check for boundary intersections */ bool hasBoundaryIntersections () const { typedef typename GridImp::LevelIntersectionIterator IntersectionIterator; IntersectionIterator end = asImp().ilevelend(); for (IntersectionIterator it = asImp().ilevelbegin(); it != end; ++it) if( it->boundary() ) return true; return false; } private: // Barton-Nackman trick EntityImp<0,dim,GridImp>& asImp () { return static_cast&>(*this); } const EntityImp<0,dim,GridImp>& asImp () const { return static_cast&>(*this); } }; //! Second-level dispatch to select the correct reference element for a grid entity. /** * This function is the default implementation of the second-level reference element dispatch * performed by Entity. * * When referenceElement() is called with an Entity, it will forward the call to * `referenceElement(const GeometryType&)`. This default implementation * will do the right thing as long as your geometry is based on a standard Dune ReferenceElement. If * it is not and you want to supply your own reference element implementation, provide an override of * this function for your specific geometry implementation. * * \related Entity */ template< int cd, int dim, class GridImp, template class EntityImp > auto referenceElement(const Entity< cd, dim, GridImp, EntityImp >& entity ) -> decltype(referenceElement::Geometry::mydimension>(entity.type())) { typedef typename GridImp::template Codim::Geometry Geo; return referenceElement< typename Geo::ctype, Geo::mydimension >(entity.type()); } } #endif // DUNE_GRID_COMMON_ENTITY_HH dune-grid-2.11.0/dune/grid/common/entityiterator.hh000066400000000000000000000114641511655130300222360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_ENTITYITERATOR_HH #define DUNE_GRID_COMMON_ENTITYITERATOR_HH #include #include namespace Dune { /** \class EntityIterator * \brief interface class for an iterator over grid entities * * An entity iterator is an iterator over a subset of entities within a * hierarchical grid. * * Examples of entity iterators are: * - iterators over the leaf level (LeafGridView::Iterator) * - iterators over a grid level (LevelGridView::Iterator) * - iterators over the children of an entity (Grid::HierarchicIterator) * . * * \tparam codim codimension of entities this iterator walks over * \tparam Grid type of the grid implementation * \tparam IteratorImp type of the iterator implementation */ template< int codim, class Grid, class IteratorImp > class EntityIterator { protected: IteratorImp realIterator; public: /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef IteratorImp Implementation; /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation &impl () { return realIterator; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation &impl () const { return realIterator; } typedef typename Grid::template Codim< codim >::Entity Entity; /** \brief Type of the reference used when dereferencing the Ptr */ typedef typename std::conditional< std::is_lvalue_reference< decltype(realIterator.dereference()) >::value, const Entity&, Entity >::type Reference; /** \brief prefix increment operator */ EntityIterator &operator++ () { realIterator.increment(); return *this; } /** \brief postfix increment operator */ EntityIterator operator++ (int) { EntityIterator tmp(*this); realIterator.increment(); return tmp; } // The behavior when dereferencing the EntityIterator facade depends on // the way the grid implementation handles returning entities. The implementation // may either return a reference to an entity stored inside the EntityIterator // implementation or a temporary Entity object. This object has to be forwarded through // the facade to the user, which requires a little trickery, especially for operator->(). // // In order to avoid confusing users reading the Doxygen documentation, we provide "clean" // function signatures to Doxygen and hide the actual implementations. #ifdef DOXYGEN /** \brief Dereferencing operator. */ const Entity& operator*() const; /** \brief Pointer operator. */ const Entity& operator->() const; #else // DOXYGEN /** \brief Dereferencing operator. */ typename std::conditional< std::is_lvalue_reference< decltype(realIterator.dereference()) >::value, const Entity&, Entity >::type operator*() const { return realIterator.dereference(); } /** \brief Pointer operator. */ decltype(handle_proxy_member_access(realIterator.dereference())) operator->() const { return handle_proxy_member_access(realIterator.dereference()); } #endif // DOXYGEN /** \brief Checks for equality. */ bool operator==(const EntityIterator& rhs) const { return this->realIterator.equals(rhs.realIterator); } /** \brief Checks for inequality. */ bool operator!=(const EntityIterator& rhs) const { return !this->realIterator.equals(rhs.realIterator); } /** \name Implementor's interface * \{ */ /** \brief default construct (undefined) iterator */ EntityIterator ( ) {} /** \brief copy constructor from implementation */ EntityIterator ( const IteratorImp &imp ) : realIterator( imp ) {} /** \} */ }; } // namespace Dune namespace std { template< int codim, class Grid, class IteratorImp > struct iterator_traits< Dune::EntityIterator< codim, Grid, IteratorImp > > { typedef ptrdiff_t difference_type; typedef const typename IteratorImp::Entity value_type; typedef value_type *pointer; typedef value_type &reference; typedef forward_iterator_tag iterator_category; }; } // namespace std #endif // #ifndef DUNE_GRID_COMMON_ENTITYITERATOR_HH dune-grid-2.11.0/dune/grid/common/entityseed.hh000066400000000000000000000043021511655130300213160ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_ENTITY_SEED_HH #define DUNE_GRID_COMMON_ENTITY_SEED_HH #include /** \file * \brief Interface class EntitySeed */ namespace Dune { /** \brief Store a reference to an entity with a minimal memory footprint * * The EntitySeed provides a light-weight way to store an entity. It is supposed * to be implemented as memory-efficiently as possible. To get back the actual * entity, you need the corresponding grid. * On the grid, there is the method entity(const EntitySeed&), which * gives you an Entity in exchange for an EntitySeed. */ template class EntitySeed { public: //! codimension of underlying entity constexpr static int codimension = EntitySeedImp::codimension; /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef EntitySeedImp Implementation; /** \brief Construct an empty (i.e. isValid() == false) seed */ EntitySeed() {} /** \brief Construct from implementation class */ EntitySeed(const EntitySeedImp& implementation) : implementation_(implementation) {} /** \brief check whether it is safe to create an Entity from this Seed */ bool isValid() const { return implementation_.isValid(); } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation& impl() { return implementation_; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation& impl() const { return implementation_; } private: /** \brief The actual implementation class */ EntitySeedImp implementation_; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/common/exceptions.hh000066400000000000000000000011331511655130300213210ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_EXCEPTIONS_HH #define DUNE_GRID_COMMON_EXCEPTIONS_HH #include namespace Dune { // GridError // --------- /** \brief Base class for exceptions in Dune grid modules */ class GridError : public Exception {}; } #endif // #ifndef DUNE_GRID_COMMON_EXCEPTIONS_HH dune-grid-2.11.0/dune/grid/common/geometry.hh000066400000000000000000000512261511655130300210030ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_GEOMETRY_HH #define DUNE_GRID_COMMON_GEOMETRY_HH /** \file \brief Wrapper and interface classes for element geometries */ #include #include #include #include #include #include namespace Dune { // External Forward Declarations // ----------------------------- template< int dim, int dimworld, class ct, class GridFamily > class GridDefaultImplementation; //***************************************************************************** // // Geometry // forwards the interface to the implementation // //***************************************************************************** /** @brief Wrapper class for geometries \tparam mydim Dimension of the domain \tparam cdim Dimension of the range \tparam GridImp Type that is a model of Dune::Grid \tparam GeometryImp Class template that is a model of Dune::Geometry

Maps

A Geometry defines a map \f[ g : D \to W\f] where \f$D\subseteq\mathbf{R}^\textrm{mydim}\f$ and \f$W\subseteq\mathbf{R}^\textrm{cdim}\f$. The domain \f$D\f$ is one of a set of predefined convex polytopes, the so-called reference elements (see Dune::ReferenceElement). The dimensionality of \f$D\f$ is mydim. In general \f$\textrm{mydim}\leq\textrm{cdim}\f$, i.e. the convex polytope may be mapped to a manifold. Moreover, we require that \f$ g\in \left( C^1(D) \right)^\textrm{cdim}\f$ and one-to-one.

Engine Concept

The Geometry class template wraps an object of type GeometryImp and forwards all member function calls to corresponding members of this class. In that sense Geometry defines the interface and GeometryImp supplies the implementation. \ingroup GIGeometry */ template< int mydim, int cdim, class GridImp, template< int, int, class > class GeometryImp > class Geometry { public: /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef GeometryImp< mydim, cdim, GridImp > Implementation; /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation &impl () { return realGeometry; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation &impl () const { return realGeometry; } //! @brief geometry dimension constexpr static int mydimension = mydim; //! @brief dimension of embedding coordinate system constexpr static int coorddimension = cdim; //! define type used for coordinates in grid module typedef typename GridImp::ctype ctype; //! type of local coordinates typedef FieldVector LocalCoordinate; //! type of the global coordinates typedef FieldVector< ctype, cdim > GlobalCoordinate; //! Number type used for the geometry volume typedef decltype(std::declval().volume()) Volume; /** * \brief type of jacobian inverse transposed * * The exact type is implementation-dependent. * However, it is guaranteed to have the following properties: * - It satisfies the ConstMatrix interface. * - It is copy constructible and copy assignable. * . */ typedef typename Implementation::JacobianInverseTransposed JacobianInverseTransposed; /** * \brief type of jacobian transposed * * The exact type is implementation-dependent. * However, it is guaranteed to have the following properties: * - It satisfies the ConstMatrix interface. * - It is copy constructible and copy assignable. * . */ typedef typename Implementation::JacobianTransposed JacobianTransposed; private: template using JacobianInverseOfImplementation = decltype(typename Implementation_T::JacobianInverse{std::declval().jacobianInverse(std::declval())}); using JacobianInverseDefault = decltype(transpose(std::declval())); template using JacobianOfImplementation = decltype(typename Implementation_T::Jacobian{std::declval().jacobian(std::declval())}); using JacobianDefault = decltype(transpose(std::declval())); auto jacobianImpl ( const LocalCoordinate &local, std::true_type /*implDetected*/ ) const { return impl().jacobian(local); } [[deprecated("Geometry implementations are required to provide a jacobian(local) method. The default implementation is deprecated and will be removed after release 2.9")]] auto jacobianImpl ( const LocalCoordinate &local, std::false_type /*implNotDetected*/ ) const { return transpose(jacobianTransposed(local)); } auto jacobianInverseImpl ( const LocalCoordinate &local, std::true_type /*implDetected*/ ) const { return impl().jacobianInverse(local); } [[deprecated("Geometry implementations are required to provide a jacobianInverse(local) method. The default implementation is deprecated and will be removed after release 2.9")]] auto jacobianInverseImpl ( const LocalCoordinate &local, std::false_type /*implNotDetected*/ ) const { return transpose(jacobianInverseTransposed(local)); } public: /** * \brief type of jacobian inverse * * The exact type is implementation-dependent. * However, it is guaranteed to have the following properties: * - You can multiply it from the right to a suitable FieldMatrix * - It is copy constructible and copy assignable. * . */ using JacobianInverse = Std::detected_or_t; /** * \brief type of jacobian * * The exact type is implementation-dependent. * However, it is guaranteed to have the following properties: * - You can multiply it from the right to a suitable FieldMatrix * - It is copy constructible and copy assignable. * . */ using Jacobian = Std::detected_or_t; /** \brief Return the type of the reference element. The type can be used to access the Dune::ReferenceElement. */ GeometryType type () const { return impl().type(); } /** \brief Return true if the geometry mapping is affine and false otherwise */ bool affine() const { return impl().affine(); } /** \brief Return the number of corners of the reference element. * Since a geometry is a convex polytope the number of corners is a well-defined concept. The method is redundant because this information is also available via the reference element. It is here for efficiency and ease of use. */ int corners () const { return impl().corners(); } /** \brief Obtain a corner of the geometry * * This method is for convenient access to the corners of the geometry. The * same result could be achieved by calling \code global( referenceElement.position( i, mydimension ) ) \endcode * * \param[in] i number of the corner (with respect to the reference element) * * \returns position of the i-th corner */ GlobalCoordinate corner ( int i ) const { return impl().corner( i ); } /** \brief Evaluate the map \f$ g\f$. \param[in] local Position in the reference element \f$D\f$ \return Position in \f$W\f$ */ GlobalCoordinate global (const LocalCoordinate& local) const { return impl().global( local ); } /** \brief Evaluate the inverse map \f$ g^{-1}\f$ \param[in] global Position in \f$W\f$ \return Position in \f$D\f$ that maps to global */ LocalCoordinate local (const GlobalCoordinate& global) const { return impl().local( global ); } /** \brief Return the factor appearing in the integral transformation formula Let \f$ g : D \to W\f$ denote the transformation described by the Geometry. Then the jacobian of the transformation is defined as the \f$\textrm{cdim}\times\textrm{mydim}\f$ matrix \f[ J_g(x) = \left( \begin{array}{ccc} \frac{\partial g_0}{\partial x_0} & \cdots & \frac{\partial g_0}{\partial x_{n-1}} \\ \vdots & \ddots & \vdots \\ \frac{\partial g_{m-1}}{\partial x_0} & \cdots & \frac{\partial g_{m-1}}{\partial x_{n-1}} \end{array} \right).\f] Here we abbreviated \f$m=\textrm{cdim}\f$ and \f$n=\textrm{mydim}\f$ for ease of readability. The integration element \f$\mu(x)\f$ for any \f$x\in D\f$ is then defined as \f[ \mu(x) = \sqrt{|\det J_g^T(x)J_g(x)|}.\f] \param[in] local Position \f$x\in D\f$ \return integration element \f$\mu(x)\f$ \note Each implementation computes the integration element with optimal efficiency. For example in an equidistant structured mesh it may be as simple as \f$h^\textrm{mydim}\f$. */ Volume integrationElement (const LocalCoordinate& local) const { return impl().integrationElement( local ); } /** \brief return volume of geometry */ Volume volume () const { return impl().volume(); } /** \brief return center of geometry * * Note that this method is still subject to a change of name and semantics. * At the moment, the center is not required to be the centroid of the * geometry, or even the centroid of its corners. This makes the current * default implementation acceptable, which maps the centroid of the * reference element to the geometry. * We may change the name (and semantic) of the method to centroid() if we * find reasonably efficient ways to implement it properly. */ GlobalCoordinate center () const { return impl().center(); } /** \brief Return the transposed of the Jacobian * * The Jacobian is defined in the documentation of * \ref Dune::Geometry::integrationElement "integrationElement". * * \param[in] local position \f$x\in D\f$ * * \return \f$J_g^T(x)\f$ * * \note The exact return type is implementation defined. */ JacobianTransposed jacobianTransposed ( const LocalCoordinate& local ) const { return impl().jacobianTransposed( local ); } /** \brief Return inverse of transposed of Jacobian * * The Jacobian is defined in the documentation of * \ref Dune::Geometry::integrationElement "integrationElement". * * \param[in] local position \f$x\in D\f$ * \return \f$J_g^{-T}(x)\f$ * * The use of this function is to compute the gradient of some function * \f$f : W \to \textbf{R}\f$ at some position \f$y=g(x)\f$, where * \f$x\in D\f$ and \f$g\f$ the transformation of the Geometry. * When we set \f$\hat{f}(x) = f(g(x))\f$ and apply the chain rule we obtain * \f[\nabla f(g(x)) = J_g^{-T}(x) \nabla \hat{f}(x).\f] * * \note In the non-quadratic case \f$\textrm{cdim} \neq \textrm{mydim}\f$, the * pseudoinverse of \f$J_g^T(x)\f$ is returned. * This means that it is inverse for all tangential vectors in * \f$g(x)\f$ while mapping all normal vectors to zero. * * \note The exact return type is implementation defined. */ JacobianInverseTransposed jacobianInverseTransposed ( const LocalCoordinate &local ) const { return impl().jacobianInverseTransposed(local); } /** \brief Return the Jacobian * * The Jacobian is defined in the documentation of * \ref Dune::Geometry::integrationElement "integrationElement". * * \param[in] local position \f$x\in D\f$ * * \return \f$J_g(x)\f$ * * \note The exact return type is implementation defined. */ Jacobian jacobian ( const LocalCoordinate& local ) const { auto implDetected = Std::is_detected{}; return jacobianImpl(local, implDetected); } /** \brief Return inverse of Jacobian * * The Jacobian is defined in the documentation of * \ref Dune::Geometry::integrationElement "integrationElement". * * \param[in] local position \f$x\in D\f$ * \return \f$J_g^{-1}(x)\f$ * * The use of this function is to compute the jacobians of some function * \f$f : W \to \textbf{R}\f$ at some position \f$y=g(x)\f$, where * \f$x\in D\f$ and \f$g\f$ the transformation of the Geometry. * When we set \f$\hat{f}(x) = f(g(x))\f$ and apply the chain rule we obtain * \f[\nabla f(g(x)) = J_{\hat{f}}(x) J_g^{-1}(x).\f] * * \note In the non-quadratic case \f$\textrm{cdim} \neq \textrm{mydim}\f$, the * pseudoinverse of \f$J_g(x)\f$ is returned. * This means that its transposed is inverse for all tangential vectors in * \f$g(x)\f$ while mapping all normal vectors to zero. * * \note The exact return type is implementation defined. */ JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { auto implDetected = Std::is_detected{}; return jacobianInverseImpl(local, implDetected); } //=========================================================== /** @name Interface for grid implementers */ //@{ //=========================================================== //! copy constructor from implementation explicit Geometry ( const Implementation &impl ) : realGeometry( impl ) {} //@} protected: Implementation realGeometry; }; //************************************************************************ // GEOMETRY Default Implementations //************************************************************************* // // --GeometryDefault // //! Default implementation for class Geometry template class GeometryImp> class GeometryDefaultImplementation { public: static const int mydimension = mydim; static const int coorddimension = cdim; // save typing typedef typename GridImp::ctype ctype; typedef FieldVector< ctype, mydim > LocalCoordinate; typedef FieldVector< ctype, cdim > GlobalCoordinate; //! Number type used for the geometry volume typedef ctype Volume; //! type of jacobian inverse transposed typedef FieldMatrix< ctype, cdim, mydim > JacobianInverseTransposed; //! type of jacobian transposed typedef FieldMatrix< ctype, mydim, cdim > JacobianTransposed; //! type of jacobian inverse typedef FieldMatrix< ctype, mydim, cdim > JacobianInverse; //! type of jacobian typedef FieldMatrix< ctype, cdim, mydim > Jacobian; //! return volume of the geometry Volume volume () const { GeometryType type = asImp().type(); // get corresponding reference element auto refElement = referenceElement< ctype , mydim >(type); LocalCoordinate localBaryCenter ( 0 ); // calculate local bary center const int corners = refElement.size(0,0,mydim); for(int i=0; i(type); // center is (for now) the centroid of the reference element mapped to // this geometry. return asImp().global(refElement.position(0,0)); } //! Return the Jacobian Jacobian jacobian ( const LocalCoordinate& local ) const { return asImp().jacobianTransposed(local).transposed(); } //! Return inverse of Jacobian JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { return asImp().jacobianInverseTransposed(local).transposed(); } private: //! Barton-Nackman trick GeometryImp& asImp () {return static_cast&>(*this);} const GeometryImp& asImp () const {return static_cast&>(*this);} }; // end GeometryDefault template class GeometryImp> class GeometryDefaultImplementation<0,cdim,GridImp,GeometryImp> { // my dimension constexpr static int mydim = 0; public: static const int mydimension = mydim; static const int coorddimension = cdim; // save typing typedef typename GridImp::ctype ctype; typedef FieldVector< ctype, mydim > LocalCoordinate; typedef FieldVector< ctype, cdim > GlobalCoordinate; typedef ctype Volume; //! type of jacobian inverse transposed typedef FieldMatrix< ctype, cdim, mydim > JacobianInverseTransposed; //! type of jacobian transposed typedef FieldMatrix< ctype, mydim, cdim > JacobianTransposed; //! type of jacobian inverse typedef FieldMatrix< ctype, mydim, cdim > JacobianInverse; //! type of jacobian typedef FieldMatrix< ctype, cdim, mydim > Jacobian; //! return the only coordinate FieldVector global (const FieldVector& /*local*/) const { return asImp().corner(0); } //! return empty vector FieldVector local (const FieldVector& ) const { return FieldVector(); } //! return volume of the geometry Volume volume () const { return Volume(1.0); } //! return center of the geometry FieldVector center () const { return asImp().corner(0); } //! Return the Jacobian Jacobian jacobian ( const LocalCoordinate& local ) const { return asImp().jacobianTransposed(local).transposed(); } //! Return inverse of Jacobian JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { return asImp().jacobianInverseTransposed(local).transposed(); } private: // Barton-Nackman trick GeometryImp& asImp () {return static_cast&>(*this);} const GeometryImp& asImp () const {return static_cast&>(*this);} }; // end GeometryDefault // referenceElement // ---------------- template< int mydim, int cdim, class GridImp, template< int, int, class > class GeometryImp> auto referenceElement(const Geometry& geo) -> decltype(referenceElement(geo,geo.impl())) { return referenceElement(geo,geo.impl()); } //! Second-level dispatch to select the correct reference element for a grid geometry. /** * This function is the default implementation of the second-level reference element dispatch * performed by Geometry. * * \note This function is only important for grid implementors with geometries that do not have * a standard reference element. * * When referenceElement() is called with a Geometry, it will forward the call to * `referenceElement(const Geometry&,const GeometryImplementation&)`. This default implementation * will do the right thing as long as your geometry is based on a standard Dune ReferenceElement. If * it is not and you want to supply your own reference element implementation, provide an override of * this function for your specific geometry implementation. * * \related Geometry */ template< int mydim, int cdim, class GridImp, template< int, int, class > class GeometryImp, typename Impl> auto referenceElement(const Geometry& geo, const Impl&) -> decltype(referenceElement(geo.type())) { using Geo = Geometry; return referenceElement(geo.type()); } } // namespace Dune #endif // DUNE_GRID_COMMON_GEOMETRY_HH dune-grid-2.11.0/dune/grid/common/grid.hh000066400000000000000000001224771511655130300201040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_GRID_HH #define DUNE_GRID_COMMON_GRID_HH /** \file \brief Different resources needed by all grid implementations */ // system includes #include #include #include // dune-common includes #include #include #include // dune-geometry includes #include // local includes #include #include #include #include #include #include #include // include this file after all other, because other files might undef the // macros that are defined in that file #include namespace Dune { /** @addtogroup Grid Grid The Dune Grid module defines a general interface to a parallel, in general nonconforming, locally refined and hierarchical finite element mesh. The interface is independent of dimension and element type. @section Grid1 Terminology @subsection subs1 Entity An entity is a geometric object that is part of a grid. It is generalized polytope that has the same dimensionality as the grid or a lower dimension. @subsection subs20 Dimension A grid has a fixed dimension \f$d\f$ which is the number of coordinates required to specify any point in the grid. The dimension is a template parameter of a grid. @subsection subs21 Codimension of an entity Each entity has a codimension \f$c\f$ where \f$0 \leq c \leq d\f$ (the dimension of the grid). An entity with codimension \f$ c\f$ in a grid of dimension \f$ d\f$ is a \f$d-c\f$-dimensional object. @subsection subs5 Subentity Entities are hierarchically constructed in the sense that entities of codimension 0 are made up of entities of codimension 1 which are themselves made up of entities of codimension 2 etc. until entities of codimension \f$d-1\f$ which consist of entities of codimension \f$ d\f$. @subsection subs3 Element An element is an entity of codimension 0. @subsection subs4 Vertex A vertex is an entity of codimension \f$ d\f$ (the same as the grid's dimension). @subsection subs22 World dimension Each grid has a world dimension \f$ w\f$ with \f$ w\geq d\f$. This is the number of coordinates of the positions of the grid's vertices. @subsection subs33 Hierarchical grid The %Dune grid interface describes not only a single grid but a sequence of grids with different resolution. This is achieved by beginning with an intentionally coarse grid, the so-called macro grid. Then each element may be individually subdivided to yield new (smaller) elements. This construction is recursive such that each macro element and all the elements that resulted from subdividing it form a tree structure. @subsection subs33333 Grid refinement The grid can only be modified in special phases, the so-called refinement phase. In between refinement phases the entities of the grid can not be modified in any way. During refinement currently only the hierachic subdivision can be modified. @subsection subs3333 Grid level All elements of the macro grid form level 0 of the grid structure. All elements that are obtained from an \f$ l\f$-fold subdivision of a macro element form level \f$ l\f$ of the grid structure. @subsection subs333 Leaf grid All elements of a grid that are not subdivided any further make up the leaf grid. The leaf grid is the mesh with the finest resolution. @subsection subs6 Assignable A type is said to be assignable if it has a (public) copy constructor and assignment operator. Note that this definition requires always both methods. @subsection subs7 Default-constructible A type is said to be default-constructible if it has a constructor without arguments. @subsection subs8 Copy-constructible from type X A type is said to be copy constructible from some other type X if it has a copy constructor that takes a reference to an object of type X. @subsection subs9 Equality-comparable A type is said to be equality-comparable if it has an operator==. @subsection subs10 LessThan-comparable A type is lessthan-comparable if it has an operator<. @subsection subs11 Dereferenceable A type is dereferenceable if it has an operator* that delivers a reference to a value type. @subsection subs11 Iterator An iterator is a type that can be dereferenced to yield an object of its value type, i.e. it behaves like a pointer, and that can be incremented to point to the next element in a linear sequence. In that respect it is comparable to ForwardIterator in the Standard Template Library. @subsection subs12 Mutable iterator An iterator is called mutable if the value it refers to can be changed, i.e. it is assignable. @subsection subs13 Immutable iterator An iterator is called immutable if the value referenced by the iterator can not be changed, i. e. the value is not assignable and only methods marked const on the value can be called. @subsection subs14 Model A type M is called a model of another type X if it implements all the methods of X with the intended semantics. Typically X is a type that describes an interface. @section Grid3 Types common to all grid implementations - Dune::ReferenceElement describes the topology and geometry of standard entities. Any given entity of the grid can be completely specified by a reference element and a map from this reference element to world coordinate space. - Dune::GeometryType defines names for the reference elements. - Dune::Communication defines an interface to global communication operations in a portable and transparent way. In particular also for sequential grids. @section Grid2 Types making up a grid implementation Each implementation of the Dune grid interface consist of a number of related types which together form a model of the grid interface. These types are the following: - %Grid which is a model of Dune::Grid where the template parameters are at least the dimension and the world dimension. It is a container of entities that allows to access these entities and that knows the number of entities. - %Entity which is a model of Dune::Entity. This class is parametrized by dimension and codimension. The entity encapsulates the topological part of an entity, i.e. its hierarchical construction from subentities and the relation to other entities. Entities cannot be created, copied or modified by the user. They can only be read-accessed through immutable iterators. - %Geometry which is a model of Dune::Geometry. This class encapsulates the geometric part of an entity by mapping local coordinates in a reference element to world coordinates. - %LevelIterator which is a model of Dune::LevelIterator is an immutable iterator that provides access to all entities of a given codimension and level of the grid. - %LeafIterator which is a model of Dune::LeafIterator is an immutable iterator that provides access to all entities of a given codimension of the leaf grid. - %HierarchicIterator which is a model of Dune::HierarchicIterator is an immutable iterator that provides access to all entities of codimension 0 that resulted from subdivision of a given entity of codimension 0. - %Intersection which is a model of Dune::Intersection provides access an intersection of codimension 1 of two entity of codimension 0 or one entity and the boundary. In a conforming mesh this is a face of an element. For two entities with a common intersection the %Intersection also provides information about the geometric location of the intersection. Furthermore it also provides information about intersections of an entity with the internal or external boundaries. - %IntersectionIterator which is a model of Dune::IntersectionIterator provides access to all intersections of a given entity of codimension 0. - %LevelIndexSet and %LeafIndexSet which are both models of Dune::IndexSet are used to attach any kind of user-defined data to (subsets of) entities of the grid. This data is supposed to be stored in one-dimensional arrays for reasons of efficiency. - %LocalIdSet and %GlobalIdSet which are both models of Dune::IdSet are used to save user data during a grid refinement phase and during dynamic load balancing in the parallel case. @section Grid22 Overview of basic capabilities of the types
Class Assignable DefaultConstructible EqualityComparable LessThanComparable
Grid no no no no
Entity no no no no
GeometryType yes yes yes yes
Geometry no no no no
LevelIterator yes no yes no
LeafIterator yes no yes no
HierarchicIterator yes no yes no
Intersection yes no yes no
IntersectionIterator yes no yes no
IndexSet no no no no
IdSet no no no no
*/ // Forward Declarations // -------------------- template class GeometryImp> class Geometry; template< int mydim, int cdim, class GridImp > class GlobalGeometryReference; template< int mydim, int cdim, class GridImp > class LocalGeometryReference; // dim is necessary because Entity will be specialized for codim==0 _and_ codim==dim // EntityImp gets GridImp as 3rd template parameter to distinguish between const and mutable grid template class EntityImp> class Entity; template< int codim, class Grid, class IteratorImp > class EntityIterator; template class EntitySeed; template< class GridImp, class IntersectionImp > class Intersection; template< class GridImp, class IntersectionIteratorImp, class IntersectionImp > class IntersectionIterator; template< class GridImp, class IndexSetImp, class IndexTypeImp = unsigned int, class TypesImp = std::vector< GeometryType > > class IndexSet; template class IdSet; //************************************************************************ // G R I D //************************************************************************ /** \brief Grid abstract base class @ingroup GIGrid This class is the base class for all grid implementations. Although no virtual functions are used we call it abstract since its methods do not contain an implementation but forward to the methods of the derived class via the Barton-Nackman trick. \tparam dim specifies the dimension of the grid. \tparam dimworld specifies the dimension of the surrounding space, this can be different from dim, if the grid is defined on a manifold . \tparam ct field type of the world vector space. \tparam GridFamily traits class providing all types associated with the grid implementation. \nosubgrouping */ template< int dim, int dimworld, class ct, class GridFamily> class Grid { typedef typename GridFamily::Traits::Grid GridImp; typedef Grid ThisType; public: //=========================================================== /** @name Exported constants */ //@{ //=========================================================== //! \brief The dimension of the grid constexpr static int dimension = dim; //! \brief The dimension of the world the grid lives in. constexpr static int dimensionworld = dimworld; //@} //=========================================================== /** @name Exported types */ //@{ //=========================================================== /** \brief type of view for leaf grid */ typedef typename GridFamily::Traits::LeafGridView LeafGridView; /** \brief type of view for level grid */ typedef typename GridFamily::Traits::LevelGridView LevelGridView; /** \brief A Traits struct that collects all associated types of one implementation \tparam cd codimension. Note that not all types in this struct depend on this template parameter. */ template struct Codim { //! A type that is a model of Dune::Geometry. typedef typename GridFamily::Traits::template Codim::Geometry Geometry; //! A type that is a model of Dune::Geometry. typedef typename GridFamily::Traits::template Codim::LocalGeometry LocalGeometry; //! A type that is a model of a Dune::Entity. typedef typename GridFamily::Traits::template Codim::Entity Entity; //! A type that is a model (not yet) of Dune::EntitySeed. typedef typename GridFamily::Traits::template Codim::EntitySeed EntitySeed; //! A struct collecting all types depending on the partition iterator type. template struct Partition { /*! \brief A type that is a model of Dune::LevelIterator which is s type of iterator that may be used to examine, but not to modify, the entities of codimension cd with partition type pitype on a certain level of the grid, i. e. the increment of the iterator adjusts it to the next entity on that level. */ typedef typename GridFamily::Traits::template Codim::template Partition::LevelIterator LevelIterator; /*! \brief A type that is a model of Dune::LeafIterator which is a type of iterator that may be used to examine, but not to modify, the entities of codimension cd with partition type pitype in the leaf grid, i. e. the increment of the iterator adjusts it to the next entity in the leaf grid. */ typedef typename GridFamily::Traits::template Codim::template Partition::LeafIterator LeafIterator; }; /*! \brief A type that is a model of Dune::LevelIterator with partition type All_Partition */ typedef typename GridFamily::Traits::template Codim::LevelIterator LevelIterator; /*! \brief A type that is a model of Dune::LeafIterator with partition type All_Partition */ typedef typename GridFamily::Traits::template Codim::LeafIterator LeafIterator; }; /*! \brief A type that is a model of Dune::Intersection, an intersections of two codimension 1 of two codimension 0 entities in the leaf view. */ typedef typename GridFamily::Traits::LeafIntersection LeafIntersection; /*! \brief A type that is a model of Dune::Intersection, an intersections of two codimension 1 of two codimension 0 entities in a level view. */ typedef typename GridFamily::Traits::LevelIntersection LevelIntersection; /*! \brief A type that is a model of Dune::IntersectionIterator which is an iterator that allows to examine, but not to modify, the intersections of codimension 1 of an leaf element (entity of codimension 0) with other leaf elements. */ typedef typename GridFamily::Traits::LeafIntersectionIterator LeafIntersectionIterator; /*! \brief A type that is a model of Dune::IntersectionIterator which is an iterator that allows to examine, but not to modify, the intersections of codimension 1 of an element (entity of codimension 0) with other elements on the same level. */ typedef typename GridFamily::Traits::LevelIntersectionIterator LevelIntersectionIterator; /*! \brief A type that is a model of Dune::HierarchicIterator A type of iterator that allows to examine, but not to modify, entities of codimension 0 that result from refinement of an entity of codimension 0. */ typedef typename GridFamily::Traits::HierarchicIterator HierarchicIterator; /*! \brief A type that is a model of Dune::IndexSet which provides a consecutive, but non persistent, numbering for entities on a grid level. */ typedef typename GridFamily::Traits::LevelIndexSet LevelIndexSet; /*! \brief A type that is a model of Dune::IndexSet which provides a consecutive, but non persistent, numbering for entities in the leaf grid. */ typedef typename GridFamily::Traits::LeafIndexSet LeafIndexSet; /*! \brief A type that is a model of Dune::IdSet which provides a unique and persistent numbering for all entities in the grid. The numbering is unique over all processes over which the grid is partitioned. The numbering is not necessarily consecutive. */ typedef typename GridFamily::Traits::GlobalIdSet GlobalIdSet; /*! \brief A type that is a model of Dune::IdSet which provides a unique and persistent numbering for all entities in the grid. The numbering is only unique in a single process and it is not necessarily consecutive. */ typedef typename GridFamily::Traits::LocalIdSet LocalIdSet; /*! \brief A type that is a model of Dune::Communication. It provides a portable way for communication on the set of processes used by the grid. */ using Communication = typename GridFamily::Traits::Communication; //! Define type used for coordinates in grid module typedef ct ctype; //@} //=========================================================== /** @name Size methods */ //@{ //=========================================================== /*! \brief Return maximum level defined in this grid. Levels are numbered 0 ... maxLevel with 0 the coarsest level. */ int maxLevel() const { CHECK_INTERFACE_IMPLEMENTATION(asImp().maxLevel()); return asImp().maxLevel(); } //! Return number of grid entities of a given codim on a given level in this process int size (int level, int codim) const { CHECK_INTERFACE_IMPLEMENTATION(asImp().size(level,codim)); return asImp().size(level,codim); } //! Return number of leaf entities of a given codim in this process int size (int codim) const { CHECK_INTERFACE_IMPLEMENTATION(asImp().size(codim)); return asImp().size(codim); } //! Return number of entities per level and geometry type in this process int size (int level, GeometryType type) const { CHECK_INTERFACE_IMPLEMENTATION(asImp().size(level,type)); return asImp().size(level,type); } //! Return number of leaf entities per geometry type in this process int size (GeometryType type) const { CHECK_INTERFACE_IMPLEMENTATION(asImp().size(type)); return asImp().size(type); } //@} /** \brief returns the number of boundary segments within the macro grid * * \returns number of boundary segments within the macro grid */ size_t numBoundarySegments () const { CHECK_INTERFACE_IMPLEMENTATION( asImp().numBoundarySegments()); return asImp().numBoundarySegments(); } //=========================================================== /** @name Views */ //@{ //=========================================================== //! View for a grid level for All_Partition LevelGridView levelGridView(int level) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().levelGridView(level))); return asImp().levelGridView(level); } //! View for the leaf grid for All_Partition LeafGridView leafGridView() const { CHECK_INTERFACE_IMPLEMENTATION((asImp().leafGridView())); return asImp().leafGridView(); } //@} //=========================================================== /** @name Access to index and id sets */ //@{ //=========================================================== //! return const reference to the grids global id set const GlobalIdSet &globalIdSet () const { CHECK_INTERFACE_IMPLEMENTATION(asImp().globalIdSet()); return asImp().globalIdSet(); } //! return const reference to the grids local id set const LocalIdSet &localIdSet () const { CHECK_INTERFACE_IMPLEMENTATION(asImp().localIdSet()); return asImp().localIdSet(); } //! return const reference to the grids level index set for level level const LevelIndexSet &levelIndexSet ( int level ) const { CHECK_INTERFACE_IMPLEMENTATION(asImp().levelIndexSet(level)); return asImp().levelIndexSet(level); } //! return const reference to the grids leaf index set const LeafIndexSet &leafIndexSet () const { CHECK_INTERFACE_IMPLEMENTATION(asImp().leafIndexSet()); return asImp().leafIndexSet(); } //@} //=========================================================== /** @name Adaptivity and grid refinement */ //@{ //=========================================================== /** \brief Refine the grid refCount times using the default refinement rule. * * This behaves like marking all elements for refinement and then calling preAdapt, adapt and postAdapt. * The state after globalRefine is comparable to the state after postAdapt. */ void globalRefine (int refCount) { CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().globalRefine(refCount)); return; } /** \brief Marks an entity to be refined/coarsened in a subsequent adapt. \param[in] refCount Number of subdivisions that should be applied. Negative value means coarsening. \param[in] e Entity that should be marked \return true if Entity was marked, false otherwise. */ bool mark( int refCount, const typename Codim<0>::Entity & e ) { return asImp().mark(refCount,e); } /** \brief returns adaptation mark for given entity \param[in] e Entity for which adaptation mark should be determined \return int adaptation mark currently set for given Entity e */ int getMark(const typename Codim<0>::Entity & e) const { return asImp().getMark(e); } /** \brief To be called after entities have been marked and before adapt() is called. * * This sets the mightVanish flags of the elements for the next adapt call. * * \return true if an entity may be coarsened during a subsequent adapt(), false otherwise. */ bool preAdapt () { return asImp().preAdapt(); } /** \brief Refine all positive marked leaf entities, coarsen all negative marked entities if possible \return true if a least one entity was refined The complete adaptation process works as follows: - mark entities with the mark() method - call preAdapt() - if preAdapt() returned true: possibly save current solution - call adapt() - if adapt() returned true: possibly interpolate the (saved) solution - call postAdapt() */ bool adapt () { return asImp().adapt(); } /** \brief To be called after grid has been adapted and information left over by the adaptation has been processed. * * This removes the isNew flags of the elements from the last adapt call. */ void postAdapt() { return asImp().postAdapt(); } //@} //=========================================================== /** @name Parallel data distribution and communication */ //@{ //=========================================================== //! return const reference to a communication object. The return type is a model of Dune::Communication. const Communication &comm () const { CHECK_INTERFACE_IMPLEMENTATION(asImp().comm()); return asImp().comm(); } //@} /*! \brief Re-balances the load each process has to handle for a parallel grid, * \return True if the grid has changed. */ bool loadBalance() { CHECK_INTERFACE_IMPLEMENTATION(asImp().loadBalance()); return asImp().loadBalance(); } /*! \brief Re-balances the load each process has to handle for a parallel grid and moves the data. * \param data A data handle telling the method which data should be communicated * and how. Has to adhere to the interface describe by CommDataHandleIf * just like the data handle for the communicate * methods. * \return True if the grid has changed. */ template bool loadBalance (DataHandle& data) { CHECK_INTERFACE_IMPLEMENTATION(asImp().loadBalance(data)); return asImp().loadBalance(data); } /** \brief obtain Entity from EntitySeed. */ template < class EntitySeed > typename Codim< EntitySeed :: codimension > :: Entity entity( const EntitySeed& seed ) const { //CHECK_INTERFACE_IMPLEMENTATION( asImp().entity( seed ) ); return asImp().entity( seed ); } protected: //! Barton-Nackman trick GridImp& asImp () {return static_cast (*this);} //! Barton-Nackman trick const GridImp& asImp () const {return static_cast(*this);} }; #undef CHECK_INTERFACE_IMPLEMENTATION #undef CHECK_AND_CALL_INTERFACE_IMPLEMENTATION /** * \addtogroup GIGridView * @{ */ /** * \brief level grid view for the given grid and level. * * Identical to the method in the Grid interface, but provided * as a free function. * * \see Grid::levelGridView * * \param grid Grid to obtain the level grid view for * \param level level of the level grid view */ template typename Grid::LevelGridView levelGridView(const Grid& grid, int level) { return grid.levelGridView(level); } /** * \brief leaf grid view for the given grid * * Identical to the method in the Grid interface, but provided * as a free function. * * \see Grid::leafGridView * * \param grid Grid to obtain the leaf grid view for */ template typename Grid::LeafGridView leafGridView(const Grid& grid) { return grid.leafGridView(); } /** @} */ /** \ingroup GridDevel @{ A Grid is a container of grid entities. Given a dimension dim these entities have a codimension codim with 0 <= codim <= dim. The Grid is assumed to be hierachically refined and nested. It enables iteration over entities of a given level and codimension. The grid can be non-matching. All information is provided to allocate degrees of freedom in appropriate vector data structures (which are not part of this module). Template class Grid defines a "base class" for all grids. \par Classes implementing the Grid Interface \li Dune::AlbertaGrid
Provides the simplicial meshes of the finite element tool box ALBERTA (http://www.alberta-fem.de/) written by Kunibert Siebert and Alfred Schmidt. \li Dune::OneDGrid
Onedimensional adaptive grid \li Dune::UGGrid
Provides the meshes of the finite element toolbox UG3. (described in https://doi.org/10.1007/s007910050003). \li Dune::YaspGrid (Yet Another Structured Parallel Grid)
Provides a distributed structured cube mesh. */ template class GridDefaultImplementation : public Grid { typedef typename GridFamily::Traits::Grid GridImp; public: /** * \brief The traits of this class. * * Presents the typedefs as described in GridTraits. */ typedef typename GridFamily::Traits Traits; //! View for a grid level for All_Partition typename Traits::LevelGridView levelGridView(int level) const { typedef typename Traits::LevelGridView View; typedef typename View::GridViewImp ViewImp; return View(ViewImp(asImp(),level)); } //! View for the leaf grid for All_Partition typename Traits::LeafGridView leafGridView() const { typedef typename Traits::LeafGridView View; typedef typename View::GridViewImp ViewImp; return View(ViewImp(asImp())); } /** \brief obtain begin intersection iterator on the leaf level */ typename Traits::LeafIntersectionIterator ileafbegin ( const typename Traits::template Codim<0>::Entity &entity ) const { return entity.impl().ileafbegin(); } /** \brief obtain end intersection iterator on the leaf level */ typename Traits::LeafIntersectionIterator ileafend ( const typename Traits::template Codim<0>::Entity &entity ) const { return entity.impl().ileafend(); } /** \brief obtain begin intersection iterator on the entity level */ typename Traits::LevelIntersectionIterator ilevelbegin ( const typename Traits::template Codim<0>::Entity &entity ) const { return entity.impl().ilevelbegin(); } /** \brief obtain end intersection iterator on the entity level */ typename Traits::LevelIntersectionIterator ilevelend ( const typename Traits::template Codim<0>::Entity &entity ) const { return entity.impl().ilevelend(); } //*************************************************************** // Interface for Adaptation //*************************************************************** /** \brief Marks an entity to be refined/coarsened in a subsequent adapt. \param[in] refCount Number of subdivisions that should be applied. Negative value means coarsening. \param[in] e Entity to Entity that should be refined \return true if Entity was marked, false otherwise. \note - \b default \b implementation is: return false; for grids with no adaptation. - for the grid programmer: this method is implemented as a template method, because the Entity type is not defined when the class is instantiated You won't need this trick in the implementation. In your implementation you should use it as \code bool mark( int refCount, typename Traits::template Codim<0>::Entity & e ). \endcode This template method will vanish due to the inheritance rules. */ bool mark( int /*refCount*/, const typename Traits :: template Codim<0>::Entity & /*e*/ ) { return false; } /** \brief returns adaptation mark for given entity, i.e. here the * default implementation returns 0. \param[in] e Entity for which adaptation mark should be determined \return int adaptation mark, here the default value 0 is returned */ int getMark ( const typename Traits::template Codim< 0 >::Entity& /*e*/ ) const { return 0; } /** \brief Refine all positive marked leaf entities coarsen all negative marked entities if possible \return true if a least one entity was refined \note this default implementation always returns false so grid with no adaptation doesn't need to implement these methods */ bool adapt () { return false; } //! returns true, if at least one entity is marked for adaption bool preAdapt () { return false; } //! clean up some markers void postAdapt() {} /*! \brief default implementation of load balance does nothing and returns false */ bool loadBalance() { return false; } /*! \brief default implementation of load balance does nothing and returns false */ template bool loadBalance ([[maybe_unused]] DataHandle& data) { return false; } protected: using Grid< dim, dimworld, ct, GridFamily >::asImp; }; /** @} */ /** \brief A traits struct that collects all associated types of one grid model @ingroup GIMiscellaneous \tparam dim Grid dimension \tparam dimw Dimension of the world that the grid is embedded in \tparam GIDType Type used for global ids \tparam LIDType Type used for local ids \tparam CCType Communication implementation class */ template class GeometryImp, template class EntityImp, template class LevelIteratorImp, template class LeafIntersectionImp, template class LevelIntersectionImp, template class LeafIntersectionIteratorImp, template class LevelIntersectionIteratorImp, template class HierarchicIteratorImp, template class LeafIteratorImp, class LevelIndexSetImp, class LeafIndexSetImp, class GlobalIdSetImp, class GIDType, class LocalIdSetImp, class LIDType, class CCType, template class LevelGridViewTraits, template class LeafGridViewTraits, template class EntitySeedImp, template class LocalGeometryImp = GeometryImp, class LevelIndexType = unsigned int, class LevelGeometryTypes = std::vector, class LeafIndexType = LevelIndexType, class LeafGeometryTypes = LevelGeometryTypes > struct GridTraits { /** \brief The type that implements the grid. */ typedef GridImp Grid; /** \brief The type of the intersection at the leafs of the grid. */ typedef Dune::Intersection< const GridImp, LeafIntersectionImp< const GridImp > > LeafIntersection; /** \brief The type of the intersection at the levels of the grid. */ typedef Dune::Intersection< const GridImp, LevelIntersectionImp< const GridImp > > LevelIntersection; /** \brief The type of the intersection iterator at the leafs of the grid. */ typedef Dune::IntersectionIterator< const GridImp, LeafIntersectionIteratorImp< const GridImp >, LeafIntersectionImp< const GridImp > > LeafIntersectionIterator; /** \brief The type of the intersection iterator at the levels of the grid. */ typedef Dune::IntersectionIterator< const GridImp, LevelIntersectionIteratorImp< const GridImp >, LevelIntersectionImp< const GridImp > > LevelIntersectionIterator; /** \brief The type of the hierarchic iterator. */ typedef Dune::EntityIterator< 0, const GridImp, HierarchicIteratorImp< const GridImp > > HierarchicIterator; /** * \brief Traits associated with a specific codim. * \tparam cd The codimension. */ template struct Codim { public: typedef GeometryImp GeometryImpl; typedef LocalGeometryImp LocalGeometryImpl; //! IMPORTANT: Codim::Geometry == Geometry /** \brief The type of the geometry associated with the entity.*/ typedef Dune::Geometry Geometry; /** \brief The type of the local geometry associated with the entity.*/ typedef Dune::Geometry LocalGeometry; /** \brief The type of the entity. */ // we could - if needed - introduce another struct for dimglobal of Geometry typedef Dune::Entity Entity; /** \brief The type of the entity seed of this codim.*/ typedef Dune::EntitySeed > EntitySeed; /** * \brief Traits associated with a specific grid partition type. * \tparam pitype The type of the grid partition. */ template struct Partition { /** \brief The type of the iterator over the level entities of this codim on this partition. */ typedef Dune::EntityIterator< cd, const GridImp, LevelIteratorImp< cd, pitype, const GridImp > > LevelIterator; /** \brief The type of the iterator over the leaf entities of this codim on this partition. */ typedef Dune::EntityIterator< cd, const GridImp, LeafIteratorImp< cd, pitype, const GridImp > > LeafIterator; }; /** \brief The type of the iterator over all leaf entities of this codim. */ typedef typename Partition< All_Partition >::LeafIterator LeafIterator; /** \brief The type of the entity pointer for entities of this codim.*/ typedef typename Partition< All_Partition >::LevelIterator LevelIterator; private: friend class Dune::Entity; }; /** \brief type of view for leaf grid */ typedef Dune::GridView< LeafGridViewTraits< const GridImp > > LeafGridView; /** \brief type of view for level grid */ typedef Dune::GridView< LevelGridViewTraits< const GridImp > > LevelGridView; /** \brief The type of the level index set. */ typedef IndexSet LevelIndexSet; /** \brief The type of the leaf index set. */ typedef IndexSet LeafIndexSet; /** \brief The type of the global id set. */ typedef IdSet GlobalIdSet; /** \brief The type of the local id set. */ typedef IdSet LocalIdSet; /** \brief The type of the communication. */ typedef CCType Communication; }; // Definition of capabilities for the interface class namespace Capabilities { // capabilities for the interface class depend on the implementation template< int dim, int dimworld, typename ct, class GridFamily , int codim > struct hasEntity< Grid< dim, dimworld, ct, GridFamily >, codim > { static const bool v = hasEntity< typename GridFamily::Traits::Grid, codim >::v; }; // capabilities for the interface class depend on the implementation template< int dim, int dimworld, typename ct, class GridFamily , int cdim > struct hasEntity< GridDefaultImplementation, cdim > { typedef GridDefaultImplementation GridType; typedef typename GridType::Traits::Grid GridImp; static const bool v = hasEntity::v; }; } // end namespace Capabilities //! for creation of an engine interface object like Entity or Geometry //! one has to derive a class to create the object because the //! constructors of the interface object classes are protected //! therefore here a generic implementation for this object creation is //! provided template struct MakeableInterfaceObject : public InterfaceType { typedef typename InterfaceType::Implementation ImplementationType; //! create interface object by calling the constructor of the base class explicit MakeableInterfaceObject ( const ImplementationType &realImp ) : InterfaceType( realImp ) {} }; } #include "geometry.hh" #include "entity.hh" #include "intersection.hh" #include "intersectioniterator.hh" #include "entityiterator.hh" #include "indexidset.hh" #endif // #ifndef DUNE_GRID_COMMON_GRID_HH dune-grid-2.11.0/dune/grid/common/gridenums.hh000066400000000000000000000116731511655130300211470ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_GRIDENUMS_HH #define DUNE_GRID_COMMON_GRIDENUMS_HH #include #include namespace Dune { /** * \addtogroup gridpartitions Parallel Grid Partitions * \{ */ /** \brief Attributes used in the generic overlap model * \code #include \endcode * * The values are ordered intentionally in order to be able to * define ranges of partition types. * * @ingroup GIRelatedTypes */ enum PartitionType { InteriorEntity=0, //!< all interior entities BorderEntity=1 , //!< on boundary between interior and overlap OverlapEntity=2 , //!< all entities lying in the overlap zone FrontEntity=3 , //!< on boundary between overlap and ghost GhostEntity=4 //!< ghost entities }; /** \brief Provide names for the partition types * \code #include \endcode * * @ingroup GIRelatedTypes */ inline std::string PartitionName(PartitionType type) { switch(type) { case InteriorEntity : return "interior"; case BorderEntity : return "border"; case OverlapEntity : return "overlap"; case FrontEntity : return "front"; case GhostEntity : return "ghost"; default : DUNE_THROW(NotImplemented, "name of unknown partition type requested"); } } //! write a PartitionType to a stream /** \code #include \endcode * * @ingroup GIRelatedTypes */ inline std::ostream &operator<< ( std::ostream &out, const PartitionType &type ) { return out << PartitionName( type ); } /** \brief Parameter to be used for the communication functions * \code #include \endcode * * @ingroup GIRelatedTypes */ enum InterfaceType { InteriorBorder_InteriorBorder_Interface=0, //!< send/receive interior and border entities InteriorBorder_All_Interface=1, //!< send interior and border, receive all entities Overlap_OverlapFront_Interface=2, //!< send overlap, receive overlap and front entities Overlap_All_Interface=3, //!< send overlap, receive all entities All_All_Interface=4 //!< send all and receive all entities }; //! write an InterfaceType to a stream /** \code #include \endcode * * @ingroup GIRelatedTypes */ inline std::ostream &operator<< ( std::ostream &out, const InterfaceType &type ) { switch( type ) { case InteriorBorder_InteriorBorder_Interface : return out << "interior-border / interior-border interface"; case InteriorBorder_All_Interface : return out << "interior-border / all interface"; case Overlap_OverlapFront_Interface : return out << "overlap / overlap-front interface"; case Overlap_All_Interface : return out << "overlap / all interface"; case All_All_Interface : return out << "all / all interface"; default : return out << "unknown interface"; } } /** \brief Parameter to be used for the parallel level- and leaf iterators * \code #include \endcode * * @ingroup GIRelatedTypes */ enum PartitionIteratorType { Interior_Partition=0, //!< only interior entities InteriorBorder_Partition=1, //!< interior and border entities Overlap_Partition=2, //!< interior, border, and overlap entities OverlapFront_Partition=3, //!< interior, border, overlap and front entities All_Partition=4, //!< all entities Ghost_Partition=5 //!< only ghost entities }; //! write a PartitionIteratorType to a stream /** \code #include \endcode * * @ingroup GIRelatedTypes */ inline std::ostream &operator<< ( std::ostream &out, const PartitionIteratorType &type ) { static std::string name[ 6 ] = { "interior partition", "interior-border partition", "overlap partition", "overlap-front partition", "all partition", "ghost partition" }; return out << name[ type ]; } /** \brief Define a type for communication direction parameter * \code #include \endcode * * @ingroup GIRelatedTypes */ enum CommunicationDirection { ForwardCommunication, //!< communicate as given in InterfaceType BackwardCommunication //!< reverse communication direction }; /** * \} */ } #endif dune-grid-2.11.0/dune/grid/common/gridfactory.hh000066400000000000000000000314201511655130300214570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_GRIDFACTORY_HH #define DUNE_GRID_COMMON_GRIDFACTORY_HH /** \file \brief Provide a generic factory class for unstructured grids. */ #include #include #include #include #include #include #include namespace Dune { /** \brief Provide a generic factory class for unstructured grids. * * \ingroup GridFactory * * This base class declares the interface. * * Example use: create a grid consisting of a cube triangulated into 6 * tetrahedra: * \image html cube-to-tet-6.png "Left: cube with vertex numbers. Middle: cube triangulated into six tetrahedra. Right: exploded version of the middle figure, with number for the tetrahedra." \code Dune::GridFactory factory; factory.insertVertex({0, 0, 0}); factory.insertVertex({1, 0, 0}); factory.insertVertex({0, 1, 0}); factory.insertVertex({1, 1, 0}); factory.insertVertex({0, 0, 1}); factory.insertVertex({1, 0, 1}); factory.insertVertex({0, 1, 1}); factory.insertVertex({1, 1, 1}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 1, 3, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 5, 1, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 4, 5, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 6, 4, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 2, 6, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 3, 2, 7}); std::shared_ptr gridp(factory.createGrid()); \endcode * Make sure that the inserted elements are not inverted, since not all * grids support that. For instance, in the following code snippet the * elements 1, 3 and 5 are inverted while elements 0, 2 and 4 are not. \code factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 1, 3, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 1, 5, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 4, 5, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 4, 6, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 2, 6, 7}); factory.insertElement(Dune::GeometryTypes::tetrahedron, {0, 2, 3, 7}); \endcode */ template class GridFactoryInterface { protected: /** \brief dimension of the grid */ static const int dimension = GridType::dimension; /** \brief The grid world dimension */ constexpr static int dimworld = GridType::dimensionworld; /** \brief Type used by the grid for coordinates */ typedef typename GridType::ctype ctype; public: template< int codim > struct Codim { typedef typename GridType::template Codim< codim >::Entity Entity; }; /** \brief Default constructor */ GridFactoryInterface() {} /** \brief virtual destructor */ virtual ~GridFactoryInterface () {} /** \brief Insert a vertex into the coarse grid */ virtual void insertVertex(const FieldVector& pos) = 0; /** \brief Insert an element into the coarse grid \param type The GeometryType of the new element \param vertices The vertices of the new element, using the DUNE numbering Make sure the inserted element is not inverted (this holds even for simplices). There are grids that can't handle inverted elements. */ virtual void insertElement(const GeometryType& type, const std::vector& vertices) = 0; /** \brief Insert a parametrized element into the coarse grid \param type The GeometryType of the new element \param vertices The vertices of the new element, using the DUNE numbering \param elementParametrization A function prescribing the shape of this element Make sure the inserted element is not inverted (this holds even for simplices). There are grids that can't handle inverted elements. */ virtual void insertElement(const GeometryType& /*type*/, const std::vector& /*vertices*/, std::function (FieldVector)> /*elementParametrization*/) { DUNE_THROW(GridError, "There is no grid factory for this grid type!"); } /** \brief insert a boundary segment * * This method inserts a boundary segment into the coarse grid. Using * this method has two advantages over not using it: * - The boundary segment gets an insertion index. * - The grid factory can verify that this is actually a boundary segment * . * * \note You are not forced to insert all boundary segments. The grid * factory will find the remaining boundary segments itself. * * \param[in] vertices the indices of the vertices of the segment */ virtual void insertBoundarySegment(const std::vector& vertices) = 0; /** \brief insert an arbitrarily shaped boundary segment * * This method inserts a boundary segment into the coarse grid. * * \param[in] vertices the indices of the vertices of the segment * \param[in] boundarySegment user defined implementation of the boundary segment's geometry */ virtual void insertBoundarySegment([[maybe_unused]] const std::vector& vertices, [[maybe_unused]] const std::shared_ptr >& boundarySegment) { DUNE_THROW(GridError, "This grid does not support parametrized boundary segments!"); } /** \brief Finalize grid creation and hand over the grid The receiver takes responsibility of the memory allocated for the grid */ virtual std::unique_ptr createGrid() = 0; /** \brief obtain an element's insertion index * * Data can be associated to the created macro grid using the insertion * index of each entity that has been inserted during the grid creation * process. * * Between grid construction (createGrid) and the first grid * modification, this method allows to obtain this insertion index from * the grid factory. This way, data can be stored using the index maps * provided by the grid. * * \param[in] entity entity whose insertion index is requested * * \returns insertion index of the entity */ virtual unsigned int insertionIndex ( [[maybe_unused]] const typename Codim< 0 >::Entity &entity ) const { DUNE_THROW( NotImplemented, "insertion indices have not yet been implemented." ); } /** \brief obtain a vertex' insertion index * * Data can be associated to the created macro grid using the insertion * index of each entity that has been inserted during the grid creation * process. * * Between grid construction (createGrid) and the first grid * modification, this method allows to obtain this insertion index from * the grid factory. This way, data can be stored using the index maps * provided by the grid. * * \param[in] entity entity whose insertion index is requested * * \returns insertion index of the entity */ virtual unsigned int insertionIndex ( [[maybe_unused]] const typename Codim< dimension >::Entity &entity ) const { DUNE_THROW( NotImplemented, "insertion indices have not yet been implemented." ); } /** \brief obtain a boundary's insertion index * * Data can be associated to the created macro grid using the insertion * index of each entity that has been inserted during the grid creation * process. * * Between grid construction (createGrid) and the first grid * modification, this method allows to obtain this insertion index from * the grid factory. This way, data can be stored using the index maps * provided by the grid. * * \param[in] intersection intersection whose insertion index is requested * * \returns insertion index of the intersection * * \note The insertion index can only be obtained for boundary * intersections that were actually inserted * (see also wasInserted). */ virtual unsigned int insertionIndex ( [[maybe_unused]] const typename GridType::LeafIntersection &intersection ) const { DUNE_THROW( NotImplemented, "insertion indices have not yet been implemented." ); } /** \brief determine whether an intersection was inserted * * This method allows checking whether an intersection was actually * inserted into the grid factory. * * \note Not all boundary segments need to be inserted into the grid * factory. * \note This method returns \b false for all interior intersections * * \param[in] intersection intersection in question * * \returns \b true, if the intersection was inserted */ virtual bool wasInserted ( [[maybe_unused]] const typename GridType::LeafIntersection &intersection ) const { DUNE_THROW( NotImplemented, "insertion indices have not yet been implemented." ); } using Communication = Dune::Communication; /** \brief Return the Communication used by the grid factory * * Defaults to the Communication induced by the process-local communicator. */ Communication comm() const { return Communication(MPIHelper::getLocalCommunicator()); } }; /** \brief Provide a generic factory class for unstructured grids. \ingroup GridFactory This is the unspecialized class, which does nothing. All work is done in the specializations for the different grid types. See GridFactoryInterface for an example how to use this class. */ template class GridFactory : public GridFactoryInterface { typedef GridFactoryInterface Base; /** \brief The grid world dimension */ constexpr static int dimworld = GridType::dimensionworld; /** \brief Type used by the grid for coordinates */ typedef typename GridType::ctype ctype; public: // use default implementation from base class using Base::insertBoundarySegment; /** \brief Default constructor */ GridFactory() { DUNE_THROW(GridError, "There is no grid factory for this grid type!"); } /** \brief Insert a vertex into the coarse grid */ virtual void insertVertex([[maybe_unused]] const FieldVector& pos) { DUNE_THROW(GridError, "There is no grid factory for this grid type!"); } /** \brief Insert an element into the coarse grid \param type The GeometryType of the new element \param vertices The vertices of the new element, using the DUNE numbering Make sure the inserted element is not inverted (this holds even for simplices). There are grids that can't handle inverted tets. */ virtual void insertElement([[maybe_unused]] const GeometryType& type, [[maybe_unused]] const std::vector& vertices) { DUNE_THROW(GridError, "There is no grid factory for this grid type!"); } /** \brief insert a boundary segment * * This method inserts a boundary segment into the coarse grid. Using * this method has two advantages over not using it: * - The boundary segment gets an insertion index. * - The grid factory can verify that this is actually a boundary segment * . * * \note You are not forced to insert all boundary segments. The grid * factory will find the remaining boundary segments itself. * * \param[in] vertices the indices of the vertices of the segment */ virtual void insertBoundarySegment([[maybe_unused]] const std::vector& vertices) { DUNE_THROW(GridError, "There is no grid factory for this grid type!"); } /** \brief Finalize grid creation and hand over the grid The receiver takes responsibility of the memory allocated for the grid */ virtual std::unique_ptr createGrid() { DUNE_THROW(GridError, "There is no grid factory for this grid type!"); } }; } #endif dune-grid-2.11.0/dune/grid/common/gridinfo.hh000066400000000000000000000157651511655130300207610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_GRIDINFO_HH #define DUNE_GRID_COMMON_GRIDINFO_HH #include #include #include #include #include #include "grid.hh" /** @file * @author Peter Bastian * @brief Some functions to list information about a grid * */ namespace Dune { /** * @addtogroup Grid * * @{ */ /** @brief A function to print some information about the grid as a whole. */ template void gridinfo (const G& grid, std::string prefix="") { // first we extract the dimensions of the grid const int dim = G::dimension; const int dimworld = G::dimensionworld; // grid type and dimension std::cout << prefix << "=> " << className(grid) << " (dim=" << dim << ", dimworld=" << dimworld << ")" << std::endl; // level information for (int level=0; level<=grid.maxLevel(); level++) { std::cout << prefix << "level " << level; for (int cd=0; cd<=dim; cd++) { std::cout << " codim[" << cd << "]=" << grid.size(level,cd); } std::cout << std::endl; } // leaf information std::cout << prefix << "leaf "; for (int cd=0; cd<=dim; cd++) { std::cout << " codim[" << cd << "]=" << grid.size(cd); } std::cout << std::endl; std::cout << prefix << "leaf" << " dim=" << dim << " types=("; bool first=true; for (int c=0; c<=dim; c++) { for (std::size_t i=0; i void gridlevellist (const G& grid, int level, std::string prefix) { // first we extract the dimensions of the grid const int dim = G::dimension; // type used for coordinates in the grid typedef typename G::ctype ct; // print info about this level std::cout << prefix << "level=" << level << " dim=" << dim << " types=("; bool first=true; for (unsigned i=0; i::general(element.type()).position(0,0)) << ")" << " first=(" << geometry.corner(0) << ")" << std::endl; std::cout << prefix << "codim " << dim << " subindex"; for (unsigned int i=0; i < element.subEntities(dim); i++) { std::cout << " " << i << ":" << grid.levelIndexSet(level).subIndex(element,i,dim); } std::cout << std::endl; std::cout << prefix << "codim " << dim-1 << " subindex"; for (unsigned int i=0; i < element.subEntities(dim-1); i++) { std::cout << " " << i << ":" << grid.levelIndexSet(level).subIndex(element,i,dim-1); } std::cout << std::endl; } } /** @brief A function to print info about a leaf grid and its entities */ template void gridleaflist (const G& grid, std::string prefix) { // first we extract the dimensions of the grid const int dim = G::dimension; // type used for coordinates in the grid typedef typename G::ctype ct; // print info about the leaf grid std::cout << prefix << "leaf" << " dim=" << dim << " types=("; bool first=true; for (int c=0; c<=dim; c++) { for (unsigned i=0; i::general(element.type()).position(0,0)) << ")" << " first=(" << geometry.corner(0) << ")" << std::endl; std::cout << prefix << "codim " << dim << " subindex"; for (unsigned int i=0; i < element.subEntities(dim); i++) { std::cout << " " << i << ":" << grid.leafIndexSet().subIndex(element,i,dim); } std::cout << std::endl; std::cout << prefix << "codim " << dim-1 << " subindex"; for (unsigned int i=0; i < element.subEntities(dim-1); i++) { std::cout << " " << i << ":" << grid.leafIndexSet().subIndex(element,i,dim-1); } std::cout << std::endl; } } /** @} */ } #endif dune-grid-2.11.0/dune/grid/common/gridview.hh000066400000000000000000000264041511655130300207700ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_GRIDVIEW_HH #define DUNE_GRID_COMMON_GRIDVIEW_HH #include #include #include #include #include #include #include namespace Dune { template< int, int, class, class > class GridDefaultImplementation; /** \addtogroup GIGridView * @{ * Though a DUNE grid is hierarchic, one often only needs access to * a certain subset of the entities in the grid, e.g., all entities * on a given level or the leaf entities in the hierarchy. * These views are provided by an * implementation of GridView. Each grid exports a LevelGridView and * a LeafGridView, corresponding to the two different subsets (views) * described above. * * A grid view provides the following functionality: * - The index set for the required subset can be accessed by the indexSet() * method. * - A pair of begin() / end() methods provide iterators for each * codimension. * - A pair of ibegin() / iend() methods return suitable intersection * iterators for a given entity of codimension 0 in the subset. * - For parallel computations, a suitable communicate() method is provided. * - The underlying grid can be accessed through the grid() method. * . * * The default GridViews can be obtained from the grid by calling one of the * levelGridView() or leafGridView() methods which are provided as both * free functions and member functions of the Grid interface class. */ /** \brief Grid view abstract base class * * Interface class for a view on grids. Grids return two types of view, * a view of the leaf grid and of a level grid, which both satisfy * the same interface. Through the view the user has access to the * iterators, the intersections and the index set. * * The interface is implemented using the engine concept. * */ template< class ViewTraits > class GridView { typedef GridView< ViewTraits > ThisType; public: /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef typename ViewTraits :: GridViewImp Implementation; typedef typename ViewTraits :: GridViewImp GridViewImp; /** \brief Traits class */ typedef ViewTraits Traits; /** \brief type of the grid */ typedef typename Traits :: Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /*! \brief A type that is a model of Dune::Communication. It provides a portable way for communication on the set of processes used by the grid. */ using Communication = typename Traits :: Communication; /** \brief A struct that collects all associated types of one implementation from the Traits class. */ template< int cd > struct Codim { /** \brief type of iterator returned by the grid view */ typedef typename Traits :: template Codim :: Iterator Iterator; /** \brief type of corresponding entity */ typedef typename Traits :: template Codim :: Entity Entity; /** \brief type of the geometry implementation */ typedef typename Traits :: template Codim :: Geometry Geometry; /** \brief type of the implementation for local geometries */ typedef typename Traits :: template Codim :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template< PartitionIteratorType pit > struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Traits :: template Codim< cd > :: template Partition< pit > :: Iterator Iterator; }; }; //: public Traits :: template Codim {}; /** \brief Export if this grid view is guaranteed conforming */ constexpr static bool conforming = Traits :: conforming; /** \brief type used for coordinates in grid */ typedef typename Grid::ctype ctype; //! \brief The dimension of the grid constexpr static int dimension = Grid :: dimension; //! \brief The dimension of the world the grid lives in constexpr static int dimensionworld = Grid :: dimensionworld; public: //=========================================================== /** @name Interface for the implementor */ //@{ //=========================================================== /** \brief constructor (engine concept) */ GridView ( const Implementation &imp ) : impl_( imp ) {} //@} /** \brief Copy constructor */ GridView ( const ThisType &other ) : impl_( other.impl_ ) {} /** \brief assignment operator */ ThisType &operator= ( const ThisType &other ) { impl_ = other.impl_; return *this; } public: /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { return impl().grid(); } /** \brief obtain the index set * * The lifetime of the returned index set is bound to the lifetime of the * grid view. Keep a copy of the grid view to prevent the index set from * becoming a dangling reference. */ const IndexSet &indexSet () const { return impl().indexSet(); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return impl().size( codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return impl().size( type ); } private: template using HasIsConformingMethod = decltype(std::declval().isConforming()); public: /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming () const { // if implementation provides a method isConforming, call it if constexpr (Std::is_detected_v) { return impl().isConforming(); } else { // otherwise default to static conforming flag return bool(conforming); } } /** @brief Return true if the given entity is contained in this grid view * @todo Currently we call the implementation on the IndexSet. This may lead to suboptimal efficiency. * * \note If the input element e is not an element of the grid, then * the result of contains() is undefined. */ template bool contains (const EntityType& e) const { return impl().indexSet().contains(e); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { return impl().template begin(); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return impl().template end(); } /** \brief obtain begin iterator for this view */ template< int cd , PartitionIteratorType pitype > typename Codim< cd > :: template Partition< pitype > :: Iterator begin () const { return impl().template begin(); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pitype > typename Codim< cd > :: template Partition< pitype > :: Iterator end () const { return impl().template end(); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return impl().ibegin(entity); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return impl().iend(entity); } /** \brief obtain communication object */ const Communication &comm () const { return impl().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize(int codim) const { return impl().overlapSize(codim); } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize(int codim) const { return impl().ghostSize(codim); } /** \brief Communicate data on this view */ template< class DataHandleImp, class DataType > auto communicate ( CommDataHandleIF< DataHandleImp, DataType > &data, InterfaceType iftype, CommunicationDirection dir ) const { typedef decltype( impl().communicate(data,iftype,dir) ) CommFuture; return communicate( data,iftype, dir, std::integral_constant< bool, std::is_same< CommFuture, void > :: value >() ); } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation &impl () { return impl_; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation &impl () const { return impl_; } protected: /** \brief Communicate data on this view */ template< class DataHandleImp, class DataType > auto communicate ( CommDataHandleIF< DataHandleImp, DataType > &data, InterfaceType iftype, CommunicationDirection dir, std::integral_constant< bool, false > ) const { return impl().communicate(data,iftype,dir); } struct DeprecatedMethodEmptyFuture : public Future { void printMessage() const { std::cerr << "WARNING: GridView::communicate of '" << typeid( Implementation ).name() << "' still returns void. Please update implementation to new interface returning a future object!" << std::endl; } bool ready () { printMessage(); return true; } void wait () { printMessage(); } bool valid () const { printMessage(); return true; } }; /** \brief Communicate data on this view */ template< class DataHandleImp, class DataType > auto communicate ( CommDataHandleIF< DataHandleImp, DataType > &data, InterfaceType iftype, CommunicationDirection dir, std::integral_constant< bool, true > ) const { impl().communicate(data,iftype,dir); return DeprecatedMethodEmptyFuture(); } Implementation impl_; }; } // namespace Dune #endif // #ifndef DUNE_GRID_COMMON_GRIDVIEW_HH dune-grid-2.11.0/dune/grid/common/idlocalref.eps000066400000000000000000000126311511655130300214410ustar00rootroot00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: idlocalref.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 %%CreationDate: Wed Mar 15 13:45:45 2006 %%BoundingBox: 0 0 512 82 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 82 moveto 0 0 lineto 512 0 lineto 512 82 lineto closepath clip newpath -98.7 304.7 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /DrawEllipse { /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc closepath savematrix setmatrix } def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Ellipse 7.500 slw n 4770 4455 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 7830 4455 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 1665 4455 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 4770 3870 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 6345 3870 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 7830 3870 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse 15.000 slw n 4747 4162 608 608 0 360 DrawEllipse gs col4 s gr % Ellipse n 7847 4215 608 608 0 360 DrawEllipse gs col4 s gr % Polyline 0 slj 0 slc 7.500 slw n 1845 4410 m 4545 4410 l 4545 4455 l 1845 4455 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline n 4950 4410 m 7650 4410 l 7650 4455 l 4950 4455 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline n 4995 3870 m 6075 3870 l 6075 3915 l 4995 3915 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline n 6570 3870 m 7650 3870 l 7650 3915 l 6570 3915 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline gs clippath 4800 4203 m 4800 4035 l 4740 4035 l 4740 4203 l 4740 4203 l 4770 4083 l 4800 4203 l cp eoclip n 4770 4320 m 4770 4050 l gs col0 s gr gr % arrowhead n 4800 4203 m 4770 4083 l 4740 4203 l col0 s % Polyline gs clippath 7860 4158 m 7860 3990 l 7800 3990 l 7800 4158 l 7800 4158 l 7830 4038 l 7860 4158 l cp eoclip n 7830 4320 m 7830 4005 l gs col0 s gr gr % arrowhead n 7860 4158 m 7830 4038 l 7800 4158 l col0 s % Polyline gs clippath 5773 4008 m 5626 3926 l 5597 3978 l 5743 4060 l 5743 4060 l 5654 3976 l 5773 4008 l cp eoclip n 6345 4365 m 5625 3960 l gs col0 s gr gr % arrowhead n 5773 4008 m 5654 3976 l 5743 4060 l col0 s % Polyline gs clippath 6907 4068 m 7048 3977 l 7016 3926 l 6874 4017 l 6874 4017 l 6992 3978 l 6907 4068 l cp eoclip n 6390 4365 m 7020 3960 l gs col0 s gr gr % arrowhead n 6907 4068 m 6992 3978 l 6874 4017 l col0 s /Times-Roman ff 285.75 scf sf 6255 4680 m gs 1 -1 sc (b) col0 sh gr /Times-Roman ff 285.75 scf sf 3060 4680 m gs 1 -1 sc (a) col0 sh gr /Times-Roman ff 285.75 scf sf 5445 3690 m gs 1 -1 sc (c) col0 sh gr /Times-Roman ff 285.75 scf sf 8685 3960 m gs 1 -1 sc (level i+1) col0 sh gr /Times-Roman ff 285.75 scf sf 8685 4545 m gs 1 -1 sc (level i) col0 sh gr /Times-Roman ff 190.50 scf sf 4545 4635 m gs 1 -1 sc (v) col0 sh gr /Times-Roman ff 190.50 scf sf 4500 4005 m gs 1 -1 sc (w) col0 sh gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF dune-grid-2.11.0/dune/grid/common/idlocalref.eps.license000066400000000000000000000002501511655130300230540ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/idlocalref.fig000066400000000000000000000033331511655130300214160ustar00rootroot00000000000000#FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4770 4455 90 90 4770 4455 4860 4455 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 7830 4455 90 90 7830 4455 7920 4455 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 1665 4455 90 90 1665 4455 1755 4455 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4770 3870 90 90 4770 3870 4860 3870 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 6345 3870 90 90 6345 3870 6435 3870 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 7830 3870 90 90 7830 3870 7920 3870 1 4 0 2 4 7 50 -1 -1 0.000 1 0.0000 4747 4162 608 608 4139 4162 5355 4162 1 4 0 2 4 7 50 -1 -1 0.000 1 0.0000 7847 4215 608 608 7239 4215 8455 4215 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 1845 4410 4545 4410 4545 4455 1845 4455 1845 4410 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 4950 4410 7650 4410 7650 4455 4950 4455 4950 4410 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 4995 3870 6075 3870 6075 3915 4995 3915 4995 3870 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 6570 3870 7650 3870 7650 3915 6570 3915 6570 3870 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4770 4320 4770 4050 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7830 4320 7830 4005 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 6345 4365 5625 3960 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 6390 4365 7020 3960 4 0 0 50 -1 0 18 0.0000 2 195 135 6255 4680 b\001 4 0 0 50 -1 0 18 0.0000 2 135 135 3060 4680 a\001 4 0 0 50 -1 0 18 0.0000 2 135 120 5445 3690 c\001 4 0 0 50 -1 0 18 0.0000 2 195 960 8685 3960 level i+1\001 4 0 0 50 -1 0 18 0.0000 2 195 675 8685 4545 level i\001 4 0 0 50 -1 0 12 0.0000 2 90 105 4545 4635 v\001 4 0 0 50 -1 0 12 0.0000 2 90 135 4500 4005 w\001 dune-grid-2.11.0/dune/grid/common/idlocalref.fig.license000066400000000000000000000002501511655130300230320ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/idlocalref.png000066400000000000000000000054141511655130300214370ustar00rootroot00000000000000PNG  IHDR8[h| pHYs M MέNtEXtSoftwareESP Ghostscript 815.03qIDATxۖ a3 ;,"PEUW35r|u]k>eY 'e}ޖIoE 0e=fU#;$iN0oj$УtNھ4g :zT %Mxw̆HG1HێnV `l=m:EƟvixb}|D~( Y%:~F A>N':\-eU +\šw A\\pqHN9 *ܑ:uhav<Thy=ezTxI\VӿEWݝ1LJJe~^I_µ^.o'PE6Xý,˨39pJUavz[Ͱ{]>zuB1 (?^oɪlV%ʇ._X:#6ӥ,o?Qw/%=*O{ Ntl8N[U/*%]Tb+SW*AP^ #k*dmu ؑb'N5]⊎" Z&,v/ frqj#BTS(o$t|(MGĔ#Gx(-hȜ|˺e^(cY,RVΞz>]/c[K˽Q@Q5pWҴK`t˚-čKhG W-\6~wEmV׏YS]*nVy_ܬZȴ̗m*&:핮#m7s"udy:b%4%cbtQzo>r1}_غj_7"ut{Y}Gܶ/|^B'V  V`fx)b 3.pYE o)8|0p@Q ڝ\g ΅Od.i0⟠?IENDB`PNG  IHDR8[h| pHYs M MέNtEXtSoftwareESP Ghostscript 815.03qsIDATx1 0ဗ~3 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ͨH3*Ҍ 4 ^S]]IENDB`dune-grid-2.11.0/dune/grid/common/idlocalref.png.license000066400000000000000000000002501511655130300230510ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/indexidset.hh000066400000000000000000000461141511655130300213100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_INDEXIDSET_HH #define DUNE_GRID_COMMON_INDEXIDSET_HH #include #include #include /** @file @author Peter Bastian @brief Provides base classes for index and id sets */ namespace Dune { #include /** @brief Index Set %Interface base class. This class template is used as a base class for all index set implementations. It uses the Barton-Nackman trick to ensure conformity to the interface. \tparam GridImp Type that is a model of Dune::Grid. \tparam IndexSetImp Type that is a model of Dune::IndexSet. \tparam IndexTypeImp The type used by IndexSetImp to store the indices \tparam TypesImp iterator range for all geometry types in domain

Overview

An index set provides a map \f[ m : E \to \mathbf{N}\f] where \f$E\f$ is a subset of the entities of a grid and \f$\mathbf{N}\f$ is the set of natural numbers (including 0). We define the subsets \f[ E_g^c = \{e\in E \ | \ \textrm{$e$ has codimension $c$ and geometry type $g$} \}.\f] The index map \f$m\f$ has the following properties: - It is unique within the subsets \f$E_g^c\f$, i.e. for any \f$e,e^\prime\in E_g^c\f$ we have \f$e\neq e^\prime \rightarrow m(e)\neq m(e^\prime)\f$. - It is consecutive and zero-starting within the subsets \f$E_g^c\f$, i.e. we have \f$0\leq m(e) < |E_g^c|\f$ for any \f$e\in E_g^c\f$. Index sets are used to assign user defined data (e.g. degrees of freedom of a discretization) to entities of the grid. For efficiency reasons the preferred data structure for user data is the array. In order to access the data from the entity, its index (with respect to an index set - there may be several) is evaluated and used as an index to an array (or some other container providing random access). Usually an index set is not used directly but a Mapper is used to compute the array index from the information supplied by an index set. It is important to note that the index assigned to an entity may change during grid modification (i.e. refinement or dynamic load balancing). The user is responsible for reorganizing the information stored in the external arrays appropriately. In order to do this the IdSet concept is supplied.

Level index

Index set where \f$E\f$ corresponds to all entities of a given grid level. All grid implementations provide level indices.

Leaf Index

Index set where \f$E\f$ corresponds to all entities of the leaf grid. All grid implementations provide a leaf index. @ingroup IndexIdSets */ template< class GridImp, class IndexSetImp, class IndexTypeImp, class TypesImp > class IndexSet { /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ typedef typename std::remove_const< GridImp >::type::Traits Traits; public: /** \brief Export the type of the entity used as parameter in the index(...) method */ template struct Codim { typedef typename Traits :: template Codim :: Entity Entity; }; /** \brief The type used for the indices */ typedef IndexTypeImp IndexType; /** \brief iterator range for geometry types in domain */ typedef TypesImp Types; /** \brief dimension of the grid (maximum allowed codimension) */ static const int dimension = std::remove_const< GridImp >::type::dimension; //=========================================================== /** @name Index access from entity */ //@{ //=========================================================== /** @brief Map entity to index. The result of calling this method with an entity that is not in the index set is undefined. \param e Reference to codim cc entity, where cc is the template parameter of the function. \return An index in the range 0 ... Max number of entities in set - 1. */ template IndexType index (const typename Traits::template Codim::Entity& e) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().template index(e))); return asImp().template index(e); } /** @brief Map entity to index. Easier to use than the above because codimension template parameter need not be supplied explicitly. The result of calling this method with an entity that is not in the index set is undefined. \param e Reference to codim cc entity. Since entity knows its codimension, automatic extraction is possible. \return An index in the range 0 ... Max number of entities in set - 1. */ template IndexType index (const Entity& e) const { constexpr static int cc = Entity::codimension; CHECK_INTERFACE_IMPLEMENTATION((asImp().template index(e))); return asImp().template index(e); } /** \brief Map a subentity to an index. * * The result of calling this method with an entity that is not in the * index set is undefined. * * \tparam cc codimension of the entity * * \param[in] e reference to codimension cc entity * \param[in] i number subentity of e within the codimension * \param[in] codim codimension of the subentity we're interested in * * \note The parameter codim denotes the codimension with respect * to the grid, i.e., it must satisfy cc <= codim <= dimension. * * \return An index in the range 0 ... Max number of entities in set - 1. */ template< int cc > IndexType subIndex ( const typename Traits::template Codim< cc >::Entity &e, int i, unsigned int codim ) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().template subIndex< cc >(e,i,codim))); return asImp().template subIndex< cc >(e,i,codim); } /** \brief Map a subentity to an index. * * The result of calling this method with an entity that is not in the * index set is undefined. * * \note This method exists for convenience only. * It extracts the codimension from the type of the entity, which can * be guessed by the compiler. * * \tparam Entity type of entity (must be GridImp::Codim< cc >::Entity * for some cc) * * \param[in] e reference to entity * \param[in] i number subentity of e within the codimension * \param[in] codim codimension of the subentity we're interested in * * \note The parameter codim denotes the codimension with respect * to the grid, i.e., it must satisfy cc <= codim <= dimension. * * \return An index in the range 0 ... Max number of entities in set - 1. */ template< class Entity > IndexType subIndex ( const Entity &e, int i, unsigned int codim ) const { static const int cc = Entity::codimension; return asImp().template subIndex< cc >( e, i, codim ); } //@} //=========================================================== /** @name Access to entity set */ //@{ //=========================================================== /** * \brief obtain all geometry types of entities in domain * * This method returns an iterator range (something that behaves like * Dune::IteratorRange) visiting all geometry types of codimension codim * in the domain of the index map exactly once. * The iterator must implement the concept of a forward iterator (in the * sense of the STL). * The elements in the iterator range are required to be of type * Dune::GeometryType. * * \param[in] codim a valid codimension * * \return iterator range over Const reference to a vector of geometry types. */ Types types ( int codim ) const { CHECK_INTERFACE_IMPLEMENTATION( (asImp().types( codim )) ); return asImp().types( codim ); } /** @brief Return total number of entities of given geometry type in entity set \f$E\f$. \param[in] type A valid geometry type. \return number of entities (type is auto determined by the implementation. std::size_t is the expected return type). */ auto size (GeometryType type) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().size(type))); return asImp().size(type); } /** @brief Return total number of entities of given codim in the entity set \f$E\f$. This is simply a sum over all geometry types. \param[in] codim A valid codimension \return number of entities (type is auto determined by the implementation. std::size_t is the expected return type). */ auto size (int codim) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().size(codim))); return asImp().size(codim); } /** @brief Return true if the given entity is contained in \f$E\f$. * * \note If the input element e is not an element of the grid, then * the result of contains() is undefined. */ template bool contains (const Entity& e) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().contains(e))); return asImp().contains(e); } protected: // Must be explicitly defined although this class should get a default constructor. IndexSet() = default; public: //! Forbid the copy constructor IndexSet(const IndexSet&) = delete; //! Forbid the assignment operator IndexSet& operator=(const IndexSet&) = delete; private: //! Barton-Nackman trick IndexSetImp& asImp () {return static_cast (*this);} //! Barton-Nackman trick const IndexSetImp& asImp () const {return static_cast(*this);} }; #undef CHECK_INTERFACE_IMPLEMENTATION #undef CHECK_AND_CALL_INTERFACE_IMPLEMENTATION /**\brief Provide default implementation of method if IndexSet @ingroup GridDevel */ template class IndexSetDefaultImplementation : public IndexSet< GridImp, IndexSetImp > { typedef IndexSet< GridImp, IndexSetImp > Base; typedef typename std::remove_const< GridImp >::type::Traits Traits; public: /** \brief The type used for the indices */ typedef typename Base::IndexType IndexType; typedef typename Base::Types Types; /** \brief dimension of the grid (maximum allowed codimension) */ static const int dimension = Base::dimension; using Base::index; using Base::subIndex; //=========================================================== /** @name Access to entity set */ //@{ //=========================================================== Types types ( int codim ) const { return asImp().geomTypes( codim ); } /** @brief Return total number of entities of given codim in the entity set \f$E\f$. This is simply a sum over all geometry types. \param[in] codim A valid codimension \return number of entities (type is auto determined by the implementation. std::size_t is the expected return type). */ auto size ( const int codim ) const { using SizeType = std::decay_t; SizeType s ( 0 ); for(GeometryType gt : types(codim)) s += Base::size(gt); return s; } //@{ private: IndexSetImp &asImp () { return static_cast< IndexSetImp & >( *this );} const IndexSetImp &asImp () const { return static_cast< const IndexSetImp & >( *this ); } }; /** @brief Id Set %Interface. This class template is used as a base class for all id set implementations. It uses the Barton-Nackman trick to ensure conformity to the interface. \tparam GridImp Type that is a model of Dune::Grid. \tparam IdSetImp Type that is a model of Dune::IdSet. \tparam IdTypeImp Type used for ids

Overview

An id set provides a map \f[ m : E \to \mathbf{I}\f] where \f$E\f$ is a subset of the entities of a grid and \f$\mathbf{I}\f$ is a finite set of indices. These indices are persistent under grid modifications, i.e. if there exists an entity \f$e\f$ with index \f$i\f$ before grid modification and an entity \f$e^\prime\f$ with index \f$i\f$ after grid modification it is guaranteed that \f$e=e^\prime\f$. In the terminology of the Dune grid interface, these indices are called 'ids'. Ids are typically numbers, but may be other things, too. If they are numbers, the ids used in a grid are not necessarily positive, and they are usually not consecutive. However, the ids must be usable as keys for STL associative containers, like a std::map or a std::unordered_map. As ids are persistent, they are used to keep data on a grid that undergoes modifications.

Injectivity properties

The id map \f$m\f$ is injective on the entire set of entities of a hierarchical grid. More formally, we have: - For any \f$e,e^\prime\in E\f$ we have \f$e\neq e^\prime \Rightarrow m(e)\neq m(e^\prime)\f$. An exception to this rule holds for entities that are copies of entities on a lower refinement level. An element is a copy of its father element if it is the only son. This concept can be transferred to all higher codimensions because in a nested grid structure the entities of any codimension form a set of trees. However, the roots of these trees are not necessarily on level 0. Thus, we define that an entity is a copy of another entity if it is the only descendant of this entity in the refinement tree. This is illustrated in the following figure where, for example, vertex w is a copy of vertex v. \image html idlocalref.png "Sharing of ids." \image latex idlocalref.eps "Sharing of ids." width=\textwidth The copy relation is an equivalence relation. We define that all copies of an entity share the same id. In the example of the figure the vertices v and w would have the same id. This definition is useful to transfer data on the leaf grid during grid modification. Note: In "Bastian et al.: A Generic Grid Interface for Adaptive and Parallel Scientific Computing. Part I: Abstract Framework, Computing 82 (2-3), 2008, pp. 103-119" it is claimed that the id map should be injective only for entities of the same codimension. This is in contrast to the actual %Dune code: in the code, grid implementations are required to provide ids that are injective even on sets of entities with different codimensions.

Properties of the IdTypeImp type

The type IdTypeImp used for ids will be specified by the grid implementation. Conceptually, it can be pretty much anything, but we require that it is usable as key for the std::map and std::unordered_map containers of the standard library. In particular, for std::map this means that IdTypeImp implements \code bool operator< ( const IdTypeImp &, const IdTypeImp & ); \endcode and that this operator implements a strict weak ordering. For use with std::unordered_map, we additionally require \code bool operator== ( const IdTypeImp &, const IdTypeImp & ); \endcode and that std::hash fulfills the requirements of an stl hash object. For convenience we further require that \code bool operator!= ( const IdTypeImp &, const IdTypeImp & ); \endcode is implemented and returns the negation of operator==. The IdTypeImp must be
  • default-constructible
  • copy-constructible
  • copy-assignable
Finally, for debugging purposes it must be possible to write objects of type IdTypeImp into standard C++ streams. Therefore \code template< class C, class T > std::basic_ostream< C, T > &operator<< ( std::basic_ostream< C, T > &, const IdTypeImp & ); \endcode has to exist and do something reasonable.

Global and local id sets

Grids are required to provide two types of id sets. These differ only of the grid is distributed over several processes:
  • A global id set provides ids that are unique over all processes over which the grid is distributed.
  • A local id set provides ids that are unique within one process, but two entities in different processes may have the same id. Obviously, a global id set is also a local id set, but a dedicated local id set implementation may be more efficient.
@ingroup IndexIdSets */ template class IdSet { /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ using Traits = typename std::remove_const< GridImp >::type::Traits; public: //! Type used to represent an id. typedef IdTypeImp IdType; /** \brief Export the type of the entity used as parameter in the id(...) method */ template struct Codim { using Entity = typename Traits::template Codim::Entity; }; /** \brief dimension of the grid (maximum allowed codimension) */ static constexpr auto dimension = std::remove_const< GridImp >::type::dimension; //! Get id of an entity. This method is simpler to use than the one below. template IdType id (const Entity& e) const { constexpr static int cc = Entity::codimension; return asImp().template id(e); } //! Get id of an entity of codim cc. Unhandy because template parameter must be supplied explicitly. template IdType id (const typename Codim::Entity& e) const { return asImp().template id(e); } /** \brief Get id of subentity i of co-dimension codim of a co-dimension 0 entity. */ IdType subId (const typename Codim<0>::Entity& e, int i, unsigned int codim) const { return asImp().subId(e,i,codim); } protected: // Default constructor (is not provided automatically because copy constructor is private) IdSet() = default; public: //! Forbid the copy constructor IdSet(const IdSet&) = delete; //! Forbid the assignment operator IdSet& operator=(const IdSet&) = delete; private: //! Barton-Nackman trick IdSetImp& asImp () {return static_cast (*this);} //! Barton-Nackman trick const IdSetImp& asImp () const {return static_cast(*this);} }; } #endif // DUNE_GRID_COMMON_INDEXIDSET_HH dune-grid-2.11.0/dune/grid/common/intersection.hh000066400000000000000000000465071511655130300216640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_INTERSECTION_HH #define DUNE_GRID_COMMON_INTERSECTION_HH #include namespace Dune { /** \brief %Intersection of a mesh entity of codimension 0 ("element") with a "neighboring" element or with the domain boundary. \tparam GridImp Type that is a model of Dune::Grid \tparam IntersectionImp Class template that is a model of Dune::Intersection

Overview

Intersections are codimension 1 objects. These intersections are accessed via an Intersection. This allows the implementation of non-matching grids, as one facet can now consist of several intersections. In a conforming mesh such an intersection corresponds to an entity of codimension 1 but in the general non-conforming case there will be no entity in the mesh that directly corresponds to the intersection. Thus, the Intersection describes these intersections implicitly.

Engine Concept

The Intersection class template wraps an object of type IntersectionImp and forwards all member function calls to corresponding members of this class. In that sense Intersection defines the interface and IntersectionImp supplies the implementation.

Methods neighbor and boundary

The following holds for both the level and the leaf intersection : The %intersection is started on a codimension 0 entity of the grid. If this entity belongs to the interior or the overlap region (see. ???) then the union of all intersections is identical to the boundary of the entity. On ghost elements the only stops on the border of the domain, i.e., only on the intersections with entities in the interior region. Depending on the boolean values returned by the methods %boundary() and %neighbor() one can detect the position of an intersection relative to the boundary. In general the method boundary() returns true if and only if the intersection is part of the physical boundary of the domain. The method neighbor() returns true only if the method outside() has a well defined return value. The following cases are possible if the intersection is started on an entity in the interior or overlap region. More details are given below:
intersectionneighbor()boundary()outside()
1with inner, overlap
or ghost entity
truefalse the neighbor entity
2on domain boundary falsetrueundefined
3on periodic boundary truetrueGhost-/Overlap cell
(with transformed geometry)
4on processor boundary false if grid has no ghosts
true otherwise
false ghost entity (if it exists)
Inner Intersections:
The type of the neighboring entity can be determined through methods defined on the outside entity.
Handling physical boundaries:
Data (like the type of boundary) can be attached to physical boundaries either using global coordinates or the intersection's boundary segment index.
The boundary segment indices form a local, zero-based, contiguous set of integer values. Each boundary segment on the macro level is assigned a unique index from this set, which is inherited by child boundary segments. The size of the boundary segment index set (i.e., the number of boundary indices on the macro level) can be determined through the method Grid::numBoundarySegments.
Note that the boundary segment index is not persistent over dynamic load balancing. \if old_documentation Different types of physical boundaries can be modeled using either the global coordinates of the intersection or by using the boundaryID method. On some grids (dune-ALUGrid, AlbertaGrid) this method returns an integer value which can be individually assigned to each boundary intersection of the macro grid and which is prolonged to higher levels during grid refinement.
A more general concept will be included in latter releases along the following guidelines: - We require differently constructed geometries outside the domain - The kind of construction depends on the discrete problem - Therefore these constructions can't be part of the Grid interface - Utility classes are required to do this construction - The utility classes must be parameterized with the intersection (in our case the Intersection) - The utility classes return a suitable transformation of the inner() entity's geometry (with respect to the intersection), e.g., reflection at the intersection point reflection reflection combined with translation... . \endif
Handling periodic boundaries:
- The Intersection stops at periodic boundaries - periodic grids are handled in correspondence to parallel grids - %At the periodic boundary one can adjust an overlap- or ghost-layer. - outer() returns a ghost or overlap cell (for ghost and overlap look into the documentation of the parallel grid interface) - outer() cell has a periodically transformed geometry (so that one does not see a jump or something like that) - outer() cell has its own index - outer() cell has the same id as the corresponding "original" cell .
Processor boundaries:
At processor boundaries, i.e. when an element has an intersection with another element in the sequential grid but this element is only stored in other processors the intersection stops but neither neighbor() nor boundary() are true.

Geometry of an intersection

The method geometry returns a geometry mapping the intersection as a codim one structure to global coordinates. The methods geometryInInside and geometryInOutside return geometries mapping the intersection into the reference elements of the originating entity and the neighboring entity, respectively. The indexInInside and indexInOutside methods return the codim one subentities which contain the intersection. @ingroup GIIntersectionIterator */ template< class GridImp, class IntersectionImp > class Intersection { public: /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef IntersectionImp Implementation; /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation &impl () { return real; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation &impl () const { return real; } protected: Implementation real; public: /** \brief Type of entity that this Intersection belongs to */ typedef typename GridImp::template Codim<0>::Entity Entity; /** \brief Codim 1 geometry returned by geometry() */ typedef typename GridImp::template Codim<1>::Geometry Geometry; /** \brief Type for vectors of coordinates on the intersection */ typedef typename Geometry::LocalCoordinate LocalCoordinate; /** \brief Type for normal vectors */ typedef typename Geometry::GlobalCoordinate GlobalCoordinate; /** \brief Codim 1 geometry returned by geometryInInside() and geometryInOutside() */ typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; //! @brief dimension of the intersection constexpr static int mydimension = GridImp::dimension - 1; //! @brief dimension of world constexpr static int dimensionworld = GridImp::dimensionworld; //! Type of individual coefficients of coordinate vectors typedef typename GridImp::ctype ctype; //! Return true if intersection is with interior or exterior boundary (see the cases above) bool boundary () const { return this->real.boundary(); } /** \brief index of the boundary segment within the macro grid * * In many applications, special data needs to be attached to the boundary * segments of the macro grid (e.g., a function selecting the boundary * condition). * Usually, this data is inherited by the children of the boundary segment. * * In the DUNE framework, data is stored in arrays, addressed by an index, * in this case the boundarySegmentIndex. The size of these arrays can be * obtained by the Grid::numBoundarySegments method. * * The indices returned by this method are consecutive, zero based, and local to the * processor. Notice that these indices do not necessarily coincide with the insertion * indices of the corresponding boundary segments as provided by the GridFactory. */ size_t boundarySegmentIndex () const { return this->real.boundarySegmentIndex(); } //! @brief return true if intersection is shared with another element. bool neighbor () const { return this->real.neighbor(); } /*! @brief return Entity on the inside of this intersection. That is the Entity where we started this. */ Entity inside() const { return this->real.inside(); } /*! @brief return Entity on the outside of this intersection. That is the neighboring Entity. @warning Don't call this method if there is no neighboring Entity (neighbor() returns false). In this case the result is undefined. */ Entity outside() const { return this->real.outside(); } /** @brief Return true if intersection is conforming. * * The intersection is called conforming if it is conforming with respect * to all involved elements, i.e., it does geometrically coincide with the * indexInInside()'s facet of the inside() element and - if neighbor() is true- * with the indexInOutside()'s facet of the outside() element. */ bool conforming () const { return this->real.conforming(); } /** \brief geometrical information about this intersection in local * coordinates of the inside() entity. * * This method returns a Geometry object that provides a mapping from * local coordinates of the intersection to local coordinates of the * inside() entity. * * \note Previously, the geometry was encapsulated in the intersection object * and a const reference was returned. * * \note The returned geometry object is guaranteed to remain valid until the * grid is modified (or deleted). */ LocalGeometry geometryInInside () const { return this->real.geometryInInside(); } /** \brief geometrical information about this intersection in local * coordinates of the outside() entity. * * This method returns a Geometry object that provides a mapping from * local coordinates of the intersection to local coordinates of the * outside() entity. * * \note Previously, the geometry was encapsulated in the intersection object * and a const reference was returned. * * \note The returned geometry object is guaranteed to remain valid until the * grid is modified (or deleted). */ LocalGeometry geometryInOutside () const { return this->real.geometryInOutside(); } /** \brief geometrical information about the intersection in global coordinates. * * This method returns a Geometry object that provides a mapping from * local coordinates of the intersection to global (world) coordinates. * * \note If the returned geometry has type none then only a limited set of features * is available for the geometry, i.e. center and volume. * * \note Previously, the geometry was encapsulated in the intersection object * and a const reference was returned. * * \note The returned geometry object is guaranteed to remain valid until the * grid is modified (or deleted). */ Geometry geometry () const { return this->real.geometry(); } /** \brief obtain the type of reference element for this intersection */ GeometryType type () const { return this->real.type(); } /** \brief Local index of codim 1 entity in the inside() entity where * intersection is contained in * * This method returns the facet number with respect to the generic reference * element. * * \note This index can be used with the inside entity's * `subEntity<1>()` method to obtain the facet. * * \returns the index of the inside entity's facet containing this * intersection (with respect to the generic reference element) */ int indexInInside () const { return this->real.indexInInside(); } /** \brief Local index of codim 1 entity in outside() entity where * intersection is contained in * * This method returns the facet number with respect to the generic reference * element. * * \note This index can be used with the outside entity's * `subEntity<1>()` method to obtain the facet. * * \returns the index of the outside entity's facet containing this * intersection (with respect to the generic reference element) */ int indexInOutside () const { return this->real.indexInOutside(); } /*! @brief Return an outer normal (length not necessarily 1) The returned vector may depend on local position within the intersection. */ GlobalCoordinate outerNormal (const LocalCoordinate& local) const { return this->real.outerNormal(local); } /*! @brief return unit outer normal scaled with the integration element The normal is scaled with the integration element of the intersection. This method is redundant but it may be more efficient to use this function rather than computing the integration element via geometry(). The returned vector may depend on local position within the intersection. */ GlobalCoordinate integrationOuterNormal (const LocalCoordinate& local) const { return this->real.integrationOuterNormal(local); } /*! @brief Return unit outer normal (length == 1) The returned vector may depend on the local position within the intersection. It is scaled to have unit length. */ GlobalCoordinate unitOuterNormal (const LocalCoordinate& local) const { return this->real.unitOuterNormal(local); } /*! @brief Return unit outer normal (length == 1) The returned vector is the normal at the center() of the intersection's geometry. It is scaled to have unit length. */ GlobalCoordinate centerUnitOuterNormal () const { return this->real.centerUnitOuterNormal(); } //! Compares two intersections for equality. bool operator==(const Intersection& other) const { return real.equals(other.real); } //! Compares two intersections for inequality. bool operator!=(const Intersection& other) const { return !real.equals(other.real); } //! Default constructor. Intersection() {} //! Copy constructor from an existing intersection. Intersection(const Intersection& other) : real(other.real) {} //! Move constructor from an existing intersection. Intersection(Intersection&& other) : real(std::move(other.real)) {} //! Copy assignment operator from an existing intersection. Intersection& operator=(const Intersection& other) { real = other.real; return *this; } //! Move assignment operator from an existing intersection. Intersection& operator=(Intersection&& other) { real = std::move(other.real); return *this; } //=========================================================== /** @name Implementor interface */ //@{ //=========================================================== /** Copy Constructor from IntersectionImp */ Intersection ( const Implementation &impl ) : real( impl ) {} /** Move Constructor from IntersectionImp */ Intersection ( Implementation&& impl ) : real( std::move(impl) ) {} //@} protected: //! give the pseudo IntersectionIterator class access to the realImp //! \todo cleanup this hack friend class IntersectionIterator; }; //********************************************************************** /** @brief Default Implementations of integrationOuterNormal and unitOuterNormal for IntersectionImp @ingroup GridDevel */ template< class GridImp, class IntersectionImp > class IntersectionDefaultNormalVectors { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; typedef typename GridImp::ctype ct; public: //! return unit outer normal, this should be dependent on //! local coordinates for higher order boundary //! the normal is scaled with the integration element of the intersection. FieldVector integrationOuterNormal (const FieldVector& local) const { FieldVector n = asImp().unitOuterNormal(local); n *= asImp().geometry().integrationElement(local); return n; } //! return unit outer normal FieldVector unitOuterNormal (const FieldVector& local) const { FieldVector n = asImp().outerNormal(local); n /= n.two_norm(); return n; } //! return unit outer normal at center of intersection geometry FieldVector centerUnitOuterNormal () const { // For now, we do this... GeometryType type = asImp().geometry().type(); auto refElement = referenceElement(type); return asImp().unitOuterNormal(refElement.position(0,0)); // But later, if we change the meaning of center(), // we may have to change to this... // return asImp().unitOuterNormal(asImp().local(asImp().center())); } private: // CRTP (curiously recurring template pattern) IntersectionImp &asImp () { return static_cast< IntersectionImp & >( *this ); } const IntersectionImp &asImp () const { return static_cast< const IntersectionImp & >( *this ); } }; } // namespace Dune #endif // DUNE_GRID_COMMON_INTERSECTION_HH dune-grid-2.11.0/dune/grid/common/intersectioniterator.hh000066400000000000000000000214031511655130300234220ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_INTERSECTIONITERATOR_HH #define DUNE_GRID_COMMON_INTERSECTIONITERATOR_HH #include #include #include namespace Dune { /** \brief Mesh entities of codimension 0 ("elements") allow to visit all intersections with "neighboring" elements and with the domain boundary. \tparam GridImp Type that is a model of Dune::Grid \tparam IntersectionIteratorImp Class template that is a model of Dune::IntersectionIterator @warning The number of neighbors may differ from the number of faces/edges of an element!

Overview

Intersections are codimension 1 objects. These intersections are accessed via an IntersectionIterator. This allows the implementation of non-matching grids, as one face can now consist of several intersections. In a conforming mesh such an intersection corresponds to an entity of codimension 1 but in the general non-conforming case there will be no entity in the mesh that directly corresponds to the intersection. Thus, the IntersectionIterator describes these intersections implicitly.

Engine Concept

The IntersectionIterator class template wraps an object of type IntersectionIteratorImp and forwards all member function calls to corresponding members of this class. In that sense IntersectionIterator defines the interface and IntersectionIteratorImp supplies the implementation.

Intersections, leaf grid and level grid

On an entity \b e of codimension zero there are two ways to create IntersectionIterators by either using ilevelbegin() / ilevelend() or ileafbegin()/ileafend(). In the first case intersections with neighboring entities having the same level as \b e are traversed; in the second case ileafbegin()==ileafend() if \b e is not a leaf otherwise all intersections with neighboring leaf entities are traversed. Consider a situation where two elements \b a and \b b have a common intersection. %Element \b b has been refined into an element \b c and \b d, while \b a has not been refined. In one space dimension this situation is depicted in the figure below. \image html islocalref.png "IntersectionIterator in a locally refined mesh." \image latex islocalref.eps "IntersectionIterator in a locally refined mesh." width=\textwidth Here the rule is the following: The %LevelIntersectionIterator delivers all intersections with elements on the same level, the %LeafIntersectionIterator delivers the intersections with all leaf elements if it has been started on a leaf element. Both iterators also stop at intersections with the grid boundary. According to this rule the level intersection iterator started at element \b a in the example above delivers an intersection with \b b and the left grid boundary, whereas the leaf intersection iterator returns \b c instead of \b b. Starting on entity \b c the level intersection iterator returns \b d and the intersection with the left boundary of the level 1 grid, but the leaf intersection iterator returns both \b d and \b a. Finally, starting on \b b the level intersection iterator returns \b a and the right boundary, but the leaf intersection iterator is empty since \b b is not a leaf entity of the grid. Starting on \b d both the level and the leaf intersection iterators will return the element \b c together with the right grid boundary. @ingroup GIIntersectionIterator */ template< class GridImp, class IntersectionIteratorImp, class IntersectionImp > class IntersectionIterator { public: /** * \brief type of underlying implementation * * \warning Implementation details may change without prior notification. **/ typedef IntersectionIteratorImp Implementation; /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ Implementation &impl () { return realIterator; } /** * \brief access to the underlying implementation * * \warning Implementation details may change without prior notification. **/ const Implementation &impl () const { return realIterator; } protected: Implementation realIterator; public: /** \brief Type of Intersection this IntersectionIterator points to */ typedef Dune::Intersection< GridImp, IntersectionImp > Intersection; //=========================================================== /** @name Dereferencing */ //@{ //=========================================================== // The behavior when dereferencing the IntersectionIterator facade depends on // the way the grid implementation handles returning intersections. The implementation // may either return a reference to an intersection stored inside the IntersectionIterator // implementation or a temporary Intersection object. This object has to be forwarded through // the facade to the user, which requires a little trickery, especially for operator->(). // // In order to avoid confusing users reading the Doxygen documentation, we provide "clean" // function signatures to Doxygen and hide the actual implementations. #ifdef DOXYGEN /** \brief Dereferencing operator. */ Intersection operator*() const; /** \brief Pointer operator. */ const Intersection* operator->() const; #else // DOXYGEN /** \brief Dereferencing operator. */ typename std::conditional< std::is_lvalue_reference< decltype(realIterator.dereference()) >::value, const Intersection&, Intersection >::type operator*() const { return this->realIterator.dereference(); } /** \brief Pointer operator. */ decltype(handle_proxy_member_access(realIterator.dereference())) operator->() const { return handle_proxy_member_access(realIterator.dereference()); } #endif // DOXYGEN //@} //=========================================================== /** @name Compare methods */ //@{ //=========================================================== /** @brief Checks for equality. Only Iterators pointing to the same intersection from the same Entity are equal. Pointing to the same intersection from neighbor is unequal as inside and outside are permuted. */ bool operator==(const IntersectionIterator& rhs) const { return rhs.equals(*this); } /** @brief Checks for inequality. Only Iterators pointing to the same intersection from the same Entity are equal. Pointing to the same intersection from neighbor is unequal as inside and outside are permuted. */ bool operator!=(const IntersectionIterator& rhs) const { return ! rhs.equals(*this); } //@} /** @brief Preincrement operator. Proceed to next intersection.*/ IntersectionIterator& operator++() { this->realIterator.increment(); return *this; } /** @brief Postincrement operator. Proceed to next intersection.*/ IntersectionIterator operator++(int) { IntersectionIterator copy(*this); this->realIterator.increment(); return copy; } /** @brief Default constructor. */ IntersectionIterator() {} //=========================================================== /** @name Implementor interface */ //@{ //=========================================================== /** @brief forward equality check to realIterator */ bool equals(const IntersectionIterator& rhs) const { return this->realIterator.equals(rhs.realIterator); } /** Copy Constructor from IntersectionIteratorImp */ IntersectionIterator ( const Implementation &impl ) : realIterator( impl ) {} //@} }; } // namespace Dune namespace std { template< class GridImp, class IntersectionIteratorImp, class IntersectionImp > struct iterator_traits< Dune::IntersectionIterator< GridImp, IntersectionIteratorImp, IntersectionImp > > { typedef ptrdiff_t difference_type; typedef const typename Dune::Intersection< GridImp, IntersectionImp > value_type; typedef value_type *pointer; typedef value_type &reference; typedef forward_iterator_tag iterator_category; }; } // namespace std #include "intersection.hh" #endif // DUNE_GRID_COMMON_INTERSECTIONITERATOR_HH dune-grid-2.11.0/dune/grid/common/islocalref.eps000066400000000000000000000234251511655130300214630ustar00rootroot00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: islocalref.fig %%Creator: fig2dev Version 3.2 Patchlevel 4 %%CreationDate: Tue Nov 14 12:45:15 2006 %%For: dedner@kirk (Andreas Dedner) %%BoundingBox: 0 0 476 157 %%Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 157 moveto 0 0 lineto 476 0 lineto 476 157 lineto closepath clip newpath -98.7 334.5 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /DrawEllipse { /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc closepath savematrix setmatrix } def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Ellipse 7.500 slw n 4770 4455 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 7830 4455 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 1665 4455 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 4770 3870 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 6345 3870 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Ellipse n 7830 3870 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr % Polyline n 1845 4410 m 4545 4410 l 4545 4455 l 1845 4455 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline n 4950 4410 m 7650 4410 l 7650 4455 l 4950 4455 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline n 4995 3870 m 6075 3870 l 6075 3915 l 4995 3915 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline n 6570 3870 m 7650 3870 l 7650 3915 l 6570 3915 l cp gs 0.00 setgray ef gr gs col0 s gr % Polyline 2 slj 15.000 slw gs clippath 3767 4343 m 3886 4326 l 3845 4041 l 3820 4288 l 3726 4058 l cp 4998 3780 m 5098 3714 l 4938 3475 l 5022 3708 l 4838 3541 l cp eoclip n 5040 3735 m 5026 3714 l 5018 3701 l 5007 3684 l 4994 3665 l 4979 3644 l 4963 3620 l 4946 3596 l 4927 3571 l 4908 3545 l 4888 3520 l 4866 3494 l 4844 3469 l 4821 3444 l 4796 3419 l 4769 3395 l 4740 3372 l 4711 3350 l 4680 3330 l 4643 3310 l 4610 3295 l 4582 3285 l 4560 3279 l 4543 3277 l 4531 3276 l 4522 3278 l 4516 3281 l 4511 3285 l 4507 3289 l 4501 3294 l 4493 3299 l 4482 3303 l 4467 3308 l 4447 3313 l 4423 3318 l 4395 3323 l 4365 3330 l 4333 3339 l 4305 3348 l 4283 3357 l 4267 3363 l 4256 3368 l 4250 3371 l 4247 3373 l 4245 3375 l 4243 3377 l 4240 3380 l 4235 3386 l 4225 3394 l 4211 3405 l 4192 3421 l 4167 3441 l 4140 3465 l 4115 3488 l 4093 3510 l 4073 3529 l 4057 3545 l 4044 3558 l 4035 3567 l 4027 3575 l 4021 3580 l 4016 3585 l 4011 3590 l 4006 3596 l 3999 3604 l 3991 3615 l 3980 3630 l 3966 3650 l 3950 3674 l 3933 3703 l 3915 3735 l 3899 3767 l 3885 3797 l 3873 3823 l 3865 3844 l 3859 3860 l 3855 3872 l 3853 3880 l 3852 3887 l 3851 3893 l 3851 3898 l 3850 3905 l 3849 3913 l 3847 3925 l 3845 3941 l 3841 3962 l 3836 3988 l 3830 4018 l 3825 4050 l 3820 4086 l 3817 4119 l 3815 4148 l 3814 4174 l 3813 4198 l 3814 4219 l 3815 4239 l 3817 4257 l 3818 4273 l 3820 4287 l 3822 4299 l 3825 4320 l gs col1 s gr gr % arrowhead 0 slj n 4838 3541 m 5022 3708 l 4938 3475 l 4838 3541 l cp gs col1 1.00 shd ef gr col1 s % arrowhead n 3726 4058 m 3820 4288 l 3845 4041 l 3726 4058 l cp gs col1 1.00 shd ef gr col1 s % Polyline 2 slj gs clippath 4186 4593 m 4079 4649 l 4213 4904 l 4155 4664 l 4319 4848 l cp 5099 4572 m 4979 4577 l 4989 4863 l 5041 4622 l 5109 4859 l cp eoclip n 5040 4590 m 5041 4618 l 5042 4633 l 5041 4650 l 5040 4669 l 5038 4689 l 5035 4711 l 5029 4734 l 5021 4759 l 5010 4786 l 4995 4815 l 4980 4840 l 4966 4861 l 4954 4879 l 4945 4894 l 4938 4904 l 4933 4912 l 4930 4919 l 4928 4924 l 4925 4929 l 4921 4934 l 4914 4940 l 4904 4948 l 4889 4958 l 4869 4970 l 4844 4983 l 4815 4995 l 4784 5005 l 4754 5012 l 4729 5017 l 4708 5021 l 4692 5023 l 4680 5024 l 4670 5025 l 4661 5025 l 4653 5025 l 4643 5024 l 4630 5023 l 4613 5021 l 4592 5017 l 4565 5012 l 4534 5005 l 4500 4995 l 4468 4983 l 4439 4970 l 4417 4958 l 4400 4948 l 4388 4939 l 4381 4932 l 4376 4926 l 4373 4920 l 4369 4914 l 4365 4907 l 4359 4899 l 4349 4888 l 4336 4874 l 4319 4857 l 4298 4837 l 4275 4815 l 4251 4790 l 4229 4766 l 4212 4745 l 4197 4727 l 4185 4710 l 4174 4694 l 4165 4680 l 4158 4667 l 4151 4656 l 4140 4635 l gs col4 s gr gr % arrowhead 0 slj n 5109 4859 m 5041 4622 l 4989 4863 l 5109 4859 l cp gs col4 1.00 shd ef gr col4 s % arrowhead n 4319 4848 m 4155 4664 l 4213 4904 l 4319 4848 l cp gs col4 1.00 shd ef gr col4 s % Polyline 2 slj gs clippath 6752 3824 m 6853 3760 l 6700 3518 l 6778 3753 l 6599 3582 l cp 5878 3730 m 5992 3767 l 6080 3494 l 5950 3704 l 5966 3457 l cp eoclip n 5940 3735 m 5951 3701 l 5956 3686 l 5962 3669 l 5969 3649 l 5976 3626 l 5985 3600 l 5993 3574 l 5999 3554 l 6000 3541 l 5999 3534 l 5996 3529 l 5994 3524 l 5994 3517 l 5999 3505 l 6011 3487 l 6030 3465 l 6047 3450 l 6063 3437 l 6078 3427 l 6089 3420 l 6099 3415 l 6106 3411 l 6113 3409 l 6119 3406 l 6127 3404 l 6137 3400 l 6150 3395 l 6167 3389 l 6188 3382 l 6210 3375 l 6239 3368 l 6260 3363 l 6270 3361 l 6274 3360 l 6278 3361 l 6290 3363 l 6312 3368 l 6345 3375 l 6371 3382 l 6395 3389 l 6414 3395 l 6430 3399 l 6441 3402 l 6450 3404 l 6458 3405 l 6465 3407 l 6474 3409 l 6485 3414 l 6501 3421 l 6520 3432 l 6544 3447 l 6570 3465 l 6594 3485 l 6614 3503 l 6629 3518 l 6638 3530 l 6644 3539 l 6647 3546 l 6649 3551 l 6650 3557 l 6652 3564 l 6657 3573 l 6664 3586 l 6675 3602 l 6689 3623 l 6705 3645 l 6723 3670 l 6738 3692 l 6750 3710 l 6761 3725 l 6769 3739 l 6777 3750 l 6783 3761 l 6795 3780 l gs col1 s gr gr % arrowhead 0 slj n 5966 3457 m 5950 3704 l 6080 3494 l 5966 3457 l cp gs col1 1.00 shd ef gr col1 s % arrowhead n 6599 3582 m 6778 3753 l 6700 3518 l 6599 3582 l cp gs col1 1.00 shd ef gr col1 s % Polyline 2 slj gs clippath 6783 3810 m 6837 3703 l 6580 3575 l 6768 3736 l 6526 3682 l cp 5442 3786 m 5514 3882 l 5744 3710 l 5516 3806 l 5672 3614 l cp eoclip n 5490 3825 m 5514 3807 l 5528 3797 l 5544 3785 l 5562 3773 l 5582 3759 l 5603 3745 l 5625 3731 l 5648 3717 l 5674 3703 l 5701 3688 l 5731 3674 l 5762 3660 l 5796 3646 l 5825 3636 l 5846 3630 l 5860 3626 l 5868 3625 l 5873 3626 l 5875 3628 l 5877 3629 l 5881 3630 l 5889 3631 l 5903 3629 l 5924 3626 l 5953 3621 l 5987 3615 l 6018 3609 l 6045 3604 l 6069 3600 l 6087 3596 l 6100 3593 l 6110 3590 l 6116 3587 l 6122 3585 l 6128 3583 l 6134 3581 l 6144 3579 l 6157 3576 l 6175 3574 l 6199 3572 l 6226 3571 l 6257 3570 l 6291 3571 l 6319 3572 l 6340 3574 l 6354 3575 l 6361 3576 l 6365 3577 l 6366 3578 l 6367 3578 l 6371 3580 l 6378 3583 l 6393 3587 l 6415 3594 l 6445 3603 l 6482 3615 l 6512 3625 l 6542 3636 l 6570 3647 l 6596 3658 l 6621 3668 l 6645 3678 l 6668 3688 l 6689 3698 l 6710 3708 l 6729 3717 l 6747 3725 l 6762 3733 l 6775 3739 l 6797 3750 l gs col4 s gr gr % arrowhead 0 slj n 5672 3614 m 5516 3806 l 5744 3710 l 5672 3614 l cp gs col4 1.00 shd ef gr col4 s % arrowhead n 6526 3682 m 6768 3736 l 6580 3575 l 6526 3682 l cp gs col4 1.00 shd ef gr col4 s /Times-Roman ff 270.00 scf sf 6255 4680 m gs 1 -1 sc (b) col0 sh gr /Times-Roman ff 270.00 scf sf 3060 4680 m gs 1 -1 sc (a) col0 sh gr /Times-Roman ff 270.00 scf sf 8145 4545 m gs 1 -1 sc (level i) col0 sh gr /Times-Roman ff 270.00 scf sf 8145 3960 m gs 1 -1 sc (level i+1) col0 sh gr /Times-Roman ff 270.00 scf sf 5445 3690 m gs 1 -1 sc (c) col0 sh gr /Times-Roman ff 270.00 scf sf 7155 3690 m gs 1 -1 sc (d) col0 sh gr /Times-Roman ff 270.00 scf sf 4635 5310 m gs 1 -1 sc (level intersection) col4 sh gr /Times-Roman ff 270.00 scf sf 3510 3015 m gs 1 -1 sc (leaf intersection) col1 sh gr % here ends figure; $F2psEnd rs showpage dune-grid-2.11.0/dune/grid/common/islocalref.eps.license000066400000000000000000000002501511655130300230730ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/islocalref.fig000066400000000000000000000041061511655130300214340ustar00rootroot00000000000000#FIG 3.2 Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4770 4455 90 90 4770 4455 4860 4455 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 7830 4455 90 90 7830 4455 7920 4455 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 1665 4455 90 90 1665 4455 1755 4455 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4770 3870 90 90 4770 3870 4860 3870 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 6345 3870 90 90 6345 3870 6435 3870 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 7830 3870 90 90 7830 3870 7920 3870 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 1845 4410 4545 4410 4545 4455 1845 4455 1845 4410 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 4950 4410 7650 4410 7650 4455 4950 4455 4950 4410 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 4995 3870 6075 3870 6075 3915 4995 3915 4995 3870 2 2 0 1 0 0 50 -1 20 0.000 0 0 -1 0 0 5 6570 3870 7650 3870 7650 3915 6570 3915 6570 3870 3 2 0 2 1 7 50 -1 -1 0.000 0 1 1 7 1 1 2.00 120.00 240.00 1 1 2.00 120.00 240.00 5040 3735 4680 3330 4365 3330 4140 3465 3915 3735 3825 4050 3825 4320 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.000 3 2 0 2 4 7 50 -1 -1 0.000 0 1 1 6 1 1 2.00 120.00 240.00 1 1 2.00 120.00 240.00 5040 4590 4995 4815 4815 4995 4500 4995 4275 4815 4140 4635 0.000 -1.000 -1.000 -1.000 -1.000 0.000 3 2 0 2 1 7 50 -1 -1 0.000 0 1 1 8 1 1 2.00 120.00 240.00 1 1 2.00 120.00 240.00 5940 3735 5985 3600 6030 3465 6210 3375 6345 3375 6570 3465 6705 3645 6795 3780 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.000 3 2 0 2 4 7 50 -1 -1 0.000 0 1 1 6 1 1 2.00 120.00 240.00 1 1 2.00 120.00 240.00 5490 3825 5762 3660 5987 3615 6257 3570 6482 3615 6797 3750 0.000 -1.000 -1.000 -1.000 -1.000 0.000 4 0 0 50 -1 0 18 0.0000 2 195 135 6255 4680 b\001 4 0 0 50 -1 0 18 0.0000 2 135 120 3060 4680 a\001 4 0 0 50 -1 0 18 0.0000 2 195 660 8145 4545 level i\001 4 0 0 50 -1 0 18 0.0000 2 195 945 8145 3960 level i+1\001 4 0 0 50 -1 0 18 0.0000 2 135 120 5445 3690 c\001 4 0 0 50 -1 0 18 0.0000 2 195 135 7155 3690 d\001 4 0 4 50 -1 0 18 0.0000 2 195 1920 4635 5310 level intersection\001 4 0 1 50 -1 0 18 0.0000 2 195 1800 3510 3015 leaf intersection\001 dune-grid-2.11.0/dune/grid/common/islocalref.fig.license000066400000000000000000000002501511655130300230510ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/common/islocalref.png000066400000000000000000000167221511655130300214620ustar00rootroot00000000000000PNG  IHDR^ pHYsHHFk> |.~+d $+v[u2 B#m?o_=6TQ2hD!$5_BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHP(BHЃSzUcP Y@ #)uu< (!PU(ʖK%(J$o Ip8N?РPE<7+jj*y*5eqP.ZAQ ~ syL#|߸Aʣf,T* IB0@8hZ{oM2 3,C.aEarA"C>䉜H4B≜^hX #Ţ Ix։ݿ~<nߙL(4E5aDohql O\.rg>uΫn*C5:U]0 oH܊T*庮R3ir6orxOwH1kC?ucQ($>,=1,-+_2›K{)C"e-//:tpBR8%nKJ8ιsN8qĉs9=3{g^Z^^ԧ>K/mn#eEq꺾:)dÒ yGU.]ll޽{wӲ{n{㿾=٬뺮R(RIR܅!_fffqIrJ˗Fӫq1 y Xq> |Wv/^pallލnZYYC? m?}cqeoiyWVV>Î?cޗ e9a$("")G+{~8@wm:33~fggG?wԩ255Aٶ-BpZS /CFouu0===;;;ʣ!B{ԩ:u>c/_Ewٻw(t3MlPgRj(}y7)oln\:6 ݫ0 3$eY ЉjyeY}j1Ǿ+=mn# ՔF*Ew'dQMyx^~帋BՔZeCO'&p&n4x$ܩOO^~GBȐryzw!Q6$,/]BH(;vN_XQ('$a։w!PN.MDDZ1LPN.EAík2!ÏB9KK.!$z%.~'eF2h>PN|{wE!D/Νv 4_. !$bTS 2(ٳ` w9!ѣPO~+q=u`?]BHBpGP&6eBIz(;Y^^?z .]62.\pĉG///[;wСCG=tЙ3gM]Q,X,x!u}aaa;`1Ɩ[fv=33o~?E!neeeffSNIwA\.w)_z:T{uA,q` oEEX,MG1g\r%o+dt婩#GwQvthOnb<==<۶-$I|@\V-<#gϞ=|,WD6uǏ>|q*q(C9rdvvvnnnvvȑ#6b&BR6Q[8 ;#i _8dxm7_ ОR ąr<+J>8de>$AӴbHbmwrJ_G;pdaDĻ>I2 UU<:4mr%d2#PWV-ߩ{yo'zaR뺼if, Gxl ~ø*QF`FGXD8}w9$x;9S,lPiZ.f}LfP/"A?T, ۷2MRT*u(P$+9Y?@6O|W&2ړO%x \wiHJ].$ 8:拑C` ?!Μ(]D8Ioi!$2#q` gxɸK0}zbvOȖQ(ܾGwY7wwȐ$ܸ῾}{UܹSo6 !htu&ΞMP)w(y䑦?ǎ%"_qZӔk7w(_ΝMS_>W_ _\*B@G!0o6qte۠qndPMy4+z+ػ)jV&#ByoNǎxxE8?kvk|ocq׃bjʿ6>񻿋~*Yj}2;Et_(RA#Fq&&Jq̛}TTd]f'#_**u#=J!7Y,;%Cjdz NɰP&<:iFlR)Eq |jb,, i{;S~.r,~KirźOO:4(j* 2!GAF #'Kj5+J%s]&MiX70MV(ךcŮP`⯮(LUcL%VB2euEJ%*fk%ʤGܩ՘,קQDCg]B}z^S8R_Ja+ 8EMXρFx#A_?I/&~j~/PQ^>M I[AbddP2,g* ÿ}VF4rUpn+6$oZGH ekm9`R ~VFU IB>(6=в.$5yp,҈B\O1Àa4^QP.D[T.㬱t櫈"*B؊]Zrvrٟ8uhZE$n?!4VBoT(2ߝѨUu\g"3;MƼcL mV EU>qB˲`GAF?1 1Y #include /** @file * @author Peter Bastian * @brief Provides classes with basic mappers which are used to attach data to a grid * */ /*! @addtogroup Mapper Mapper \ingroup Grid @section Mapper1 What is a Mapper ? A mapper class is used to attach user-defined data to a subset of the grid entities \f$E^\prime\subseteq E\f$. It is assumed that the data \f$D(E^\prime)\f$ associated with \f$E^\prime\f$ is stored in an array. The array can be viewed as a map \f[ a : I_{E^\prime} \to D(E^\prime) \f] from the consecutive, zero-starting index set \f$ I_{E^\prime} = \{0, \ldots, |E^\prime|-1\}\f$ of \f$E^\prime\f$ to the data set. The mapper class provides a mapping \f[ m : E^\prime \to I_{E^\prime} \f] from the entity set to the index set. Access from a grid entity \f$e\in E^\prime\f$ to its associated data element \f$d_e\f$ then is a two step process: \f[ a(m(e)) = d_e. \f] @section Mapper2 Different Kinds of Mappers There are different kinds of mappers depending on functionality and efficiency of their implementation. The user selects an appropriate mapper depending on her/his needs. All mappers conform to the same interface. @subsection para1 Index based Mappers An index-based mapper is allocated for a grid and can be used as long as the grid is not changed (i.e. refined, coarsened or load balanced). The implementation of static mappers is based on a Dune::IndexSet and is typically of \f$O(1)\f$ complexity with a very small constant. Index-based mappers are only available for restricted (but usually sufficient) entity sets. @subsection para2 Id based Mappers An id-based mapper can also be used while a grid changes. For that it has to be implemented on the basis of a Dune::IdSet. This may be relatively slow because the data type used for ids is usually not an int and the non-consecutive ids require more complicated search data structures (typically a map). Access is therefore at least \f$O(\log |E^\prime|)\f$. On the other hand, id-based mappers can treat arbitrary entity sets \f$E^\prime\f$. @section Mapper3 Mapper Interface This interface is implemented by the class template Dune::Mapper. For a full documentation see the description of this class. The function Dune::Mapper::index delivers the index for an entity. Note that that for performance reasons it is usually not checked whether the entity is really in the entity set. The functions Dune::Mapper::index delivers the index for a (sub-)entity The function Dune::Mapper::size returns the size of the entity set, i.e. \f$|E^\prime|\f$ The different implementations of the mapper interface are listed below. @section Mapper4 Overview of Different Mapper Implementations @section Mapper5 Mappers and Mesh Changes */ namespace Dune { /** * @addtogroup Mapper * * @{ */ /** @brief Mapper interface. This class template is used as a base class for all mapper implementations. It uses the Barton-Nackman trick to ensure conformity to the interface. \tparam G Type that is a model of Dune::Grid \tparam MapperImp Type that is a model of Dune::Mapper \tparam IndexType Integer type used for indices. Default type is for backward-compatibility \todo IndexType should be extracted from MapperImp, but gcc doesn't let me */ template class Mapper { public: /** \brief Number type used for indices */ using Index = IndexType; /** @brief Map entity to array index. \param e Reference to codim cc entity. The codim is extracted from the entity. \return An index in the range 0 ... Max number of entities in set - 1. */ template Index index (const EntityType& e) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().map(e))); return asImp().index(e); } /** @brief Map subentity i of codim cc of a codim 0 entity to array index. * * \param e Reference to codim 0 entity. * \param i Number of codim cc subentity of e, where cc is the template parameter of the function. * \param codim codimension of subentity of e * \return An index in the range 0 ... Max number of entities in set - 1. */ Index subIndex (const typename G::Traits::template Codim<0>::Entity& e, int i, unsigned int codim) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().map(e,i,codim))); return asImp().subIndex(e,i,codim); } /** @brief Return total number of entities in the entity set managed by the mapper. This number can be used to allocate a vector of data elements associated with the entities of the set. In the parallel case this number is per process (i.e. it may be different in different processes). \return Size of the entity set. */ auto size () const { CHECK_INTERFACE_IMPLEMENTATION((asImp().size())); return asImp().size(); } /** @brief Returns true if the entity is contained in the index set and at the same time the array index is returned. \param[in] e Reference to entity \param[out] result Filled with array index if entity is contained \return true if entity is in entity set of the mapper */ template bool contains (const EntityType& e, IndexType& result) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().contains(e,result ))); return asImp().contains(e,result ); } /** @brief Returns true if the subentity is contained in the index set and at the same time the array index is returned. \param[in] e Reference to codim 0 entity \param[in] i subentity number \param[in] cc subentity codim \param[out] result Filled with array index if entity is contained \return true if entity is in entity set of the mapper */ bool contains (const typename G::Traits::template Codim<0>::Entity& e, int i, int cc, IndexType& result) const { CHECK_INTERFACE_IMPLEMENTATION((asImp().contains(e,i,cc,result))) return asImp().contains(e,i,cc,result); } /** @brief Reinitialize mapper after grid has been modified. */ template void update (GridView&& gridView) { CHECK_AND_CALL_INTERFACE_IMPLEMENTATION((asImp().update(std::forward(gridView)))); } private: //! Barton-Nackman trick MapperImp& asImp () {return static_cast (*this);} //! Barton-Nackman trick const MapperImp& asImp () const {return static_cast(*this);} }; /** @} */ #undef CHECK_INTERFACE_IMPLEMENTATION #undef CHECK_AND_CALL_INTERFACE_IMPLEMENTATION } #endif dune-grid-2.11.0/dune/grid/common/mcmgmapper.hh000066400000000000000000000305501511655130300212750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_MCMGMAPPER_HH #define DUNE_GRID_COMMON_MCMGMAPPER_HH #include #include #include #include #include #include #include #include #include "mapper.hh" /** * @file * @brief Mapper for multiple codim and multiple geometry types * @author Peter Bastian */ namespace Dune { /** * @addtogroup Mapper * * @{ */ ////////////////////////////////////////////////////////////////////// // // Common Layout templates // /** * \brief layout function for `MultipleCodimMultipleGeomTypeMapper` * * The layout function indicates which entity types are contained in the * mapper. It is called for each `GeometryType` and the grid dimension. * A `true` value indicates the geometry type is part of the map; `false` * that it is not. * * For commonly used layouts containing only entities of a fixed dimension * or codimension, convenience functions returning a `MCMGLayout` are provided. * * The following example is equivalent to \ref mcmgElementLayout(): \code MCMGLayout layout = [](GeometryType gt, int griddim) { return gt.dim() == griddim; }; \endcode * * \see MultipleCodimMultipleGeomTypeMapper * \see mcmgLayout(Codim) * \see mcmgLayout(Dim) * \see mcmgElementLayout() * \see mcmgVertexLayout() */ using MCMGLayout = std::function; /** * \brief layout for entities of codimension `codim` * * \see MultipleCodimMultipleGeomTypeMapper */ template MCMGLayout mcmgLayout(Codim) { return [](GeometryType gt, int dimgrid) { return dimgrid - gt.dim() == codim; }; } /** * \brief layout for entities of dimension `dim` * * \see MultipleCodimMultipleGeomTypeMapper */ template MCMGLayout mcmgLayout(Dim) { return [](GeometryType gt, int) { return gt.dim() == dim; }; } /** * \brief layout for elements (codim-0 entities) * * \see MultipleCodimMultipleGeomTypeMapper */ inline MCMGLayout mcmgElementLayout() { return mcmgLayout(Codim<0>()); } /** * \brief layout for vertices (dim-0 entities) * * \see MultipleCodimMultipleGeomTypeMapper */ inline MCMGLayout mcmgVertexLayout() { return mcmgLayout(Dim<0>()); } ////////////////////////////////////////////////////////////////////// // // MultipleCodimMultipleGeomTypeMapper // /** @brief Implementation class for a multiple codim and multiple geometry type mapper. * * In this implementation of a mapper the entity set used as domain for the map consists * of the entities of a subset of codimensions in the given index set. The index * set may contain entities of several geometry types. * * The geometry types to be included in the mapper are selected using a * layout functional (\ref MCMGLayout) that is passed to the constructor. */ template class MultipleCodimMultipleGeomTypeMapper : public Mapper, typename GV::IndexSet::IndexType > { public: /** \brief Underlying GridView */ typedef GV GridView; /** \brief Number type used for indices */ typedef typename GV::IndexSet::IndexType Index; /** \brief Number type used for the overall size (the return value of the 'size' method) * * The type used here is set to be the corresponding type used by the GridView's index set. */ using size_type = decltype(std::declval().size(0)); /** * \brief construct mapper from grid and layout description * * The `layout` parameter is a functional describing entities of which * geometry types are included in the mapper. For commonly used cases, * convenience functions are provided. See the \ref MCMGLayout type * documentation for details. * * \param gridView grid view whose entities should be included in the mapper * \param layout functional describing how many dof to store on each entity (fixed per geometry type) */ MultipleCodimMultipleGeomTypeMapper(const GV& gridView, const MCMGLayout& layout) : gridView_(gridView) , indexSet_(&gridView_.indexSet()) , layout_(layout) { update(gridView); } /*! * \brief Map entity to starting index in array for dof block * * \tparam EntityType * \param e Reference to codim \a EntityType entity. * \return An index in the range 0 ... (Max number of entities in set)*blockSize - 1. */ template Index index (const EntityType& e) const { const GeometryType gt = e.type(); assert(offset(gt) != invalidOffset); return indexSet_->index(e)*blockSize(gt) + offset(gt); } /** @brief Map subentity of codim 0 entity to starting index in array for dof block \param e Reference to codim 0 entity. \param i Number of subentity of e \param codim Codimension of the subentity \return An index in the range 0 ... Max number of entities in set - 1. */ Index subIndex (const typename GV::template Codim<0>::Entity& e, int i, unsigned int codim) const { const GeometryType eType = e.type(); GeometryType gt = eType.isNone() ? GeometryTypes::none( GV::dimension - codim ) : ReferenceElements::general(eType).type(i,codim) ; //GeometryType gt=ReferenceElements::general(e.type()).type(i,codim); assert(offset(gt) != invalidOffset); return indexSet_->subIndex(e, i, codim)*blockSize(gt) + offset(gt); } /** @brief Return total number of entities in the entity set managed by the mapper. This number can be used to allocate a vector of data elements associated with the entities of the set. In the parallel case this number is per process (i.e. it may be different in different processes). \return Size of the entity set. */ size_type size () const { return n; } /** @brief return number of entries for a given geometry type **/ size_type size(GeometryType gt) const { return blockSize(gt); } /** @brief return the geometry types with entries **/ const std::vector< GeometryType >& types ( int codim ) const { return myTypes_[ codim ]; } /** @brief Returns a pair with the starting point in the dof vector * and the number of degrees of freedom if the entity is contained in the index set * otherwise {0,0} is returned \param e Reference to entity \param result integer reference to the start of the block \return pair with first entry equal to index for that entity and the second entry the number of degrees of freedom (zero if entity is not in entity set of the mapper) */ template IntegralRange indices (const EntityType& e) const { if(!indexSet_->contains(e) || offset(e.type()) == invalidOffset) return {0,0}; Index start = index(e); return {start, start+blockSize(e.type())}; } /** @brief Returns a pair with the starting point in the dof vector * and the number of degrees of freedom if the entity is contained in the index set * otherwise {0,0} is returned \param e Reference to codim 0 entity \param i subentity number \param cc subentity codim \param result integer reference to the start of the block \return pair with first entry equal to index for that entity and the second entry the number of degrees of freedom (zero if sub entity is not in entity set of the mapper) */ IntegralRange indices (const typename GV::template Codim<0>::Entity& e, int i, int cc) const { const GeometryType eType = e.type(); const GeometryType gt = eType.isNone() ? GeometryTypes::none(GV::dimension - cc) : ReferenceElements::general(eType).type(i,cc) ; if (offset(gt) == invalidOffset) return {0,0}; else { Index start = subIndex(e,i,cc); return {start, start+blockSize(gt)}; } } /** @brief Returns true if the entity is contained in the index set \param e Reference to entity \param result integer reference where corresponding index is stored if true \return true if entity is in entity set of the mapper */ template bool contains (const EntityType& e, Index& result) const { if(!indexSet_->contains(e) || offset(e.type()) == invalidOffset) { result = 0; return false; } result = index(e); return true; } /** @brief Returns true if the entity is contained in the index set \param e Reference to codim 0 entity \param i subentity number \param cc subentity codim \param result integer reference where corresponding index is stored if true \return true if entity is in entity set of the mapper */ bool contains (const typename GV::template Codim<0>::Entity& e, int i, int cc, Index& result) const { const GeometryType eType = e.type(); const GeometryType gt = eType.isNone() ? GeometryTypes::none( GV::dimension - cc ) : ReferenceElements::general(eType).type(i,cc) ; if (offset(gt) == invalidOffset) return false; result = indexSet_->subIndex(e, i, cc)*blockSize(gt) + offset(gt); return true; } /** @brief Recalculates indices after grid adaptation * * After grid adaptation you need to call this to update * the stored gridview and recalculate the indices. */ void update (const GV& gridView) { gridView_ = gridView; indexSet_ = &gridView_.indexSet(); update_(); } /** @brief Recalculates indices after grid adaptation * * After grid adaptation you need to call this to update * the stored gridview and recalculate the indices. */ void update (GV&& gridView) { gridView_ = std::move(gridView); indexSet_ = &gridView_.indexSet(); update_(); } const MCMGLayout &layout () const { return layout_; } const GridView &gridView () const { return gridView_; } private: void update_() { n = 0; std::fill(offsets.begin(),offsets.end(),Index(0)); std::fill(blocks.begin(),blocks.end(),Index(0)); for (unsigned int codim = 0; codim <= GV::dimension; ++codim) { // walk over all geometry types in the codimension for (const GeometryType& gt : indexSet_->types(codim)) { Index offset; size_t block = layout()(gt, GV::Grid::dimension); // if the geometry type is contained in the layout, increment offset // and store geometry type if (block) { offset = n; n += indexSet_->size(gt) * block; myTypes_[codim].push_back(gt); } else { offset = invalidOffset; } offsets[GlobalGeometryTypeIndex::index(gt)] = offset; blocks[GlobalGeometryTypeIndex::index(gt)] = block; } } } Index offset(GeometryType gt) const { return offsets[GlobalGeometryTypeIndex::index(gt)]; } Index blockSize(GeometryType gt) const { return blocks[GlobalGeometryTypeIndex::index(gt)]; } static const Index invalidOffset = std::numeric_limits::max(); // number of data elements required unsigned int n; // GridView is needed to keep the IndexSet valid GV gridView_; const typename GV::IndexSet* indexSet_; // provide an array for the offsets std::array offsets; std::array blocks; MCMGLayout layout_; // get layout object std::vector myTypes_[GV::dimension+1]; }; /** @} */ } #endif dune-grid-2.11.0/dune/grid/common/partitionset.hh000066400000000000000000000243751511655130300217020ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_PARTITIONSET_HH #define DUNE_GRID_COMMON_PARTITIONSET_HH #include #include namespace Dune { /** * \addtogroup GIRelatedTypes * \{ */ namespace { // Simple TMP to deduce partition iterator type from set of partitions. template struct derive_partition_iterator_type { // We did not match any specialization, bail out... static_assert(AlwaysFalse >::value, "There is no partition iterator for this combination of entity partitions"); }; // specializations of derive_partition_iterator_type for existing PartitionIteratorTypes template<> struct derive_partition_iterator_type< (1 << InteriorEntity) > : public std::integral_constant {}; template<> struct derive_partition_iterator_type< (1 << InteriorEntity) | (1 << BorderEntity) > : public std::integral_constant {}; template<> struct derive_partition_iterator_type< (1 << InteriorEntity) | (1 << BorderEntity) | (1 << OverlapEntity) > : public std::integral_constant {}; template<> struct derive_partition_iterator_type< (1 << InteriorEntity) | (1 << BorderEntity) | (1 << OverlapEntity) | (1 << FrontEntity) > : public std::integral_constant {}; template<> struct derive_partition_iterator_type< (1 << InteriorEntity) | (1 << BorderEntity) | (1 << OverlapEntity) | (1 << FrontEntity) | (1 << GhostEntity) > : public std::integral_constant {}; template<> struct derive_partition_iterator_type< (1 << GhostEntity) > : public std::integral_constant {}; // Simple TMP to deduce set of partitions from partition iterator type. template struct derive_partition_set; // specializations of derive_partition_set for existing PartitionIteratorTypes template<> struct derive_partition_set : std::integral_constant {}; template<> struct derive_partition_set : std::integral_constant {}; template<> struct derive_partition_set : std::integral_constant {}; template<> struct derive_partition_set : std::integral_constant {}; template<> struct derive_partition_set : std::integral_constant {}; template<> struct derive_partition_set : std::integral_constant {}; } // anonymous namespace //! A set of PartitionType values. /** * PartitionSet contains a set of PartitionType values fixed at compile time. The contents * of the set is encoded in the template parameter partitions, but the exact semantics are * an implementation detail. PartitionSets can be combined by adding them up. They also support * removing partitions by subtracting them. * * \tparam partitions Implementation-defined representation of the partition set. */ template struct PartitionSet { //! \private The actual representation should not be used outside of the implementation. static constexpr unsigned int value = partitions; //! Returns a new PartitionSet that also contains the partitions in set. template struct PartitionSet constexpr operator+(const PartitionSet

&) const { return PartitionSet(); } //! Returns a new PartitionSet that does not contain the partitions in set. template struct PartitionSet constexpr operator-(const PartitionSet

&) const { return PartitionSet(); } //! Writes the PartitionSet to an output stream. friend std::ostream& operator<<(std::ostream& os, const PartitionSet&) { unsigned int set = partitions; os << "partition set {"; bool first = true; for (unsigned int p = 0; set; set &= ~(1 << p++)) { if (!(set & (1 << p))) continue; if (!first) os << ","; first = false; os << static_cast(p); } os << "}"; return os; } //! Returns the PartitionIteratorType that can be used to iterate over the partitions in the set. /** * * \throws raises a static assertion if the partitions do not correspond to a valid PartitionIteratorType. */ static constexpr PartitionIteratorType partitionIterator() { return derive_partition_iterator_type::value; } //! Tests whether the given PartitionType is contained in this set. static constexpr bool contains(PartitionType pt) { return partitions & (1 << pt); } //! Tests whether the given PartitionSet is contained in this set. template static constexpr bool contains(PartitionSet) { return (partitions & contained_partitions) == contained_partitions; } //! Tests whether two PartitionsSet are equal. template constexpr bool operator==(PartitionSet) const { return partitions == p2; } //! Tests whether two PartitionsSet are not equal. template constexpr bool operator!=(PartitionSet) const { return partitions != p2; } }; //! Creates a PartitionSet for the given PartitionType. /** * \related PartitionSet */ template PartitionSet<(1 << p)> partitionSet() { return PartitionSet<(1 << p)>(); } /** * \brief creates a PartitionSet for the given PartitionIteratorType * \related PartitionSet */ template constexpr PartitionSet::value> partitionSet() { return PartitionSet::value>(); } //! Predefined PartitionSets for commonly used combinations of parallel grid PartitionTypes. namespace Partitions { #ifdef DOXYGEN //! Type of PartitionSet for the interior partition. typedef PartitionSet<...> Interior; //! Type of PartitionSet for the border partition. typedef PartitionSet<...> Border; //! Type of PartitionSet for the overlap partition. typedef PartitionSet<...> Overlap; //! Type of PartitionSet for the front partition. typedef PartitionSet<...> Front; //! Type of PartitionSet for the ghost partition. typedef PartitionSet<...> Ghost; //! Type of PartitionSet for the interior and border partitions. typedef PartitionSet<...> InteriorBorder; //! Type of PartitionSet for the interior, border and overlap partitions. typedef PartitionSet<...> InteriorBorderOverlap; //! Type of PartitionSet for the interior, border, overlap and front partitions. typedef PartitionSet<...> InteriorBorderOverlapFront; //! Type of PartitionSet for all partitions. typedef PartitionSet<...> All; //! PartitionSet for the interior partition. constexpr Interior interior; //! PartitionSet for the border partition. constexpr Border border; //! PartitionSet for the overlap partition. constexpr Overlap overlap; //! PartitionSet for the front partition. constexpr Front front; //! PartitionSet for the ghost partition. constexpr Ghost ghost; //! PartitionSet for the interior and border partitions. constexpr InteriorBorder interiorBorder; //! PartitionSet for the interior, border and overlap partitions. constexpr InteriorBorderOverlap interiorBorderOverlap; //! PartitionSet for the interior, border, overlap and front partitions. constexpr InteriorBorderOverlapFront interiorBorderOverlapFront; //! PartitionSet for all partitions. constexpr All all; #else // DOXYGEN // First declare the types and objects for individual partitions typedef decltype(partitionSet()) Interior; typedef decltype(partitionSet()) Border; typedef decltype(partitionSet()) Overlap; typedef decltype(partitionSet()) Front; typedef decltype(partitionSet()) Ghost; inline constexpr Interior interior = {}; inline constexpr Border border = {}; inline constexpr Overlap overlap = {}; inline constexpr Front front = {}; inline constexpr Ghost ghost = {}; // Now we can declare the partition sets that are a result of combining partitions typedef decltype(interior + border) InteriorBorder; typedef decltype(interior + border + overlap) InteriorBorderOverlap; typedef decltype(interior + border + overlap + front) InteriorBorderOverlapFront; typedef decltype(interior + border + overlap + front + ghost) All; inline constexpr InteriorBorder interiorBorder = {}; inline constexpr InteriorBorderOverlap interiorBorderOverlap = {}; inline constexpr InteriorBorderOverlapFront interiorBorderOverlapFront = {}; inline constexpr All all = {}; #endif // DOXYGEN } // namespace Partitions /** * \} group Parallel Grid Partitions */ } // namespace Dune #endif // DUNE_GRID_COMMON_PARTITIONSET_HH dune-grid-2.11.0/dune/grid/common/rangegenerators.hh000066400000000000000000001144331511655130300223360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_RANGEGENERATORS_HH #define DUNE_GRID_COMMON_RANGEGENERATORS_HH #include #include #include #include #include namespace Dune { #ifdef DOXYGEN /** * \addtogroup GIIteration * \brief Iterator ranges for entities and intersections to support iteration with range-based for loops. * * Iterating over sets of entities or intersections is one of the most common operations when * writing DUNE code. The grid interface implements this in the standard C++ ways by providing * iterators and matching begin() and end() methods, but their usage can be rather unwieldy. * * This page describes a much simpler alternative based on a C++11 feature called range-based for loop. * *

Range-based for loop

* * A range-based for loop is a short-hand way of iterating over any object that provides the standard * begin() and end() methods. It looks like this: * \code for (auto& i : vec) i *= 2; \endcode * * This code will multiply all entries of `vec` by 2. The loop head always looks like `for ( : )`. * You can also specify the exact type of the variable, but it is normally much easier to let the compiler * do that for you using `auto`. * * For those interested in the technical details, the compiler has translated the loop into * something resembling this (not quite, but we'll forget about the minor details here): * \code for (auto it = vec.begin(), end = vec.end(); it != end; ++it) { auto& i = *it; i *= 2; } \endcode * * For further details, see e.g. http://en.cppreference.com/w/cpp/language/range-for. * *

Entities

* * You cannot simply iterate over all entities of a GridView by passing it to a range-based for loop, * simply because you cannot (and probably do not want to) iterator over *all* of its entities. Instead, * algorithms typically have to iterate over all entities with a particular codimension, e.g. over all * grid cells. The functions listed at the top of this page allow you to do just this. Assuming you have * a GridView `gv`, you can iterate over its cells and vertices like this: * \code // iterate over cells for (const auto& cell : elements(gv)) { std::cout << "Cell " << gv.indexSet().index(cell) << " is centered at " << cell.geometry().center() << std::endl; } // iterate over vertices for (const auto& vertex : vertices(gv)) { std::cout << "Vertex " << gv.indexSet().index(vertex) << " at " << vertex.geometry().center() << std::endl; } \endcode * * There are also functions for iterating over facets() and edges() as well as generic entities() functions, * which allow you to specify a numeric codimension or dimension. * * If you are using Dune for parallel computations, you probably know that the GridView offers iterators with * different \link PartitionIteratorType PartitionIteratorTypes\endlink. Those are also supported with range-based * for loops: By default, the functions above will iterate over all entities (Dune::All_Partition), but they * accept an additional parameter for selecting a different set of partitions. This parameter is of type * Dune::PartitionSet. You can find pre-instantiated objects for all partitions and allowed combinations in the * namespace Dune::Partitions. Using those objects, you can iterate over all interior and border vertices like * this: * \code // use prebuild PartitionSet for (const auto& vertex : vertices(gv,Dune::Partitions::interiorBorder)) { ... } // construct PartitionSet by combining partitions for (const auto& vertex : vertices(gv,Dune::Partitions::interior + Dune::Partitions::border)) { ... } \endcode * *

Intersections

* * If you want to iterate over the \link Intersection intersections \endlink of an Entity, you can * use the function intersections() to obtain a range that is suitable for a range-based for loop. * Intersections are always defined with respect to a GridView; for further information, see the discussion * on locally refined grids. * * As an example, the following code counts the number of boundary intersections for a given GridView `gv`: * * \code std::size_t count = 0; for (const auto& e : elements(gv)) { do_stuff(); for (const auto& i : intersections(gv,e)) { if (i.boundary()) ++count; } } \endcode * *

Sub-entities

* * The grid interface allows to iterate over sub-entities of a given * codim-0-entity, sub-entities being entities contained in the given entity * with a codimension equal (returns the entity itself) or larger than * the given entity. * * As an example, the following code prints the index of all vertices * of an element `e` * * \code for (const auto& vertex : subEntities(e, Codim{})) std::cout << gv.indexSet().index(vertex) << " "; \endcode * * Note that the number of for example codim-1 entities (facets) of an element can be obtained with * \code const auto numFacets = subEntities(e, Codim<1>{}).size(); \endcode * which is equivalent to * \code const auto numFacets = referenceElement(e).size(1); \endcode * * Iteration over sub-entities is only possible for codim-0-entities (elements). * *

Information for grid implementors

* *

Custom range implementations

* * The default implementation of the range generator functions calls the correct begin() and end() * methods on the GridView / the Entity and stores the iterators returned by these methods in an * IteratorRange object which is then returned by value (as a temporary object). While any overhead * associated with this process will normally be negligible compared with the ensuing grid traversal, * you can guarantee optimal performance by making sure that your iterators are move-constructible and * move-assignable. * If, for some reason, you don't want to rely on this default implementation, you only have to provide * an overload for the function `entities(const GV&, Dune::Codim, Dune::PartitionSet)`. All * other functions simply forward to this single function. Apart from that, you will of course have * to overload `intersections()` and `descendantElements()` as well - those are entirely separate. * *

ADL lookup for grids in non-standard namespaces

* * The range generator functions described on this page are found by means of argument-dependent * lookup (ADL). That way, users don't have to explicitly specify the namespace when using those * functions. * * Making ADL work does however require some care from grid implementors who are developing grids * which are not placed in the namespace `Dune`. More precisely, the GridView and the Entity classes * have to be in that namespace. If you are using the default facade classes, you don't have to worry * about this fact (the facade classes are in the correct namespace), but if your implementation * does not use those facades, you will have to import the functions on this page into the namespace * of your GridView and / or Entity classes to make ADL work: * * \code namespace MyAweSomeGrid { using Dune::entities; using Dune::elements; using Dune::facets; using Dune::edges; using Dune::vertices; using Dune::descendantElements; using Dune::intersections; using Dune::subEntities; ... } \endcode * * Of course, you can also reimplement all functions in your own namespace, but that's probably * a bad idea... * * \{ */ // ***************************************************************************************** // Doxygen documentation // ***************************************************************************************** // // In the following, the range generating functions are documented for Doxygen; the actual // implementations are further down in this file and hidden from Doxygen. // The main reason for this split are the return types of those functions, which either contain // long type listings to obtain the iterator type or (in the case of the forwarded functions // use the new-style function syntax and calculate the return type using decltype. In both cases, // Doxygen generates function signatures that are very confusing to the average user. // // ***************************************************************************************** //! \name Common entity ranges //! \brief Entity ranges for common entity types. If in doubt, use one of these. //! \{ //! Iterates over all elements / cells (entities with codimension 0) of a GridView. /** * This functions returns an object representing the range of *elements* or *cells* * contained in the GridView gv. The main purpose of this function is to enable iteration * over those entities by means of a range-based for loop. * * Example: * \code // iterate over all cells in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : elements(gv)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This is the default version of the elements() function. It will always iterate over all * elements in the GridView, regardless of their Dune::PartitionType. If you are interested * in cells with specific PartitionType(s), use elements(const GV&,PartitionSet) * instead. * * \sa elements(const GV&,PartitionSet) * * \relates GridView * \param gv a GridView object that contains the elements. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> elements(const GV& gv); //! Iterates over all facets (entities with codimension 1) of a GridView. /** * This functions returns an object representing the range of *facets* * contained in the GridView gv. The main purpose of this function is to enable iteration * over those entities by means of a range-based for loop. * * Example: * \code // iterate over all facets in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : facets(gv)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This is the default version of the facets() function. It will always iterate over all * elements in the GridView, regardless of their Dune::PartitionType. If you are interested * in cells with specific PartitionType(s), use facets(const GV&,PartitionSet) * instead. * * \sa facets(const GV&,PartitionSet) * * \relates GridView * \param gv a GridView object that contains the facets. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> facets(const GV& gv); //! Iterates over all edges (entities with dimension 1) of a GridView. /** * This functions returns an object representing the range of *edges* * contained in the GridView gv. The main purpose of this function is to enable iteration * over those entities by means of a range-based for loop. * * Example: * \code // iterate over all edges in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : edges(gv)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This is the default version of the edges() function. It will always iterate over all * elements in the GridView, regardless of their Dune::PartitionType. If you are interested * in cells with specific PartitionType(s), use edges(const GV&,PartitionSet) * instead. * * \sa edges(const GV&,PartitionSet) * * \relates GridView * \param gv a GridView object that contains the edges. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> edges(const GV& gv); //! Iterates over all vertices (entities with dimension 0) of a GridView. /** * This functions returns an object representing the range of *vertices* * contained in the GridView gv. The main purpose of this function is to enable iteration * over those entities by means of a range-based for loop. * * Example: * \code // iterate over all vertices in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : vertices(gv)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This is the default version of the vertices() function. It will always iterate over all * elements in the GridView, regardless of their Dune::PartitionType. If you are interested * in cells with specific PartitionType(s), use vertices(const GV&,PartitionSet) * instead. * * \sa vertices(const GV&,PartitionSet) * * \relates GridView * \param gv a GridView object that contains the vertices. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> vertices(const GV& gv); //! \} //! \name Intersection Range //! \brief Iterator range for \link Intersection intersections \endlink. //! \{ //! Iterates over all \link Intersection Intersections \endlink of an Entity with respect to the given GridView. /** * This functions returns an object representing the range of `Intersection`s of the Entity * e with respect to the GridView gv. The main purpose of this function is to enable * iteration over those intersections by means of a range-based for loop: * \code // iterate over all intersections of an entity with respect to the LeafGridView auto gv = grid.leafGridView(); const auto& entity = ...; // get an entity from somewhere for (const auto& i : intersections(gv,entity)) { std::cout << i.geometry().center() << std::endl; } \endcode * * \relates GridView * \relates Entity * \param gv the GridView to use for determining interior intesections. * \param e the Entity whose intersections should be iterated over. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> intersections(const GV& gv, const Entity& e); //! \} //! \name Hierarchic Entity range //! \brief Iterator range for hierarchic access to the more-refined entities that result from the subdivision of a given element. //! \{ //! Iterates over all descendant elements of the given element up to a maximum level. /** * This functions returns an object representing the range of descendat elements of the * element (Entity with codimension 0) e. The main purpose of this function is to enable * iteration over those descendants by means of a range-based for loop: * \code // iterate over all descendants of an entity const auto& entity = ...; // get an entity from somewhere for (const auto& e : descendantElements(entity,grid.maxLevel())) { std::cout << e.geometry().center() << std::endl; } \endcode * * \note This function only works for elements (entities with codimension 0). Attempting to * call this function with an entity of higher codimension will result in a compile * time error. * * \relates Entity * \param e the Entity whose descendants should be iterated over. * \param maxLevel the maximum grid level for which to return descendants. Elements with * `level > maxLevel` will be omitted from the range. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> descendantElements(const Entity& e, int maxLevel); // Entity class EntityImp> //! \} //! \name Entity ranges with (co)dimension template argument //! \brief Entity ranges which allow specifying the codimension / dimension as a numeric template parameter. //! \{ //! Iterates over all entities of a GridView with the given codimension. /** * This functions returns an object representing the range of entities of codimension * cd contained in the GridView gv. The main purpose of this function is to enable iteration * over those entities by means of a range-based for loop: * \code // iterate over all cells in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : entities(gv,Dune::Codim<0>())) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This function allows you to write loops that are parameterized on the codimension of * the entities. While this allows for extra flexibility (for e.g. some codimension-agnostic * algorithms), it reduces the code readability. If you don't need this flexibility, consider * using elements(), facets(), edges() or vertices() instead. * * \remark This is the default version of the entities() function. It will always iterate over all * entities in the GridView, regardless of their Dune::PartitionType. If you are interested * in entities with specific PartitionType(s), use * entities(const GV&,Codim,PartitionSet) instead. * * \remark If you have to iterate over entities with a specific *dimension*, consider using * entities(const GV&,Dim) instead to improve the readability of your code. * * \sa entities(const GV&,Codim,PartitionSet) * \sa entities(const GV&,Dim) * * \relates GridView * \param gv a GridView object that contains the entities. * \param cd a Codim object that is used to specify the codimension of the entities by means * of its template parameter. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> entities(const GV& gv, Codim cd); //! Iterates over all entities of a GridView with the given dimension. /** * This functions returns an object representing the range of entities of dimension * d contained in the GridView gv. The main purpose of this function is to enable iteration * over those entities by means of a range-based for loop. * * Example: * \code // iterate over all edges in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : entities(gv,Dune::Dim<1>())) { std::cout << e.geometry().center() << std::endl; } \endcode * \remark This function allows you to write loops that are parameterized on the codimension of * the entities. While this allows for extra flexibility (for e.g. some codimension-agnostic * algorithms), it reduces the code readability. If you don't need this flexibility, consider * using elements(), facets(), edges() or vertices() instead. * * \remark This is the default version of the entities() function. It will always iterate over all * entities in the GridView, regardless of their Dune::PartitionType. If you are interested * in entities with specific PartitionType(s), use * entities(const GV&,Dim,PartitionSet) instead. * * \remark If you have to iterate over entities with a specific *codimension*, consider using * entities(const GV&,Codim) instead to improve the readability of your code. * * \sa entities(const GV&,Dim,PartitionSet) * \sa entities(const GV&,Codim) * * \relates GridView * \param gv a GridView object that contains the entities. * \param d a Dim object that is used to specify the dimension of the entities by means * of its template parameter. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> entities(const GV& gv, Dim d); //! \} //! \name Common entity ranges for non-standard parallel partitions //! \brief The following Entity ranges make it possible to specify a PartitionSet which is sometimes needed in parallel code. //! \{ //! Iterates over all elements / cells (entities with codimension 0) of a GridView that belong to the given PartitionSet. /** * This functions returns an object representing the range of *elements* or *cells* contained * in the GridView gv which belong to the PartitionSet ps. The main purpose of this function * is to enable iteration over those entities by means of a range-based for loop. * * Example: * \code // iterate over all ghost cells in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : elements(gv,Dune::Partitions::ghost)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \sa elements(const GV&) * * \relates GridView * \param gv a GridView object that contains the elements. * \param ps a PartitionSet object that is used to specify the set of Dune::PartitionType to which * the elements must belong. * \returns an unspecified object that is guaranteed to fulfill the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> elements(const GV& gv, PartitionSet ps); //! Iterates over all facets (entities with codimension 1) of a GridView that belong to the given PartitionSet. /** * This functions returns an object representing the range of *facets* contained * in the GridView gv which belong to the PartitionSet ps. The main purpose of this function * is to enable iteration over those entities by means of a range-based for loop. * * Example: * \code // iterate over all interior and border facets in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : facets(gv,Dune::Partitions::interiorBorder)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \sa facets(const GV&) * * \relates GridView * \param gv a GridView object that contains the facets. * \param ps a PartitionSet object that is used to specify the set of Dune::PartitionType to which * the facets must belong. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ /** * \relates GridView */ template inline IteratorRange<...> facets(const GV& gv, PartitionSet ps); //! Iterates over all edges (entities with dimension 1) of a GridView that belong to the given PartitionSet. /** * This functions returns an object representing the range of *edges* contained * in the GridView gv which belong to the PartitionSet ps. The main purpose of this function * is to enable iteration over those entities by means of a range-based for loop. * * Example: * \code // iterate over all interior edges in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : edges(gv,Dune::Partitions::interior)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \sa edges(const GV&) * * \relates GridView * \param gv a GridView object that contains the edges. * \param ps a PartitionSet object that is used to specify the set of Dune::PartitionType to which * the edges must belong. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> edges(const GV& gv, PartitionSet ps); //! Iterates over all vertices (entities with dimension 0) of a GridView that belong to the given PartitionSet. /** * This functions returns an object representing the range of *vertices* contained * in the GridView gv which belong to the PartitionSet ps. The main purpose of this function * is to enable iteration over those entities by means of a range-based for loop. * * Example: * \code // iterate over all interior vertices in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : vertices(gv,Dune::Partitions::interior)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \sa vertices(const GV&) * * \relates GridView * \param gv a GridView object that contains the vertices. * \param ps a PartitionSet object that is used to specify the set of Dune::PartitionType to which * the vertices must belong. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> vertices(const GV& gv, PartitionSet ps); //! \} //! \name Generic entity ranges for non-standard parallel partitions //! \brief These Entity ranges allow for the maximum flexibility; they are parameterized on both the co(cimension) and the parallel PartitionSet. //! \{ //! Iterates over all entities of a GridView with the given codimension that belong to the given PartitionSet. /** * This functions returns an object representing the range of entities of codimension cd contained * in the GridView gv which belong to the PartitionSet ps. The main purpose of this function is to * enable iteration over those entities by means of a range-based for loop: * \code // iterate over all interior and border cells in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : entities(gv,Dune::Codim<0>(),Dune::Partitions::interiorBorder)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This function allows you to write loops that are parameterized on the codimension of * the entities. While this allows for extra flexibility (for e.g. some codimension-agnostic * algorithms), it reduces the code readability. If you don't need this flexibility, consider * using elements(), facets(), edges() or vertices() instead. * * \remark If you have to iterate over entities with a specific *dimension*, consider using * entities(const GV&,Dim,PartitionSet) instead to improve the readability * of your code. * * \sa entities(const GV&,Codim) * \sa entities(const GV&,Dim,PartitionSet) * * \relates GridView * \param gv a GridView object that contains the entities. * \param cd a Codim object that is used to specify the codimension of the entities by means * of its template parameter. * \param ps a PartitionSet object that is used to specify the set of Dune::PartitionType to which * the entities must belong. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> entities(const GV& gv, Codim cd, PartitionSet ps); //! Iterates over all entities of a GridView with the given dimension that belong to the given PartitionSet. /** * This functions returns an object representing the range of entities of dimension d contained * in the GridView gv which belong to the PartitionSet ps. The main purpose of this function is to * enable iteration over those entities by means of a range-based for loop: * \code // iterate over all interior and border edges in the LeafGridView auto gv = grid.leafGridView(); for (const auto& e : entities(gv,Dune::Dim<1>(),Dune::Partitions::interiorBorder)) { std::cout << e.geometry().center() << std::endl; } \endcode * * \remark This function allows you to write loops that are parameterized on the dimension of * the entities. While this allows for extra flexibility (for e.g. some codimension-agnostic * algorithms), it reduces the code readability. If you don't need this flexibility, consider * using elements(), facets(), edges() or vertices() instead. * * \remark If you have to iterate over entities with a specific *codimension*, consider using * entities(const GV&,Codim,PartitionSet) instead to improve the readability * of your code. * * \sa entities(const GV&,Dim) * \sa entities(const GV&,Codim,PartitionSet) * * \relates GridView * \param gv a GridView object that contains the entities. * \param d a Dim object that is used to specify the dimension of the entities by means * of its template parameter. * \param ps a PartitionSet object that is used to specify the set of Dune::PartitionType to which * the entities must belong. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop. */ template inline IteratorRange<...> entities(const GV& gv, Dim d, PartitionSet ps); //! Iterates over all sub-entities of an entity given the codimension of the sub-entities /** * This functions returns an object representing the range of sub-entities of codimension c contained * in the given entity. The main purpose of this function is to * enable iteration over sub-entities by means of a range-based for loop: * \code // iterate over all interior and border edges in the LeafGridView auto gv = grid.leafGridView(); for (const auto& element : elements(gv)) for (const auto& vertex : subEntities(element, Codim{})) std::cout << vertex.geometry().center() << "\n"; \endcode * \note This functionality is only available for codim-0-entities (elements) * \relates Entity * \param e an Entity object that contains the sub-entities. * \param c a Codim object that is used to specify the codimension of the sub-entities by means * of its template parameter. * \returns an unspecified object that is guaranteed to fulfil the interface * of IteratorRange and that can be iterated over using a range-based * for loop and that provides a `size()` member function. */ template inline IteratorRange<...> subEntities(const E& e, Codim c); //! \} #else // DOXYGEN // ****************************************************************************************** // Implementations // ****************************************************************************************** /** * Master entity range implementation - all other functions that return an entity range eventually * end up calling this function. The return type of this function is forwarded by those other functions * with the help of decltype. * * It is thus possible for a grid to use a different type of iterator range object by overloading * or partially specializing this single function. The specialization has to be placed either in the * Dune namespace or in the namespace of the GridView object. */ template inline auto entities(const GV& gv, Codim, PartitionSet) -> IteratorRange::value>())> { static_assert(0 <= codim && codim <= GV::dimension, "invalid codimension for given GridView"); const PartitionIteratorType pit = derive_partition_iterator_type::value; typedef IteratorRange())> return_type; return return_type(gv.template begin(),gv.template end()); } /** * Entity range implementation without PartitionSet parameter. The default implementation obtains the * standard iterators by calling begin() and end() without specifying a partition type. This makes it * possible to have user-defined GridView-like objects with a different default partition. * * All other functions without PartitionSet parameter forward to this function. */ template inline auto entities(const GV& gv, Codim) -> IteratorRange())> { static_assert(0 <= codim && codim <= GV::dimension, "invalid codimension for given GridView"); typedef IteratorRange())> return_type; return return_type(gv.template begin(),gv.template end()); } /** * Hierarchic entity range implementation. */ template inline IteratorRange descendantElements(const Entity& e, int maxLevel) { typedef IteratorRange return_type; return return_type(e.hbegin(maxLevel),e.hend(maxLevel)); } /** * Intersection range implementation. */ template inline auto intersections(const GV& gv, const Entity& e) -> IteratorRange { return IteratorRange(gv.ibegin(e),gv.iend(e)); } /** * Remaining implementations - these are mostly copy and paste and making sure to forward to the * correct function. */ template inline auto entities(const GV& gv, Dim, PartitionSet) -> decltype(entities(gv,Codim(),PartitionSet())) { static_assert(0 <= dim && dim <= GV::dimension, "invalid dimension for given GridView"); return entities(gv,Codim(),PartitionSet()); } template inline auto entities(const GV& gv, Dim) -> decltype(entities(gv,Codim())) { static_assert(0 <= dim && dim <= GV::dimension, "invalid dimension for given GridView"); return entities(gv,Codim()); } template inline auto elements(const GV& gv, PartitionSet) -> decltype(entities(gv,Codim<0>(),PartitionSet())) { return entities(gv,Codim<0>(),PartitionSet()); } template inline auto elements(const GV& gv) -> decltype(entities(gv,Codim<0>())) { return entities(gv,Codim<0>()); } template inline auto facets(const GV& gv, PartitionSet) -> decltype(entities(gv,Codim<1>(),PartitionSet())) { return entities(gv,Codim<1>(),PartitionSet()); } template inline auto facets(const GV& gv) -> decltype(entities(gv,Codim<1>())) { return entities(gv,Codim<1>()); } template inline auto edges(const GV& gv, PartitionSet) -> decltype(entities(gv,Dim<1>(),PartitionSet())) { return entities(gv,Dim<1>(),PartitionSet()); } template inline auto edges(const GV& gv) -> decltype(entities(gv,Dim<1>())) { return entities(gv,Dim<1>()); } template inline auto vertices(const GV& gv, PartitionSet) -> decltype(entities(gv,Dim<0>(),PartitionSet())) { return entities(gv,Dim<0>(),PartitionSet()); } template inline auto vertices(const GV& gv) -> decltype(entities(gv,Dim<0>())) { return entities(gv,Dim<0>()); } template inline auto subEntities(const E& e, Codim c) { static_assert(E::codimension <= codim, "Can only iterate over sub-entities with equal or larger codimension"); return transformedRangeView( range(static_cast(e.subEntities(c))), [&](const int i){ return e.template subEntity(i); } ); } #endif // DOXYGEN /** * \} // GIIteration */ } // namespace Dune #endif // DUNE_GRID_COMMON_RANGEGENERATORS_HH dune-grid-2.11.0/dune/grid/common/scsgmapper.hh000066400000000000000000000122571511655130300213150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_SCSGMAPPER_HH #define DUNE_GRID_COMMON_SCSGMAPPER_HH #include #include "mapper.hh" #include /** * @file * @brief Mapper classes are used to attach data to a grid * @author Peter Bastian */ namespace Dune { /** * @addtogroup Mapper * * @{ */ /** @brief Implementation class for a single codim and single geometry type mapper. * * In this implementation of a mapper the entity set used as domain for the map consists * of the entities of a given codimension c for all entities in the given index set. The index * set may only contain entities of a single geometry type, otherwise an exception is thrown. * * \tparam GV A Dune grid view type * * \tparam c A valid codimension */ template class SingleCodimSingleGeomTypeMapper : public Mapper, typename GV::IndexSet::IndexType > { public: /** \brief Number type used for indices */ typedef typename GV::IndexSet::IndexType Index; /** \brief Number type used for the overall size (the return value of the 'size' method) * * The type used here is set to be the corresponding type used by the GridView's index set. */ using size_type = decltype(std::declval().size(0)); /** @brief Construct mapper from grid and one of its index sets. \param gridView A Dune GridView object. */ SingleCodimSingleGeomTypeMapper (const GV& gridView) : gridView_(gridView) , indexSet_(&gridView_.indexSet()) { // check that grid has only a single geometry type if (indexSet_->types(c).size() != 1) DUNE_THROW(GridError, "mapper treats only a single codim and a single geometry type"); } /** @brief Map entity to array index. \param e Reference to codim cc entity, where cc is the template parameter of the function. \return An index in the range 0 ... Max number of entities in set - 1. */ template Index index (const EntityType& e) const { static_assert(EntityType::codimension == c, "Entity of wrong codim passed to SingleCodimSingleGeomTypeMapper"); return indexSet_->index(e); } /** @brief Map subentity of codim 0 entity to array index. \param e Reference to codim 0 entity. \param i Number of the subentity of e, where cc is the template parameter of the function. \param codim Codimension of the subentity of e \return An index in the range 0 ... Max number of entities in set - 1. */ Index subIndex (const typename GV::template Codim<0>::Entity& e, int i, unsigned int codim) const { if (codim != c) DUNE_THROW(GridError, "Id of wrong codim requested from SingleCodimSingleGeomTypeMapper"); return indexSet_->subIndex(e,i,codim); } /** @brief Return total number of entities in the entity set managed by the mapper. This number can be used to allocate a vector of data elements associated with the entities of the set. In the parallel case this number is per process (i.e. it may be different in different processes). \return Size of the entity set. */ size_type size () const { return indexSet_->size(c); } /** @brief Returns true if the entity is contained in the index set \param e Reference to entity \param result integer reference where corresponding index is stored if true \return true if entity is in entity set of the mapper */ template bool contains (const EntityType& e, Index& result) const { result = index(e); return true; } /** @brief Returns true if the entity is contained in the index set \param e Reference to codim 0 entity \param i subentity number \param cc subentity codim \param result integer reference where corresponding index is stored if true \return true if entity is in entity set of the mapper */ bool contains (const typename GV::template Codim<0>::Entity& e, int i, int cc, Index& result) const { result = subIndex(e,i,cc); return true; } /** @brief Recalculates indices after grid adaptation * * After grid adaptation you need to call this to update * the stored gridview and recalculate the indices. */ void update (const GV& gridView) { gridView_ = gridView; indexSet_ = &gridView_.indexSet(); } /** @brief Recalculates indices after grid adaptation * * After grid adaptation you need to call this to update * the stored gridview and recalculate the indices. */ void update (GV&& gridView) { gridView_ = std::move(gridView); indexSet_ = &gridView_.indexSet(); } private: GV gridView_; const typename GV::IndexSet* indexSet_; }; /** @} */ } #endif dune-grid-2.11.0/dune/grid/common/sizecache.hh000066400000000000000000000265631511655130300211140ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_COMMON_SIZECACHE_HH #define DUNE_GRID_COMMON_SIZECACHE_HH #include #include #include #include #include #include #include #include #include #include /** @file @author Robert Kloefkorn @brief Provides size cache classes to implement the grids size method efficiently. */ namespace Dune { //! organizes the caching of sizes for one grid and one GeometryType template class SizeCache { typedef SizeCache ThisType; //! our dimension constexpr static int dim = GridImp::dimension; //! number of codims constexpr static int nCodim = GridImp::dimension + 1; // type of grid typedef GridImp GridType; // coordinate type typedef typename GridType :: ctype ctype ; // stores all sizes of the levels mutable std::vector< int > levelSizes_[nCodim]; // stores all sizes of the levels mutable std::vector< std::vector< int > > levelTypeSizes_[nCodim]; // stores all sizes of leafs mutable int leafSizes_[nCodim]; // stores all sizes of leafs mutable std::vector< int > leafTypeSizes_[nCodim]; // the grid const GridType & grid_; // count elements of set by iterating the grid template < int codim, bool gridHasCodim > struct CountLevelEntitiesBase { template < class SzCacheType > static void apply(const SzCacheType & sc, int level, int cd) { if( cd == codim ) { sc.template countLevelEntities (level); } } }; template < int codim > struct CountLevelEntitiesBase< codim, false > { template < class SzCacheType > static void apply(const SzCacheType & sc, int level, int cd) { if( cd == codim ) { sc.template countLevelEntitiesNoCodim (level); } } }; template < int codim > struct CountLevelEntities : public CountLevelEntitiesBase< codim, Capabilities :: hasEntity< GridType, codim > :: v > {}; // count elements of set by iterating the grid template < int codim, bool gridHasCodim > struct CountLeafEntitiesBase { template static void apply(const SzCacheType & sc, int cd) { if( cd == codim ) { sc.template countLeafEntities (); } } }; // count elements of set by iterating the grid template < int codim > struct CountLeafEntitiesBase< codim, false > { template static void apply(const SzCacheType & sc, int cd) { if( cd == codim ) { sc.template countLeafEntitiesNoCodim (); } } }; template < int codim > struct CountLeafEntities : public CountLeafEntitiesBase< codim, Capabilities :: hasEntity< GridType, codim > :: v > {}; int gtIndex( const GeometryType& type ) const { return type.id() >> 1 ; } int sizeCodim( const int codim ) const { const int mydim = GridType :: dimension - codim; return ((1 << mydim) + 1) / 2; } // private copy constructor SizeCache (const SizeCache & ); public: /** \brief constructor taking grid reference */ SizeCache (const GridType & grid) : grid_( grid ) { reset(); } /** \brief reset all cached sizes */ void reset() { for(int codim=0; codim & vec = levelSizes_[codim]; vec.resize(numMxl); levelTypeSizes_[codim].resize( numMxl ); for(int level = 0; level= 0 ); assert( codim < nCodim ); assert( level >= 0 ); if( level >= (int) levelSizes_[codim].size() ) return 0; if( levelSizes_[codim][level] < 0) Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( auto i ){ CountLevelEntities< i >::apply( *this, level, codim ); } ); // CountLevelEntities::count(*this,level,codim); assert( levelSizes_[codim][level] >= 0 ); return levelSizes_[codim][level]; } /** \copydoc Dune::Grid::size(int level,GeometryType type) const */ int size (int level, GeometryType type) const { int codim = GridType ::dimension - type.dim(); if( levelSizes_[codim][level] < 0) Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( auto i ){ CountLevelEntities< i >::apply( *this, level, codim ); } ); assert( levelTypeSizes_[codim][level][gtIndex( type )] >= 0 ); return levelTypeSizes_[codim][level][gtIndex( type )]; } //******************************************************************** // leaf sizes //******************************************************************** /** \copydoc Dune::Grid::size(int codim) const */ int size (int codim) const { assert( codim >= 0 ); assert( codim < nCodim ); if( leafSizes_[codim] < 0 ) Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( auto i ){ CountLeafEntities< i >::apply( *this, codim ); } ); assert( leafSizes_[codim] >= 0 ); return leafSizes_[codim]; }; /** \copydoc Dune::Grid::size(GeometryType type) const */ int size ( const GeometryType type ) const { int codim = GridType :: dimension - type.dim(); if( leafSizes_[codim] < 0 ) Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( auto i ){ CountLeafEntities< i >::apply( *this, codim ); } ); assert( leafTypeSizes_[codim][ gtIndex( type )] >= 0 ); return leafTypeSizes_[codim][ gtIndex( type )]; } private: template void countLevelEntities(int level) const { typedef typename GridType :: LevelGridView GridView ; typedef typename GridView :: template Codim< codim > :: template Partition :: Iterator Iterator ; GridView gridView = grid_.levelGridView( level ); Iterator it = gridView.template begin (); Iterator end = gridView.template end (); levelSizes_[codim][level] = countElements(it,end, levelTypeSizes_[codim][level]); } template void countLeafEntities() const { // count All_Partition entities typedef typename GridType :: LeafGridView GridView ; typedef typename GridView :: template Codim< codim > :: template Partition :: Iterator Iterator ; GridView gridView = grid_.leafGridView(); Iterator it = gridView.template begin (); Iterator end = gridView.template end (); leafSizes_[codim] = countElements(it,end, leafTypeSizes_[codim] ); } // counts entities with given type for given iterator template int countElements(IteratorType & it, const IteratorType & end, std::vector& typeSizes) const { int overall = 0; const size_t types = typeSizes.size(); for(size_t i=0; itype(); ++typeSizes[ gtIndex( type ) ]; ++overall; } #ifndef NDEBUG int sumtypes = 0; for(size_t i=0; i void countLevelEntitiesNoCodim(int level) const { typedef typename GridType :: LevelGridView GridView ; typedef typename GridView :: template Codim< 0 > :: template Partition :: Iterator Iterator ; GridView gridView = grid_.levelGridView( level ); Iterator it = gridView.template begin< 0, pitype> (); Iterator end = gridView.template end< 0, pitype> (); levelSizes_[codim][level] = countElementsNoCodim< codim >(it,end, levelTypeSizes_[codim][level]); } template void countLeafEntitiesNoCodim() const { // count All_Partition entities typedef typename GridType :: LeafGridView GridView ; typedef typename GridView :: template Codim< 0 > :: template Partition :: Iterator Iterator ; GridView gridView = grid_.leafGridView(); Iterator it = gridView.template begin< 0, pitype > (); Iterator end = gridView.template end< 0, pitype > (); leafSizes_[codim] = countElementsNoCodim< codim >(it,end, leafTypeSizes_[codim] ); } // counts entities with given type for given iterator template < int codim, class IteratorType > int countElementsNoCodim(IteratorType & it, const IteratorType & end, std::vector& typeSizes) const { typedef typename GridType :: LocalIdSet LocalIdSet ; typedef typename LocalIdSet :: IdType IdType ; typedef ReferenceElements< ctype, dim > ReferenceElementContainerType; typedef typename ReferenceElementContainerType::ReferenceElement ReferenceElementType; typedef std::set< IdType > CodimIdSetType ; typedef typename IteratorType :: Entity ElementType ; // get id set const LocalIdSet& idSet = grid_.localIdSet(); const size_t types = typeSizes.size(); for(size_t i=0; i typeCount( types ); // count all elements of codimension codim for( ; it != end; ++it ) { // get entity const ElementType& element = *it ; // get reference element ReferenceElementType refElem = ReferenceElementContainerType :: general( element.type() ); // count all sub entities of codimension codim const int count = element.subEntities( codim ); for( int i=0; i< count; ++ i ) { // get geometry type const GeometryType geomType = refElem.type( i, codim ); // get id of sub entity const IdType id = idSet.subId( element, i, codim ); // insert id into set typeCount[ gtIndex( geomType ) ].insert( id ); } } // accumulate numbers int overall = 0; for(size_t i=0; i #include #include #include // HAVE_DUNE_UGGRID #include #include #include #if HAVE_DUNE_UGGRID #include #include "../../../../doc/grids/gridfactory/hybridtestgrids.hh" #endif using namespace Dune; /*! * \brief Layout template for edges and elements * This layout template is for use in the MultipleCodimMultipleGeomTypeMapper. * It selects edges and elements (entities with dim=1 or dim=dimgrid). * * \tparam dimgrid The dimension of the grid. */ template struct MCMGElementEdgeLayout { /*! * \brief: test whether entities of the given geometry type should be included in * the map */ bool contains(GeometryType gt) { return (gt.dim() == dimgrid || gt.dim() == 1); } }; /*! * \brief Check whether the index created for element data is unique, * consecutive and starting from zero. */ template void checkElementDataMapper(const Dune::Mapper& mapper, const GridView& gridView) { using Mapper = Dune::Mapper; using Index = typename Mapper::Index; Index min = 1; Index max = 0; std::set indices; for (const auto& element : elements(gridView)) { const auto index = mapper.index(element); min = std::min(min, index); max = std::max(max, index); [[maybe_unused]] const auto [it, wasInserted] = indices.insert(index); if (!wasInserted) // not inserted because already existing DUNE_THROW(GridError, "Mapper element index is not unique!"); } if (min != 0) DUNE_THROW(GridError, "Mapper element index is not starting from zero!"); if (max != gridView.indexSet().size(0) - 1) DUNE_THROW(GridError, "Mapper element index is not consecutive!"); } /*! * \brief Check whether the index created for vertex data is consecutive * and starting from zero. */ template void checkVertexDataMapper(const Dune::Mapper& mapper, const GridView& gridView) { const size_t dim = GridView::dimension; using Mapper = Dune::Mapper; using Index = typename Mapper::Index; Index min = 1; Index max = 0; std::set< Index > indices; for (const auto& element : elements(gridView)) { size_t numVertices = element.subEntities(dim); for (size_t curVertex = 0; curVertex < numVertices; ++curVertex) { Index testIdx = Index(-1); bool contains = mapper.contains(element, curVertex, dim, testIdx ); Index index = mapper.subIndex(element, curVertex, dim); if( contains && (index != testIdx) ) { DUNE_THROW(GridError, "subIndex and contains do not return the same index!"); } min = std::min(min, index); max = std::max(max, index); indices.insert(index); } } if (min != 0) DUNE_THROW(GridError, "Mapper vertex index is not starting from zero!"); if (max != gridView.indexSet().size(dim) - 1) DUNE_THROW(GridError, "Mapper vertex index is not consecutive!"); for (size_t i = 0; i < max; ++i) { if (indices.find(i) == indices.end()) DUNE_THROW(GridError, "Mapper vertex index is not consecutive!"); } } /*! * \brief Check whether the index created for element and edge data is * unique, consecutive and starting from zero. * \note Tests the multiple indices per entity interface (types/indices) specific to the MCMGMapper */ template void checkMixedDataMapper(const Mapper& mapper, const GridView& gridView) { using Index = typename Mapper::Index; const size_t dim = GridView::dimension; Index min = 1; Index max = 0; std::set indices; Index elementBlockSize = 0, edgeBlockSize = 0; for (const auto& element : elements(gridView)) { const auto >s = mapper.types(0); if (std::find(gts.begin(),gts.end(),element.type()) == gts.end()) DUNE_THROW(GridError, "Mapper mixed index does not have correct geometry type information"); auto block = mapper.indices(element); if (block.empty()) DUNE_THROW(GridError, "Mapper mixed index does not have element indices"); if (elementBlockSize == 0) elementBlockSize = block.size(); if (elementBlockSize != block.size()) DUNE_THROW(GridError, "Mapper mixed index does not have the same block size on all elements"); if ( block.size() != mapper.size(element.type()) ) DUNE_THROW(GridError, "Mapper mixed index does not return correct size for given geometry type "); // handle elements min = std::min(min, *(block.begin())); max = std::max(max, *(block.end())-1); for (Index i : block) { [[maybe_unused]] const auto [it, wasInserted] = indices.insert(i); if (!wasInserted) // not inserted because already existing DUNE_THROW(GridError, "Mapper mixed index is not unique for elements!"); } // handle edges size_t numEdges = element.subEntities(dim-1); for (size_t curEdge = 0; curEdge < numEdges; ++curEdge) { auto block = mapper.indices(element,curEdge,dim-1); if (block.empty()) DUNE_THROW(GridError, "Mapper mixed index does not have edges indices"); if (edgeBlockSize == 0) edgeBlockSize = block.size(); else if (edgeBlockSize != block.size()) DUNE_THROW(GridError, "Mapper mixed index does not have the same block size on all edges"); min = std::min(min, *(block.begin())); max = std::max(max, *(block.end())-1); for (Index i : block) indices.insert(i); Index testIdx = Index(-1); const bool contains = mapper.contains(element, curEdge, dim-1, testIdx ); const Index index = mapper.subIndex(element, curEdge, dim-1); if( contains && (index != testIdx) ) { DUNE_THROW(GridError, "subIndex and contains do not return the same index!"); } } } if (min != 0) DUNE_THROW(GridError, "Mapper mixed index is not starting from zero!"); if (max != gridView.indexSet().size(0)*elementBlockSize + gridView.indexSet().size(dim - 1)*edgeBlockSize - 1) DUNE_THROW(GridError, "Mapper mixed index is not consecutive!"); for (size_t i = 0; i < max; ++i) { if (indices.find(i) == indices.end()) DUNE_THROW(GridError, "Mapper mixed index is not consecutive!"); } } template void update(Dune::Mapper& mapper, const GV& gv) { mapper.update(gv); } /*! * \brief Run checks for a given grid. * * \param grid Grid to perform the checks. */ template void checkGrid(Grid& grid) { using LeafMCMGMapper = MultipleCodimMultipleGeomTypeMapper; using LevelMCMGMapper = MultipleCodimMultipleGeomTypeMapper; // Create various mappers ******************************************************************* // Create element mappers for leaf and levels LeafMCMGMapper leafElementMCMGMapper(grid.leafGridView(), mcmgElementLayout()); std::vector levelElementMCMGMappers; for (int i = 0; i <= grid.maxLevel(); i++) levelElementMCMGMappers.emplace_back(grid.levelGridView(i), mcmgElementLayout()); // Create vertex mappers for leaf and levels LeafMCMGMapper leafVertexMCMGMapper(grid.leafGridView(), mcmgVertexLayout()); std::vector levelVertexMCMGMappers; for (int i = 0; i <= grid.maxLevel(); i++) levelVertexMCMGMappers.emplace_back(grid.levelGridView(i), mcmgVertexLayout()); // Create mixed element and edge mappers for leaf and levels const auto elementEdgeLayout = [](GeometryType gt, unsigned int dimgrid) { return (gt.dim() == dimgrid)? 3 : (gt.dim() == 1? 2 : 0); }; LeafMCMGMapper leafMixedMCMGMapper(grid.leafGridView(), elementEdgeLayout); std::vector levelMixedMCMGMappers; for (int i = 0; i <= grid.maxLevel(); i++) levelMixedMCMGMappers.emplace_back(grid.levelGridView(i), elementEdgeLayout); // Check mappers ******************************************************************* checkElementDataMapper(leafElementMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelElementMCMGMappers.size(); i++) checkElementDataMapper(levelElementMCMGMappers[i], grid.levelGridView(i)); checkVertexDataMapper(leafVertexMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelVertexMCMGMappers.size(); i++) checkVertexDataMapper(levelVertexMCMGMappers[i], grid.levelGridView(i)); checkMixedDataMapper(leafMixedMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelMixedMCMGMappers.size(); i++) checkMixedDataMapper(levelMixedMCMGMappers[i], grid.levelGridView(i)); // Refine grid and update mappers ******************************************************************* grid.globalRefine(1); update(leafElementMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelElementMCMGMappers.size(); i++) update(levelElementMCMGMappers[i], grid.levelGridView(i)); update(leafVertexMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelVertexMCMGMappers.size(); i++) update(levelVertexMCMGMappers[i], grid.levelGridView(i)); update(leafMixedMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelMixedMCMGMappers.size(); i++) update(levelMixedMCMGMappers[i], grid.levelGridView(i)); // Check mappers ******************************************************************* checkElementDataMapper(leafElementMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelElementMCMGMappers.size(); i++) checkElementDataMapper(levelElementMCMGMappers[i], grid.levelGridView(i)); checkVertexDataMapper(leafVertexMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelVertexMCMGMappers.size(); i++) checkVertexDataMapper(levelVertexMCMGMappers[i], grid.levelGridView(i)); checkMixedDataMapper(leafMixedMCMGMapper, grid.leafGridView()); for (std::size_t i = 0; i < levelMixedMCMGMappers.size(); i++) checkMixedDataMapper(levelMixedMCMGMappers[i], grid.levelGridView(i)); } int main(int argc, char** argv) try { // initialize MPI if necessary Dune::MPIHelper::instance(argc, argv); // Check grids with more than one element type. // So far only UGGrid does this, so we use it to test the mappers. #if HAVE_DUNE_UGGRID // Do the test for a 2d UGGrid { typedef UGGrid<2> Grid; std::unique_ptr grid(make2DHybridTestGrid()); // create hybrid grid grid->mark(1, *grid->leafGridView().begin<0>()); grid->adapt(); grid->globalRefine(1); checkGrid(*grid); } // Do the test for a 3d UGGrid { typedef UGGrid<3> Grid; std::unique_ptr grid(make3DHybridTestGrid()); // create hybrid grid grid->mark(1, *grid->leafGridView().begin<0>()); grid->adapt(); grid->globalRefine(1); checkGrid(*grid); } #endif // Do the test for a 2d YaspGrid { Dune::FieldVector< double, 2 > lower( 0 ); Dune::FieldVector< double, 2 > upper( 1 ); std::array elements = {{ 4 ,4 }}; typedef Dune::YaspGrid<2> Grid; auto grid = Dune::StructuredGridFactory< Grid >::createCubeGrid( lower, upper, elements ); // create hybrid grid checkGrid(*grid); } // Do the test for a 3d YaspGrid { Dune::FieldVector< double, 3 > lower( 0 ); Dune::FieldVector< double, 3 > upper( 1 ); std::array elements = {{ 4 ,4, 4 }}; typedef Dune::YaspGrid<3> Grid; auto grid = Dune::StructuredGridFactory< Grid >::createCubeGrid( lower, upper, elements ); // create hybrid grid checkGrid(*grid); } return EXIT_SUCCESS; } catch (Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/common/test/scsgmappertest.cc000066400000000000000000000114641511655130300231610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief A unit test for the SingleCodimSingleGeomTypeMapper */ #include #include #include #include #include #include using namespace Dune; // ///////////////////////////////////////////////////////////////////////////////// // Check whether the index created for element data is unique, consecutive // and starting from zero. // ///////////////////////////////////////////////////////////////////////////////// template void checkElementDataMapper(const Dune::Mapper& mapper, const GridView& gridView) { const auto& is = gridView.indexSet(); using Mapper = Dune::Mapper; using Index = typename Mapper::Index; Index min = 1; Index max = 0; std::set indices; const auto size = mapper.size(); if (size != is.size(0)) DUNE_THROW(GridError, "Mapper size does not agree with index set " "size!"); for (const auto& element : elements(gridView)) { Index index; bool contained = mapper.contains(element, index); if ((is.types(0)[0] == element.type()) != contained) DUNE_THROW(GridError, "Mapper::contains() does not agree with the " "element's geometry type!"); if (!contained) continue; if (index != mapper.index(element)) DUNE_THROW(GridError, "Mapper::contains() and mapper.index() " "compute different indices!"); min = std::min(min, index); max = std::max(max, index); // typedef typename GridView::IntersectionIterator IntersectionIterator; // IntersectionIterator iIt = gridView.ibegin(element); // IntersectionIterator iEndIt = gridView.iend(element); // for (; iIt!=iEndIt; ++iIt) { // int oldindex = mapper.template map<1>(element, iIt->numberInSelf()); // int index = mapper.map(element, iIt->indexInInside(), 1); // assert(oldindex == index); // } [[maybe_unused]] const auto [it, wasInserted] = indices.insert(index); if (!wasInserted) // not inserted because already existing DUNE_THROW(GridError, "Mapper element index is not unique!"); } if (size!=indices.size()) DUNE_THROW(GridError, "Mapper size does not agree with the number of " "elements counted by iteration."); if (min!=0) DUNE_THROW(GridError, "Mapper element index is not starting from zero!"); if (max+1!=size) DUNE_THROW(GridError, "Mapper element index is not consecutive!"); } template void update(Dune::Mapper& mapper, const GV& gv) { mapper.update(gv); } int main (int argc, char** argv) try { // initialize MPI if necessary Dune :: MPIHelper::instance( argc, argv ); // //////////////////////////////////////////////////////////////////////// // Do the test for a 2d YaspGrid // //////////////////////////////////////////////////////////////////////// { static const int dim = 2; using Grid = YaspGrid; using ctype = Grid::ctype; Dune::FieldVector L(1.0); std::array s; std::fill(s.begin(), s.end(), 1); Grid grid(L, s); // create hybrid grid grid.mark(1, * grid.leafbegin<0>()); grid.adapt(); grid.globalRefine(1); using LeafGridView = typename Grid::LeafGridView; using LeafMapper = SingleCodimSingleGeomTypeMapper; LeafMapper leafMapper(grid.leafGridView()); using LevelGridView = typename Grid::LevelGridView; using LevelMapper = SingleCodimSingleGeomTypeMapper; std::vector levelMappers; for (int i=0; i<=grid.maxLevel(); i++) levelMappers.emplace_back(grid.levelGridView(i)); // Check mappers checkElementDataMapper(leafMapper, grid.leafGridView()); for (std::size_t i=0; i= 201907L) * (ii) The concepts in the standard library (i.e. __cpp_lib_concepts >= 202002L) * * - `gcc>=9` and `clang>=12` are known to fulfill (i) and (iii). * - `libstdc++>10` and `libc++>=13` are known to fulfill (ii). */ // check whether c++20 concept can be used #if __has_include() && __has_include() #include #if __cpp_concepts >= 201907L && __cpp_lib_concepts >= 202002L #ifndef DUNE_GRID_HAVE_CONCEPTS #define DUNE_GRID_HAVE_CONCEPTS 1 #endif #endif #endif //! Grid concepts are available #if DUNE_GRID_HAVE_CONCEPTS // Include all concept headers #include #include #include #include #include #include #include #include #include #include #endif // DUNE_GRID_HAVE_CONCEPTS #endif // DUNE_GRID_CONCEPTS_HH dune-grid-2.11.0/dune/grid/concepts/000077500000000000000000000000001511655130300171475ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/concepts/CMakeLists.txt000066400000000000000000000007171511655130300217140ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception install(FILES datahandle.hh entity.hh entityiterator.hh geometry.hh grid.hh gridview.hh indexidset.hh intersection.hh intersectioniterator.hh messagebuffer.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/concepts) add_subdirectory(archetypes)dune-grid-2.11.0/dune/grid/concepts/archetypes/000077500000000000000000000000001511655130300213165ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/concepts/archetypes/CMakeLists.txt000066400000000000000000000005111511655130300240530ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception install(FILES datahandle.hh entity.hh geometry.hh messagebuffer.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/concepts/archetypes) dune-grid-2.11.0/dune/grid/concepts/archetypes/datahandle.hh000066400000000000000000000021661511655130300237310ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_ARCHETYPES_COMMDATAHANDLE_HH #define DUNE_GRID_CONCEPTS_ARCHETYPES_COMMDATAHANDLE_HH #include #include #ifndef DOXYGEN namespace Dune::Concept::Archetypes { template struct CommDataHandle : public Dune::CommDataHandleIF, Data> { using DataType = Data; bool contains (int dim, int codim) const; bool fixedSize (int dim, int codim) const; template std::size_t size (const Entity& entity) const; template void gather (Buffer& buffer, const Entity& entity) const; template void scatter (Buffer& buffer, const Entity& entity, std::size_t size); }; } // end namespace Dune::Concept::Archetypes #endif // DOXYGEN #endif // DUNE_GRID_CONCEPTS_ARCHETYPES_COMMDATAHANDLE_HH dune-grid-2.11.0/dune/grid/concepts/archetypes/entity.hh000066400000000000000000000026701511655130300231600ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPT_ARCHETYPES_ENTITY_HH #define DUNE_GRID_CONCEPT_ARCHETYPES_ENTITY_HH #include #include #include #ifndef DOXYGEN namespace Dune::Concept::Archetypes { template struct EntitySeed { static constexpr int codimension = codim; bool isValid () const; }; template struct Entity { static constexpr int dimension = dim; static constexpr int codimension = codim; static constexpr int mydimension = dim - codim; using Geometry = Archetypes::Geometry; using EntitySeed = Archetypes::EntitySeed; int level () const; Dune::PartitionType partitionType () const; Geometry geometry () const; Dune::GeometryType type () const; unsigned int subEntities (int cd) const; EntitySeed seed () const; template Archetypes::Entity subEntity (int i) const; bool operator== (Entity const& entity) const; bool operator!= (Entity const& entity) const; }; } // end namespace Dune::Concept::Archetypes #endif // DOXYGEN #endif // DUNE_GRID_CONCEPT_ARCHETYPES_ENTITY_HH dune-grid-2.11.0/dune/grid/concepts/archetypes/geometry.hh000066400000000000000000000040061511655130300234720ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_ARCHETYPES_GEOMETRY_HH #define DUNE_GRID_CONCEPTS_ARCHETYPES_GEOMETRY_HH #include #include #include #ifndef DOXYGEN namespace Dune::Concept::Archetypes { struct ReferenceElement {}; template struct Geometry { static constexpr int mydimension = mydim; static constexpr int coorddimension = cdim; using ctype = double; using Volume = ctype; using LocalCoordinate = Dune::FieldVector; using GlobalCoordinate = Dune::FieldVector; using Jacobian = Dune::FieldMatrix; using JacobianTransposed = Dune::FieldMatrix; using JacobianInverse = Dune::FieldMatrix; using JacobianInverseTransposed = Dune::FieldMatrix; Dune::GeometryType type () const; bool affine () const; int corners () const; GlobalCoordinate corner (int i) const; GlobalCoordinate global (const LocalCoordinate& local) const; LocalCoordinate local (const GlobalCoordinate& global) const; GlobalCoordinate center () const; Volume integrationElement (const LocalCoordinate& local) const; Volume volume () const; Jacobian jacobian (const LocalCoordinate& local) const; JacobianTransposed jacobianTransposed (const LocalCoordinate& local) const; JacobianInverse jacobianInverse (const LocalCoordinate& local) const; JacobianInverseTransposed jacobianInverseTransposed (const LocalCoordinate& local) const; }; template Archetypes::ReferenceElement referenceElement (const Geometry& g); } // end namespace Dune::Concept::Archetypes #endif // DOXYGEN #endif // DUNE_GRID_CONCEPTS_ARCHETYPES_GEOMETRY_HH dune-grid-2.11.0/dune/grid/concepts/archetypes/messagebuffer.hh000066400000000000000000000012441511655130300244560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_ARCHETYPES_MESSAGEBUFFER_HH #define DUNE_GRID_CONCEPTS_ARCHETYPES_MESSAGEBUFFER_HH #ifndef DOXYGEN namespace Dune::Concept::Archetypes { template struct MessageBuffer { void write(const DataType& data); void read(DataType& data); }; } // end namespace Dune::Concept::Archetypes #endif // DOXYGEN #endif // DUNE_GRID_CONCEPTS_ARCHETYPES_MESSAGEBUFFER_HH dune-grid-2.11.0/dune/grid/concepts/datahandle.hh000066400000000000000000000023561511655130300215630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_DATAHANDLE_HH #define DUNE_GRID_CONCEPTS_DATAHANDLE_HH #include #include #include #include namespace Dune::Concept { template concept CommDataHandle = requires(const DH chandle, const Archetypes::Entity<2,0>& entity) { typename DH::DataType; { chandle.contains(/*dim*/ 0, /*codim*/ 0) } -> std::convertible_to; { chandle.fixedSize(/*dim*/ 0, /*codim*/ 0) } -> std::convertible_to; { chandle.size(entity) } -> std::integral; requires requires(DH handle, Archetypes::MessageBuffer buffer) { handle.gather(buffer, entity); handle.scatter(buffer, entity, /*size*/ 0u); }; }; static_assert(CommDataHandle< Archetypes::CommDataHandle >); } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_DATAHANDLE_HH dune-grid-2.11.0/dune/grid/concepts/entity.hh000066400000000000000000000103211511655130300210010ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPT_ENTITY_HH #define DUNE_GRID_CONCEPT_ENTITY_HH #include #include #include #include #include #include #include namespace Dune::Concept { /** * @brief Model of an entity seed * @ingroup GridConcepts * @details Dune::EntitySeed is a template for this model */ template concept EntitySeed = std::semiregular && requires(const S seed) { { S::codimension } -> std::convertible_to; { seed.isValid() } -> std::convertible_to; }; static_assert(EntitySeed< Archetypes::EntitySeed<0> >); /** * @brief Model of a grid entity for any codimension * @ingroup GridConcepts * @details Dune::Entity is a template for this model. */ template concept EntityGeneral = std::regular && Geometry && EntitySeed && requires(const E e, unsigned int codim) { requires E::mydimension == (E::dimension - E::codimension); { e.level() } -> std::convertible_to; { e.partitionType() } -> std::same_as; { e.geometry() } -> std::same_as; { e.type() } -> std::same_as; { e.subEntities(codim) } -> std::convertible_to; { e.seed() } -> std::same_as; }; static_assert(EntityGeneral< Archetypes::Entity<2,0> >); namespace Impl { // only check if Codim::Entity exists template concept EntityCodimExtended = ( !requires { typename E::template Codim::Entity; } ) || ( EntityGeneral::Entity> && requires(const E e, int subEntity) { { e.template subEntity(subEntity) } -> std::same_as::Entity>; } ); template void entityAllCodimsExtended(std::integer_sequence) requires (EntityCodimExtended &&...); } // end namespace Impl /** * @brief Model of a grid entity with extended requirements for codimension 0 * @ingroup GridConcepts * @details Dune::Entity of codimension 0 is a template for this model. * @note The type `typename E::template Codim<0>::Entity` is required to satisfy the EntityGeneral concept * only if the type exists (i.e. substitution failure is allowed). */ template concept EntityExtended = EntityGeneral && Geometry && requires(const E e, int maxLevel) { requires (E::codimension == 0); { e.father() } -> std::same_as; { e.hasFather() } -> std::convertible_to; { e.isLeaf() } -> std::convertible_to; { e.isRegular() } -> std::convertible_to; { e.geometryInFather() } -> std::same_as; { e.hbegin(maxLevel) } -> std::same_as; { e.hend(maxLevel) } -> std::same_as; { e.isNew() } -> std::convertible_to; { e.mightVanish() } -> std::convertible_to; { e.hasBoundaryIntersections() } -> std::convertible_to; requires std::same_as::Entity>; } && Impl::EntityCodimExtended && requires (index_constant<1> from, index_constant to) { Impl::entityAllCodimsExtended(range(from, to).to_integer_sequence()); }; /** * @brief Model of a grid entity * @ingroup GridConcepts * @details Codimension 0 entities are required to have an extended interface. * Dune::Entity is a template for this model. */ template concept Entity = EntityGeneral && ((E::codimension != 0) || EntityExtended); } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPT_ENTITY_HH dune-grid-2.11.0/dune/grid/concepts/entityiterator.hh000066400000000000000000000014771511655130300225670ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_ENTITY_ITERATOR_HH #define DUNE_GRID_CONCEPTS_ENTITY_ITERATOR_HH #include #include #include namespace Dune::Concept { /** * @brief Model of an entity iterator * @ingroup GridConcepts * @details Dune::EntityIterator is a template for this model */ template concept EntityIterator = std::forward_iterator && std::default_initializable && Entity; } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_ENTITY_ITERATOR_HH dune-grid-2.11.0/dune/grid/concepts/geometry.hh000066400000000000000000000046041511655130300213270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_GEOMETRY_HH #define DUNE_GRID_CONCEPTS_GEOMETRY_HH #include #include #include #include #include namespace Dune::Concept { template concept ReferenceElement = true; static_assert(ReferenceElement< Archetypes::ReferenceElement >); /** * @brief Model of a geometry object * @ingroup GridConcepts * @details Dune::Geometry is a template for this model */ template concept Geometry = requires(const G g, typename G::GlobalCoordinate global, typename G::LocalCoordinate local) { typename G::ctype; { G::mydimension } -> std::convertible_to; { G::coorddimension } -> std::convertible_to; { g.type() } -> std::same_as; { g.affine() } -> std::convertible_to; { g.corners() } -> std::convertible_to; { g.corner(/*i*/ int{}) } -> std::convertible_to; { g.global(local) } -> std::convertible_to; { g.local(global) } -> std::convertible_to; { g.integrationElement(local) } -> std::convertible_to; { g.volume() } -> std::convertible_to; { g.center() } -> std::convertible_to; { g.jacobian(local) } -> std::convertible_to; { g.jacobianInverse(local) } -> std::convertible_to; { g.jacobianTransposed(local) } -> std::convertible_to; { g.jacobianInverseTransposed(local) } -> std::convertible_to; { referenceElement(g) } -> ReferenceElement; }; static_assert(Geometry< Archetypes::Geometry<2,3> >); } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_GEOMETRY_HH dune-grid-2.11.0/dune/grid/concepts/grid.hh000066400000000000000000000152741511655130300204260ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_GRID_HH #define DUNE_GRID_CONCEPTS_GRID_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*!@defgroup GridConcepts Grid Concepts * @ingroup Grid * @{ * @par Description * This group gathers several concepts related to grids. * @} */ namespace Dune::Concept { namespace Impl { template concept GridCodimPartition = EntityIterator::template Partition::LevelIterator> && EntityIterator::template Partition::LeafIterator>; template concept GridCodimAllPartitions = ( !(Dune::Capabilities::hasEntityIterator::v) ) || ( GridCodimPartition && GridCodimPartition && GridCodimPartition && GridCodimPartition && GridCodimPartition && GridCodimPartition ); template concept GridCodim = ( !(Dune::Capabilities::hasEntity::v) ) || ( Geometry::Geometry> && Geometry::LocalGeometry> && Entity::Entity> && EntitySeed::EntitySeed> && std::same_as::Entity, typename G::template Codim<0>::Entity::template Codim::Entity> && std::same_as::Entity, typename G::LeafIndexSet::template Codim::Entity> && std::same_as::Entity, typename G::LevelIndexSet::template Codim::Entity> && requires(const G cg, const typename G::template Codim::EntitySeed& seed) { { cg.entity(seed) } -> std::convertible_to::Entity>; requires (not Dune::Capabilities::canCommunicate::v) || requires(G g, Archetypes::CommDataHandle& handle) { { g.loadBalance(handle) } -> std::convertible_to; }; } && GridCodimAllPartitions ); template void gridAllCodims(std::index_sequence) requires (GridCodim &&...); } // end namespace Impl /** * \brief Requirements for implementations of the Dune::Grid interface. * \ingroup GridConcepts * * The `Grid` concept defines interface requirements of a parallel, in general * nonconforming, locally refined and hierarchical finite element mesh. * It consists of sub-concepts for `Dune::Concept::GridView`, `Dune::Concept::IndexSet`, * `Dune::Concept::IdSet`, and `Dune::Concept::Intersection`. * * See \ref Dune::Grid for an "abstract" interface definition of this concept. * * \par Models: * - `Dune::AlbertaGrid` * - `Dune::GeometryGrid` if `G` is a model of `Dune::Concept::Grid`. * - `Dune::IdentityGrid` if `G` is a model of `Dune::Concept::Grid`. * - `Dune::OneDGrid` * - `Dune::UGGrid` * - `Dune::YaspGrid` * * \hideinitializer */ template concept Grid = GridView && GridView && Intersection && Intersection && IntersectionIterator && IntersectionIterator && IndexSet && IndexSet && IdSet && IdSet && requires(const G cg, int level, int codim, Dune::GeometryType type) { // static constants { G::dimension } -> std::convertible_to; { G::dimensionworld } -> std::convertible_to; // type and concepts requirements requires std::same_as; requires std::same_as; typename G::ctype; typename G::HierarchicIterator; // const methods { cg.maxLevel() } -> std::convertible_to; { cg.size(level, codim) } -> std::convertible_to; { cg.size(codim) } -> std::convertible_to; { cg.size(level, type) } -> std::convertible_to; { cg.size(type) } -> std::convertible_to; { cg.numBoundarySegments() } -> std::convertible_to; { cg.levelGridView(level) } -> std::same_as; { cg.leafGridView() } -> std::same_as; { cg.globalIdSet() } -> std::same_as; { cg.localIdSet() } -> std::same_as; { cg.levelIndexSet(level) } -> std::same_as; { cg.leafIndexSet() } -> std::same_as; { cg.comm() } -> std::convertible_to; // mutable methods requires requires(G g, int refCount, const typename G::template Codim<0>::Entity& entity) { { g.mark(refCount,entity) } -> std::convertible_to; { g.getMark(entity) } -> std::convertible_to; { g.preAdapt() } -> std::convertible_to; { g.adapt() } -> std::convertible_to; { g.loadBalance() } -> std::convertible_to; g.globalRefine(refCount); g.postAdapt(); }; } && Impl::GridCodim && requires (index_constant<1> from, index_constant to) { Impl::gridAllCodims(range(from, to).to_integer_sequence()); }; } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_GRID_HH dune-grid-2.11.0/dune/grid/concepts/gridview.hh000066400000000000000000000111221511655130300213050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_GRIDVIEW_HH #define DUNE_GRID_CONCEPTS_GRIDVIEW_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune::Concept { namespace Impl { template concept GridViewPartition = EntityIterator::template Partition::Iterator> && requires(const GV gv) { { gv.template begin() } -> std::same_as::template Partition::Iterator>; { gv.template end() } -> std::same_as::template Partition::Iterator>; }; template concept GridViewAllPartitions = GridViewPartition && GridViewPartition && GridViewPartition && GridViewPartition && GridViewPartition; template concept GridViewCodim = Geometry::Geometry> && Geometry::LocalGeometry> && EntityIterator::Iterator> && requires(const GV gv) { { gv.template begin() } -> std::same_as::Iterator>; { gv.template end() } -> std::same_as::Iterator>; } && GridViewAllPartitions; template requires Dune::Capabilities::hasEntityIterator::v void requireGridViewCodim() requires GridViewCodim {} template requires (not Dune::Capabilities::hasEntityIterator::v) void requireGridViewCodim() {} template void gridViewAllCodims(std::index_sequence) requires requires { (requireGridViewCodim(),...); }; } // end namespace Impl /** * @brief Model of a grid view * @ingroup GridConcepts * @details Dune::GridView is a template for this model */ template concept GridView = std::copyable && IndexSet && Intersection && IntersectionIterator && requires(const GV gv, int codim, Dune::GeometryType type) { typename GV::Traits; typename GV::ctype; { GV::conforming } -> std::convertible_to; { GV::dimension } -> std::convertible_to; { GV::dimensionworld } -> std::convertible_to; { gv.grid() } -> std::same_as; { gv.indexSet() } -> std::same_as; { gv.size(codim) } -> std::convertible_to; { gv.size(type) } -> std::convertible_to; { gv.comm() } -> std::convertible_to; { gv.overlapSize(codim) } -> std::convertible_to; { gv.ghostSize(codim) } -> std::convertible_to; requires requires(Archetypes::CommDataHandle& handle, InterfaceType iface, CommunicationDirection dir) { gv.communicate(handle, iface, dir); }; } && ( !Dune::Capabilities::hasEntity::v || requires(const GV gv, const typename GV::template Codim<0>::Entity& entity) { { gv.ibegin(entity) } -> std::same_as; { gv.iend(entity) } -> std::same_as; } ) && Impl::GridViewCodim && requires (index_constant<1> from, index_constant to) { Impl::gridViewAllCodims(range(from, to).to_integer_sequence()); }; } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_GRIDVIEW_HH dune-grid-2.11.0/dune/grid/concepts/indexidset.hh000066400000000000000000000102421511655130300216270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_INDEX_SET_HH #define DUNE_GRID_CONCEPTS_INDEX_SET_HH #include #include #include #include #include #include #include namespace Dune::Concept { namespace Impl { // only check if Codim::Entity exists template concept IndexSetEntityCodim = ( !requires { typename IS::template Codim::Entity; } ) || ( Entity::Entity> && requires(const IS is, int i, unsigned int cc, const typename IS::template Codim::Entity& entity) { { is.template index(entity) } -> std::same_as; { is.index(entity) } -> std::same_as; { is.template subIndex(entity,i,cc) } -> std::same_as; { is.subIndex(entity,i,cc) } -> std::same_as; { is.contains(entity) } -> std::convertible_to; } ); template void indexSetEntityAllCodims(std::integer_sequence) requires (IndexSetEntityCodim &&...); } // end namespace Impl /** * @brief Model of an index set * @ingroup GridConcepts * @details Dune::Grid::LevelIndexSet and Dune::Grid::LeafIndexSet are templates * for this model * @note The type `typename IS::template Codim<0>::Entity` is required to satisfy the EntityGeneral concept * only if the type exists (i.e. substitution failure is allowed). */ template concept IndexSet = requires(const IS is, Dune::GeometryType type, int codim) { { IS::dimension } -> std::convertible_to; requires RandomAccessContainer; { is.types(codim) } -> std::convertible_to; requires std::integral; { is.size(type) } -> std::convertible_to; { is.size(codim) } -> std::convertible_to; } && Impl::IndexSetEntityCodim && requires (index_constant<1> from, index_constant to) { Impl::indexSetEntityAllCodims(range(from, to).to_integer_sequence()); }; namespace Impl { // only check if Codim::Entity exists template concept IdSetEntityCodim = ( !requires { typename IS::template Codim::Entity; } ) || ( Entity::Entity> && requires(const IS is, const typename IS::template Codim::Entity& entity) { { is.template id(entity) } -> std::same_as; { is.id(entity) } -> std::same_as; } ); template void idSetEntityAllCodims(std::integer_sequence) requires (IdSetEntityCodim &&...); } // end namespace Impl /** * @brief Model of an id set * @ingroup GridConcepts * @details Dune::Grid::GlobalIdSet and Dune::Grid::LocalIdSet are templates * for this model * @note The type `typename IS::template Codim<0>::Entity` is required to satisfy the EntityGeneral concept * only if the type exists (i.e. substitution failure is allowed). */ template concept IdSet = requires(const IS is, const typename IS::template Codim<0>::Entity& entity, int i, unsigned int cc) { requires Hashable; requires std::totally_ordered; { is.subId(entity,i,cc) } -> std::same_as; } && Impl::IdSetEntityCodim && requires (index_constant<1> from, index_constant to) { Impl::idSetEntityAllCodims(range(from, to).to_integer_sequence()); }; } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_INDEX_SET_HH dune-grid-2.11.0/dune/grid/concepts/intersection.hh000066400000000000000000000045311511655130300222010ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_INTERSECTION_HH #define DUNE_GRID_CONCEPTS_INTERSECTION_HH #include #include #include #include #include namespace Dune::Concept { /** * @brief Model of an intersection * @ingroup GridConcepts * @details Dune::Grid::Intersection is a template for this model */ template concept Intersection = std::regular && EntityGeneral && Geometry && Geometry && requires(const I i, typename I::LocalCoordinate local) { typename I::ctype; { I::mydimension } -> std::convertible_to; { I::dimensionworld } -> std::convertible_to; { i.boundary() } -> std::convertible_to; { i.boundarySegmentIndex() } -> std::convertible_to; { i.neighbor() } -> std::convertible_to; { i.inside() } -> std::same_as; { i.outside() } -> std::same_as; { i.conforming() } -> std::convertible_to; { i.geometryInInside() } -> std::same_as; { i.geometryInOutside() } -> std::same_as; { i.geometry() } -> std::same_as; { i.type() } -> std::same_as; { i.indexInInside() } -> std::convertible_to; { i.indexInOutside() } -> std::convertible_to; { i.outerNormal(local) } -> std::convertible_to; { i.integrationOuterNormal(local) } -> std::convertible_to; { i.unitOuterNormal(local) } -> std::convertible_to; { i.centerUnitOuterNormal() } -> std::convertible_to; }; } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_INTERSECTION_HH dune-grid-2.11.0/dune/grid/concepts/intersectioniterator.hh000066400000000000000000000015651511655130300237570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPTS_INTERSECTION_ITERATOR_HH #define DUNE_GRID_CONCEPTS_INTERSECTION_ITERATOR_HH #include #include #include namespace Dune::Concept { /** * @brief Model of an intersection iterator * @ingroup GridConcepts * @details Dune::IntersectionIterator is a template for this model */ template concept IntersectionIterator = std::forward_iterator && std::default_initializable && Intersection; } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPTS_INTERSECTION_ITERATOR_HH dune-grid-2.11.0/dune/grid/concepts/messagebuffer.hh000066400000000000000000000014661511655130300223150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CONCEPT_MESSAGEBUFFER_HH #define DUNE_GRID_CONCEPT_MESSAGEBUFFER_HH #include namespace Dune::Concept { /** * @brief Model of a message buffer * @ingroup GridConcepts */ template concept MessageBuffer = requires(MB mb, DataType& data) { mb.write(data); mb.read(data); }; static_assert(Concept::MessageBuffer, unsigned char>); } // end namespace Dune::Concept #endif // DUNE_GRID_CONCEPT_MESSAGEBUFFER_HH dune-grid-2.11.0/dune/grid/geometrygrid.hh000066400000000000000000000135451511655130300203630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include /** \addtogroup GeoGrid * * The GeometryGrid is an implementation of the DUNE grid interface that can * wrap any other DUNE grid (called host grid) and replace its geometry. * To this end, the grid also gets a coordinate function that maps the corners * of the host grid into any larger Euklidian space. * The generic geometries are then used to provide a geometry implementation * for the grid, interpolating the corners in a linear (respectively n-linear) * manner. * * \image html helix.png * The figure above displays a GeometryGrid< YaspGrid< 2 >, Helix >, * where Helix models the following coordinate function: * \f[ * \left(\begin{array}{c}r\\\varphi\end{array}\right) * \mapsto * \left(\begin{array}{c} * (r + \frac{1}{5}) \cos( 2 \pi \varphi )\\ * (r + \frac{1}{5}) \sin( 2 \pi \varphi )\\ * \varphi * \end{array}\right). * \f] * Though YaspGrid can only model planar, Cartesian grids, using GeometryGrid * we have obtained a nonplanar surface grid with quadrilateral elements. * * \section features Features * * Features of the GeometryGrid include: * - Complete wrapper of the host grid * (i.e., no non-geometric feature of the host grid is lost) * - Only uses the coordinate of the corners of each entity - * no other geometric information needs to be provided. * - Provides entities for all codimensions, even if the host grid does not * (though communication is not extended to these codimensions) * . * * \section usage Usage * * There are two different construction mechanisms for a geometry grid. * They differ in how the new geometry is provided. * - The geometry can be specified by giving a global functions that maps the * world space of the host grid to another Euclidean space. In principle * this target space can have any dimension, but in practice its dimension will * be larger than or equal to the dimension of the host grid world. * The function will be evaluated at the vertex positions of the host grid. * It may be given analytically or defined on some grid. In the latter * case note, however, that the function arguments are global coordinates * and you may have efficiency problems. * - The geometry can also be specified by giving a vector containing new positions * for each vertex of the host grid. * . * Remark: for the second case no geometry class has to be implemented by the * host grid. * In the first case the host grid must provide an implementation of * the method corner on the geometry class for codimension * zero entity. * * The approach taken is determined by the second template argument: \code GeometryGrid grid(hostGrid,coordFunction); \endcode * The class \c CoordFunction must either be derived from * Dune::AnalyticalCoordFunction or from Dune::DiscreteCoordFunction. * If you want to use the first approach derive from Dune::AnalyticalCoordFunction. * An example of a analytical coordinate function is given by the following code: \code class ExampleFunction : public Dune :: AnalyticalCoordFunction< double, 2, 3, ExampleFunction > { typedef ExampleFunction This; typedef Dune :: AnalyticalCoordFunction< double, 2, 3, This > Base; public: typedef Base :: DomainVector DomainVector; typedef Base :: RangeVector RangeVector; void evaluate ( const DomainVector &x, RangeVector &y ) const { y[ 0 ] = x[ 0 ]; y[ 1 ] = x[ 1 ]; y[ 2 ] = x[ 0 ] + x[ 1 ]; } }; \endcode * * If you want to prescribe your geometry by a set of coordinates you have to write * a deformation class and have it derive from Dune::DiscreteCoordFunction. * An example is given by the following code snippet. Central to the class are the * two evaluate methods. The first one accepts a host grid vertex and computes its new * position. The second one accepts an element and a local corner number and * computes the position of this corner. It is trivial to implement this using the * first evaluate method, and I don't know why it isn't done by default. \code template class DeformationFunction : public Dune :: DiscreteCoordFunction< double, dim, DeformationFunction > { typedef DeformationFunction This; typedef Dune :: DiscreteCoordFunction< double, dim, This > Base; public: DeformationFunction(const GridView& gridView, const double* deformedPosition) : gridView_(gridView), deformedPosition_(deformedPosition) {} void evaluate ( const typename GridView::template Codim::Entity& hostEntity, unsigned int corner, FieldVector &y ) const { const typename GridView::IndexSet& indexSet = gridView_.indexSet(); int idx = indexSet.index(hostEntity); for (int i=0; i::Entity& hostEntity, unsigned int corner, FieldVector &y ) const { const typename GridView::IndexSet& indexSet = gridView_.indexSet(); int idx = indexSet.subIndex(hostEntity, corner,dim); for (int i=0; i #include #include #include #include namespace Dune { namespace GeoGrid { // BackupRestoreFacilities // ----------------------- template< class Grid, bool hasBackupRestoreFacilities = Capabilities::hasBackupRestoreFacilities< Grid > ::v > class BackupRestoreFacilities {}; template< class Grid > class BackupRestoreFacilities< Grid, true > { typedef BackupRestoreFacilities< Grid, true > This; protected: BackupRestoreFacilities () {} private: BackupRestoreFacilities ( const This & ); This &operator= ( const This & ); protected: const Grid &asImp () const { return static_cast< const Grid & >( *this ); } Grid &asImp () { return static_cast< Grid & >( *this ); } }; } // namespace GeoGrid // BackupRestoreFacility for GeometryGrid // -------------------------------------- template< class HostGrid, class CoordFunction, class Allocator > struct BackupRestoreFacility< GeometryGrid< HostGrid, CoordFunction, Allocator > > { typedef GeometryGrid< HostGrid, CoordFunction, Allocator > Grid; typedef BackupRestoreFacility< HostGrid > HostBackupRestoreFacility; /// \brief Backup the grid to file or stream template static void backup ( const Grid &grid, const Output &filename_or_stream ) { // notice: We should also backup the coordinate function HostBackupRestoreFacility::backup( grid.hostGrid(), filename_or_stream ); } /// \brief Restore the grid from file or stream template static Grid *restore ( const Input &filename_or_stream ) { // notice: assumes the CoordFunction to be default-constructible return restore_impl(filename_or_stream, std::is_default_constructible{}); } private: template static Grid *restore_impl ( const Input &filename_or_stream, std::true_type ) { // notice: We should also restore the coordinate function HostGrid *hostGrid = HostBackupRestoreFacility::restore( filename_or_stream ); CoordFunction *coordFunction = new CoordFunction(); return new Grid( hostGrid, coordFunction ); } template static Grid *restore_impl ( const Input &filename_stream, std::false_type ) { DUNE_THROW(NotImplemented, "Restoring a GeometryGrid with a CoordFunction that is not default-constructible is not implemented."); return nullptr; } }; } // namespace Dune #endif // #ifndef DUNE_GEOGRID_BACKUPRESTORE_HH dune-grid-2.11.0/dune/grid/geometrygrid/cachedcoordfunction.hh000066400000000000000000000132771511655130300243710ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_CACHEDCOORDFUNCTION_HH #define DUNE_GEOGRID_CACHEDCOORDFUNCTION_HH #include #include #include #include #include #include #include namespace Dune { // Internal Forward Declarations // ----------------------------- template< class HostGrid, class CoordFunction > class CachedCoordFunction; // GeoGrid::CoordCache // ------------------- namespace GeoGrid { template< class HostGrid, class Coordinate > class CoordCache { typedef CoordCache< HostGrid, Coordinate > This; static const unsigned int dimension = HostGrid::dimension; typedef typename HostGrid::template Codim< dimension >::Entity Vertex; typedef PersistentContainer< HostGrid, Coordinate > DataCache; public: explicit CoordCache ( const HostGrid &hostGrid ) : data_( hostGrid, dimension ) {} template< class Entity > const Coordinate &operator() ( const Entity &entity, unsigned int corner ) const { return data_( entity, corner ); } const Coordinate &operator() ( const Vertex &vertex, unsigned int corner ) const { assert( corner == 0 ); return data_[ vertex ]; } template< class Entity > Coordinate &operator() ( const Entity &entity, unsigned int corner ) { return data_( entity,corner) ; } Coordinate &operator() ( const Vertex &vertex, unsigned int corner ) { assert( corner == 0 ); return data_[ vertex ]; } void adapt () { data_.resize(); data_.shrinkToFit(); } private: CoordCache ( const This & ); This &operator= ( const This & ); DataCache data_; }; } // namespace GeoGrid // CachedCoordFunction // ------------------- template< class HostGrid, class CoordFunction > class CachedCoordFunction : public DiscreteCoordFunction< typename CoordFunction::ctype, CoordFunction::dimRange, CachedCoordFunction< HostGrid, CoordFunction > > { typedef CachedCoordFunction< HostGrid, CoordFunction > This; typedef DiscreteCoordFunction< typename CoordFunction::ctype, CoordFunction::dimRange, This > Base; public: typedef typename Base::ctype ctype; typedef typename Base::RangeVector RangeVector; private: typedef GeoGrid::CoordCache< HostGrid, RangeVector > Cache; public: explicit CachedCoordFunction ( const HostGrid &hostGrid, const CoordFunction &coordFunction = CoordFunction() ) : hostGrid_( hostGrid ), coordFunction_( coordFunction ), cache_( hostGrid ) { buildCache(); } void adapt () { cache_.adapt(); buildCache(); } void buildCache (); template< class HostEntity > void insertEntity ( const HostEntity &hostEntity ); template< class HostEntity > void evaluate ( const HostEntity &hostEntity, unsigned int corner, RangeVector &y ) const { y = cache_( hostEntity, corner ); #ifndef NDEBUG typedef GeoGrid::CoordFunctionCaller< HostEntity, typename CoordFunction::Interface > CoordFunctionCaller; RangeVector z; CoordFunctionCaller coordFunctionCaller( hostEntity, coordFunction_ ); coordFunctionCaller.evaluate( corner, z ); assert( ((y - z).two_norm() < 1e-6) ); #endif } private: const HostGrid &hostGrid_; const CoordFunction &coordFunction_; Cache cache_; }; // Implementation of CachedCoordFunction // ------------------------------------- template< class HostGrid, class CoordFunction > inline void CachedCoordFunction< HostGrid, CoordFunction >::buildCache () { typedef typename HostGrid::template Codim< 0 >::Entity Element; typedef typename HostGrid::LevelGridView MacroView; typedef typename HostGrid::HierarchicIterator HierarchicIterator; typedef typename MacroView::template Codim< 0 >::template Partition< All_Partition >::Iterator MacroIterator; const MacroView macroView = hostGrid_.levelGridView( 0 ); const int maxLevel = hostGrid_.maxLevel(); const MacroIterator mend = macroView.template end< 0, All_Partition >(); for( MacroIterator mit = macroView.template begin< 0, All_Partition >(); mit != mend; ++mit ) { const Element ¯oElement = *mit; insertEntity( macroElement ); const HierarchicIterator hend = macroElement.hend( maxLevel ); for( HierarchicIterator hit = macroElement.hbegin( maxLevel ); hit != hend; ++hit ) insertEntity( *hit ); } } template< class HostGrid, class CoordFunction > template< class HostEntity > inline void CachedCoordFunction< HostGrid, CoordFunction > ::insertEntity ( const HostEntity &hostEntity ) { typedef GeoGrid::CoordFunctionCaller< HostEntity, typename CoordFunction::Interface > CoordFunctionCaller; CoordFunctionCaller coordFunctionCaller( hostEntity, coordFunction_ ); auto refElement = referenceElement< ctype, HostEntity::dimension >( hostEntity.type() ); const unsigned int numCorners = refElement.size( HostEntity::dimension ); for( unsigned int i = 0; i < numCorners; ++i ) coordFunctionCaller.evaluate( i, cache_( hostEntity, i ) ); } } // namespace Dune #endif // #ifndef DUNE_GEOGRID_CACHEDCOORDFUNCTION_HH dune-grid-2.11.0/dune/grid/geometrygrid/capabilities.hh000066400000000000000000000102441511655130300230050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_CAPABILITIES_HH #define DUNE_GEOGRID_CAPABILITIES_HH #include #include #include #include #include #include namespace Dune { // Capabilities // ------------ namespace Capabilities { // Capabilities from dune-grid // --------------------------- template< class HostGrid, class CoordFunction, class Allocator > struct hasSingleGeometryType< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static const bool v = hasSingleGeometryType< HostGrid > :: v; static const unsigned int topologyId = hasSingleGeometryType< HostGrid > :: topologyId; }; template< class HostGrid, class CoordFunction, class Allocator, int codim > struct hasEntity< GeometryGrid< HostGrid, CoordFunction, Allocator >, codim > { static const bool v = true; }; template< class HostGrid, class CoordFunction, class Allocator, int codim > struct hasEntityIterator< GeometryGrid< HostGrid, CoordFunction, Allocator >, codim > { static const bool v = hasEntityIterator::v; }; template< class HostGrid, class CoordFunction, class Allocator, int codim > struct canCommunicate< GeometryGrid< HostGrid, CoordFunction, Allocator >, codim > { static const bool v = canCommunicate< HostGrid, codim >::v && hasEntity< HostGrid, codim >::v; }; template< class HostGrid, class CoordFunction, class Allocator > struct hasBackupRestoreFacilities< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static const bool v = hasBackupRestoreFacilities< HostGrid >::v && std::is_default_constructible< CoordFunction >::value; }; template< class HostGrid, class CoordFunction, class Allocator > struct isLevelwiseConforming< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static const bool v = isLevelwiseConforming< HostGrid >::v; }; template< class HostGrid, class CoordFunction, class Allocator > struct isLeafwiseConforming< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static const bool v = isLeafwiseConforming< HostGrid >::v; }; template< class HostGrid, class CoordFunction, class Allocator > struct threadSafe< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static const bool v = false; }; template< class HostGrid, class CoordFunction, class Allocator > struct viewThreadSafe< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static const bool v = false; }; // hasHostEntity // ------------- template< class Grid, int codim > struct hasHostEntity; template< class Grid, int codim > struct hasHostEntity< const Grid, codim > { static const bool v = hasHostEntity< Grid, codim >::v; }; template< class HostGrid, class CoordFunction, class Allocator, int codim > struct hasHostEntity< GeometryGrid< HostGrid, CoordFunction, Allocator >, codim > { static const bool v = hasEntity< HostGrid, codim >::v; }; // CodimCache // ---------- template< class Grid > class CodimCache { static const int dimension = Grid::dimension; bool hasHostEntity_[ Grid::dimension + 1 ]; CodimCache () { Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ hasHostEntity_[ i ] = Capabilities::hasHostEntity< Grid, i >::v; } ); } static CodimCache &instance () { static CodimCache singleton; return singleton; } public: static bool hasHostEntity ( int codim ) { assert( (codim >= 0) && (codim <= dimension) ); return instance().hasHostEntity_[ codim ]; } }; } // namespace Capabilities } // namespace Dune #endif // #ifndef DUNE_GEOGRID_CAPABILITIES_HH dune-grid-2.11.0/dune/grid/geometrygrid/coordfunction.hh000066400000000000000000000240051511655130300232300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_COORDFUNCTION_HH #define DUNE_GEOGRID_COORDFUNCTION_HH #include #include #include namespace Dune { // Internal Forward Declarations // ----------------------------- template< class ct, unsigned int dimD, unsigned int dimR, class Impl > class AnalyticalCoordFunction; template< class ct, unsigned int dimR, class Impl > class DiscreteCoordFunction; // AnalyticalCoordFunctionInterface // -------------------------------- /** \brief Interface class for using an analytical function to define the * geometry of a Dune::GeometryGrid. An implementation should be derived * from Dune::AnalyticalCoordFunction and the evaluate * method mapping \f$ R^d\to R^r \f$ has to be supplied. * * \tparam ct coordinate field type (\c ct in Dune::GeometryGrid) * \tparam dimD dimension of the domain of the mapping (\c dimension * in the host grid). * \tparam dimR dimension of the range of the mapping (\c dimensionworld * in Dune::GeometryGrid) * \tparam Impl implementation class (BN trick) **/ template< class ct, unsigned int dimD, unsigned int dimR, class Impl > class AnalyticalCoordFunctionInterface { typedef AnalyticalCoordFunctionInterface< ct, dimD, dimR, Impl > This; friend class AnalyticalCoordFunction< ct, dimD, dimR, Impl >; public: typedef This Interface; typedef Impl Implementation; //! field type of the coordinate vector typedef ct ctype; //! dimension of the range vector (dimensionworld of host grid) static const unsigned int dimDomain = dimD; //! dimension of the range vector static const unsigned int dimRange = dimR; //! domain vector for the evaluate method typedef FieldVector< ctype, dimDomain > DomainVector; //! range vector for the evaluate method typedef FieldVector< ctype, dimRange > RangeVector; private: AnalyticalCoordFunctionInterface () = default; AnalyticalCoordFunctionInterface ( const This & ) = default; AnalyticalCoordFunctionInterface ( This && ) = default; ~AnalyticalCoordFunctionInterface () = default; This &operator= ( const This & ) = default; This &operator= ( This && ) = default; // helper for picking the correct version of evaluate further down template using has_operator_parentheses = decltype(std::declval()(std::declval())); public: #ifdef DOXYGEN //! evaluate method for global mapping void evaluate ( const DomainVector &x, RangeVector &y ) const; #else template std::enable_if_t< Std::is_detected::value > evaluate ( const DV &x, RangeVector &y ) const { y = asImp()(x); } template std::enable_if_t< not Std::is_detected::value > evaluate ( const DV &x, RangeVector &y ) const { assert( static_cast(&This::evaluate) != static_cast(&Impl::evaluate) && "You need to implement either operator() or evaluate() in your coordinate function!"); asImp().evaluate( x, y ); } #endif // DOXYGEN protected: const Implementation &asImp () const { return static_cast< const Implementation & >( *this ); } Implementation &asImp () { return static_cast< Implementation & >( *this ); } }; // AnalyticalCoordFunction // ----------------------- /** @brief Derive an implementation of an analytical coordinate function * from this class. **/ template< class ct, unsigned int dimD, unsigned int dimR, class Impl > class AnalyticalCoordFunction : public AnalyticalCoordFunctionInterface< ct, dimD, dimR, Impl > { typedef AnalyticalCoordFunction< ct, dimD, dimR, Impl > This; typedef AnalyticalCoordFunctionInterface< ct, dimD, dimR, Impl > Base; public: typedef typename Base :: DomainVector DomainVector; typedef typename Base :: RangeVector RangeVector; protected: AnalyticalCoordFunction () = default; AnalyticalCoordFunction ( const This & ) = default; AnalyticalCoordFunction ( This && ) = default; ~AnalyticalCoordFunction () = default; This &operator= ( const This & ) = default; This &operator= ( This && ) = default; private: }; // DiscreteCoordFunctionInterface // ------------------------------ /** \brief Interface class for using a discrete function to define the * geometry of a Dune::GeometryGrid. An implementation should be derived * from Dune::DiscreteCoordinateFunction and the evaluate method taking an entity * of the host grid together with the number of a vertex returns the coordinate in * \f$ R^r \f$ * of that corner. The user must ensure continuity of this mapping. * In addition an adapt method is provided which is called whenever * \c adapt() is called on the Dune::GeometryGrid. * * \tparam ct coordinate field type (\c ct in Dune::GeometryGrid) * \tparam dimR dimension of the range of the mapping (\c dimensionworld * in Dune::GeometryGrid) * \tparam Impl implementation class (BN trick) **/ template< class ct, unsigned int dimR, class Impl > class DiscreteCoordFunctionInterface { typedef DiscreteCoordFunctionInterface< ct, dimR, Impl > This; friend class DiscreteCoordFunction< ct, dimR, Impl >; public: typedef This Interface; typedef Impl Implementation; //! field type of the coordinate vector typedef ct ctype; //! dimension of the range vector static const unsigned int dimRange = dimR; //! range vector for the evaluate method typedef FieldVector< ctype, dimRange > RangeVector; private: DiscreteCoordFunctionInterface () = default; DiscreteCoordFunctionInterface ( const This & ) = default; DiscreteCoordFunctionInterface ( This && ) = default; ~DiscreteCoordFunctionInterface () = default; This &operator= ( const This & ) = default; This &operator= ( This && ) = default; public: /** \brief evaluate method * \param hostEntity an entity of the host grid * \param corner the local number of the corner in the host entity * \param y return value for the coordinate of this corner * * \note This method needs to work for entities of all codimensions, * not just for elements! **/ template< class HostEntity > void evaluate ( const HostEntity &hostEntity, unsigned int corner, RangeVector &y ) const { asImp().evaluate( hostEntity, corner, y ); } /** \brief method called from grid.adapt() method to allow adaptation * of the discrete coordinate function **/ void adapt () { asImp().adapt(); } protected: const Implementation &asImp () const { return static_cast< const Implementation & >( *this ); } Implementation &asImp () { return static_cast< Implementation & >( *this ); } }; // DiscreteCoordFunction // --------------------- // /** @brief Derive an implementation of a discrete coordinate function * from this class. **/ template< class ct, unsigned int dimR, class Impl > class DiscreteCoordFunction : public DiscreteCoordFunctionInterface< ct, dimR, Impl > { typedef DiscreteCoordFunction< ct, dimR, Impl > This; typedef DiscreteCoordFunctionInterface< ct, dimR, Impl > Base; public: typedef typename Base :: RangeVector RangeVector; protected: DiscreteCoordFunction () = default; DiscreteCoordFunction ( const This & ) = default; DiscreteCoordFunction ( This && ) = default; ~DiscreteCoordFunction () = default; This &operator= ( const This & ) = default; This &operator= ( This && ) = default; void adapt () {} private: template< class HostEntity > void evaluate ( const HostEntity &hostEntity, unsigned int corner, RangeVector &y ) const; }; namespace GeoGrid { // isCoordFunctionInterface // ------------------------ template< class CoordFunctionInterface > struct isCoordFunctionInterface { static const bool value = false; }; template< class ct, unsigned int dimD, unsigned int dimR, class Impl > struct isCoordFunctionInterface < AnalyticalCoordFunctionInterface< ct, dimD, dimR, Impl > > { static const bool value = true; }; template< class ct, unsigned int dimR, class Impl > struct isCoordFunctionInterface < DiscreteCoordFunctionInterface< ct, dimR, Impl > > { static const bool value = true; }; // isDiscreteCoordFunctionInterface // -------------------------------- template< class CoordFunctionInterface > struct isDiscreteCoordFunctionInterface { static const bool value = false; }; template< class ct, unsigned int dimR, class Impl > struct isDiscreteCoordFunctionInterface < DiscreteCoordFunctionInterface< ct, dimR, Impl > > { static const bool value = true; }; // AdaptCoordFunction // ------------------ template< class CoordFunctionInterface > struct AdaptCoordFunction { static void adapt ( CoordFunctionInterface & ) {} }; template< class ct, unsigned int dimR, class Impl > struct AdaptCoordFunction< DiscreteCoordFunctionInterface< ct, dimR, Impl > > { typedef DiscreteCoordFunctionInterface< ct, dimR, Impl > CoordFunctionInterface; static void adapt ( CoordFunctionInterface &coordFunction ) { coordFunction.adapt(); } }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_COORDFUNCTION_HH dune-grid-2.11.0/dune/grid/geometrygrid/coordfunctioncaller.hh000066400000000000000000000060211511655130300244110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_COORDFUNCTIONCALLER_HH #define DUNE_GEOGRID_COORDFUNCTIONCALLER_HH #include #include namespace Dune { namespace GeoGrid { // CoordFunctionCaller // ------------------- template< class HostEntity, class CoordFunctionInterface > class CoordFunctionCaller; template< class HostEntity, class ct, unsigned int dimD, unsigned int dimR, class Impl > class CoordFunctionCaller< HostEntity, AnalyticalCoordFunctionInterface< ct, dimD, dimR, Impl > > { typedef AnalyticalCoordFunctionInterface< ct, dimD, dimR, Impl > CoordFunctionInterface; typedef CoordFunctionCaller< HostEntity, CoordFunctionInterface > This; static const int codimension = HostEntity::codimension; public: typedef typename CoordFunctionInterface::RangeVector RangeVector; CoordFunctionCaller ( const HostEntity &hostEntity, const CoordFunctionInterface &coordFunction ) : hostCorners_( hostEntity ), coordFunction_( coordFunction ) {} void evaluate ( unsigned int i, RangeVector &y ) const { coordFunction_.evaluate( hostCorners_[ i ], y ); } GeometryType type () const { return hostCorners_.type(); } std::size_t size () const { return hostCorners_.size(); } private: const HostCorners< HostEntity > hostCorners_; const CoordFunctionInterface &coordFunction_; }; template< class HostEntity, class ct, unsigned int dimR, class Impl > class CoordFunctionCaller< HostEntity, DiscreteCoordFunctionInterface< ct, dimR, Impl > > { typedef DiscreteCoordFunctionInterface< ct, dimR, Impl > CoordFunctionInterface; typedef CoordFunctionCaller< HostEntity, CoordFunctionInterface > This; typedef typename CoordFunctionInterface::RangeVector RangeVector; public: CoordFunctionCaller ( const HostEntity &hostEntity, const CoordFunctionInterface &coordFunction ) : hostEntity_( hostEntity ), coordFunction_( coordFunction ) {} void evaluate ( unsigned int i, RangeVector &y ) const { coordFunction_.evaluate( hostEntity_, i, y ); } GeometryType type () const { return hostEntity_.type(); } std::size_t size () const { auto refElement = referenceElement< ct, HostEntity::mydimension >( type() ); return refElement.size( HostEntity::mydimension ); } private: const HostEntity &hostEntity_; const CoordFunctionInterface &coordFunction_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_COORDFUNCTIONCALLER_HH dune-grid-2.11.0/dune/grid/geometrygrid/cornerstorage.hh000066400000000000000000000147341511655130300232410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_CORNERSTORAGE_HH #define DUNE_GEOGRID_CORNERSTORAGE_HH #include #include namespace Dune { namespace GeoGrid { // CoordVector // ----------- template< int mydim, class Grid, bool fake > class CoordVector; template< int mydim, class Grid > class CoordVector< mydim, Grid, false > { typedef typename std::remove_const< Grid >::type::Traits Traits; typedef typename Traits::ctype ctype; static const int dimension = Traits::dimension; static const int mydimension = mydim; static const int codimension = dimension - mydimension; static const int dimensionworld = Traits::dimensionworld; typedef FieldVector< ctype, dimensionworld > Coordinate; typedef typename Traits::HostGrid HostGrid; typedef typename Traits::CoordFunction CoordFunction; typedef typename HostGrid::template Codim< codimension >::Entity HostEntity; typedef GeoGrid :: CoordFunctionCaller< HostEntity, typename CoordFunction::Interface > CoordFunctionCaller; public: CoordVector ( const HostEntity &hostEntity, const CoordFunction &coordFunction ) : coordFunctionCaller_( hostEntity, coordFunction ) {} template< std::size_t size > void calculate ( std::array< Coordinate, size > (&corners) ) const { const std::size_t numCorners = coordFunctionCaller_.size(); assert( size >= numCorners ); for( std::size_t i = 0; i < numCorners; ++i ) coordFunctionCaller_.evaluate( i, corners[ i ] ); } private: const CoordFunctionCaller coordFunctionCaller_; }; template< int mydim, class Grid > class CoordVector< mydim, Grid, true > { typedef typename std::remove_const< Grid > :: type :: Traits Traits; typedef typename Traits::ctype ctype; static const int dimension = Traits::dimension; static const int mydimension = mydim; static const int codimension = dimension - mydimension; static const int dimensionworld = Traits::dimensionworld; typedef FieldVector< ctype, dimensionworld > Coordinate; typedef typename Traits::HostGrid HostGrid; typedef typename Traits::CoordFunction CoordFunction; typedef typename HostGrid::template Codim< 0 >::Entity HostElement; typedef GeoGrid::CoordFunctionCaller< HostElement, typename CoordFunction::Interface > CoordFunctionCaller; public: CoordVector ( const HostElement &hostElement, const unsigned int subEntity, const CoordFunction &coordFunction ) : coordFunctionCaller_( hostElement, coordFunction ), subEntity_( subEntity ) {} template< std::size_t size > void calculate ( std::array< Coordinate, size > (&corners) ) const { const GeometryType type = coordFunctionCaller_.type(); auto refElement = referenceElement< ctype, dimension >( type ); const std::size_t numCorners = refElement.size( subEntity_, codimension, dimension ); assert( size >= numCorners ); for( std::size_t i = 0; i < numCorners; ++i ) { const std::size_t j = refElement.subEntity( subEntity_, codimension, i, dimension ); coordFunctionCaller_.evaluate( j, corners[ i ] ); } } private: const CoordFunctionCaller coordFunctionCaller_; const unsigned int subEntity_; }; // IntersectionCoordVector // ----------------------- template< class Grid > class IntersectionCoordVector { typedef typename std::remove_const< Grid >::type::Traits Traits; typedef typename Traits::ctype ctype; static const int dimension = Traits::dimension; static const int codimension = 1; static const int mydimension = dimension-codimension; static const int dimensionworld = Traits::dimensionworld; typedef FieldVector< ctype, dimensionworld > Coordinate; typedef typename Traits::HostGrid HostGrid; typedef typename Traits::template Codim< 0 >::GeometryImpl ElementGeometryImpl; typedef typename Traits::template Codim< codimension >::LocalGeometry HostLocalGeometry; public: IntersectionCoordVector ( const ElementGeometryImpl &elementGeometry, const HostLocalGeometry &hostLocalGeometry ) : elementGeometry_( elementGeometry ), hostLocalGeometry_( hostLocalGeometry ) {} template< std::size_t size > void calculate ( std::array< Coordinate, size > (&corners) ) const { const std::size_t numCorners = hostLocalGeometry_.corners(); assert( size >= numCorners ); for( std::size_t i = 0; i < numCorners; ++i ) corners[ i ] = elementGeometry_.global( hostLocalGeometry_.corner( i ) ); } template< unsigned int numCorners > void calculate ( Coordinate (&corners)[ numCorners ] ) const { assert( numCorners == hostLocalGeometry_.corners() ); } private: const ElementGeometryImpl &elementGeometry_; HostLocalGeometry hostLocalGeometry_; }; // CornerStorage // ------------- template< int mydim, int cdim, class Grid > class CornerStorage { typedef typename std::remove_const< Grid >::type::Traits Traits; typedef typename Traits::ctype ctype; typedef FieldVector< ctype, cdim > Coordinate; typedef std::array< Coordinate, (1 << mydim) > Coords; public: typedef typename Coords::const_iterator const_iterator; template< bool fake > explicit CornerStorage ( const CoordVector< mydim, Grid, fake > &coords ) { coords.calculate( coords_ ); } explicit CornerStorage ( const IntersectionCoordVector< Grid > &coords ) { coords.calculate( coords_ ); } const Coordinate &operator[] ( unsigned int i ) const { return coords_[ i ]; } const_iterator begin () const { return coords_.begin(); } const_iterator end () const { return coords_.end(); } private: Coords coords_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_CORNERSTORAGE_HH dune-grid-2.11.0/dune/grid/geometrygrid/datahandle.hh000066400000000000000000000061641511655130300224470ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_DATAHANDLE_HH #define DUNE_GEOGRID_DATAHANDLE_HH #include #include #include #include #include namespace Dune { namespace GeoGrid { // GeometryGridDataHandle // ---------------------- template< class Grid, class WrappedHandle > class CommDataHandle : public CommDataHandleIF< CommDataHandle< Grid, WrappedHandle >, typename WrappedHandle::DataType > { typedef typename std::remove_const< Grid >::type::Traits Traits; public: CommDataHandle ( const Grid &grid, WrappedHandle &handle ) : grid_( grid ), wrappedHandle_( handle ) {} bool contains ( int dim, int codim ) const { const bool contains = wrappedHandle_.contains( dim, codim ); if( contains ) assertHostEntity( dim, codim ); return contains; } bool fixedSize ( int dim, int codim ) const { return wrappedHandle_.fixedSize( dim, codim ); } template< class HostEntity > size_t size ( const HostEntity &hostEntity ) const { typedef typename Grid::Traits::template Codim< HostEntity::codimension >::Entity Entity; typedef typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl EntityImpl; Entity entity( EntityImpl( grid_, hostEntity ) ); return wrappedHandle_.size( entity ); } template< class MessageBuffer, class HostEntity > void gather ( MessageBuffer &buffer, const HostEntity &hostEntity ) const { typedef typename Grid::Traits::template Codim< HostEntity::codimension >::Entity Entity; typedef typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl EntityImpl; Entity entity( EntityImpl( grid_, hostEntity ) ); wrappedHandle_.gather( buffer, entity ); } template< class MessageBuffer, class HostEntity > void scatter ( MessageBuffer &buffer, const HostEntity &hostEntity, size_t size_ ) { typedef typename Grid::Traits::template Codim< HostEntity::codimension >::Entity Entity; typedef typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl EntityImpl; Entity entity( EntityImpl( grid_, hostEntity ) ); wrappedHandle_.scatter( buffer, entity, size_ ); } private: static void assertHostEntity ( int , int codim ) { if( !Capabilities::CodimCache< Grid >::hasHostEntity( codim ) ) DUNE_THROW( NotImplemented, "Host grid has no entities for codimension " << codim << "." ); } const Grid &grid_; WrappedHandle &wrappedHandle_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_DATAHANDLE_HH dune-grid-2.11.0/dune/grid/geometrygrid/declaration.hh000066400000000000000000000010071511655130300226360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_DECLARATION_HH #define DUNE_GEOGRID_DECLARATION_HH namespace Dune { template< class HostGrid, class CoordFunction, class Allocator > class GeometryGrid; } // namespace Dune #endif // #ifndef DUNE_GEOGRID_DECLARATION_HH dune-grid-2.11.0/dune/grid/geometrygrid/entity.hh000066400000000000000000000665561511655130300217110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_ENTITY_HH #define DUNE_GEOGRID_ENTITY_HH #include #include #include #include namespace Dune { namespace GeoGrid { // Internal Forward Declarations // ----------------------------- /** \class EntityBase * \brief actual implementation of the entity * \ingroup GeoGrid * * \tparam codim codimension of the entity * \tparam Grid GeometryGrid, this entity belongs to * \tparam fake \b true, if the host grid does not provide this entity * (do not specify, the default value is already the * intended use) */ template< int codim, class Grid, bool fake = !(Capabilities::hasHostEntity< Grid, codim >::v) > class EntityBase; /** \class Entity * \brief DUNE-conform implementation of the entity * \ingroup GeoGrid * * This class merely changes the template parameters of the entity to make * DUNE happy. The actual implementation of the entity can be found in * EntityBase. * * \tparam codim codimension of the entity * \tparam dim dimension of the Grid (redundant information) * \tparam Grid GeometryGrid, this entity belongs to */ template< int codim, int dim, class Grid > class Entity; // External Forward Declarations // ----------------------------- template< class Grid > class HierarchicIterator; template< class Grid, class HostIntersectionIterator > class IntersectionIterator; // EntityBase (real) // ----------------- /** \copydoc EntityBase * * This specialization implements the case, where the host grid provides * the entity for this codimension, i.e., \em fake = \b false. * * \nosubgrouping */ template< int codim, class Grid > class EntityBase< codim, Grid, false > { typedef typename std::remove_const< Grid >::type::Traits Traits; public: /** \name Attributes * \{ */ //! codimensioon of the entity static const int codimension = codim; //! dimension of the grid static const int dimension = Traits::dimension; //! dimension of the entity static const int mydimension = dimension - codimension; //! dimension of the world static const int dimensionworld = Traits::dimensionworld; //! \b true, if the entity is faked, i.e., if there is no corresponding host entity static const bool fake = false; /** \} */ /** \name Types Required by DUNE * \{ */ //! coordinate type of the grid typedef typename Traits::ctype ctype; //! type of corresponding geometry typedef typename Traits::template Codim< codimension >::Geometry Geometry; /** \} */ private: typedef typename Traits::HostGrid HostGrid; typedef typename Traits::CoordFunction CoordFunction; public: /** \name Host Types * \{ */ //! type of corresponding host entity typedef typename HostGrid::template Codim< codimension >::Entity HostEntity; //! type of corresponding entity seed typedef typename Traits::template Codim< codimension >::EntitySeed EntitySeed; //! type of host elements, i.e., of host entities of codimension 0 typedef typename HostGrid::template Codim< 0 >::Entity HostElement; /** \} */ typedef typename Traits::template Codim< codim >::GeometryImpl GeometryImpl; private: typedef typename HostGrid::template Codim< codimension >::Geometry HostGeometry; typedef GeoGrid::CoordVector< mydimension, Grid, fake > CoordVector; public: /** \name Construction, Initialization and Destruction * \{ */ EntityBase () : hostEntity_() , grid_( nullptr ) , geo_() {} EntityBase ( const Grid &grid, const EntitySeed &seed ) : hostEntity_( grid.hostGrid().entity( seed.impl().hostEntitySeed() ) ) , grid_( &grid ) {} EntityBase ( const Grid &grid, const HostElement &hostElement, int i ) : hostEntity_( hostElement.template subEntity(i) ) , grid_( &grid ) {} EntityBase ( const GeometryImpl &geo, const HostEntity &hostEntity ) : hostEntity_( hostEntity ) , grid_( &geo.grid() ) , geo_( geo ) {} EntityBase ( const GeometryImpl &geo, HostEntity&& hostEntity ) : hostEntity_( std::move( hostEntity ) ) , grid_( &geo.grid() ) , geo_( geo ) {} EntityBase ( const Grid &grid, const HostEntity& hostEntity ) : hostEntity_( hostEntity ) , grid_( &grid ) {} EntityBase ( const Grid &grid, HostEntity&& hostEntity ) : hostEntity_( std::move( hostEntity ) ) , grid_( &grid ) {} EntityBase ( const EntityBase &other ) : hostEntity_( other.hostEntity_ ) , grid_( other.grid_ ) , geo_( other.geo_ ) {} EntityBase ( EntityBase&& other ) : hostEntity_( std::move( other.hostEntity_ ) ) , grid_( other.grid_ ) , geo_( std::move( other.geo_ ) ) {} /** \} */ const EntityBase &operator= ( const EntityBase &other ) { hostEntity_ = other.hostEntity_; grid_ = other.grid_; geo_ = other.geo_; return *this; } const EntityBase &operator= ( EntityBase&& other ) { hostEntity_ = std::move( other.hostEntity_ ); grid_ = std::move( other.grid_ ); geo_ = std::move( other.geo_ ); return *this; } /** \brief compare two entities */ bool equals ( const EntityBase &other) const { return hostEntity_ == other.hostEntity_; } public: /** \name Methods Shared by Entities of All Codimensions * \{ */ /** \brief obtain the name of the corresponding reference element * * This type can be used to access the DUNE reference element. */ GeometryType type () const { return hostEntity().type(); } /** \brief obtain the level of this entity */ int level () const { return hostEntity().level(); } /** \brief obtain the partition type of this entity */ PartitionType partitionType () const { return hostEntity().partitionType(); } /** obtain the geometry of this entity * * Each DUNE entity encapsulates a geometry object, representing the map * from the reference element to world coordinates. Wrapping the geometry * is the main objective of the GeometryGrid. * * The GeometryGrid provides geometries of order 1, obtained by * interpolation of its corners \f$y_i\f$. There corners are calculated * from the corners \f$x_i\f$ of the host geometry through the * GeometryGrid's coordinate function \f$c\f$, i.e., * \f$y_i = c( x_i )\f$. * * \returns a const reference to the geometry */ Geometry geometry () const { if( !geo_ ) { CoordVector coords( hostEntity(), grid().coordFunction() ); geo_ = GeometryImpl( grid(), type(), coords ); } return Geometry( geo_ ); } unsigned int subEntities ( unsigned int cc ) const { return hostEntity().subEntities( cc ); } /** \brief return EntitySeed of host grid entity */ EntitySeed seed () const { return typename EntitySeed::Implementation( hostEntity().seed() ); } /** \} */ /** \name Methods Supporting the Grid Implementation * \{ */ const Grid &grid () const { assert( grid_ ); return *grid_; } const HostEntity &hostEntity () const { return hostEntity_; } /** \brief initialize an entity * * \param[in] hostEntity reference to the host entity * */ void initialize ( const HostEntity &hostEntity ) { hostEntity_ = hostEntity; } /** \brief obtain the entity's index from a host IndexSet * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param[in] indexSet host IndexSet to use */ template< class HostIndexSet > typename HostIndexSet::IndexType index ( const HostIndexSet &indexSet ) const { return indexSet.template index< codimension >( hostEntity() ); } /** \brief obtain the index of a subentity from a host IndexSet * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param[in] indexSet host IndexSet to use * \param[in] i number of the subentity * \param[in] cd codimension of the subentity */ template< class HostIndexSet > typename HostIndexSet::IndexType subIndex ( const HostIndexSet &indexSet, int i, unsigned int cd ) const { return indexSet.subIndex( hostEntity(), i, cd ); } /** \brief check whether the entity is contained in a host index set * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param indexSet host IndexSet to use */ template< class HostIndexSet > bool isContained ( const HostIndexSet &indexSet ) const { return indexSet.contains( hostEntity() ); } /** \brief obtain the entity's id from a host IdSet * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param idSet host IdSet to use */ template< class HostIdSet > typename HostIdSet::IdType id ( const HostIdSet &idSet ) const { return idSet.template id< codimension >( hostEntity() ); } /** \} */ private: HostEntity hostEntity_; const Grid *grid_; mutable GeometryImpl geo_; }; // EntityBase (fake) // ----------------- /** \copydoc EntityBase * * This specialization implements the case, where the host grid does not * provide the entity for this codimension, i.e., \em fake = \b true. * * \nosubgrouping */ template< int codim, class Grid > class EntityBase< codim, Grid, true > { typedef typename std::remove_const< Grid >::type::Traits Traits; public: /** \name Attributes * \{ */ //! codimensioon of the entity static const int codimension = codim; //! dimension of the grid static const int dimension = Traits::dimension; //! dimension of the entity static const int mydimension = dimension - codimension; //! dimension of the world static const int dimensionworld = Traits::dimensionworld; //! \b true, if the entity is faked, i.e., if there is no corresponding host entity static const bool fake = true; /** \} */ /** \name Types Required by DUNE * \{ */ //! coordinate type of the grid typedef typename Traits::ctype ctype; //! type of corresponding geometry typedef typename Traits::template Codim< codimension >::Geometry Geometry; /** \} */ private: typedef typename Traits::HostGrid HostGrid; typedef typename Traits::CoordFunction CoordFunction; public: /** \name Host Types * \{ */ //! type of corresponding host entity typedef typename HostGrid::template Codim< codimension >::Entity HostEntity; //! type of corresponding entity seed typedef typename Traits::template Codim< codimension >::EntitySeed EntitySeed; //! type of host elements, i.e., of host entities of codimension 0 typedef typename HostGrid::template Codim< 0 >::Entity HostElement; /** \} */ typedef typename Traits::template Codim< codimension >::GeometryImpl GeometryImpl; private: typedef typename HostGrid::template Codim< 0 >::Geometry HostGeometry; typedef GeoGrid::CoordVector< mydimension, Grid, fake > CoordVector; public: /** \name Construction, Initialization and Destruction * \{ */ EntityBase () : hostElement_() , subEntity_(-1) , grid_(nullptr) , geo_() {} EntityBase(const Grid& grid, const HostElement& hostElement, unsigned int subEntity) : hostElement_(hostElement) , subEntity_(subEntity) , grid_(&grid) {} EntityBase ( const Grid &grid, const EntitySeed &seed ) : hostElement_( grid.hostGrid().entity( seed.impl().hostElementSeed() ) ) , subEntity_( seed.impl().subEntity() ) , grid_( &grid ) {} EntityBase ( const EntityBase &other ) : hostElement_( other.hostElement_ ) , subEntity_( other.subEntity_ ) , grid_(other.grid_) , geo_( other.geo_ ) {} EntityBase ( EntityBase &&other ) : hostElement_( std::move( other.hostElement_ ) ) , subEntity_( std::move( other.subEntity_ ) ) , grid_( std::move( other.grid_ ) ) , geo_( std::move( other.geo_ ) ) {} /* * This method is required by constructors in the `Entity` class * below, however it cannot do anything useful for fake * entities. */ EntityBase(const Grid& grid, const HostEntity& hostEntity) { DUNE_THROW(Dune::Exception, "GeometryGrid: Cannot create fake entity of codim " << codimension << " from real host entity."); } /** \} */ const EntityBase &operator= ( const EntityBase &other ) { hostElement_ = other.hostElement_; subEntity_ = other.subEntity_; grid_ = other.grid_; geo_ = other.geo_; return *this; } const EntityBase &operator= ( EntityBase&& other ) { hostElement_ = std::move( other.hostElement_ ); subEntity_ = std::move( other.subEntity_ ); grid_ = std::move( other.grid_ ); geo_ = std::move( other.geo_ ); return *this; } /** \brief compare two entities */ bool equals ( const EntityBase &other) const { const bool thisEnd = (subEntity() < 0); const bool otherEnd = (other.subEntity() < 0); if( thisEnd || otherEnd ) return thisEnd && otherEnd; const int lvl = level(); if( lvl != other.level() ) return false; const typename Traits::HostGrid::Traits::LevelIndexSet &indexSet = grid().hostGrid().levelIndexSet( lvl ); const HostElement &thisElement = hostElement(); assert( indexSet.contains( thisElement ) ); const HostElement &otherElement = other.hostElement(); assert( indexSet.contains( otherElement ) ); const int thisIndex = indexSet.subIndex( thisElement, subEntity(), codimension ); const int otherIndex = indexSet.subIndex( otherElement, other.subEntity(), codimension ); return (thisIndex == otherIndex); } /** \name Methods Shared by Entities of All Codimensions * \{ */ /** \brief obtain the name of the corresponding reference element * * This type can be used to access the DUNE reference element. */ GeometryType type () const { auto refElement = referenceElement< ctype, dimension >( hostElement().type() ); return refElement.type( subEntity_, codimension ); } /** \brief obtain the level of this entity */ int level () const { return hostElement().level(); } /** \brief obtain the partition type of this entity */ PartitionType partitionType () const { auto refElement = referenceElement< ctype, dimension >( hostElement().type() ); PartitionType type = vertexPartitionType( refElement, 0 ); if( (type != BorderEntity) && (type != FrontEntity) ) return type; const int numVertices = refElement.size( subEntity_, codimension, dimension ); for( int i = 1; i < numVertices; ++i ) { PartitionType vtxType = vertexPartitionType( refElement, i ); if( (vtxType != BorderEntity) && (vtxType != FrontEntity) ) return vtxType; if( type != vtxType ) return OverlapEntity; } assert( (type == BorderEntity) || (type == FrontEntity) ); return type; } /** obtain the geometry of this entity * * Each DUNE entity encapsulates a geometry object, representing the map * from the reference element to world coordinates. Wrapping the geometry * is the main objective of the GeometryGrid. * * The GeometryGrid provides geometries of order 1, obtained by * interpolation of its corners \f$y_i\f$. There corners are calculated * from the corners \f$x_i\f$ of the host geometry through the * GeometryGrid's coordinate function \f$c\f$, i.e., * \f$y_i = c( x_i )\f$. * * \returns a geometry object */ Geometry geometry () const { if( !geo_ ) { CoordVector coords( hostElement(), subEntity_, grid().coordFunction() ); geo_ = GeometryImpl( grid(), type(), coords ); } return Geometry( geo_ ); } unsigned int subEntities ( unsigned int cc ) const { auto refElement = referenceElement< ctype, dimension >( hostElement().type() ); return refElement.size( subEntity_, codimension, cc ); } /** \brief return EntitySeed of host grid entity */ EntitySeed seed () const { return typename EntitySeed::Implementation( hostElement().seed(), subEntity_ ); } /** \} */ /** \name Methods Supporting the Grid Implementation * \{ */ const Grid &grid () const { assert( grid_ ); return *grid_; } const HostEntity &hostEntity () const { DUNE_THROW( NotImplemented, "HostGrid has no entities of codimension " << codimension << "." ); } const HostElement &hostElement () const { return hostElement_; } int subEntity () const { return subEntity_; } /** \brief initialize an entity * * \param[in] hostElement reference to the host element * * \note The reference must remain valid as long as this entity is in * use. */ void initialize ( const HostElement &hostElement ) { hostElement_ = hostElement; } /** \brief obtain the entity's index from a host IndexSet * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param[in] indexSet host IndexSet to use */ template< class HostIndexSet > typename HostIndexSet::IndexType index ( const HostIndexSet &indexSet ) const { return indexSet.subIndex( hostElement(), subEntity_, codimension ); } /** \brief obtain the index of a subentity from a host IndexSet * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param[in] indexSet host IndexSet to use * \param[in] i number of the subentity * \param[in] cd codimension of the subentity */ template< class HostIndexSet > typename HostIndexSet::IndexType subIndex ( const HostIndexSet &indexSet, int i, unsigned int cd ) const { auto refElement = referenceElement< ctype, dimension >( hostElement().type() ); const int j = refElement.subEntity( subEntity_, codimension, i, codimension+cd ); return indexSet.subIndex( hostElement(), j, codimension+cd ); } /** \brief check whether the entity is contained in a host index set * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param indexSet host IndexSet to use */ template< class HostIndexSet > bool isContained ( const HostIndexSet &indexSet ) const { return indexSet.contains( hostElement() ); } /** \brief obtain the entity's id from a host IdSet * * \internal This method is provided by the entity, because its * implementation is different for fake and non-fake entities. * * \param idSet host IdSet to use */ template< class HostIdSet > typename HostIdSet::IdType id ( const HostIdSet &idSet ) const { return idSet.subId( hostElement(), subEntity_, codimension ); } /** \} */ private: PartitionType vertexPartitionType ( typename Dune::ReferenceElements< ctype, dimension >::ReferenceElement refElement, int i ) const { const int j = refElement.subEntity( subEntity_, codimension, i, dimension ); return hostElement().template subEntity< dimension >( j ).partitionType(); } private: HostElement hostElement_; unsigned int subEntity_; const Grid *grid_; mutable GeometryImpl geo_; }; // Entity // ------ template< int codim, int dim, class Grid > class Entity : public EntityBase< codim, Grid > { typedef EntityBase< codim, Grid > Base; public: typedef typename Base::HostEntity HostEntity; typedef typename Base::HostElement HostElement; typedef typename Base::GeometryImpl GeometryImpl; typedef typename Base::EntitySeed EntitySeed; Entity () : Base() {} Entity ( const Grid &grid, const EntitySeed &seed ) : Base( grid, seed ) {} Entity ( const Grid &grid, const HostEntity &hostEntity ) : Base( grid, hostEntity ) {} Entity ( const Grid &grid, HostEntity&& hostEntity ) : Base( grid, std::move( hostEntity ) ) {} Entity ( const Grid &grid, const HostElement &hostEntity, int i ) : Base( grid, hostEntity, i ) {} }; // Entity for codimension 0 // ------------------------ template< int dim, class Grid > class Entity< 0, dim, Grid > : public EntityBase< 0, Grid > { typedef EntityBase< 0, Grid > Base; typedef typename std::remove_const< Grid >::type::Traits Traits; typedef typename Traits::HostGrid HostGrid; public: /** \name Attributes * \{ */ //! codimensioon of the entity static const int codimension = Base::codimension; //! dimension of the grid static const int dimension = Base::dimension; //! dimension of the entity static const int mydimension = Base::mydimension; //! dimension of the world static const int dimensionworld = Base::dimensionworld; //! \b true, if the entity is faked, i.e., if there is no corresponding host entity static const bool fake = Base::fake; /** \} */ /** \name Types Required by DUNE * \{ */ //! type of corresponding local geometry typedef typename Traits::template Codim< codimension >::LocalGeometry LocalGeometry; typedef Dune::Entity< 0, dim, Grid, Dune::GeoGrid::Entity > EntityFacade; //! type of hierarchic iterator typedef typename Traits::HierarchicIterator HierarchicIterator; //! type of leaf intersection iterator typedef typename Traits::LeafIntersectionIterator LeafIntersectionIterator; //! type of level intersection iterator typedef typename Traits::LevelIntersectionIterator LevelIntersectionIterator; /** \} */ typedef typename Base::HostEntity HostEntity; typedef typename Base::HostElement HostElement; typedef typename Base::GeometryImpl GeometryImpl; typedef typename Base::EntitySeed EntitySeed; using Base::grid; using Base::hostEntity; Entity () : Base() {} Entity ( const Grid &g, const HostEntity &hostE ) : Base( g, hostE ) {} Entity ( const Grid &g, HostEntity&& hostE ) : Base( g, std::move( hostE ) ) {} Entity ( const GeometryImpl &geo, const HostEntity& hostE ) : Base( geo, hostE ) {} Entity ( const GeometryImpl &geo, HostEntity &&hostE ) : Base( geo, std::move( hostE ) ) {} Entity ( const Grid &g, const EntitySeed &seed ) : Base( g, seed ) {} Entity ( const Grid &g, const HostEntity &hostE, int i ) : Base( g, hostE ) { assert( i == 0 ); } template< int codim > typename Grid::template Codim< codim >::Entity subEntity ( int i ) const { typedef typename Traits::template Codim< codim >::EntityImpl EntityImpl; return EntityImpl( grid(), hostEntity(), i ); } LevelIntersectionIterator ilevelbegin () const { typedef GeoGrid::IntersectionIterator< Grid, typename HostGrid::LevelIntersectionIterator > LevelIntersectionIteratorImpl; return LevelIntersectionIteratorImpl( *this, hostEntity().ilevelbegin() ); } LevelIntersectionIterator ilevelend () const { typedef GeoGrid::IntersectionIterator< Grid, typename HostGrid::LevelIntersectionIterator > LevelIntersectionIteratorImpl; return LevelIntersectionIteratorImpl( *this, hostEntity().ilevelend() ); } LeafIntersectionIterator ileafbegin () const { typedef GeoGrid::IntersectionIterator< Grid, typename HostGrid::LeafIntersectionIterator > LeafIntersectionIteratorImpl; return LeafIntersectionIteratorImpl( *this, hostEntity().ileafbegin() ); } LeafIntersectionIterator ileafend () const { typedef GeoGrid::IntersectionIterator< Grid, typename HostGrid::LeafIntersectionIterator > LeafIntersectionIteratorImpl; return LeafIntersectionIteratorImpl( *this, hostEntity().ileafend() ); } bool hasBoundaryIntersections () const { return hostEntity().hasBoundaryIntersections(); } bool isLeaf () const { return hostEntity().isLeaf(); } EntityFacade father () const { return Entity( grid(), hostEntity().father() ); } bool hasFather () const { return hostEntity().hasFather(); } LocalGeometry geometryInFather () const { return hostEntity().geometryInFather(); } HierarchicIterator hbegin ( int maxLevel ) const { typedef GeoGrid::HierarchicIterator< Grid > HierarchicIteratorImpl; return HierarchicIteratorImpl( grid(), hostEntity().hbegin( maxLevel ) ); } HierarchicIterator hend ( int maxLevel ) const { typedef GeoGrid::HierarchicIterator< Grid > HierarchicIteratorImpl; return HierarchicIteratorImpl( grid(), hostEntity().hend( maxLevel ) ); } bool isRegular () const { return hostEntity().isRegular(); } bool isNew () const { return hostEntity().isNew(); } bool mightVanish () const { return hostEntity().mightVanish(); } }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_ENTITY_HH dune-grid-2.11.0/dune/grid/geometrygrid/entityseed.hh000066400000000000000000000065321511655130300225360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_ENTITYSEED_HH #define DUNE_GEOGRID_ENTITYSEED_HH #include #include #include namespace Dune { namespace GeoGrid { // Internal Forward Declarations // ----------------------------- template< int codim, class Grid, bool fake = !(Capabilities::hasHostEntity< Grid, codim >::v) > class EntitySeed; // EntitySeed (real) // ----------------- template< int codim, class Grd > class EntitySeed< codim, Grd, false > { typedef typename std::remove_const< Grd >::type::Traits Traits; public: static const int codimension = codim; static const int dimension = Traits::dimension; static const int mydimension = dimension - codimension; static const int dimensionworld = Traits::dimensionworld; static const bool fake = false; typedef typename Traits::Grid Grid; typedef typename Traits::template Codim< codim >::Entity Entity; typedef typename Traits::HostGrid HostGrid; typedef typename HostGrid::template Codim< codim >::EntitySeed HostEntitySeed; //! default construct an invalid entity seed EntitySeed ( ) {} explicit EntitySeed ( const HostEntitySeed &hostEntitySeed ) : hostEntitySeed_( hostEntitySeed ) {} //! check whether the EntitySeed refers to a valid Entity bool isValid() const { return hostEntitySeed_.isValid(); } const HostEntitySeed &hostEntitySeed () const { return hostEntitySeed_; } private: HostEntitySeed hostEntitySeed_; }; // EntitySeed (fake) // ----------------- template< int codim, class Grd > class EntitySeed< codim, Grd, true > { typedef typename std::remove_const< Grd >::type::Traits Traits; public: static const int codimension = codim; static const int dimension = Traits::dimension; static const int mydimension = dimension - codimension; static const int dimensionworld = Traits::dimensionworld; static const bool fake = true; typedef typename Traits::Grid Grid; typedef typename Traits::template Codim< codim >::Entity Entity; typedef typename Traits::HostGrid HostGrid; typedef typename HostGrid::template Codim< 0 >::EntitySeed HostElementSeed; //! default construct an invalid entity seed EntitySeed ( ) {} explicit EntitySeed ( const HostElementSeed &hostElementSeed, unsigned int subEntity ) : hostElementSeed_( hostElementSeed ), subEntity_( subEntity ) {} //! check whether the EntitySeed refers to a valid Entity bool isValid() const { return hostElementSeed_.isValid(); } const HostElementSeed &hostElementSeed () const { return hostElementSeed_; } unsigned int subEntity () const { return subEntity_; } private: HostElementSeed hostElementSeed_; unsigned int subEntity_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_ENTITYSEED_HH dune-grid-2.11.0/dune/grid/geometrygrid/geometry.hh000066400000000000000000000157411511655130300222160ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_GEOMETRY_HH #define DUNE_GEOGRID_GEOMETRY_HH #include #include #include #include #include #include #include namespace Dune { namespace GeoGrid { // InferHasSingleGeometryType // -------------------------- template< class hasSingleGeometryType, int dim, int mydim > struct InferHasSingleGeometryType { private: static const unsigned int id = hasSingleGeometryType::topologyId; static const unsigned int idMask = (1u << mydim) - 1u; public: static const bool v = hasSingleGeometryType::v && ((mydim == dim) || ((id | 1u) == 1u) || ((id | 1u) == idMask)); static const unsigned int topologyId = (v ? id & idMask : ~0u); }; template< class hasSingleGeometryType, int dim > struct InferHasSingleGeometryType< hasSingleGeometryType, dim, 1 > { static const bool v = true; static const unsigned int topologyId = GeometryTypes::cube(1).id(); }; template< class hasSingleGeometryType, int dim > struct InferHasSingleGeometryType< hasSingleGeometryType, dim, 0 > { static const bool v = true; static const unsigned int topologyId = GeometryTypes::cube(1).id(); }; // GeometryTraits // -------------- template< class Grid > struct GeometryTraits { typedef typename std::remove_const< Grid >::type::Traits Traits; typedef typename Traits::ctype ctype; typedef Impl::FieldMatrixHelper< ctype > MatrixHelper; static ctype tolerance () { return 16 * std::numeric_limits< ctype >::epsilon(); } template< int mydim, int cdim > struct CornerStorage { typedef GeoGrid::CornerStorage< mydim, cdim, Grid > Type; }; template< int mydim > struct hasSingleGeometryType : public InferHasSingleGeometryType< Capabilities::hasSingleGeometryType< Grid >, Traits::dimension, mydim > {}; }; // Geometry // -------- template< int mydim, int cdim, class Grid > class Geometry { typedef Geometry< mydim, cdim, Grid > This; typedef typename std::remove_const< Grid >::type::Traits Traits; template< int, int, class > friend class Geometry; public: typedef typename Traits::ctype ctype; static const int mydimension = mydim; static const int coorddimension = cdim; static const int dimension = Traits::dimension; static const int codimension = dimension - mydimension; protected: typedef CachedMultiLinearGeometry< ctype, mydimension, coorddimension, GeometryTraits< Grid > > BasicMapping; struct Mapping : public BasicMapping { template< class CoordVector > Mapping ( const GeometryType &type, const CoordVector &coords ) : BasicMapping( type, coords ), refCount_( 0 ) {} void addReference () { ++refCount_; } bool removeReference () { return (--refCount_ == 0); } private: unsigned int refCount_; }; public: typedef typename Mapping::LocalCoordinate LocalCoordinate; typedef typename Mapping::GlobalCoordinate GlobalCoordinate; typedef typename Mapping::JacobianTransposed JacobianTransposed; typedef typename Mapping::JacobianInverseTransposed JacobianInverseTransposed; typedef typename Mapping::Jacobian Jacobian; typedef typename Mapping::JacobianInverse JacobianInverse; Geometry () : grid_( nullptr ), mapping_( nullptr ) {} explicit Geometry ( const Grid &grid ) : grid_( &grid ), mapping_( nullptr ) {} template< class CoordVector > Geometry ( const Grid &grid, const GeometryType &type, const CoordVector &coords ) : grid_( &grid ) { assert( int( type.dim() ) == mydimension ); void *mappingStorage = grid.allocateStorage( sizeof( Mapping ) ); mapping_ = new( mappingStorage ) Mapping( type, coords ); mapping_->addReference(); } Geometry ( const This &other ) : grid_( other.grid_ ), mapping_( other.mapping_ ) { if( mapping_ ) mapping_->addReference(); } Geometry ( This&& other ) : grid_( other.grid_ ), mapping_( other.mapping_ ) { other.grid_ = nullptr; other.mapping_ = nullptr; } ~Geometry () { if( mapping_ && mapping_->removeReference() ) destroyMapping(); } const This &operator= ( const This &other ) { if( other.mapping_ ) other.mapping_->addReference(); if( mapping_ && mapping_->removeReference() ) destroyMapping(); grid_ = other.grid_; mapping_ = other.mapping_; return *this; } const This &operator= ( This&& other ) { using std::swap; swap( grid_, other.grid_ ); swap( mapping_, other.mapping_ ); return *this; } explicit operator bool () const { return bool( mapping_ ); } bool affine () const { return mapping_->affine(); } GeometryType type () const { return mapping_->type(); } int corners () const { return mapping_->corners(); } GlobalCoordinate corner ( const int i ) const { return mapping_->corner( i ); } GlobalCoordinate center () const { return mapping_->center(); } GlobalCoordinate global ( const LocalCoordinate &local ) const { return mapping_->global( local ); } LocalCoordinate local ( const GlobalCoordinate &global ) const { return mapping_->local( global ); } ctype integrationElement ( const LocalCoordinate &local ) const { return mapping_->integrationElement( local ); } ctype volume () const { return mapping_->volume(); } JacobianTransposed jacobianTransposed ( const LocalCoordinate &local ) const { return mapping_->jacobianTransposed( local ); } JacobianInverseTransposed jacobianInverseTransposed ( const LocalCoordinate &local ) const { return mapping_->jacobianInverseTransposed( local ); } Jacobian jacobian ( const LocalCoordinate &local ) const { return mapping_->jacobian( local ); } JacobianInverse jacobianInverse ( const LocalCoordinate &local ) const { return mapping_->jacobianInverse( local ); } const Grid &grid () const { assert( grid_ ); return *grid_; } private: void destroyMapping () { mapping_->~Mapping(); grid().deallocateStorage( mapping_, sizeof( Mapping ) ); } const Grid *grid_; Mapping* mapping_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_GEOMETRY_HH dune-grid-2.11.0/dune/grid/geometrygrid/grid.hh000066400000000000000000000513331511655130300213050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_GRID_HH #define DUNE_GEOGRID_GRID_HH #include #include #include #include #include #include #include #include #include namespace Dune { // DefaultCoordFunction // -------------------- template< class HostGrid > class DefaultCoordFunction : public IdenticalCoordFunction< typename HostGrid::ctype, HostGrid::dimensionworld > {}; // GeometryGrid // ------------ /** \class GeometryGrid * \brief grid wrapper replacing the geometries * \ingroup GeoGrid * * GeometryGrid wraps another DUNE grid and replaces its geometry by the * generic geometries from dune-grid. These are linear (respectively * n-linear) DUNE geometries interpolating some given corners. These corners * are obtained by mapping the corners of the host grid's geometry (also * called host geometry) by a coordinate function. * * An example of a coordinate function is given by the following code: \code class ExampleFunction : public Dune :: AnalyticalCoordFunction< double, 2, 3, ExampleFunction > { typedef ExampleFunction This; typedef Dune :: AnalyticalCoordFunction< double, 2, 3, This > Base; public: typedef Base :: DomainVector DomainVector; typedef Base :: RangeVector RangeVector; void evaluate ( const DomainVector &x, RangeVector &y ) const { y[ 0 ] = x[ 0 ]; y[ 1 ] = x[ 1 ]; y[ 2 ] = x[ 0 ] + x[ 1 ]; } }; \endcode * * \note A dune-fem Function can be used as a coordinate function. * The evaluation of discrete functions would be very expensive, * though. * * \tparam HostGrid DUNE grid to be wrapped (called host grid) * \tparam CoordFunction coordinate function * * \nosubgrouping */ template< class HostGrid, class CoordFunction = DefaultCoordFunction< HostGrid >, class Allocator = std::allocator< void > > class GeometryGrid /** \cond */ : public GridDefaultImplementation < HostGrid::dimension, CoordFunction::dimRange, typename HostGrid::ctype, GeoGrid::GridFamily< HostGrid, CoordFunction, Allocator > >, public GeoGrid::ExportParams< HostGrid, CoordFunction >, public GeoGrid::BackupRestoreFacilities< GeometryGrid< HostGrid, CoordFunction, Allocator > > /** \endcond */ { typedef GeometryGrid< HostGrid, CoordFunction, Allocator > Grid; typedef GridDefaultImplementation < HostGrid::dimension, CoordFunction::dimRange, typename HostGrid::ctype, GeoGrid::GridFamily< HostGrid, CoordFunction, Allocator > > Base; friend class GeoGrid::HierarchicIterator< const Grid >; template< int, class, bool > friend class GeoGrid::EntityBase; template< int, int, class > friend class GeoGrid::Geometry; template< class, class, class > friend class GeoGrid::GridView; template< class, class > friend class GeoGrid::Intersection; template< class, class > friend class GeoGrid::IntersectionIterator; template< class, class > friend class GeoGrid::IdSet; template< class, class > friend class GeoGrid::IndexSet; template< class > friend struct HostGridAccess; template< class, class > friend class GeoGrid::CommDataHandle; public: /** \cond */ typedef GeoGrid::GridFamily< HostGrid, CoordFunction, Allocator > GridFamily; /** \endcond */ /** \name Traits * \{ */ //! type of the grid traits typedef typename GridFamily::Traits Traits; /** \brief traits structure containing types for a codimension * * \tparam codim codimension * * \nosubgrouping */ template< int codim > struct Codim; /** \} */ /** \name Iterator Types * \{ */ //! iterator over the grid hierarchy typedef typename Traits::HierarchicIterator HierarchicIterator; //! iterator over intersections with other entities on the leaf level typedef typename Traits::LeafIntersectionIterator LeafIntersectionIterator; //! iterator over intersections with other entities on the same level typedef typename Traits::LevelIntersectionIterator LevelIntersectionIterator; /** \} */ /** \name Grid View Types * \{ */ /** \brief type of view for leaf grid */ typedef typename GridFamily::Traits::LeafGridView LeafGridView; /** \brief type of view for level grid */ typedef typename GridFamily::Traits::LevelGridView LevelGridView; /** \} */ /** \name Index and Id Set Types * \{ */ /** \brief type of leaf index set * * The index set assigns consecutive indices to the entities of the * leaf grid. The indices are of integral type and can be used to access * arrays. * * The leaf index set is a model of Dune::IndexSet. */ typedef typename Traits::LeafIndexSet LeafIndexSet; /** \brief type of level index set * * The index set assigns consecutive indices to the entities of a grid * level. The indices are of integral type and can be used to access * arrays. * * The level index set is a model of Dune::IndexSet. */ typedef typename Traits::LevelIndexSet LevelIndexSet; /** \brief type of global id set * * The id set assigns a unique identifier to each entity within the * grid. This identifier is unique over all processes sharing this grid. * * \note Id's are neither consecutive nor necessarily of an integral * type. * * The global id set is a model of Dune::IdSet. */ typedef typename Traits::GlobalIdSet GlobalIdSet; /** \brief type of local id set * * The id set assigns a unique identifier to each entity within the * grid. This identifier needs only to be unique over this process. * * Though the local id set may be identical to the global id set, it is * often implemented more efficiently. * * \note Ids are neither consecutive nor necessarily of an integral * type. * \note Local ids need not be compatible with global ids. Also, no * mapping from local ids to global ones needs to exist. * * The global id set is a model of Dune::IdSet. */ typedef typename Traits::LocalIdSet LocalIdSet; /** \} */ /** \name Miscellaneous Types * \{ */ //! type of vector coordinates (e.g., double) typedef typename Traits::ctype ctype; //! communicator with all other processes having some part of the grid typedef typename Traits::Communication Communication; /** \} */ /** \name Construction and Destruction * \{ */ /** \brief constructor * * The references to host grid and coordinate function are stored in the * grid. Therefore, they must remain valid until the grid is destroyed. * * \param[in] hostGrid reference to the grid to wrap * \param[in] coordFunction reference to the coordinate function * \param[in] allocator storage allocator */ GeometryGrid ( HostGrid &hostGrid, CoordFunction &coordFunction, const Allocator &allocator = Allocator() ) : hostGrid_( Dune::stackobject_to_shared_ptr(hostGrid) ), coordFunction_( Dune::stackobject_to_shared_ptr(coordFunction) ), levelIndexSets_( hostGrid_->maxLevel()+1 ), storageAllocator_( allocator ) {} /** \brief constructor * * The grid takes ownership of the pointers to host grid and coordinate * function. They will be deleted when the grid is destroyed. * * \param[in] hostGrid shared pointer to the grid to wrap * \param[in] coordFunction shared pointer to the coordinate function * \param[in] allocator storage allocator */ GeometryGrid ( std::shared_ptr hostGrid, std::shared_ptr coordFunction, const Allocator &allocator = Allocator() ) : hostGrid_( hostGrid ), coordFunction_( coordFunction ), levelIndexSets_( hostGrid_->maxLevel()+1 ), storageAllocator_( allocator ) {} /** \brief constructor * * The grid takes ownership of the pointer to host grid and it will * be deleted when the grid is destroyed. The coordinate function * is automatically constructed. * * \param[in] hostGrid shared pointer to the grid to wrap * \param[in] allocator storage allocator */ GeometryGrid ( std::shared_ptr hostGrid, const Allocator &allocator = Allocator() ) : hostGrid_( hostGrid ), coordFunction_( std::make_shared( this->hostGrid() ) ), levelIndexSets_( hostGrid_->maxLevel()+1 ), storageAllocator_( allocator ) {} /** \} */ /** \name Size Methods * \{ */ /** \brief obtain maximal grid level * * Grid levels are numbered 0, ..., L, where L is the value returned by * this method. * * \returns maximal grid level */ int maxLevel () const { return hostGrid().maxLevel(); } /** \brief obtain number of entities on a level * * \param[in] level level to consider * \param[in] codim codimension to consider * * \returns number of entities of codimension \em codim on grid level * \em level. */ int size ( int level, int codim ) const { return levelGridView( level ).size( codim ); } /** \brief obtain number of leaf entities * * \param[in] codim codimension to consider * * \returns number of leaf entities of codimension \em codim */ int size ( int codim ) const { return leafGridView().size( codim ); } /** \brief obtain number of entities on a level * * \param[in] level level to consider * \param[in] type geometry type to consider * * \returns number of entities with a geometry of type \em type on grid * level \em level. */ int size ( int level, GeometryType type ) const { return levelGridView( level ).size( type ); } /** \brief obtain number of leaf entities * * \returns number of leaf entities with a geometry of type \em type */ int size ( GeometryType type ) const { return leafGridView().size( type ); } /** \brief returns the number of boundary segments within the macro grid * * \returns number of boundary segments within the macro grid */ size_t numBoundarySegments () const { return hostGrid().numBoundarySegments( ); } /** \} */ const GlobalIdSet &globalIdSet () const { if( !globalIdSet_ ) globalIdSet_ = GlobalIdSet( hostGrid().globalIdSet() ); assert( globalIdSet_ ); return globalIdSet_; } const LocalIdSet &localIdSet () const { if( !localIdSet_ ) localIdSet_ = LocalIdSet( hostGrid().localIdSet() ); assert( localIdSet_ ); return localIdSet_; } const LevelIndexSet &levelIndexSet ( int level ) const { assert( levelIndexSets_.size() == (size_t)(maxLevel()+1) ); if( (level < 0) || (level > maxLevel()) ) { DUNE_THROW( GridError, "LevelIndexSet for nonexisting level " << level << " requested." ); } auto& levelIndexSetPtr = levelIndexSets_[ level ]; if( !levelIndexSetPtr ) levelIndexSetPtr = std::make_unique( hostGrid().levelIndexSet( level ) ); assert( levelIndexSetPtr ); return *levelIndexSetPtr; } const LeafIndexSet &leafIndexSet () const { if( !leafIndexSet_ ) leafIndexSet_.reset( hostGrid().leafIndexSet() ); assert( leafIndexSet_ ); return leafIndexSet_; } void globalRefine ( int refCount ) { hostGrid().globalRefine( refCount ); update(); } bool mark ( int refCount, const typename Codim< 0 >::Entity &entity_ ) { return hostGrid().mark( refCount, getHostEntity< 0 >( entity_ ) ); } int getMark ( const typename Codim< 0 >::Entity &entity_ ) const { return hostGrid().getMark( getHostEntity< 0 >( entity_ ) ); } bool preAdapt () { return hostGrid().preAdapt(); } bool adapt () { bool ret = hostGrid().adapt(); update(); return ret; } void postAdapt () { hostGrid().postAdapt(); } /** \name Parallel Data Distribution and Communication Methods * \{ */ /** \brief obtain Communication object * * The Communication object should be used to globally * communicate information between all processes sharing this grid. * * \note The Communication object returned is identical to the * one returned by the host grid. */ const Communication &comm () const { return hostGrid().comm(); } #if 0 // data handle interface different between geo and interface /** \brief rebalance the load each process has to handle * * A parallel grid is redistributed such that each process has about * the same load (e.g., the same number of leaf entities). * * \note DUNE does not specify, how the load is measured. * * \returns \b true, if the grid has changed. */ bool loadBalance () { const bool gridChanged= hostGrid().loadBalance(); if( gridChanged ) update(); return gridChanged; } /** \brief rebalance the load each process has to handle * * A parallel grid is redistributed such that each process has about * the same load (e.g., the same number of leaf entities). * * The data handle is used to communicate the data associated with * entities that move from one process to another. * * \note DUNE does not specify, how the load is measured. * * \param datahandle communication data handle (user defined) * * \returns \b true, if the grid has changed. */ template< class DataHandle, class Data > bool loadBalance ( CommDataHandleIF< DataHandle, Data > &datahandle ) { typedef CommDataHandleIF< DataHandle, Data > DataHandleIF; typedef GeoGrid :: CommDataHandle< Grid, DataHandleIF > WrappedDataHandle; WrappedDataHandle wrappedDataHandle( *this, datahandle ); const bool gridChanged = hostGrid().loadBalance( wrappedDataHandle ); if( gridChanged ) update(); return gridChanged; } #endif /** \brief obtain Entity from EntitySeed * * EntitySeed survives to a grid modification which only changes the grid coordinates. * Therefore it is consistent to use an EntitySeed to rebuild an Entity after this kind of grid modification. * * An example of this is given by the following code: \code // store seed of the first entity in the leaf view const auto& gv = grid.leafGridView(); const auto& entity = (*(gv.template begin<0>())); auto seed = entity.seed(); // perform a grid modification grid.coordFunction().setTime(t); // rebuild first entity from the seed const auto& newEntity = grid.entity(seed); \endcode */ template< class EntitySeed > typename Traits::template Codim< EntitySeed::codimension >::Entity entity ( const EntitySeed &seed ) const { typedef typename Traits::template Codim< EntitySeed::codimension >::EntityImpl EntityImpl; return EntityImpl( *this, seed ); } /** \} */ /** \name Grid Views * \{ */ /** \brief View for a grid level */ LevelGridView levelGridView ( int level ) const { typedef typename LevelGridView::GridViewImp ViewImp; return LevelGridView( ViewImp( *this, hostGrid().levelGridView( level ) ) ); } /** \brief View for the leaf grid */ LeafGridView leafGridView () const { typedef typename LeafGridView::GridViewImp ViewImp; return LeafGridView( ViewImp( *this, hostGrid().leafGridView() ) ); } /** \} */ /** \name Miscellaneous Methods * \{ */ /** \brief obtain constant reference to the host grid */ const HostGrid &hostGrid () const { return *hostGrid_; } /** \brief obtain mutable reference to the host grid */ HostGrid &hostGrid () { return *hostGrid_; } /** \brief update grid caches * * This method has to be called whenever the underlying host grid changes. * * \note If you adapt the host grid through this geometry grid's * adaptation or load balancing methods, update is automatically * called. */ void update () { // adapt the coordinate function GeoGrid::AdaptCoordFunction< typename CoordFunction::Interface >::adapt( coordFunction() ); levelIndexSets_.resize( maxLevel()+1 ); } /** \brief obtain constant reference to the coordinate function */ const CoordFunction &coordFunction () const { return *coordFunction_; } /** \brief obtain mutable reference to the coordinate function. */ CoordFunction &coordFunction () { return *coordFunction_; } /** \} */ protected: template< int codim > static const typename HostGrid::template Codim< codim >::Entity & getHostEntity( const typename Codim< codim >::Entity &entity ) { return entity.impl().hostEntity(); } void *allocateStorage ( std::size_t size ) const { return storageAllocator_.allocate( size ); } void deallocateStorage ( void *p, std::size_t size ) const { storageAllocator_.deallocate( (char *)p, size ); } private: std::shared_ptr const hostGrid_; std::shared_ptr coordFunction_; mutable std::vector> levelIndexSets_; mutable LeafIndexSet leafIndexSet_; mutable GlobalIdSet globalIdSet_; mutable LocalIdSet localIdSet_; mutable typename std::allocator_traits::template rebind_alloc< char > storageAllocator_; }; // GeometryGrid::Codim // ------------------- template< class HostGrid, class CoordFunction, class Allocator > template< int codim > struct GeometryGrid< HostGrid, CoordFunction, Allocator >::Codim : public Base::template Codim< codim > { /** \name Entity types * \{ */ /** \brief type of entity * * The entity is a model of Dune::Entity. */ typedef typename Traits::template Codim< codim >::Entity Entity; /** \} */ /** \name Geometry Types * \{ */ /** \brief type of world geometry * * Models the geometry mapping of the entity, i.e., the mapping from the * reference element into world coordinates. * * The geometry is a model of Dune::Geometry, implemented through the * generic geometries provided by dune-grid. */ typedef typename Traits::template Codim< codim >::Geometry Geometry; /** \brief type of local geometry * * Models the geometry mapping into the reference element of dimension * \em dimension. * * The local geometry is a model of Dune::Geometry, implemented through * the generic geometries provided by dune-grid. */ typedef typename Traits::template Codim< codim >::LocalGeometry LocalGeometry; /** \} */ /** \name Iterator Types * \{ */ template< PartitionIteratorType pitype > struct Partition { typedef typename Traits::template Codim< codim > ::template Partition< pitype >::LeafIterator LeafIterator; typedef typename Traits::template Codim< codim > ::template Partition< pitype >::LevelIterator LevelIterator; }; /** \brief type of leaf iterator * * This iterator enumerates the entities of codimension \em codim of a * grid level. * * The level iterator is a model of Dune::LevelIterator. */ typedef typename Partition< All_Partition >::LeafIterator LeafIterator; /** \brief type of level iterator * * This iterator enumerates the entities of codimension \em codim of the * leaf grid. * * The leaf iterator is a model of Dune::LeafIterator. */ typedef typename Partition< All_Partition >::LevelIterator LevelIterator; /** \} */ }; } // namespace Dune #endif // #ifndef DUNE_GEOGRID_GRID_HH dune-grid-2.11.0/dune/grid/geometrygrid/gridfamily.hh000066400000000000000000000116131511655130300225040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_GRIDFAMILY_HH #define DUNE_GEOGRID_GRIDFAMILY_HH #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \brief namespace containing the implementations of GeometryGrid * \ingroup GeoGrid */ namespace GeoGrid { // ExportParams // ------------ template< class HG, class CF > class ExportParams { static const bool isCoordFunction = isCoordFunctionInterface< typename CF::Interface >::value; static_assert(isCoordFunction, "Invalid CoordFunction."); public: typedef HG HostGrid; typedef CF CoordFunction; }; // GridFamily // ---------- template< class HG, class CF, class Allocator > struct GridFamily { struct Traits { typedef GeometryGrid< HG, CF, Allocator > Grid; typedef HG HostGrid; typedef CF CoordFunction; typedef typename HostGrid::ctype ctype; static const int dimension = HostGrid::dimension; static const int dimensionworld = CoordFunction::dimRange; typedef Dune::Intersection< const Grid, GeoGrid::Intersection< const Grid, typename HostGrid::LeafIntersection > > LeafIntersection; typedef Dune::Intersection< const Grid, GeoGrid::Intersection< const Grid, typename HostGrid::LevelIntersection > > LevelIntersection; typedef Dune::IntersectionIterator < const Grid, GeoGrid::IntersectionIterator< const Grid, typename HostGrid::LeafIntersectionIterator >, GeoGrid::Intersection< const Grid, typename HostGrid::LeafIntersection > > LeafIntersectionIterator; typedef Dune::IntersectionIterator < const Grid, GeoGrid::IntersectionIterator< const Grid, typename HostGrid::LevelIntersectionIterator >, GeoGrid::Intersection< const Grid, typename HostGrid::LevelIntersection > > LevelIntersectionIterator; typedef Dune::EntityIterator< 0, const Grid, GeoGrid::HierarchicIterator< const Grid > > HierarchicIterator; template< int codim > struct Codim { typedef Dune::GeoGrid::Geometry< dimension-codim, dimensionworld, const Grid > GeometryImpl; typedef Dune::Geometry< dimension-codim, dimensionworld, const Grid, Dune::GeoGrid::Geometry > Geometry; typedef typename HostGrid::template Codim< codim >::LocalGeometry LocalGeometry; typedef GeoGrid::Entity< codim, dimension, const Grid > EntityImpl; typedef Dune::Entity< codim, dimension, const Grid, GeoGrid::Entity > Entity; typedef Dune::EntitySeed< const Grid, GeoGrid::EntitySeed< codim, const Grid > > EntitySeed; template< PartitionIteratorType pitype > struct Partition { typedef GeoGrid::Iterator< typename HostGrid::LeafGridView, codim, pitype, const Grid > LeafIteratorImp; typedef Dune::EntityIterator< codim, const Grid, LeafIteratorImp > LeafIterator; typedef GeoGrid::Iterator< typename HostGrid::LevelGridView, codim, pitype, const Grid > LevelIteratorImp; typedef Dune::EntityIterator< codim, const Grid, LevelIteratorImp > LevelIterator; }; typedef typename Partition< All_Partition >::LeafIterator LeafIterator; typedef typename Partition< All_Partition >::LevelIterator LevelIterator; }; typedef GeoGrid::IndexSet< const Grid, typename HostGrid::Traits::LeafIndexSet > LeafIndexSet; typedef GeoGrid::IndexSet< const Grid, typename HostGrid::Traits::LevelIndexSet > LevelIndexSet; typedef GeoGrid::IdSet< const Grid, typename HostGrid::Traits::GlobalIdSet > GlobalIdSet; typedef GeoGrid::IdSet< const Grid, typename HostGrid::Traits::LocalIdSet > LocalIdSet; typedef typename HostGrid::Traits::Communication Communication; typedef Dune::GridView< GeoGrid::GridViewTraits< typename HostGrid::LeafGridView, CoordFunction, Allocator > > LeafGridView; typedef Dune::GridView< GeoGrid::GridViewTraits< typename HostGrid::LevelGridView, CoordFunction, Allocator > > LevelGridView; }; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_GRIDFAMILY_HH dune-grid-2.11.0/dune/grid/geometrygrid/gridview.hh000066400000000000000000000170131511655130300221750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_GRIDVIEW_HH #define DUNE_GEOGRID_GRIDVIEW_HH #include #include #include #include #include #include #include #include #include namespace Dune { namespace GeoGrid { // Internal Forward Declarations // ----------------------------- template< class HGV, class CoordFunction, class Allocator > class GridView; // GridViewTraits // -------------- template< class HGV, class CoordFunction, class Allocator > class GridViewTraits { friend class GridView< HGV, CoordFunction, Allocator >; typedef HGV HostGridView; typedef typename HostGridView::Grid HostGrid; typedef typename HostGridView::Intersection HostIntersection; typedef typename HostGridView::IntersectionIterator HostIntersectionIterator; public: typedef GridView< HostGridView, CoordFunction, Allocator > GridViewImp; typedef Dune::GeometryGrid< HostGrid, CoordFunction, Allocator > Grid; typedef GeoGrid::IndexSet< const Grid, typename HostGridView::IndexSet > IndexSet; typedef Dune::Intersection< const Grid, GeoGrid::Intersection< const Grid, HostIntersection > > Intersection; typedef Dune::IntersectionIterator < const Grid, GeoGrid::IntersectionIterator< const Grid, HostIntersectionIterator >, GeoGrid::Intersection< const Grid, HostIntersection > > IntersectionIterator; typedef typename HostGridView::Communication Communication; template< int codim > struct Codim { typedef GeoGrid::Iterator< HostGridView, codim, All_Partition, const Grid > IteratorImp; typedef Dune::EntityIterator< codim, const Grid, IteratorImp > Iterator; typedef typename Grid::Traits::template Codim< codim >::Entity Entity; typedef typename Grid::template Codim< codim >::Geometry Geometry; typedef typename Grid::template Codim< codim >::LocalGeometry LocalGeometry; template< PartitionIteratorType pit > struct Partition { typedef GeoGrid::Iterator< HostGridView, codim, pit, const Grid > IteratorImp; typedef Dune::EntityIterator< codim, const Grid, IteratorImp > Iterator; }; }; static const bool conforming = HostGridView::conforming; }; // GridView // -------- template< class HGV, class CoordFunction, class Allocator > class GridView { typedef GridView< HGV, CoordFunction, Allocator > This; public: typedef GridViewTraits< HGV, CoordFunction, Allocator > Traits; typedef typename Traits::HostGridView HostGridView; typedef typename Traits::Grid Grid; typedef typename Traits::IndexSet IndexSet; typedef typename Traits::Intersection Intersection; typedef typename Traits::IntersectionIterator IntersectionIterator; typedef typename Traits::Communication Communication; template< int codim > struct Codim : public Traits::template Codim< codim > {}; static const bool conforming = Traits::conforming; GridView ( const Grid &grid, const HostGridView &hostGridView ) : grid_( &grid ), hostGridView_( hostGridView ) {} GridView ( const This &other ) : grid_( other.grid_ ), hostGridView_( other.hostGridView_ ) {} GridView ( This &&other ) : grid_( other.grid_ ), hostGridView_( std::move( other.hostGridView_ ) ) {} This &operator= ( const This &other ) { grid_ = other.grid_; hostGridView_ = other.hostGridView_; if( indexSet_ ) indexSet_.reset( hostGridView().indexSet() ); return *this; } This &operator= ( This &&other ) { grid_ = other.grid_; hostGridView_ = std::move( other.hostGridView_ ); if( indexSet_ ) indexSet_.reset( hostGridView().indexSet() ); return *this; } const Grid &grid () const { assert( grid_ ); return *grid_; } const IndexSet &indexSet () const { indexSet_.reset( hostGridView().indexSet() ); return indexSet_; } bool isConforming() const { return hostGridView().isConforming(); } int size ( int codim ) const { return hostGridView().size( codim ); } int size ( const GeometryType &type ) const { return hostGridView().size( type ); } template< int codim > typename Codim< codim >::Iterator begin () const { return begin< codim, All_Partition >(); } template< int codim, PartitionIteratorType pit > typename Codim< codim >::template Partition< pit >::Iterator begin () const { return Traits::template Codim< codim >::template Partition< pit >::IteratorImp::begin( grid(), hostGridView() ); } template< int codim > typename Codim< codim >::Iterator end () const { return end< codim, All_Partition >(); } template< int codim, PartitionIteratorType pit > typename Codim< codim >::template Partition< pit >::Iterator end () const { return Traits::template Codim< codim >::template Partition< pit >::IteratorImp::end( grid(), hostGridView() ); } IntersectionIterator ibegin ( const typename Codim< 0 >::Entity &entity ) const { typedef GeoGrid::IntersectionIterator< const Grid, typename HostGridView::IntersectionIterator > IntersectionIteratorImpl; return IntersectionIteratorImpl( entity, hostGridView().ibegin( entity.impl().hostEntity() ) ); } IntersectionIterator iend ( const typename Codim< 0 >::Entity &entity ) const { typedef GeoGrid::IntersectionIterator< const Grid, typename HostGridView::IntersectionIterator > IntersectionIteratorImpl; return IntersectionIteratorImpl( entity, hostGridView().iend( entity.impl().hostEntity() ) ); } const Communication &comm () const { return hostGridView().comm(); } int overlapSize ( int codim ) const { return hostGridView().overlapSize( codim ); } int ghostSize ( int codim ) const { return hostGridView().ghostSize( codim ); } template< class DataHandle, class Data > auto communicate ( CommDataHandleIF< DataHandle, Data > &dataHandle, InterfaceType interface, CommunicationDirection direction ) const { typedef CommDataHandleIF< DataHandle, Data > DataHandleIF; typedef GeoGrid::CommDataHandle< Grid, DataHandleIF > WrappedDataHandle; WrappedDataHandle wrappedDataHandle( grid(), dataHandle ); return hostGridView().communicate( wrappedDataHandle, interface, direction ); } const HostGridView &hostGridView () const { return hostGridView_; } private: const Grid *grid_; HostGridView hostGridView_; mutable IndexSet indexSet_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_GRIDVIEW_HH dune-grid-2.11.0/dune/grid/geometrygrid/helix.png000066400000000000000000000321301511655130300216500ustar00rootroot00000000000000PNG  IHDRݡ IDATx[՝ߏJb+Nj+ċַ1-@`.B@\d E!@ Ypc'FU[ݼe\e7t>Υgzfrsg , A B`!,A BX A A A`!,A BX,A X A`!A B`!,A BX,A X A`!A B`! y[PӉyK Pk7oz"bސ>Qa!LF%iU 냖ADU^! Y~08Ζ{84}~`!s_gd~!Bː qk ~`!snqEV,`?g"R,jd(.s Y.+ jW%Bɵi2*,5 Ul0vL1[CEv1Z#Wۯ ` O/Or 'oV XuE.,JXVl߸r֔$[M-M(6 ` jb>G9T[Y͇AUc*G2˖(6 `MP ,{z^Rx=1r٪CY}:hOj9JCATy\Hz[ X `M WЩl),Vp(SMVF2ސVlw_챴J4 Zje=g<:UH.po$"[.a"{8"D/_9B+5yXcl]2[: wC[]Qo3꾟O*|%]li>(XT^j&S^fAD!̖5"9ifZEe.a?ѡ;Zy+< d˖c#'w3hen"rZidlM~@+5CUVhDp[m>bX<f$UJ`UK6o2Qј\i:,5Qb$2b^evk\+mg6yO `5gTV$&%r1Q_j+ք8*W_Ӎ\>Y![*XS9jΙY~\^Z|Q`,{4 B۴m~,Z+,?޾>6EU)$"YRr]eW{UE|+ʳ絷tsRO*hsϟ*@J%h&sn''ր)cMk㳭UwCMwW+ )DRn4TX(Z.k4[Wա5Qʲ)6TXγ3n|y"T: `1:/ْX&Pi eDļXN0f~͒N%yt$h3[b TH{ؽEGD3w޼PUD@%嚗"dP+v'ͬ>*~̫Yof<9f BUH4yuSpŞe]DOϬ?uJUf<|^oo}Pa]ATy$C wGsOG*xK> -)"OtπdX&[\JJ]7fWk`5w|D^``{k@ˬU>m? rؒYSp@;*d q`,w=M6n'ߧam)nV[$! S*,Ӭk;u$8 ْRw^79 K6UYNM,M;]0ekM*tTؐ] ӵͿ%\k@CL,; FʖS&2SMFYk VA?boR e ֤2, gKJ\vfjf%z3K.eˢ*qR=Ulp*:!jӘ/7ν`-/U2K=(,drZ 5@7e e~SdcV{8^!f9o+K"٤~mdTR|\dc { *Yn%,Ȣ̡t>6A,Sd9:t Qa!K([+6 Ah,LLeprBbՏTSd!3W9,d }g]!Pa!HѬͅBW WXb' +$R3|G|FXla AR|E>HJ B-+X9 AZv 2wQQ~<]!BC`!\Sp4t)O>K Ȭ%D_|_Sxky{B;2ׇD$"M\P/Ȝ6D.Y ělY_y,d1EA"e#F?/F&~!BːG s8sS1Ai ȬZp/ 5#GN`yل1Q" `!Șp2[x6 2ꈜ0Zt_YosXȘ+e\<|Y; ,̣V{k.t3;\L?%A,bu_}:Oh-B^85oJ? d,5?oJuo҅9Dw1}39]a!k+j+="WNd=Bf ,+tM +vJt'ŏK$(Oc6|޼*)&X|++Yݬ'4z\QO`QB5J$"wPL[;I%[c NFD"߮Oj4Yv֫DDT}eF}W(1TX+wu/ָj=jk*oWX; -"b~&"-sZP#2*,5U#ak*a$X;C TljI"{bޝ1V_A15ybڥCAueifXZQ昕Vo\~-mXkTM-{ފK"%"/w:(ڥVYfkV -Z- `ISU^˿mnt"5d˥UB5tlVRje]_kDTŲ SA2] +{sZQ9Zu+R+ߪ/5 z*ӄ *'׮$_"IzKUD*Z,5L<9S6l <0AMuyfUZo-٘ZcV,PeK۷f`\/DZ֊li֊wӴr*3ݧFU)㡗|)@M6߉.g?O"2a|t(,UNmNRշڊ}S{Y}/#zD!V8Uu%"?'^dyVֈu׷l g]uSejR!j/鴢oki- ;uVS/DU_l d]U_IY-`*,{KuߞHJ+RXP!̪Wott9:.I@s_iκҊVVi~ DU,[մbۿ(uc_ˉˈs3Z%a+2VV~cVr"rصDTUQuiI*>O- S\,?^Ili[B"j|AU~z˱GoZmJPe-eJD^oiؽNP&[Uc2juD4kZ囵*[ ZGhа!쟦UpZz'ti62+PU- Q"fUj =HyWxk#sɱLtz6Nx:r̊*: ` nVŌ2C+}f%"թCAUV&Xk;BvFȡJ} VX9׊L.]fchٺQՀ V< 1pYfD; X)iTLDD用h4f4UZY+ r,|5>W|cjx #َwZZϦ%r2rOdʁYkfU K#*UcUz r,_{'o>t>%Yk`CCLP.h$}σ,UzD!"fj/FV,kKZ=Ygg_*c/,5k`Hy*ٕr{cj%rf{mҀE%:_sT Tf f |y2wWaZYW,Aޙ_[+m4j~iKZYYkdfirܱ2-SZCLM3V󷋬QI co¬ uE[&rO9DVݨi(+6fufnQμY̗,TX/+ιt KLoZ%nDļ/ifϟ_cӶ<,UE7SyX_B k•~0heEVRZŘQg9Y "a'* |2ƞ_> 49TUPav+ˊV,[(BXȜũw[Xܳ4 ~XuJ3g NEF?8n.]QO`guq-K2ވ|~xJE/Pa!c~g.&}tL`,iοyO/Q;.rrA A9LƯǹyBw ?Lw)3=خ;,W7U ,"y응,H(jOERO`Y]1`!SYPcщM:QJ ?m\?.<<5Q4HwSry啤{;HVV>m*uz+kWBf'zoY6gJH:/N%*dV qZ9᩷1YQx^{(MKdU{x,4f3]zbXiżϸe~15B9oիqFhM٣tMD1m&K=Z?2Ǔ~oo?Kt[w%)TXC8u&xHRZ++r2Gu~VV? ` `*,S.lJ˜3jDw]gVӚ<*qc" `*>}lEU:w yyY,C+;#M+z~3z{bjKml$"yQT]a|t(|mNtR৪U;TUx0]aݷ%D6Zi:ÙWgWWTUJXKJyn@37Jl44*,ej+VKԊŷ_f+P̪ ѽ |fo/-Vql,c~=",WNI5I0^ӮHklN+[VTh2꾜d*B~~LV-9yGe1 5m*U+lcS'ڽa>>u'X7>X?D< ġge`yάƩ22.QܓKgeVGĢL:[ۂeVkZU`yWfcJ>[zl{G-IګkZ 9Ҋ2.4ʫ||_Aʲ*rq߾Zc3ׯadGH^nihX#ʚc*VYtn ܗoGG!o;"Vk ء:lHs[:>BaKB{ϦJiTTKh;֌W3ӣrJckG(/"bXl2nU @`Edoe1Mr76XW:Y$,U`l}8e(ҕWZW[mrIYsXTw~2˯UBW2+-hZf0~MŗuԧH#ECn9j oj/KV XSQ*+^戤g<fʁקK|w[~IJࣙ]ˬ2=ϒ&Uf^nvDS5>':ı^OolLG({;?mrdcw:K>]pdƀDjJX3K6X ͸}QvPU ּYIfbo- J䪾sq_*ܨD$:l9EYK|yJAUy`r5PJȦq -8s (&P:]1"+Pgyo fh0!YkEƬyrŔK&UR (sُKgZ`axj 彲ze{Jh!ND5X fmo>6I"飪[4ʴTd]Wh*?x U,[`?[Ϗ*Y(X*lT*wLGS?_V:YaV>,5Yu |}gUmj7̻Δ}|Sƍ?Wf8`*`֠P;U%Sup|*͑<"b^5:eUĬW,5MeȕVUӭՄr >"b~XJEz%A+˽ V\_+>֕)΢WzқITT1cEWRٹܫfeTIQyX.1ZK_=uJJ?!"{\aN-_a ڴJY$e Jd91_Ftxh3J(SR捭GsnT4|`5K "3S[+G\f^4`+\3o\!ʘUk+ .c%rb3W`nVla|`=-y26d0bYvL:3Xs–`\.ibj<׽ Z*4=c3 Z%zB/em| *XZCd;hXbK *mLD I[DUrO5|qklTt]q+EYWU;//2rқc2j `IePusBhXʕyզazf?yg蕳QW`-W_SP E jtm˫ hͺ#sT-Tܺ1Pa Xm/mUBbWjWXdo+F"'#Yؘ,TXU[rRK:0Z)Y:wl._:2:w6yTXQyMjNz`* /_ eوFH\ADWX( +Q h@媒Y}ySd7-<4WQAV35dU59"UL`-a7%M]ukd-7MXU3=΢WpJ193^m:ٷ0\TX2"PP3*,Aykfd*)fz `!#GSdub:\^BkBEքX2j_BgsXx_ 庂3>ƢXږsl #A8$ X2䟡Zj[0)BQas>`! [+47 s  T[.dW?gt ]!BDWB%BWdVTt AF9pA B`!,A BX A A A`!,A BX,A X A`!A B`!,A BX,A X A`!A B`!,A}?/pQEIENDB`dune-grid-2.11.0/dune/grid/geometrygrid/helix.png.license000066400000000000000000000002501511655130300232670ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/geometrygrid/hostcorners.hh000066400000000000000000000023311511655130300227230ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_HOSTCORNERS_HH #define DUNE_GEOGRID_HOSTCORNERS_HH #include #include namespace Dune { namespace GeoGrid { // HostCorners // ----------- template< class HostEntity > class HostCorners { typedef typename HostEntity::Geometry HostGeometry; public: typedef typename HostGeometry::GlobalCoordinate Coordinate; explicit HostCorners ( const HostEntity &hostEntity ) : hostGeometry_( hostEntity.geometry() ) {} GeometryType type () const { return hostGeometry_.type(); } Coordinate operator[] ( int i ) const { return hostGeometry_.corner( i ); } std::size_t size () const { return hostGeometry_.corners(); } private: HostGeometry hostGeometry_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_HOSTCORNERS_HH dune-grid-2.11.0/dune/grid/geometrygrid/identity.hh000066400000000000000000000017651511655130300222150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_IDENTITY_HH #define DUNE_GEOGRID_IDENTITY_HH #include namespace Dune { template< class ctype, unsigned int dim > class IdenticalCoordFunction : public AnalyticalCoordFunction < ctype, dim, dim, IdenticalCoordFunction< ctype, dim > > { typedef IdenticalCoordFunction< ctype, dim > This; typedef AnalyticalCoordFunction< ctype, dim, dim, This > Base; public: typedef typename Base :: DomainVector DomainVector; typedef typename Base :: RangeVector RangeVector; template< typename... Args > IdenticalCoordFunction( Args&... ) {} RangeVector operator()(const DomainVector& x) const { return x; } }; } #endif dune-grid-2.11.0/dune/grid/geometrygrid/idset.hh000066400000000000000000000041061511655130300214640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_IDSET_HH #define DUNE_GEOGRID_IDSET_HH #include namespace Dune { namespace GeoGrid { // IdSet // ----- template< class Grid, class HostIdSet > class IdSet : public Dune::IdSet< Grid, IdSet< Grid, HostIdSet >, typename HostIdSet::IdType > { typedef IdSet< Grid, HostIdSet > This; typedef Dune::IdSet< Grid, This, typename HostIdSet::IdType > Base; typedef typename std::remove_const< Grid >::type::Traits Traits; public: typedef typename HostIdSet::IdType IdType; using Base::subId; IdSet () : hostIdSet_( 0 ) {} explicit IdSet ( const HostIdSet &hostIdSet ) : hostIdSet_( &hostIdSet ) {} IdSet ( const This &other ) : hostIdSet_( other.hostIdSet_ ) {} const This &operator= ( const This &other ) { hostIdSet_ = other.hostIdSet_; return *this; } template< int codim > IdType id ( const typename Traits::template Codim< codim >::Entity &entity ) const { return entity.impl().id( hostIdSet() ); } template< class Entity > IdType id ( const Entity &entity ) const { return id< Entity::codimension >( entity ); } IdType subId ( const typename Traits::template Codim< 0 >::Entity &entity, int i, unsigned int codim ) const { return hostIdSet().subId( Grid::template getHostEntity< 0 >( entity ), i, codim ); } explicit operator bool () const { return bool( hostIdSet_ ); } private: const HostIdSet &hostIdSet () const { assert( *this ); return *hostIdSet_; } const HostIdSet *hostIdSet_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_IDSET_HH dune-grid-2.11.0/dune/grid/geometrygrid/indexsets.hh000066400000000000000000000060641511655130300223670ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_INDEXSETS_HH #define DUNE_GEOGRID_INDEXSETS_HH #include #include #include #include #include namespace Dune { namespace GeoGrid { // IndexSet // -------- template< class Grid, class HostIndexSet > class IndexSet : public Dune::IndexSet< Grid, IndexSet< Grid, HostIndexSet >, typename HostIndexSet::IndexType, typename HostIndexSet::Types > { typedef IndexSet< Grid, HostIndexSet > This; typedef Dune::IndexSet< Grid, This, typename HostIndexSet::IndexType, typename HostIndexSet::Types > Base; typedef typename std::remove_const< Grid >::type::Traits Traits; typedef typename Traits::HostGrid HostGrid; public: static const int dimension = Traits::dimension; typedef typename Base::IndexType IndexType; typedef typename Base::Types Types; IndexSet () = default; explicit IndexSet ( const HostIndexSet &hostIndexSet ) : hostIndexSet_( &hostIndexSet ) {} // The index set contains a pointer to the host index set, so copying or assigning this can be dangerous. IndexSet ( const This & ) = delete; IndexSet ( This && ) = delete; IndexSet &operator= ( const This & ) = delete; IndexSet &operator= ( This && ) = delete; using Base::index; using Base::subIndex; template< int cc > IndexType index ( const typename Traits::template Codim< cc >::Entity &entity ) const { return entity.impl().index( hostIndexSet() ); } template< int cc > IndexType subIndex ( const typename Traits::template Codim< cc >::Entity &entity, int i, unsigned int codim ) const { return entity.impl().subIndex( hostIndexSet(), i, codim ); } std::size_t size ( GeometryType type ) const { return hostIndexSet().size( type ); } std::size_t size ( int codim ) const { return hostIndexSet().size( codim ); } template< class Entity > bool contains ( const Entity &entity ) const { return entity.impl().isContained( hostIndexSet() ); } Types types ( int codim ) const { return hostIndexSet().types( codim ); } explicit operator bool () const { return bool( hostIndexSet_ ); } void reset () { hostIndexSet_ = nullptr; } void reset ( const HostIndexSet &hostIndexSet ) { hostIndexSet_ = &hostIndexSet; } private: const HostIndexSet &hostIndexSet () const { assert( *this ); return *hostIndexSet_; } const HostIndexSet *hostIndexSet_ = nullptr; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_INDEXSETS_HH dune-grid-2.11.0/dune/grid/geometrygrid/intersection.hh000066400000000000000000000140551511655130300230660ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_INTERSECTION_HH #define DUNE_GEOGRID_INTERSECTION_HH #include #include namespace Dune { namespace GeoGrid { // Intersection // ------------ template< class Grid, class HostIntersection > class Intersection { typedef typename HostIntersection::Geometry HostGeometry; typedef typename HostIntersection::LocalGeometry HostLocalGeometry; typedef typename std::remove_const< Grid >::type::Traits Traits; public: typedef typename Traits::ctype ctype; static const int dimension = Traits::dimension; static const int dimensionworld = Traits::dimensionworld; typedef typename Traits::template Codim< 0 >::Entity Entity; typedef typename Traits::template Codim< 1 >::Geometry Geometry; typedef typename Traits::template Codim< 1 >::LocalGeometry LocalGeometry; typedef typename Traits::template Codim< 0 >::Geometry ElementGeometry; private: typedef GeoGrid::IntersectionCoordVector< Grid > CoordVector; typedef typename Traits::template Codim< 0 >::EntityImpl EntityImpl; typedef typename Traits::template Codim< 1 >::GeometryImpl GeometryImpl; typedef typename Traits::template Codim< 0 >::GeometryImpl ElementGeometryImpl; public: Intersection() {} explicit Intersection ( const HostIntersection &hostIntersection, const ElementGeometryImpl &insideGeo ) : hostIntersection_( hostIntersection ) , insideGeo_ ( insideGeo ) , geo_( grid() ) {} explicit Intersection ( HostIntersection&& hostIntersection, const ElementGeometryImpl &insideGeo ) : hostIntersection_( std::move( hostIntersection ) ) , insideGeo_ ( insideGeo ) , geo_( grid() ) {} bool equals ( const Intersection &other) const { return hostIntersection_ == other.hostIntersection_; } explicit operator bool () const { return bool( hostIntersection_ ); } Entity inside () const { return EntityImpl( insideGeo_, hostIntersection().inside() ); } Entity outside () const { return EntityImpl( grid(), hostIntersection().outside() ); } bool boundary () const { return hostIntersection().boundary(); } bool conforming () const { return hostIntersection().conforming(); } bool neighbor () const { return hostIntersection().neighbor(); } size_t boundarySegmentIndex () const { return hostIntersection().boundarySegmentIndex(); } LocalGeometry geometryInInside () const { return hostIntersection().geometryInInside(); } LocalGeometry geometryInOutside () const { return hostIntersection().geometryInOutside(); } Geometry geometry () const { if( !geo_ ) { CoordVector coords( insideGeo_, geometryInInside() ); geo_ = GeometryImpl( grid(), type(), coords ); } return Geometry( geo_ ); } GeometryType type () const { return hostIntersection().type(); } int indexInInside () const { return hostIntersection().indexInInside(); } int indexInOutside () const { return hostIntersection().indexInOutside(); } FieldVector< ctype, dimensionworld > integrationOuterNormal ( const FieldVector< ctype, dimension-1 > &local ) const { const LocalGeometry geoInInside = geometryInInside(); const int idxInInside = indexInInside(); auto refElement = referenceElement< ctype, dimension >( insideGeo_.type() ); FieldVector< ctype, dimension > x( geoInInside.global( local ) ); const typename ElementGeometryImpl::JacobianInverseTransposed &jit = insideGeo_.jacobianInverseTransposed( x ); FieldVector< ctype, dimension > refNormal = refElement.integrationOuterNormal( idxInInside ); FieldVector< ctype, dimensionworld > normal; jit.mv( refNormal, normal ); if( !conforming() ) normal *= geoInInside.volume() / refElement.template geometry< 1 >( idxInInside ).volume(); normal *= jit.detInv(); //normal *= insideGeo_.integrationElement( x ); return normal; } FieldVector< ctype, dimensionworld > outerNormal ( const FieldVector< ctype, dimension-1 > &local ) const { auto refElement = referenceElement< ctype, dimension >( insideGeo_.type() ); FieldVector< ctype, dimension > x( geometryInInside().global( local ) ); const typename ElementGeometryImpl::JacobianInverseTransposed &jit = insideGeo_.jacobianInverseTransposed( x ); FieldVector< ctype, dimension > refNormal = refElement.integrationOuterNormal( indexInInside() ); FieldVector< ctype, dimensionworld > normal; jit.mv( refNormal, normal ); return normal; } FieldVector< ctype, dimensionworld > unitOuterNormal ( const FieldVector< ctype, dimension-1 > &local ) const { FieldVector< ctype, dimensionworld > normal = outerNormal( local ); normal *= (ctype( 1 ) / normal.two_norm()); return normal; } FieldVector< ctype, dimensionworld > centerUnitOuterNormal () const { auto refFace = referenceElement< ctype, dimension-1 >( type() ); return unitOuterNormal( refFace.position( 0, 0 ) ); } const HostIntersection &hostIntersection () const { return hostIntersection_; } const Grid &grid () const { return insideGeo_.grid(); } private: HostIntersection hostIntersection_; ElementGeometryImpl insideGeo_; mutable GeometryImpl geo_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_INTERSECTION_HH dune-grid-2.11.0/dune/grid/geometrygrid/intersectioniterator.hh000066400000000000000000000051131511655130300246330ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_INTERSECTIONITERATOR_HH #define DUNE_GEOGRID_INTERSECTIONITERATOR_HH #include namespace Dune { namespace GeoGrid { // IntersectionIterator // -------------------- template< class Grid, class HostIntersectionIterator > class IntersectionIterator { typedef typename std::remove_const< Grid >::type::Traits Traits; typedef GeoGrid::Intersection< Grid, typename HostIntersectionIterator::Intersection > IntersectionImpl; typedef typename Traits::template Codim< 0 >::Geometry ElementGeometry; typedef typename Traits::template Codim< 0 >::GeometryImpl ElementGeometryImpl; public: typedef Dune::Intersection< Grid, IntersectionImpl > Intersection; IntersectionIterator() {} template< class Entity > IntersectionIterator ( const Entity &inside, const HostIntersectionIterator &hostIterator ) : hostIterator_( hostIterator ) , insideGeo_( inside.geometry().impl() ) {} IntersectionIterator ( const IntersectionIterator &other ) : hostIterator_( other.hostIterator_ ) , insideGeo_( other.insideGeo_ ) {} IntersectionIterator ( IntersectionIterator&& other ) : hostIterator_( std::move( other.hostIterator_ ) ) , insideGeo_( std::move( other.insideGeo_ ) ) {} IntersectionIterator &operator= ( const IntersectionIterator &other ) { hostIterator_ = other.hostIterator_; insideGeo_ = other.insideGeo_; return *this; } IntersectionIterator &operator= ( IntersectionIterator&& other ) { hostIterator_ = std::move( other.hostIterator_ ); insideGeo_ = std::move( other.insideGeo_ ); return *this; } bool equals ( const IntersectionIterator &other ) const { return (hostIterator_ == other.hostIterator_); } void increment () { ++hostIterator_; } Intersection dereference () const { return IntersectionImpl( *hostIterator_, insideGeo_ ); } private: HostIntersectionIterator hostIterator_; ElementGeometryImpl insideGeo_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_INTERSECTIONITERATOR_HH dune-grid-2.11.0/dune/grid/geometrygrid/iterator.hh000066400000000000000000000332531511655130300222120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_ITERATOR_HH #define DUNE_GEOGRID_ITERATOR_HH #include #include #include #include #include #include #include namespace Dune { namespace GeoGrid { // Internal Forward Declarations // ----------------------------- template< class HostGridView, int codim, PartitionIteratorType pitype, class Grid, bool fake = !Capabilities::hasHostEntity< Grid, codim >::v > class Iterator; template< class Grid > class HierarchicIterator; // PartitionIteratorFilter // ----------------------- template< int codim, PartitionIteratorType pitype, class Grid > struct PartitionIteratorFilter; template< int codim, class Grid > struct PartitionIteratorFilter< codim, Interior_Partition, Grid > { static const int dimension = std::remove_const< Grid >::type::dimension; static const int codimension = codim; static const PartitionIteratorType Element_Partition = Interior_Partition; typedef typename std::remove_const< Grid >::type::ctype ctype; typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element; typedef typename ReferenceElements< ctype, dimension >::ReferenceElement RefElement; static bool apply ( const RefElement &refElement, const Element &element, int subEntity ) { const int size = refElement.size( subEntity, codim, dimension ); for( int i = 0; i < size; ++i ) { const int j = refElement.subEntity( subEntity, codim, i, dimension ); PartitionType type = element.template subEntity< dimension >( j ).partitionType(); if( type == InteriorEntity ) return true; } return false; } }; template< int codim, class Grid > struct PartitionIteratorFilter< codim, InteriorBorder_Partition, Grid > { static const int dimension = std::remove_const< Grid >::type::dimension; static const int codimension = codim; static const PartitionIteratorType Element_Partition = Interior_Partition; typedef typename std::remove_const< Grid >::type::ctype ctype; typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element; typedef typename ReferenceElements< ctype, dimension >::ReferenceElement RefElement; static bool apply ( const RefElement &refElement, const Element &element, int subEntity ) { return true; } }; template< int codim, class Grid > struct PartitionIteratorFilter< codim, Overlap_Partition, Grid > { static const int dimension = std::remove_const< Grid >::type::dimension; static const int codimension = codim; static const PartitionIteratorType Element_Partition = Overlap_Partition; typedef typename std::remove_const< Grid >::type::ctype ctype; typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element; typedef typename ReferenceElements< ctype, dimension >::ReferenceElement RefElement; static bool apply ( const RefElement &refElement, const Element &element, int subEntity ) { if( element.partitionType() == InteriorEntity ) return true; const int size = refElement.size( subEntity, codim, dimension ); for( int i = 0; i < size; ++i ) { const int j = refElement.subEntity( subEntity, codim, i, dimension ); PartitionType type = element.template subEntity< dimension >( j ).partitionType(); if( (type == OverlapEntity) || (type == BorderEntity) ) return true; } return false; } }; template< int codim, class Grid > struct PartitionIteratorFilter< codim, OverlapFront_Partition, Grid > { static const int dimension = std::remove_const< Grid >::type::dimension; static const int codimension = codim; static const PartitionIteratorType Element_Partition = Overlap_Partition; typedef typename std::remove_const< Grid >::type::ctype ctype; typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element; typedef typename ReferenceElements< ctype, dimension >::ReferenceElement RefElement; static bool apply ( const RefElement &refElement, const Element &element, int subEntity ) { return true; } }; template< int codim, class Grid > struct PartitionIteratorFilter< codim, All_Partition, Grid > { static const int dimension = std::remove_const< Grid >::type::dimension; static const int codimension = codim; static const PartitionIteratorType Element_Partition = All_Partition; typedef typename std::remove_const< Grid >::type::ctype ctype; typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element; typedef typename ReferenceElements< ctype, dimension >::ReferenceElement RefElement; static bool apply ( const RefElement &refElement, const Element &element, int subEntity ) { return true; } }; template< int codim, class Grid > struct PartitionIteratorFilter< codim, Ghost_Partition, Grid > { static const int dimension = std::remove_const< Grid >::type::dimension; static const int codimension = codim; static const PartitionIteratorType Element_Partition = Ghost_Partition; typedef typename std::remove_const< Grid >::type::ctype ctype; typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element; typedef typename ReferenceElements< ctype, dimension >::ReferenceElement RefElement; static bool apply ( const RefElement &refElement, const Element &element, int subEntity ) { const int size = refElement.size( subEntity, codim, dimension ); for( int i = 0; i < size; ++i ) { const int j = refElement.subEntity( subEntity, codim, i, dimension ); PartitionType type = element.template subEntity< dimension >( j ).partitionType(); if( type == GhostEntity ) return true; } return false; } }; // Iterator (real) // --------------- template< class HostGridView, int codim, PartitionIteratorType pitype, class G > class Iterator< HostGridView, codim, pitype, G, false > { typedef typename std::remove_const< G >::type::Traits Traits; public: typedef typename Traits::Grid Grid; static const int codimension = codim; typedef typename Traits::template Codim< codimension >::Entity Entity; static const bool fake = false; private: typedef GeoGrid::Entity< codimension, Traits::dimension, G > EntityImpl; typedef typename HostGridView::template Codim< codim >::template Partition< pitype >::Iterator HostEntityIterator; public: Iterator () : grid_( nullptr ) {} Iterator ( const Grid &grid, HostEntityIterator hostEntityIterator ) : grid_( &grid ), hostEntityIterator_( std::move( hostEntityIterator ) ) {} void increment () { ++hostEntityIterator_; } bool equals ( const Iterator &rhs ) const { return hostEntityIterator_ == rhs.hostEntityIterator_; } Entity dereference () const { return EntityImpl( grid(), *hostEntityIterator_ ); } int level () const { return hostEntityIterator_.level(); } const Grid &grid () const { assert( grid_ ); return *grid_; } static Iterator begin ( const Grid &grid, const HostGridView &hostGridView ) { HostEntityIterator hostEntityIterator = hostGridView.template begin< codimension, pitype >(); return Iterator( grid, std::move( hostEntityIterator ) ); } static Iterator end ( const Grid &grid, const HostGridView &hostGridView ) { HostEntityIterator hostEntityIterator = hostGridView.template end< codimension, pitype >(); return Iterator( grid, std::move( hostEntityIterator ) ); } private: const Grid *grid_; HostEntityIterator hostEntityIterator_; }; // Iterator (fake) // --------------- template< class HostGridView, int codim, PartitionIteratorType pitype, class G > class Iterator< HostGridView, codim, pitype, G, true > { typedef typename std::remove_const< G >::type::Traits Traits; public: typedef typename Traits::Grid Grid; static const int codimension = codim; typedef typename Traits::template Codim< codimension >::Entity Entity; private: typedef GeoGrid::Entity< codimension, Traits::dimension, G > EntityImpl; typedef PartitionIteratorFilter< codim, pitype, typename HostGridView::Grid > Filter; typedef typename HostGridView::template Codim<0>::template Partition< Filter::Element_Partition >::Iterator HostElementIterator; typedef typename HostElementIterator::Entity HostElement; typedef typename HostGridView::IndexSet HostIndexSet; public: Iterator () : grid_( nullptr ), subEntity_( -1 ), hostIndexSet_( nullptr ) {} Iterator ( const Grid &grid, HostElementIterator hostElementIterator, HostElementIterator hostEnd, const HostIndexSet &hostIndexSet ) : grid_( &grid ), hostElementIterator_( hostElementIterator ), hostEnd_( hostEnd ), subEntity_( -1 ), hostIndexSet_( &hostIndexSet ) { if( hostElementIterator_ != hostEnd_ ) { visited_.resize( hostIndexSet_->size( codimension ), false ); increment(); } } void increment () { typedef typename Traits::ctype ctype; while( hostElementIterator_ != hostEnd_ ) { const HostElement &hostElement = *hostElementIterator_; auto refElement = referenceElement< ctype, Traits::dimension >( hostElement.type() ); ++subEntity_; const int count = refElement.size( codimension ); for( ; subEntity_ < count; ++subEntity_ ) { if( !Filter::apply( refElement, hostElement, subEntity_ ) ) continue; const size_t index = hostIndexSet_->subIndex( hostElement, subEntity_, codimension ); if( !visited_[ index ] ) { visited_[ index ] = true; return; } } ++hostElementIterator_; subEntity_ = -1; } } bool equals ( const Iterator &rhs ) const { return hostElementIterator_ == rhs.hostElementIterator_ && ( hostElementIterator_ == hostEnd_ || subEntity_ == rhs.subEntity_ ); } Entity dereference () const { return EntityImpl( grid(), *hostElementIterator_, subEntity_ ); } int level () const { return hostElementIterator_.level(); } const Grid &grid () const { assert( grid_ ); return *grid_; } static Iterator begin ( const Grid &grid, const HostGridView &hostGridView ) { HostElementIterator first = hostGridView.template begin< 0, Filter::Element_Partition >(); HostElementIterator last = hostGridView.template end< 0, Filter::Element_Partition >(); return Iterator( grid, std::move( first ), std::move( last ), hostGridView.indexSet() ); } static Iterator end ( const Grid &grid, const HostGridView &hostGridView ) { HostElementIterator last = hostGridView.template end< 0, Filter::Element_Partition >(); return Iterator( grid, last, last, hostGridView.indexSet() ); } private: const Grid *grid_; HostElementIterator hostElementIterator_, hostEnd_; int subEntity_; const HostIndexSet *hostIndexSet_; std::vector< bool > visited_; }; // HierarchicIterator // ------------------ template< class G > class HierarchicIterator { typedef typename std::remove_const< G >::type::Traits Traits; public: typedef typename Traits::Grid Grid; static const int codimension = 0; typedef typename Traits::template Codim< codimension >::Entity Entity; private: typedef GeoGrid::Entity< codimension, Traits::dimension, G > EntityImpl; typedef typename Grid::HostGrid::HierarchicIterator HostEntityIterator; public: HierarchicIterator () : grid_( nullptr ) {} HierarchicIterator ( const Grid &grid, HostEntityIterator hostEntityIterator ) : grid_( &grid ), hostEntityIterator_( std::move( hostEntityIterator ) ) {} void increment () { ++hostEntityIterator_; } bool equals ( const HierarchicIterator &rhs ) const { return hostEntityIterator_ == rhs.hostEntityIterator_; } Entity dereference () const { return EntityImpl( grid(), *hostEntityIterator_ ); } int level () const { return hostEntityIterator_.level(); } const Grid &grid () const { assert( grid_ ); return *grid_; } private: const Grid *grid_; HostEntityIterator hostEntityIterator_; }; } // namespace GeoGrid } // namespace Dune #endif // #ifndef DUNE_GEOGRID_ITERATOR_HH dune-grid-2.11.0/dune/grid/geometrygrid/persistentcontainer.hh000066400000000000000000000024071511655130300244610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_PERSISTENTCONTAINER_HH #define DUNE_GEOGRID_PERSISTENTCONTAINER_HH #include #include #include namespace Dune { // PersistentContainer for GeometryGrid // ------------------------------------ template< class HostGrid, class CoordFunction, class Allocator, class T > class PersistentContainer< GeometryGrid< HostGrid, CoordFunction, Allocator >, T > : public PersistentContainerWrapper< GeometryGrid< HostGrid, CoordFunction, Allocator >, T > { typedef PersistentContainerWrapper< GeometryGrid< HostGrid, CoordFunction, Allocator >, T > Base; public: typedef typename Base::Grid Grid; typedef typename Base::Value Value; PersistentContainer ( const Grid &grid, int codim, const Value &value = Value() ) : Base( grid, codim, value ) {} }; } // namespace Dune #endif // #ifndef DUNE_GEOGRID_PERSISTENTCONTAINER_HH dune-grid-2.11.0/dune/grid/identitygrid.hh000066400000000000000000000375241511655130300203640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IDENTITYGRID_HH #define DUNE_GRID_IDENTITYGRID_HH /** \file * \brief The IdentityGrid class */ #include #include #include #include #include // The components of the IdentityGrid interface #include "identitygrid/identitygridgeometry.hh" #include "identitygrid/identitygridentity.hh" #include "identitygrid/identitygridentityseed.hh" #include "identitygrid/identitygridintersectioniterator.hh" #include "identitygrid/identitygridleveliterator.hh" #include "identitygrid/identitygridleafiterator.hh" #include "identitygrid/identitygridhierarchiciterator.hh" #include "identitygrid/identitygridindexsets.hh" namespace Dune { // Forward declaration template class IdentityGrid; // External forward declarations template< class Grid > struct HostGridAccess; template struct IdentityGridFamily { public: typedef GridTraits< dim, HostGrid::dimensionworld, Dune::IdentityGrid, IdentityGridGeometry, IdentityGridEntity, IdentityGridLevelIterator, IdentityGridLeafIntersection, IdentityGridLevelIntersection, IdentityGridLeafIntersectionIterator, IdentityGridLevelIntersectionIterator, IdentityGridHierarchicIterator, IdentityGridLeafIterator, IdentityGridLevelIndexSet< const IdentityGrid >, IdentityGridLeafIndexSet< const IdentityGrid >, IdentityGridGlobalIdSet< const IdentityGrid >, typename HostGrid::Traits::GlobalIdSet::IdType, IdentityGridLocalIdSet< const IdentityGrid >, typename HostGrid::Traits::LocalIdSet::IdType, Communication, DefaultLevelGridViewTraits, DefaultLeafGridViewTraits, IdentityGridEntitySeed, IdentityGridGeometry, typename HostGrid::Traits::LevelIndexSet::IndexType, typename HostGrid::Traits::LevelIndexSet::Types, typename HostGrid::Traits::LeafIndexSet::IndexType, typename HostGrid::Traits::LeafIndexSet::Types > Traits; }; //********************************************************************** // // --IdentityGrid // //************************************************************************ /*! * \brief Provides a meta grid that is identical to its host * \ingroup GridImplementations * \ingroup IdentityGrid * * \tparam HostGrid The host grid type wrapped by the IdentityGrid */ template class IdentityGrid : public GridDefaultImplementation > { friend class IdentityGridLevelIndexSet >; friend class IdentityGridLeafIndexSet >; friend class IdentityGridGlobalIdSet >; friend class IdentityGridLocalIdSet >; friend class IdentityGridHierarchicIterator >; friend class IdentityGridLevelIntersectionIterator >; friend class IdentityGridLeafIntersectionIterator >; template friend class IdentityGridLevelIterator; template friend class IdentityGridLeafIterator; template friend class IdentityGridEntity; friend struct HostGridAccess< IdentityGrid< HostGrid > >; public: /** \todo Should not be public */ typedef HostGrid HostGridType; //********************************************************** // The Interface Methods //********************************************************** //! type of the used GridFamily for this grid typedef IdentityGridFamily GridFamily; //! the Traits typedef typename IdentityGridFamily::Traits Traits; //! The type used to store coordinates, inherited from the HostGrid typedef typename HostGrid::ctype ctype; /** \brief Constructor * * \param hostgrid The host grid wrapped by the IdentityGrid */ explicit IdentityGrid(HostGrid& hostgrid) : hostgrid_(&hostgrid), leafIndexSet_(*this), globalIdSet_(*this), localIdSet_(*this) { setIndices(); } //! Destructor ~IdentityGrid() { // Delete level index sets for (size_t i=0; imaxLevel(); } //! Iterator to first entity of given codim on level template typename Traits::template Codim::LevelIterator lbegin (int level) const { return IdentityGridLevelIterator >(this, level); } //! one past the end on this level template typename Traits::template Codim::LevelIterator lend (int level) const { return IdentityGridLevelIterator >(this, level, true); } //! Iterator to first entity of given codim on level template typename Traits::template Codim::template Partition::LevelIterator lbegin (int level) const { return IdentityGridLevelIterator >(this, level); } //! one past the end on this level template typename Traits::template Codim::template Partition::LevelIterator lend (int level) const { return IdentityGridLevelIterator >(this, level, true); } //! Iterator to first leaf entity of given codim template typename Traits::template Codim::LeafIterator leafbegin() const { return IdentityGridLeafIterator >(this); } //! one past the end of the sequence of leaf entities template typename Traits::template Codim::LeafIterator leafend() const { return IdentityGridLeafIterator >(this, true); } //! Iterator to first leaf entity of given codim template typename Traits::template Codim::template Partition::LeafIterator leafbegin() const { return IdentityGridLeafIterator >(this); } //! one past the end of the sequence of leaf entities template typename Traits::template Codim::template Partition::LeafIterator leafend() const { return IdentityGridLeafIterator >(this, true); } /** \brief Number of grid entities per level and codim */ int size (int level, int codim) const { return hostgrid_->size(level,codim); } /** \brief returns the number of boundary segments within the macro grid */ size_t numBoundarySegments () const { return hostgrid_->numBoundarySegments(); } //! number of leaf entities per codim in this process int size (int codim) const { return leafIndexSet().size(codim); } //! number of entities per level, codim and geometry type in this process int size (int level, GeometryType type) const { return levelIndexSets_[level]->size(type); } //! number of leaf entities per codim and geometry type in this process int size (GeometryType type) const { return leafIndexSet().size(type); } /** \brief Access to the GlobalIdSet */ const typename Traits::GlobalIdSet& globalIdSet() const { return globalIdSet_; } /** \brief Access to the LocalIdSet */ const typename Traits::LocalIdSet& localIdSet() const { return localIdSet_; } /** \brief Access to the LevelIndexSets */ const typename Traits::LevelIndexSet& levelIndexSet(int level) const { if (level < 0 || level > maxLevel()) { DUNE_THROW(GridError, "levelIndexSet of nonexisting level " << level << " requested!"); } return *levelIndexSets_[level]; } /** \brief Access to the LeafIndexSet */ const typename Traits::LeafIndexSet& leafIndexSet() const { return leafIndexSet_; } /** \brief Create Entity from EntitySeed */ template < class EntitySeed > typename Traits::template Codim::Entity entity(const EntitySeed& seed) const { typedef IdentityGridEntity< EntitySeed::codimension, HostGrid::dimension, const typename Traits::Grid > EntityImp; return EntityImp(this, hostgrid_->entity(seed.impl().hostEntitySeed())); } /** @name Grid Refinement Methods */ /*@{*/ /** global refinement * \todo optimize implementation */ void globalRefine (int refCount) { hostgrid_->globalRefine(refCount); } /** \brief Mark entity for refinement * * This only works for entities of codim 0. * The parameter is currently ignored * * \return
    *
  • true, if marking was successful
  • *
  • false, if marking was not possible
  • *
*/ bool mark(int refCount, const typename Traits::template Codim<0>::Entity & e) { return hostgrid_->mark(refCount, getHostEntity<0>(e)); } /** \brief Return refinement mark for entity * * \return refinement mark (1,0,-1) */ int getMark(const typename Traits::template Codim<0>::Entity & e) const { return hostgrid_->getMark(getHostEntity<0>(e)); } /** \brief returns true, if at least one entity is marked for adaption */ bool preAdapt() { return hostgrid_->preAdapt(); } //! Triggers the grid refinement process bool adapt() { return hostgrid_->adapt(); } /** \brief Clean up refinement markers */ void postAdapt() { return hostgrid_->postAdapt(); } /*@}*/ /** \brief Size of the overlap on the leaf level */ unsigned int overlapSize(int codim) const { return hostgrid_->leafGridView().overlapSize(codim); } /** \brief Size of the ghost cell layer on the leaf level */ unsigned int ghostSize(int codim) const { return hostgrid_->leafGridView().ghostSize(codim); } /** \brief Size of the overlap on a given level */ unsigned int overlapSize(int level, int codim) const { return hostgrid_->levelGridView(level).overlapSize(codim); } /** \brief Size of the ghost cell layer on a given level */ unsigned int ghostSize(int level, int codim) const { return hostgrid_->levelGridView(level).ghostSize(codim); } #if 0 /** \brief Distributes this grid over the available nodes in a distributed machine * * \param minlevel The coarsest grid level that gets distributed * \param maxlevel does currently get ignored */ void loadBalance(int strategy, int minlevel, int depth, int maxlevel, int minelement){ DUNE_THROW(NotImplemented, "IdentityGrid::loadBalance()"); } #endif /** \brief dummy communication */ const Communication& comm () const { return ccobj; } /** \brief Communicate data of level gridView */ template void communicate (DataHandle& handle, InterfaceType iftype, CommunicationDirection dir, int level) const { hostgrid_->levelGridView(level).communicate(handle,iftype,dir); } /** \brief Communicate data of leaf gridView */ template void communicate (DataHandle& handle, InterfaceType iftype, CommunicationDirection dir) const { hostgrid_->leafGridView().communicate(handle,iftype,dir); } // ********************************************************** // End of Interface Methods // ********************************************************** //! Returns the hostgrid this IdentityGrid lives in HostGridType& getHostGrid() const { return *hostgrid_; } //! Returns the hostgrid entity encapsulated in given IdentityGrid entity template const typename HostGrid::Traits::template Codim::Entity& getHostEntity(const typename Traits::template Codim::Entity& e) const { return e.impl().hostEntity_; } protected: //! The host grid which contains the actual grid hierarchy structure HostGrid* hostgrid_; private: //! compute the grid indices and ids void setIndices() { localIdSet_.update(); globalIdSet_.update(); // ////////////////////////////////////////// // Create the index sets // ////////////////////////////////////////// for (int i=levelIndexSets_.size(); i<=maxLevel(); i++) { IdentityGridLevelIndexSet >* p = new IdentityGridLevelIndexSet >(); levelIndexSets_.push_back(p); } for (int i=0; i<=maxLevel(); i++) if (levelIndexSets_[i]) levelIndexSets_[i]->update(*this, i); leafIndexSet_.update(*this); } //! \todo Please doc me ! Communication ccobj; //! Our set of level indices std::vector >*> levelIndexSets_; //! \todo Please doc me ! IdentityGridLeafIndexSet > leafIndexSet_; //! \todo Please doc me ! IdentityGridGlobalIdSet > globalIdSet_; //! \todo Please doc me ! IdentityGridLocalIdSet > localIdSet_; }; // end Class IdentityGrid namespace Capabilities { /** \brief has entities for some codimensions as host grid * \ingroup IdentityGrid */ template struct hasEntity, codim> { static const bool v = hasEntity::v; }; template struct hasEntityIterator, codim> { static const bool v = hasEntityIterator::v; }; /** \brief IdentityGrid can communicate when the host grid can communicate * \ingroup IdentityGrid */ template struct canCommunicate, codim> { static const bool v = canCommunicate::v; }; /** \brief has conforming level grids when host grid has * \ingroup IdentityGrid */ template struct isLevelwiseConforming > { static const bool v = isLevelwiseConforming::v; }; /** \brief has conforming leaf grids when host grid has * \ingroup IdentityGrid */ template struct isLeafwiseConforming > { static const bool v = isLeafwiseConforming::v; }; } // end namespace Capabilities } // namespace Dune #endif // DUNE_GRID_IDENTITYGRID_HH dune-grid-2.11.0/dune/grid/identitygrid/000077500000000000000000000000001511655130300200305ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/identitygrid/CMakeLists.txt000066400000000000000000000010451511655130300225700ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS identitygridentity.hh identitygridentityseed.hh identitygridhierarchiciterator.hh identitygridgeometry.hh identitygridintersectioniterator.hh identitygridintersections.hh identitygridindexsets.hh identitygridleafiterator.hh identitygridleveliterator.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/identitygrid) dune-grid-2.11.0/dune/grid/identitygrid/identitygridentity.hh000066400000000000000000000303021511655130300243030ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRIDENTITY_HH #define DUNE_IDENTITYGRIDENTITY_HH /** \file * \brief The IdentityGridEntity class */ #include namespace Dune { // Forward declarations template class IdentityGridEntity; template class IdentityGridLevelIterator; template class IdentityGridLevelIntersectionIterator; template class IdentityGridLeafIntersectionIterator; template class IdentityGridHierarchicIterator; // External forward declarations template< class Grid > struct HostGridAccess; //********************************************************************** // // --IdentityGridEntity // --Entity // /** \brief The implementation of entities in a IdentityGrid * \ingroup IdentityGrid * * A Grid is a container of grid entities. An entity is parametrized by the codimension. * An entity of codimension c in dimension d is a d-c dimensional object. * */ template class IdentityGridEntity : public EntityDefaultImplementation { template friend class IdentityGridLevelIndexSet; template friend class IdentityGridLeafIndexSet; template friend class IdentityGridLocalIdSet; template friend class IdentityGridGlobalIdSet; friend struct HostGridAccess< typename std::remove_const< GridImp >::type >; private: typedef typename GridImp::ctype ctype; // The codimension of this entity wrt the host grid constexpr static int CodimInHostGrid = GridImp::HostGridType::dimension - GridImp::dimension + codim; // equivalent entity in the host grid typedef typename GridImp::HostGridType::Traits::template Codim::Entity HostGridEntity; public: typedef typename GridImp::template Codim::Geometry Geometry; //! The type of the EntitySeed interface class typedef typename GridImp::template Codim::EntitySeed EntitySeed; IdentityGridEntity() : identityGrid_(nullptr) {} IdentityGridEntity(const GridImp* identityGrid, const HostGridEntity& hostEntity) : hostEntity_(hostEntity) , identityGrid_(identityGrid) {} IdentityGridEntity(const GridImp* identityGrid, HostGridEntity&& hostEntity) : hostEntity_(std::move(hostEntity)) , identityGrid_(identityGrid) {} //! \todo Please doc me ! IdentityGridEntity(const IdentityGridEntity& original) : hostEntity_(original.hostEntity_) , identityGrid_(original.identityGrid_) {} IdentityGridEntity(IdentityGridEntity&& original) : hostEntity_(std::move(original.hostEntity_)) , identityGrid_(original.identityGrid_) {} //! \todo Please doc me ! IdentityGridEntity& operator=(const IdentityGridEntity& original) { if (this != &original) { identityGrid_ = original.identityGrid_; hostEntity_ = original.hostEntity_; } return *this; } //! \todo Please doc me ! IdentityGridEntity& operator=(IdentityGridEntity&& original) { if (this != &original) { identityGrid_ = original.identityGrid_; hostEntity_ = std::move(original.hostEntity_); } return *this; } bool equals(const IdentityGridEntity& other) const { return hostEntity_ == other.hostEntity_; } //! returns true if father entity exists bool hasFather () const { return hostEntity_.hasFather(); } //! Create EntitySeed EntitySeed seed () const { return EntitySeed(hostEntity_); } //! level of this element int level () const { return hostEntity_.level(); } /** \brief The partition type for parallel computing */ PartitionType partitionType () const { return hostEntity_.partitionType(); } /** \brief Return the number of subEntities of codimension codim. */ unsigned int subEntities (unsigned int cc) const { return hostEntity_.subEntities(cc); } //! geometry of this entity Geometry geometry () const { return Geometry( hostEntity_.geometry() ); } HostGridEntity hostEntity_; private: const GridImp* identityGrid_; }; //*********************** // // --IdentityGridEntity // //*********************** /** \brief Specialization for codim-0-entities. * \ingroup IdentityGrid * * This class embodies the topological parts of elements of the grid. * It has an extended interface compared to the general entity class. * For example, Entities of codimension 0 allow to visit all neighbors. */ template class IdentityGridEntity<0,dim,GridImp> : public EntityDefaultImplementation<0,dim,GridImp, IdentityGridEntity> { friend struct HostGridAccess< typename std::remove_const< GridImp >::type >; public: // The codimension of this entitypointer wrt the host grid constexpr static int CodimInHostGrid = GridImp::HostGridType::dimension - GridImp::dimension; // equivalent entity in the host grid typedef typename GridImp::HostGridType::Traits::template Codim::Entity HostGridEntity; typedef typename GridImp::template Codim<0>::Geometry Geometry; typedef typename GridImp::template Codim<0>::LocalGeometry LocalGeometry; //! The Iterator over intersections on this level typedef IdentityGridLevelIntersectionIterator LevelIntersectionIterator; //! The Iterator over intersections on the leaf level typedef IdentityGridLeafIntersectionIterator LeafIntersectionIterator; //! Iterator over descendants of the entity typedef IdentityGridHierarchicIterator HierarchicIterator; //! The type of the EntitySeed interface class typedef typename GridImp::template Codim<0>::EntitySeed EntitySeed; IdentityGridEntity() : identityGrid_(nullptr) {} IdentityGridEntity(const GridImp* identityGrid, const HostGridEntity& hostEntity) : hostEntity_(hostEntity) , identityGrid_(identityGrid) {} IdentityGridEntity(const GridImp* identityGrid, HostGridEntity&& hostEntity) : hostEntity_(std::move(hostEntity)) , identityGrid_(identityGrid) {} //! \todo Please doc me ! IdentityGridEntity(const IdentityGridEntity& original) : hostEntity_(original.hostEntity_) , identityGrid_(original.identityGrid_) {} IdentityGridEntity(IdentityGridEntity&& original) : hostEntity_(std::move(original.hostEntity_)) , identityGrid_(original.identityGrid_) {} //! \todo Please doc me ! IdentityGridEntity& operator=(const IdentityGridEntity& original) { if (this != &original) { identityGrid_ = original.identityGrid_; hostEntity_ = original.hostEntity_; } return *this; } //! \todo Please doc me ! IdentityGridEntity& operator=(IdentityGridEntity&& original) { if (this != &original) { identityGrid_ = original.identityGrid_; hostEntity_ = std::move(original.hostEntity_); } return *this; } bool equals(const IdentityGridEntity& other) const { return hostEntity_ == other.hostEntity_; } //! returns true if father entity exists bool hasFather () const { return hostEntity_.hasFather(); } //! Create EntitySeed EntitySeed seed () const { return EntitySeed(hostEntity_); } //! Level of this element int level () const { return hostEntity_.level(); } /** \brief The partition type for parallel computing */ PartitionType partitionType () const { return hostEntity_.partitionType(); } //! Geometry of this entity Geometry geometry () const { return Geometry( hostEntity_.geometry() ); } /** \brief Return the number of subEntities of codimension codim. */ unsigned int subEntities (unsigned int codim) const { return hostEntity_.subEntities(codim); } /** \brief Provide access to sub entity i of given codimension. Entities * are numbered 0 ... subEntities(cc)-1 */ template typename GridImp::template Codim::Entity subEntity (int i) const { return IdentityGridEntity(identityGrid_, hostEntity_.template subEntity(i)); } //! First level intersection IdentityGridLevelIntersectionIterator ilevelbegin () const { return IdentityGridLevelIntersectionIterator( identityGrid_, identityGrid_->getHostGrid().levelGridView(level()).ibegin(hostEntity_)); } //! Reference to one past the last neighbor IdentityGridLevelIntersectionIterator ilevelend () const { return IdentityGridLevelIntersectionIterator( identityGrid_, identityGrid_->getHostGrid().levelGridView(level()).iend(hostEntity_)); } //! First leaf intersection IdentityGridLeafIntersectionIterator ileafbegin () const { return IdentityGridLeafIntersectionIterator( identityGrid_, identityGrid_->getHostGrid().leafGridView().ibegin(hostEntity_)); } //! Reference to one past the last leaf intersection IdentityGridLeafIntersectionIterator ileafend () const { return IdentityGridLeafIntersectionIterator( identityGrid_, identityGrid_->getHostGrid().leafGridView().iend(hostEntity_)); } //! returns true if Entity has NO children bool isLeaf() const { return hostEntity_.isLeaf(); } //! Inter-level access to father element on coarser grid. //! Assumes that meshes are nested. typename GridImp::template Codim<0>::Entity father () const { return IdentityGridEntity(identityGrid_, hostEntity_.father()); } /** \brief Location of this element relative to the reference element element of the father. * This is sufficient to interpolate all dofs in conforming case. * Nonconforming may require access to neighbors of father and * computations with local coordinates. * On the fly case is somewhat inefficient since dofs are visited several times. * If we store interpolation matrices, this is tolerable. We assume that on-the-fly * implementation of numerical algorithms is only done for simple discretizations. * Assumes that meshes are nested. */ LocalGeometry geometryInFather () const { return LocalGeometry( hostEntity_.geometryInFather() ); } /** \brief Inter-level access to son elements on higher levels<=maxlevel. * This is provided for sparsely stored nested unstructured meshes. * Returns iterator to first son. */ IdentityGridHierarchicIterator hbegin (int maxLevel) const { return IdentityGridHierarchicIterator(identityGrid_, *this, maxLevel); } //! Returns iterator to one past the last son IdentityGridHierarchicIterator hend (int maxLevel) const { return IdentityGridHierarchicIterator(identityGrid_, *this, maxLevel, true); } //! \todo Please doc me ! bool wasRefined () const { if (identityGrid_->adaptationStep!=GridImp::adaptDone) return false; int level = this->level(); int index = identityGrid_->levelIndexSet(level).index(*this); return identityGrid_->refinementMark_[level][index]; } //! \todo Please doc me ! bool mightBeCoarsened () const { return true; } // ///////////////////////////////////////// // Internal stuff // ///////////////////////////////////////// HostGridEntity hostEntity_; const GridImp* identityGrid_; private: typedef typename GridImp::ctype ctype; }; // end of IdentityGridEntity codim = 0 } // namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridentityseed.hh000066400000000000000000000035361511655130300251550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITY_GRID_ENTITY_SEED_HH #define DUNE_IDENTITY_GRID_ENTITY_SEED_HH /** * \file * \brief The IdentityGridEntitySeed class */ namespace Dune { /** * \brief The EntitySeed class provides the minimal information needed to restore an Entity using the grid. * \ingroup IdentityGrid * */ template class IdentityGridEntitySeed { protected: // Entity type of the hostgrid typedef typename GridImp::HostGridType::Traits::template Codim::Entity HostEntity; // EntitySeed type of the hostgrid typedef typename GridImp::HostGridType::Traits::template Codim::EntitySeed HostEntitySeed; public: constexpr static int codimension = codim; /** * \brief Construct an empty (i.e. isValid() == false) seed. */ IdentityGridEntitySeed() {} /** * \brief Create EntitySeed from hostgrid Entity * * We call hostEntity.seed() directly in the constructor * of IdentityGridEntitySeed to allow for return value optimization. */ IdentityGridEntitySeed(const HostEntity& hostEntity) : hostEntitySeed_(hostEntity.seed()) {} /** * \brief Get stored HostEntitySeed */ const HostEntitySeed& hostEntitySeed() const { return hostEntitySeed_; } /** * \brief Check whether it is safe to create an Entity from this Seed */ bool isValid() const { return hostEntitySeed_.isValid(); } private: HostEntitySeed hostEntitySeed_; }; } // namespace Dune #endif // #define DUNE_IDENTITY_GRID_ENTITY_SEED_HH dune-grid-2.11.0/dune/grid/identitygrid/identitygridgeometry.hh000066400000000000000000000073521511655130300246330ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRIDGEOMETRY_HH #define DUNE_IDENTITYGRIDGEOMETRY_HH /** \file * \brief The IdentityGridGeometry class and its specializations */ #include #include #include namespace Dune { template class IdentityGridGeometry : public GeometryDefaultImplementation { private: typedef typename GridImp::ctype ctype; public: // The codimension of this entitypointer wrt the host grid constexpr static int CodimInHostGrid = GridImp::HostGridType::dimension - mydim; constexpr static int DimensionWorld = GridImp::HostGridType::dimensionworld; // select appropriate hostgrid geometry via typeswitch typedef typename GridImp::HostGridType::Traits::template Codim::Geometry HostGridGeometryType; typedef typename GridImp::HostGridType::Traits::template Codim::Geometry HostGridLocalGeometryType; typedef typename std::conditional::type HostGridGeometry; //! type of jacobian transposed typedef typename HostGridGeometryType::JacobianInverseTransposed JacobianInverseTransposed; typedef typename HostGridGeometryType::JacobianTransposed JacobianTransposed; /** constructor from host geometry */ IdentityGridGeometry(const HostGridGeometry& hostGeometry) : hostGeometry_(hostGeometry) {} /** \brief Return the element type identifier */ GeometryType type () const { return hostGeometry_.type(); } // return whether we have an affine mapping bool affine() const { return hostGeometry_.affine(); } //! return the number of corners of this element. Corners are numbered 0...n-1 int corners () const { return hostGeometry_.corners(); } //! access to coordinates of corners. Index is the number of the corner const FieldVector corner (int i) const { return hostGeometry_.corner(i); } /** \brief Maps a local coordinate within reference element to * global coordinate in element */ FieldVector global (const FieldVector& local) const { return hostGeometry_.global(local); } /** \brief Return the transposed of the Jacobian */ JacobianTransposed jacobianTransposed ( const FieldVector& local ) const { return hostGeometry_.jacobianTransposed(local); } /** \brief Maps a global coordinate within the element to a * local coordinate in its reference element */ FieldVector local (const FieldVector& global) const { return hostGeometry_.local(global); } //! Returns true if the point is in the current element bool checkInside(const FieldVector &local) const { return hostGeometry_.checkInside(local); } /** */ ctype integrationElement (const FieldVector& local) const { return hostGeometry_.integrationElement(local); } //! The Jacobian matrix of the mapping from the reference element to this element JacobianInverseTransposed jacobianInverseTransposed (const FieldVector& local) const { return hostGeometry_.jacobianInverseTransposed(local); } HostGridGeometry hostGeometry_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridhierarchiciterator.hh000066400000000000000000000044611511655130300266510ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRIDHIERITERATOR_HH #define DUNE_IDENTITYGRIDHIERITERATOR_HH /** \file * \brief The IdentityGridHierarchicIterator class */ namespace Dune { //********************************************************************** // /** \brief Iterator over the descendants of an entity. * \ingroup IdentityGrid Mesh entities of codimension 0 ("elements") allow to visit all entities of codimension 0 obtained through nested, hierarchic refinement of the entity. Iteration over this set of entities is provided by the HierarchicIterator, starting from a given entity. */ template class IdentityGridHierarchicIterator { // Type of the corresponding HierarchicIterator in the host grid typedef typename GridImp::HostGridType::template Codim<0>::Entity::HierarchicIterator HostGridHierarchicIterator; public: constexpr static int codimension = 0; typedef typename GridImp::template Codim<0>::Entity Entity; //! the default Constructor explicit IdentityGridHierarchicIterator(const GridImp* identityGrid, const Entity& startEntity, int maxLevel) : identityGrid_(identityGrid), hostHierarchicIterator_(startEntity.impl().hostEntity_.hbegin(maxLevel)) {} //! \todo Please doc me ! explicit IdentityGridHierarchicIterator(const GridImp* identityGrid, const Entity& startEntity, int maxLevel, [[maybe_unused]] bool endDummy) : identityGrid_(identityGrid), hostHierarchicIterator_(startEntity.impl().hostEntity_.hend(maxLevel)) {} //! \todo Please doc me ! void increment() { ++hostHierarchicIterator_; } //! dereferencing Entity dereference() const { return Entity{{identityGrid_,*hostHierarchicIterator_}}; } //! equality bool equals(const IdentityGridHierarchicIterator& i) const { return hostHierarchicIterator_ == i.hostHierarchicIterator_; } private: const GridImp* identityGrid_; HostGridHierarchicIterator hostHierarchicIterator_; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridindexsets.hh000066400000000000000000000205661511655130300250100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRID_INDEXSETS_HH #define DUNE_IDENTITYGRID_INDEXSETS_HH /** \file * \brief The index and id sets for the IdentityGrid class */ #include #include namespace Dune { /** \todo Take the index types from the host grid */ template class IdentityGridLevelIndexSet : public IndexSet, typename std::remove_const::type::HostGridType::LevelGridView::IndexSet::IndexType, typename std::remove_const::type::HostGridType::LevelGridView::IndexSet::Types > { public: typedef typename std::remove_const::type::HostGridType HostGrid; typedef typename HostGrid::LevelGridView::IndexSet::Types Types; constexpr static int dim = GridImp::dimension; //! get index of an entity template int index (const typename GridImp::Traits::template Codim::Entity& e) const { return grid_->hostgrid_->levelIndexSet(level_).template index(grid_->template getHostEntity(e)); } //! get index of subEntity of a codim 0 entity template int subIndex (const typename GridImp::Traits::template Codim::Entity& e, int i, int codim) const { return grid_->hostgrid_->levelIndexSet(level_).subIndex(grid_->template getHostEntity(e), i, codim); } //! get number of entities of given codim, type and on this level std::size_t size (int codim) const { return grid_->hostgrid_->levelIndexSet(level_).size(codim); } //! get number of entities of given codim, type and on this level std::size_t size (GeometryType type) const { return grid_->hostgrid_->levelIndexSet(level_).size(type); } /** \brief Deliver all geometry types used in this grid */ Types types (int codim) const { return grid_->hostgrid_->levelIndexSet(level_).types(codim); } /** \brief Return true if the given entity is contained in the index set */ template bool contains (const EntityType& e) const { return grid_->hostgrid_->levelIndexSet(level_).contains(grid_->template getHostEntity(e)); } /** \brief Set up the index set */ void update(const GridImp& grid, int level) { grid_ = &grid; level_ = level; } GridImp* grid_; int level_; }; template class IdentityGridLeafIndexSet : public IndexSet, typename std::remove_const::type::HostGridType::LeafGridView::IndexSet::IndexType, typename std::remove_const::type::HostGridType::LeafGridView::IndexSet::Types > { typedef typename std::remove_const::type::HostGridType HostGrid; public: typedef typename HostGrid::LevelGridView::IndexSet::Types Types; /* * We use the remove_const to extract the Type from the mutable class, * because the const class is not instantiated yet. */ constexpr static int dim = std::remove_const::type::dimension; //! constructor stores reference to a grid and level IdentityGridLeafIndexSet (const GridImp& grid) : grid_(&grid) {} //! get index of an entity /* We use the RemoveConst to extract the Type from the mutable class, because the const class is not instantiated yet. */ template int index (const typename std::remove_const::type::template Codim::Entity& e) const { return grid_->hostgrid_->leafIndexSet().template index(grid_->template getHostEntity(e)); } //! get index of subEntity of a codim 0 entity /* We use the RemoveConst to extract the Type from the mutable class, because the const class is not instantiated yet. */ template int subIndex (const typename std::remove_const::type::Traits::template Codim::Entity& e, int i, int codim) const { return grid_->hostgrid_->leafIndexSet().subIndex(grid_->template getHostEntity(e),i, codim); } //! get number of entities of given type std::size_t size (GeometryType type) const { return grid_->hostgrid_->leafIndexSet().size(type); } //! get number of entities of given codim std::size_t size (int codim) const { return grid_->hostgrid_->leafIndexSet().size(codim); } /** \brief Deliver all geometry types used in this grid */ Types types (int codim) const { return grid_->hostgrid_->leafIndexSet().types(codim); } /** \brief Return true if the given entity is contained in the index set */ template bool contains (const EntityType& e) const { return grid_->hostgrid_->leafIndexSet().contains(grid_->template getHostEntity(e)); } /** \todo Currently we support only vertex and element indices */ void update(const GridImp& grid) { grid_ = &grid; } GridImp* grid_; }; template class IdentityGridGlobalIdSet : public IdSet, typename std::remove_const::type::HostGridType::Traits::GlobalIdSet::IdType> { typedef typename std::remove_const::type::HostGridType HostGrid; public: //! constructor stores reference to a grid IdentityGridGlobalIdSet (const GridImp& g) : grid_(&g) {} //! define the type used for persistent indices typedef typename HostGrid::Traits::GlobalIdSet::IdType IdType; //! get id of an entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template IdType id (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { // Return id of the host entity return grid_->hostgrid_->globalIdSet().id(e.impl().hostEntity_); } //! get id of subEntity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ IdType subId (const typename std::remove_const::type::Traits::template Codim<0>::Entity& e, int i, int codim) const { // Return sub id of the host entity return grid_->hostgrid_->globalIdSet().subId(e.impl().hostEntity_,i, codim); } /** \todo Should be private */ void update() {} const GridImp* grid_; }; template class IdentityGridLocalIdSet : public IdSet, typename std::remove_const::type::HostGridType::Traits::LocalIdSet::IdType> { private: typedef typename std::remove_const::type::HostGridType HostGrid; public: //! define the type used for persistent local ids typedef typename HostGrid::Traits::LocalIdSet::IdType IdType; //! constructor stores reference to a grid IdentityGridLocalIdSet (const GridImp& g) : grid_(&g) {} //! get id of an entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template IdType id (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { // Return id of the host entity return grid_->hostgrid_->localIdSet().id(e.impl().hostEntity_); } //! get id of subEntity /* * We use the remove_const to extract the Type from the mutable class, * because the const class is not instantiated yet. */ IdType subId (const typename std::remove_const::type::template Codim<0>::Entity& e, int i, int codim) const { // Return sub id of the host entity return grid_->hostgrid_->localIdSet().subId(e.impl().hostEntity_,i,codim); } /** \todo Should be private */ void update() {} const GridImp* grid_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridintersectioniterator.hh000066400000000000000000000074731511655130300272640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRID_INTERSECTIONITERATOR_HH #define DUNE_IDENTITYGRID_INTERSECTIONITERATOR_HH #include "identitygridintersections.hh" #include "identitygridentity.hh" #include /** \file * \brief The IdentityGridLeafIntersectionIterator and IdentityGridLevelIntersectionIterator classes */ namespace Dune { /** \brief Iterator over all element neighbors * \ingroup IdentityGrid * Mesh entities of codimension 0 ("elements") allow to visit all neighbors, where * a neighbor is an entity of codimension 0 which has a common entity of codimension 1 * These neighbors are accessed via a IntersectionIterator. This allows the implement * non-matching meshes. The number of neighbors may be different from the number * of an element! */ template class IdentityGridLeafIntersectionIterator { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; // The type used to store coordinates typedef typename GridImp::ctype ctype; typedef typename GridImp::HostGridType::LeafGridView::IntersectionIterator HostLeafIntersectionIterator; public: typedef Dune::Intersection > Intersection; IdentityGridLeafIntersectionIterator() {} IdentityGridLeafIntersectionIterator(const GridImp* identityGrid, const HostLeafIntersectionIterator& hostIterator) : identityGrid_(identityGrid) , hostIterator_(hostIterator) {} //! equality bool equals(const IdentityGridLeafIntersectionIterator& other) const { return hostIterator_ == other.hostIterator_; } //! prefix increment void increment() { ++hostIterator_; } //! \brief dereferencing Intersection dereference() const { return IdentityGridLeafIntersection(identityGrid_,*hostIterator_); } private: //********************************************************** // private data //********************************************************** const GridImp* identityGrid_ = nullptr; HostLeafIntersectionIterator hostIterator_ = {}; }; //! \todo Please doc me ! template class IdentityGridLevelIntersectionIterator { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; // The type used to store coordinates typedef typename GridImp::ctype ctype; typedef typename GridImp::HostGridType::LevelGridView::IntersectionIterator HostLevelIntersectionIterator; public: typedef Dune::Intersection > Intersection; IdentityGridLevelIntersectionIterator() {} IdentityGridLevelIntersectionIterator(const GridImp* identityGrid, const HostLevelIntersectionIterator& hostIterator) : identityGrid_(identityGrid) , hostIterator_(hostIterator) {} //! equality bool equals(const IdentityGridLevelIntersectionIterator& other) const { return hostIterator_ == other.hostIterator_; } //! prefix increment void increment() { ++hostIterator_; } //! \brief dereferencing Intersection dereference() const { return IdentityGridLevelIntersection(identityGrid_,*hostIterator_); } private: const GridImp* identityGrid_ = nullptr; HostLevelIntersectionIterator hostIterator_ = {}; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridintersections.hh000066400000000000000000000256771511655130300257030ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRID_INTERSECTIONS_HH #define DUNE_IDENTITYGRID_INTERSECTIONS_HH #include "identitygridleafiterator.hh" #include /** \file * \brief The IdentityGridLeafIntersection and IdentityGridLevelIntersection classes */ namespace Dune { // External forward declarations template< class Grid > struct HostGridAccess; /** \brief An intersection with a leaf neighbor element * \ingroup IdentityGrid * Mesh entities of codimension 0 ("elements") allow to visit all neighbors, where * a neighbor is an entity of codimension 0 which has a common entity of codimension 1 * These neighbors are accessed via a IntersectionIterator. This allows the implement * non-matching meshes. The number of neighbors may be different from the number * of an element! */ template class IdentityGridLeafIntersection { friend class IdentityGridLeafIntersectionIterator; friend struct HostGridAccess< typename std::remove_const< GridImp >::type >; constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; // The type used to store coordinates typedef typename GridImp::ctype ctype; typedef typename GridImp::HostGridType::LeafGridView::Intersection HostLeafIntersection; public: typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::Entity Entity; typedef FieldVector NormalVector; IdentityGridLeafIntersection() {} IdentityGridLeafIntersection(const GridImp* identityGrid, const HostLeafIntersection& hostIntersection) : identityGrid_(identityGrid) , hostIntersection_(hostIntersection) {} IdentityGridLeafIntersection(const GridImp* identityGrid, HostLeafIntersection&& hostIntersection) : identityGrid_(identityGrid) , hostIntersection_(std::move(hostIntersection)) {} bool equals(const IdentityGridLeafIntersection& other) const { return hostIntersection_ == other.hostIntersection_; } //! return Entity on the inside of this intersection //! (that is the Entity where we started this Iterator) Entity inside() const { return IdentityGridEntity<0,dim,GridImp>(identityGrid_,hostIntersection_.inside()); } //! return Entity on the outside of this intersection //! (that is the neighboring Entity) Entity outside() const { return IdentityGridEntity<0,dim,GridImp>(identityGrid_,hostIntersection_.outside()); } //! return true if intersection is with boundary. bool boundary () const { return hostIntersection_.boundary(); } /** \brief Return unit outer normal (length == 1) * * The returned vector is the normal at the center() of the * intersection's geometry. * It is scaled to have unit length. */ NormalVector centerUnitOuterNormal () const { return hostIntersection_.centerUnitOuterNormal(); } //! return true if across the edge an neighbor on this level exists bool neighbor () const { return hostIntersection_.neighbor(); } //! return the boundary segment index size_t boundarySegmentIndex() const { return hostIntersection_.boundarySegmentIndex(); } //! Return true if this is a conforming intersection bool conforming () const { return hostIntersection_.conforming(); } //! Geometry type of an intersection GeometryType type () const { return hostIntersection_.type(); } //! intersection of codimension 1 of this neighbor with element where //! iteration started. //! Here returned element is in LOCAL coordinates of the element //! where iteration started. LocalGeometry geometryInInside () const { return LocalGeometry( hostIntersection_.geometryInInside() ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in LOCAL coordinates of neighbor LocalGeometry geometryInOutside () const { return LocalGeometry( hostIntersection_.geometryInOutside() ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in GLOBAL coordinates of the element where iteration started. Geometry geometry () const { return Geometry( hostIntersection_.geometry() ); } //! local number of codim 1 entity in self where intersection is contained in int indexInInside () const { return hostIntersection_.indexInInside(); } //! local number of codim 1 entity in neighbor where intersection is contained int indexInOutside () const { return hostIntersection_.indexInOutside(); } //! return outer normal FieldVector outerNormal (const FieldVector& local) const { return hostIntersection_.outerNormal(local); } //! return outer normal multiplied by the integration element FieldVector integrationOuterNormal (const FieldVector& local) const { return hostIntersection_.integrationOuterNormal(local); } //! return unit outer normal FieldVector unitOuterNormal (const FieldVector& local) const { return hostIntersection_.unitOuterNormal(local); } private: //********************************************************** // private methods //********************************************************** const GridImp* identityGrid_; HostLeafIntersection hostIntersection_; }; //! \todo Please doc me ! template class IdentityGridLevelIntersection { friend class IdentityGridLevelIntersectionIterator; friend struct HostGridAccess< typename std::remove_const< GridImp >::type >; constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; // The type used to store coordinates typedef typename GridImp::ctype ctype; typedef typename GridImp::HostGridType::LevelGridView::Intersection HostLevelIntersection; public: typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::Entity Entity; typedef FieldVector NormalVector; IdentityGridLevelIntersection() {} IdentityGridLevelIntersection(const GridImp* identityGrid, const HostLevelIntersection& hostIntersection) : identityGrid_(identityGrid) , hostIntersection_(hostIntersection) {} IdentityGridLevelIntersection(const GridImp* identityGrid, HostLevelIntersection&& hostIntersection) : identityGrid_(identityGrid) , hostIntersection_(std::move(hostIntersection)) {} bool equals(const IdentityGridLevelIntersection& other) const { return hostIntersection_ == other.hostIntersection_; } //! return Entity on the inside of this intersection //! (that is the Entity where we started this Iterator) Entity inside() const { return IdentityGridEntity<0,dim,GridImp>(identityGrid_,hostIntersection_.inside()); } //! return Entity on the outside of this intersection //! (that is the neighboring Entity) Entity outside() const { return IdentityGridEntity<0,dim,GridImp>(identityGrid_,hostIntersection_.outside()); } /** \brief return true if intersection is with boundary. */ bool boundary () const { return hostIntersection_.boundary(); } /** \brief Return unit outer normal (length == 1) * * The returned vector is the normal at the center() of the * intersection's geometry. * It is scaled to have unit length. */ NormalVector centerUnitOuterNormal () const { return hostIntersection_.centerUnitOuterNormal(); } //! return true if across the edge an neighbor on this level exists bool neighbor () const { return hostIntersection_.neighbor(); } //! return the boundary segment index size_t boundarySegmentIndex() const { return hostIntersection_.boundarySegmentIndex(); } //! Return true if this is a conforming intersection bool conforming () const { return hostIntersection_.conforming(); } //! Geometry type of an intersection GeometryType type () const { return hostIntersection_.type(); } //! intersection of codimension 1 of this neighbor with element where //! iteration started. //! Here returned element is in LOCAL coordinates of the element //! where iteration started. LocalGeometry geometryInInside () const { return LocalGeometry( hostIntersection_.geometryInInside() ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in LOCAL coordinates of neighbor LocalGeometry geometryInOutside () const { return LocalGeometry( hostIntersection_.geometryInOutside() ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in GLOBAL coordinates of the element where iteration started. Geometry geometry () const { return Geometry( hostIntersection_.geometry() ); } //! local number of codim 1 entity in self where intersection is contained in int indexInInside () const { return hostIntersection_.indexInInside(); } //! local number of codim 1 entity in neighbor where intersection is contained int indexInOutside () const { return hostIntersection_.indexInOutside(); } //! return outer normal FieldVector outerNormal (const FieldVector& local) const { return hostIntersection_.outerNormal(local); } //! return outer normal multiplied by the integration element FieldVector integrationOuterNormal (const FieldVector& local) const { return hostIntersection_.integrationOuterNormal(local); } //! return unit outer normal FieldVector unitOuterNormal (const FieldVector& local) const { return hostIntersection_.unitOuterNormal(local); } private: const GridImp* identityGrid_; HostLevelIntersection hostIntersection_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridleafiterator.hh000066400000000000000000000042001511655130300254460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRIDLEAFITERATOR_HH #define DUNE_IDENTITYGRIDLEAFITERATOR_HH #include /** \file * \brief The IdentityGridLeafIterator class */ namespace Dune { /** \brief Iterator over all entities of a given codimension and level of a grid. * \ingroup IdentityGrid */ template class IdentityGridLeafIterator { private: // LevelIterator to the equivalent entity in the host grid typedef typename GridImp::HostGridType::template Codim::template Partition::LeafIterator HostGridLeafIterator; public: constexpr static int codimension = codim; typedef typename GridImp::template Codim::Entity Entity; //! \todo Please doc me ! explicit IdentityGridLeafIterator(const GridImp* identityGrid) : identityGrid_(identityGrid), hostLeafIterator_(identityGrid->hostgrid_->leafGridView().template begin()) {} /** \brief Constructor which create the end iterator * \param endDummy Here only to distinguish it from the other constructor * \param identityGrid pointer to grid instance */ explicit IdentityGridLeafIterator(const GridImp* identityGrid, [[maybe_unused]] bool endDummy) : identityGrid_(identityGrid), hostLeafIterator_(identityGrid->hostgrid_->leafGridView().template end()) {} //! prefix increment void increment() { ++hostLeafIterator_; } //! dereferencing Entity dereference() const { return Entity{{identityGrid_,*hostLeafIterator_}}; } //! equality bool equals(const IdentityGridLeafIterator& i) const { return hostLeafIterator_ == i.hostLeafIterator_; } private: const GridImp* identityGrid_; HostGridLeafIterator hostLeafIterator_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/identitygrid/identitygridleveliterator.hh000066400000000000000000000042701511655130300256550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IDENTITYGRIDLEVELITERATOR_HH #define DUNE_IDENTITYGRIDLEVELITERATOR_HH #include /** \file * \brief The IdentityGridLevelIterator class */ namespace Dune { /** \brief Iterator over all entities of a given codimension and level of a grid. * \ingroup IdentityGrid */ template class IdentityGridLevelIterator { typedef typename GridImp::HostGridType::Traits::template Codim::template Partition::LevelIterator HostGridLevelIterator; public: constexpr static int codimension = codim; typedef typename GridImp::template Codim::Entity Entity; //! Constructor explicit IdentityGridLevelIterator(const GridImp* identityGrid, int level) : identityGrid_(identityGrid), hostLevelIterator_(identityGrid->hostgrid_->levelGridView(level).template begin()) {} /** \brief Constructor which create the end iterator \param endDummy Here only to distinguish it from the other constructor \param identityGrid pointer to IdentityGrid instance \param level grid level on which the iterator shall be created */ explicit IdentityGridLevelIterator(const GridImp* identityGrid, int level, [[maybe_unused]] bool endDummy) : identityGrid_(identityGrid), hostLevelIterator_(identityGrid->hostgrid_->levelGridView(level).template end()) {} //! prefix increment void increment() { ++hostLevelIterator_; } //! dereferencing Entity dereference() const { return Entity{{identityGrid_,*hostLevelIterator_}}; } //! equality bool equals(const IdentityGridLevelIterator& i) const { return hostLevelIterator_ == i.hostLevelIterator_; } private: const GridImp* identityGrid_; HostGridLevelIterator hostLevelIterator_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/io/000077500000000000000000000000001511655130300157405ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/CMakeLists.txt000066400000000000000000000003041511655130300204750ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(file) dune-grid-2.11.0/dune/grid/io/file/000077500000000000000000000000001511655130300166575ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/CMakeLists.txt000066400000000000000000000007621511655130300214240ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(gmsh) add_subdirectory(test) add_subdirectory(dgfparser) add_subdirectory(vtk) add_subdirectory(gnuplot) set(HEADERS dgfparser.hh gmshreader.hh gmshwriter.hh gnuplot.hh printgrid.hh starcdreader.hh vtk.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file) dune-grid-2.11.0/dune/grid/io/file/dgfparser.hh000066400000000000000000000011731511655130300211570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGFPARSER_HH #define DUNE_DGFPARSER_HH // include dgf parser #include "dgfparser/dgfparser.hh" /* include the implementations */ #include #include "dgfparser/dgfug.hh" #include "dgfparser/dgfoned.hh" #include "dgfparser/dgfyasp.hh" #include "dgfparser/dgfgeogrid.hh" #include "dgfparser/dgfidentitygrid.hh" #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/000077500000000000000000000000001511655130300206345ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/dgfparser/CMakeLists.txt000066400000000000000000000011361511655130300233750ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(blocks) add_subdirectory(test) add_subdirectory(utils) target_sources(dunegrid PRIVATE dgfparser.cc dgfug.cc) install(FILES dgfexception.hh dgfidentitygrid.hh dgfug.hh dgfparser.hh dgfgeogrid.hh dgfwriter.hh dgfyasp.hh entitykey.hh entitykey_inline.hh dgfoned.hh dgfgridfactory.hh macrogrid.hh gridptr.hh parser.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/dgfparser) dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/000077500000000000000000000000001511655130300221115ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/CMakeLists.txt000066400000000000000000000014121511655130300246470ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception target_sources(dunegrid PRIVATE basic.cc boundarydom.cc boundaryseg.cc cube.cc dim.cc general.cc gridparameter.cc interval.cc periodicfacetrans.cc projection.cc simplex.cc simplexgeneration.cc vertex.cc) #add_dune_mpi_flags(dgfparserblocks) set(HEADERS basic.hh boundarydom.hh boundaryseg.hh cube.hh dim.hh general.hh gridparameter.hh interval.hh periodicfacetrans.hh polygon.hh polyhedron.hh projection.hh simplex.hh simplexgeneration.hh vertex.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/dgfparser/blocks) dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/basic.cc000066400000000000000000000061241511655130300235040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // BasicBlock // ---------- BasicBlock :: BasicBlock ( std :: istream &in, const char *id ) : pos(-1), active(false), empty(true), identifier(id), linecount(0) { makeupcase( identifier ); in.clear(); in.seekg(0); if (!in) { DUNE_THROW(DGFException, "file not found in BasicBlock::BasicBlock"); } getblock( in ); empty = (linecount == 0); if (active && !empty) { //linecount=countlines(); reset(); } in.clear(); in.seekg(0); } // read the current block which is ended by a line starting // with a # symbol. void BasicBlock :: getblock ( std :: istream &in ) { linecount = 0; while( in.good() ) { std::string curLine; getline( in, curLine ); std::istringstream linestream( curLine ); std :: string id; linestream >> id; makeupcase( id ); if( id == identifier ) break; } if( in.eof() ) return; active = true; while( in.good() ) { std::string curLine; getline( in, curLine ); // strip comments if( !curLine.empty() ) { std::size_t comment = curLine.find( '%' ); if( comment != std::string::npos ) curLine.erase( comment ); } if( curLine.empty() ) continue; std :: istringstream linestream( curLine ); char test = 0; linestream >> test; if( test == '#' ) return; ++linecount; block_ << curLine << std :: endl; } DUNE_THROW( DGFException, "Error reading from stream, expected \"#\" to end the block." ); } // get next line and store in string stream bool BasicBlock :: getnextline () { getline( block_, oneline ); line.clear(); line.str( oneline ); ++pos; return !oneline.empty(); } bool BasicBlock :: gettokenparam ( std :: string token, std :: string &entry ) { reset(); makeupcase( token ); while( getnextline() ) { std :: string ltoken; line >> ltoken; makeupcase( ltoken ); if( ltoken == token ) { getline( line, entry ); return true; } } return false; } bool BasicBlock :: findtoken ( std :: string token ) { reset(); makeupcase( token ); while( getnextline() ) { std :: string ltoken; line >> ltoken; makeupcase( ltoken ); if( ltoken == token ) return true; } return false; } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/basic.hh000066400000000000000000000053431511655130300235200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_BASICBLOCK_HH #define DUNE_DGF_BASICBLOCK_HH #include #include #include #include #include #include #include #include namespace Dune { namespace dgf { inline void makeupcase( std :: string &s ) { for (size_t i=0; i bool getnextentry( ENTRY &entry ) { line >> entry; return static_cast< bool >( line ); } bool gettokenparam ( std :: string token, std :: string &entry ); bool findtoken( std :: string token ); public: // search for block in file and store in buffer BasicBlock ( std::istream &in, const char* id ); // some information on this block bool isactive () { return active; } bool isempty () { return empty; } int &noflines () { return linecount; } int linenumber () { return pos; } const std::string & id () const { return identifier; } // for error messages friend std :: ostream &operator<< ( std :: ostream &os, const BasicBlock &b ) { return os << "block " << b.identifier << " (line " << b.pos << ")"; } }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/boundarydom.cc000066400000000000000000000106421511655130300247460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // BoundaryDomBlock // ---------------- BoundaryDomBlock :: BoundaryDomBlock(std::istream& in,int cdimworld ) : BasicBlock( in, "boundarydomain" ), dimworld_( cdimworld ), counter_( -1 ), default_( 0 ), ndomains_( 0 ) { if ( !isactive() ) return; assert( cdimworld > 0 ); if (findtoken("default")) { int id; BoundaryParameter parameter = DGFBoundaryParameter::defaultValue(); // try to read boundary id if ( getnextentry( id ) ) { if( id <= 0 ) { DUNE_THROW(DGFException, "ERROR in " << *this << " non-positive boundary id (" << id << ") read!"); } // check for parameter std::string currentline = line.str(); std::size_t delimiter = currentline.find( DGFBoundaryParameter::delimiter ); if( delimiter != std::string::npos ) { parameter = DGFBoundaryParameter::convert( currentline.substr( delimiter+1, std::string::npos ) ); } // create default domain data default_ = new DomainData( id, parameter, true ); } } readBlock(); reset(); } void BoundaryDomBlock :: readBlock () { reset(); assert( ok() ); while( getnextline() ) { int id; BoundaryParameter parameter = DGFBoundaryParameter::defaultValue(); if( getnextentry( id ) ) { if( id <= 0 ) { DUNE_THROW(DGFException, "ERROR in " << *this << " non-positive boundary id (" << id << ") read!"); } // check for parameter std::string currentline = line.str(); std::size_t delimiter = currentline.find( DGFBoundaryParameter::delimiter ); if( delimiter != std::string::npos ) { parameter = DGFBoundaryParameter::convert( currentline.substr( delimiter+1, std::string::npos ) ); } DomainData data( id, parameter ); // read vertices std::vector< double > left( dimworld_ ), right( dimworld_ ); double x; int n = 0; while ( getnextentry( x ) ) { if ( 0 <= n && n < dimworld_ ) left.at( n ) = x; else if ( dimworld_ <= n && n < 2*dimworld_ ) { right.at( n-dimworld_ ) = x; if ( right.at( n-dimworld_ )< left.at( n-dimworld_ ) ) { DUNE_THROW(DGFException, "ERROR in " << *this << " second coordinate smaller than first coordinate: " << right.at(n-dimworld_) << " read but expected value larger or equal to " << left.at(n-dimworld_) << std::endl << "Line was: '" << line.str() << "'"); } } n++; } bool goodline = ( n == dimworld_*2 ); if ( !goodline ) { DUNE_THROW(DGFException, "ERROR in " << *this << " wrong number of coordinates: " << n << " read but expected 2*" << dimworld_ << std::endl << "Line was: '" << line.str() << "'"); } Domain domain( left, right, data ); domains_.push_back( domain ); } } ndomains_ = domains_.size(); } bool BoundaryDomBlock :: hasParameter () const { for( int i = 0; i < ndomains_; ++i ) { if( domains_[ i ].data().hasParameter() ) return true; } if( hasDefaultData() ) return defaultData()->hasParameter(); return false; } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/boundarydom.hh000066400000000000000000000165331511655130300247650ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_BOUNDARYDOMBLOCK_HH #define DUNE_DGF_BOUNDARYDOMBLOCK_HH #include #include #include #include #include namespace Dune { namespace dgf { struct DomainData { typedef DGFBoundaryParameter::type BoundaryParameter; DomainData () : id_( 0 ), parameter_( DGFBoundaryParameter::defaultValue() ), defaultData_( false ) { } ~DomainData () { } // constructor DomainData ( int id, BoundaryParameter parameter, bool defaultData = false ) : id_( id ), parameter_( parameter ), defaultData_( defaultData ) { } // return id int id () const { return id_; } // return true, if additional parameters given bool hasParameter () const { return (!parameter_.empty()); } // return additional parameters const BoundaryParameter & parameter () const { return parameter_; } // reset data void reset ( int id, BoundaryParameter parameter, bool defaultData = false ) { id_ = id; parameter_ = parameter; defaultData_ = defaultData; } // returns true if data origins from default boundary domain bool isDefault () const { return defaultData_; } friend std::ostream & operator<< ( std :: ostream & os, const DomainData & ddata ) { os << "domain data: id = " << ddata.id(); if( ddata.hasParameter() ) os << ", parameter = " << ddata.parameter(); return os; } private: int id_; BoundaryParameter parameter_; bool defaultData_; }; // end struct DomainData struct Domain { // dimension of world coordinates const int dimensionworld; typedef DGFBoundaryParameter::type BoundaryParameter; // constructor Domain( std::vector< double > p1, std::vector< double > p2, int id, BoundaryParameter & parameter ) : dimensionworld( p1.size() ), left_( p1 ), right_( p2 ), data_( id, parameter ) { if( int( p2.size() ) != dimensionworld ) { DUNE_THROW(DGFException, "ERROR in " << *this << "!"); } } // constructor Domain( std::vector< double > p1, std::vector< double > p2, DomainData & data ) : dimensionworld( p1.size() ), left_( p1 ), right_( p2 ), data_( data ) { if( int( p2.size() ) != dimensionworld ) { DUNE_THROW(DGFException, "ERROR in " << *this << "!"); } } // copy constructor Domain ( const Domain & other ) : dimensionworld( other.dimensionworld ), left_( other.left_ ), right_( other.right_ ), data_( other.data_ ) { if( dimensionworld != other.dimensionworld ) { DUNE_THROW(DGFException, "ERROR in " << *this << "!"); } } // assignment Domain & operator = ( const Domain & other ) { if( dimensionworld != other.dimensionworld ) { DUNE_THROW(DGFException, "ERROR in " << *this << "!"); } left_ = other.left_; right_= other.right_; data_= other.data_; return *this; } // return true if point is contained in boundary domain template< class Vector > bool contains ( const Vector & x ) const { bool ret = true; for( int i = 0; i < dimensionworld; ++i ) { if( x[ i ] < left_[ i ] || x[ i ] > right_[ i ] ) ret = false; } return ret; } const DomainData & data () const { return data_; } // for error messages friend std::ostream & operator<< ( std :: ostream &os, const Domain & domain ) { os << "domain: " << std::endl; os << "left = "; for( int i = 0; i < domain.dimensionworld; ++i ) os << domain.left_[ i ] << " "; os << std::endl; os << "right = "; for( int i = 0; i < domain.dimensionworld; ++i ) os << domain.right_[ i ] << " "; os << std::endl; os << domain.data(); return os; } private: std::vector< double > left_, right_; DomainData data_; }; class BoundaryDomBlock : public BasicBlock { typedef DGFBoundaryParameter::type BoundaryParameter; // the dimension of the vertices (is given from user) int dimworld_; // internal counter int counter_; // default values if given DomainData * default_; // storage for all domains; int ndomains_; std::vector< Domain > domains_; public: // initialize vertex block and get first vertex BoundaryDomBlock ( std::istream & in, int cdimworld ); // destructor ~BoundaryDomBlock () { if( default_ ) delete default_; } // go to next domain in block bool next () { counter_++; return ( counter_ < ndomains_ ); } // return domain const Domain & domain () const { return domains_.at( counter_ ); } // return true if default is given bool hasDefaultData () const { return bool( default_ ); } // return default data const DomainData * defaultData () const { return default_; } // return true if any boundary domain block has // additional parameters bool hasParameter () const; void reset () { BasicBlock::reset(); counter_ = -1; } // return true while block is active bool ok () { return ( counter_ <= ndomains_ ); } // return data if all vectors in array are contained within // a single domain template< class Vector > const DomainData * contains ( const std::vector< Vector > & v ) const { std::vector< int > index( ndomains_ ); for( int i = 0; i < ndomains_; ++i) index[ i ] = i; size_t N = v.size(); for( size_t i = 0; i < N; ++i ) { if( index.empty() ) break; const int n = index.size(); assert( n > 0 ); for( int j = n-1; j >= 0; --j ) { bool inside = domains_[ index[ j ] ].contains( v[ i ] ); if( !inside ) index.erase( index.begin() + j ); } } // check whether no boundary domain found if( index.empty() ) return default_; // check for ambiguity if( index.size() > 1 ) dwarn << "WARNING: ambiguous boundary domain assignment, use first boundary domain in list" << std::endl; return &domains_[ index[ 0 ] ].data(); } private: void readBlock (); }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/boundaryseg.cc000066400000000000000000000111501511655130300247400ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // BoundarySegBlock // ---------------- BoundarySegBlock :: BoundarySegBlock ( std :: istream &in, int /* pnofvtx */, int pdimworld,bool psimplexgrid ) : BasicBlock(in,"boundarysegments"), dimworld(pdimworld), goodline(true), p(), bndid(-1), simplexgrid(psimplexgrid) { if (!isactive()) return; assert(dimworld>0); next(); } int BoundarySegBlock :: get( std :: map< EntityKey, BndParam > &facemap, bool fixedsize, int vtxoffset ) { static int cube2simplex[3][3] = { {0,1,3}, {0,2,3}, {1,2,3} }; int lnofbound; int face = ElementFaceUtil::faceSize(dimworld,simplexgrid); for (lnofbound=0; ok(); next()) { for (size_t i=0; i bound( face ); for (int j=0; jface) { assert(dimworld==2 || face==3); if (dimworld==3) { for (int i=0; i<3; i++) { for (int j=0; j k( 2 ); for (size_t i=0; i> x; bndid = x; if ( bndid <= 0 ) { DUNE_THROW( DGFException, "ERROR in " << *this << " non-positive boundary id (" << bndid << ") read!" ); } while( lstream >> x ) p.push_back( x ); } // read parameter from right hand side if( delimiter != std::string::npos ) { std::string strParam = currentline.substr( delimiter+1, std::string::npos ); parameter = DGFBoundaryParameter::convert( strParam ); } goodline=true; return goodline; } else return next(); } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/boundaryseg.hh000066400000000000000000000036351511655130300247630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_BOUNDARYSEGBLOCK_HH #define DUNE_DGF_BOUNDARYSEGBLOCK_HH #include #include #include #include #include #include #include namespace Dune { namespace dgf { class BoundarySegBlock : public BasicBlock { int dimworld; // the dimension of the vertices (is given from user) bool goodline; // active line describes a vertex std :: vector< unsigned int > p; // active vertex int bndid; typedef DGFBoundaryParameter::type BoundaryParameter; BoundaryParameter parameter; bool simplexgrid; public: typedef DGFEntityKey< unsigned int> EntityKey; typedef std::pair < int, BoundaryParameter > BndParam; // initialize vertex block and get first vertex BoundarySegBlock ( std :: istream &in, int pnofvtx, int pdimworld, bool psimplexgrid ); // some information int get( std :: map< EntityKey, BndParam > & facemap, bool fixedsize, int vtxoffset ); bool ok() { return goodline; } int nofbound() { return noflines(); } private: bool next(); // get coordinates of active vertex int operator[] (int i) { assert(ok()); assert(linenumber()>=0); assert(0<=i && i namespace Dune { namespace dgf { // CubeBlock // --------- CubeBlock :: CubeBlock ( std::istream &in, int pnofvtx, int pvtxoffset, int &pdimgrid ) : BasicBlock( in, "Cube" ), nofvtx(pnofvtx), dimgrid( pdimgrid ), goodline(true), map(0), nofparams(0), vtxoffset(pvtxoffset) { if( !isactive() ) return; if( findtoken( "parameters" ) ) { int x = 0; if( getnextentry( x ) ) { if( x > 0 ) nofparams = x; } if( x <= 0 ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Key 'parameters' found with no or non-positive value." ); } } if( dimgrid < 0 ) dimgrid = getDimGrid(); pdimgrid = dimgrid; map.resize( 1 << dimgrid ); for( size_t i = 0; i < map.size(); ++i ) map[ i ] = i; if( findtoken( "map" ) ) { for( size_t i = 0; i < map.size(); ++i ) { int x; if( !getnextentry( x ) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Incomplete reference mapping " << "(got " << i << " entries, " << "expected " << map.size() << " entries." ); } map[ i ] = x; } } } int CubeBlock :: getDimGrid () { reset(); while( getnextline() ) { int count = 0; double x; while( getnextentry( x ) ) ++count; if( count > nofparams ) { count -= nofparams; // int dim = (int)(log( count ) / M_LN2); int dim = 1; while (1< > &cubes, std :: vector< std :: vector< double > > ¶ms, int &nofp ) { nofp = nofparams; reset(); std :: vector< unsigned int > cube( 1 << dimgrid ); std :: vector< double > param( nofparams ); int nofcubes = 0; for( ; next( cube, param ); ++nofcubes ) { cubes.push_back( cube ); /* for( size_t j = 0; j < cube.size(); ++j ) cubes[ nofcubes ][ j ] = cubes[ j ]; */ if( nofparams > 0 ) params.push_back( param ); } return nofcubes; } bool CubeBlock :: next ( std :: vector< unsigned int > &cube, std :: vector< double > ¶m ) { assert( ok() ); if( !getnextline() ) return (goodline = false); for( std :: size_t n = 0; n < cube.size(); ++n ) { int idx; if( !getnextentry( idx ) ) { if( n > 0 ) { DUNE_THROW ( DGFException, "Error in " << *this << ": " << "Wrong number of vertex indices " << "(got " << idx << ", expected " << cube.size() << ")" ); } else return next( cube, param ); } if( (vtxoffset > idx) || (idx >= int(nofvtx + vtxoffset)) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Invalid vertex index " << "(" << idx << " not in [" << vtxoffset << ", " << (nofvtx + vtxoffset) << "[)" ); } cube[ map[ n ] ] = idx - vtxoffset; } std :: size_t np = 0; double x; for( ; getnextentry( x ); ++np ) { if( np < param.size() ) param[ np ] = x; } if( np != param.size() ) { DUNE_THROW ( DGFException, "Error in " << *this << ": " << "Wrong number of simplex parameters " << "(got " << np << ", expected " << param.size() << ")" ); } return (goodline = true); } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/cube.hh000066400000000000000000000026441511655130300233560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_CUBEBLOCK_HH #define DUNE_DGF_CUBEBLOCK_HH #include #include #include #include namespace Dune { namespace dgf { class CubeBlock : public BasicBlock { unsigned int nofvtx; int dimgrid; bool goodline; // active line describes a vertex std :: vector< unsigned int > map; // active vertex int nofparams; int vtxoffset; public: CubeBlock ( std :: istream &in, int pnofvtx, int pvtxoffset, int &pdimgrid ); int get ( std :: vector< std :: vector< unsigned int> > &simplex, std :: vector< std :: vector< double > > ¶ms, int &nofp ); // some information bool ok () { return goodline; } int nofsimplex () { return noflines(); } private: // get the dimension of the grid int getDimGrid (); // get next simplex bool next ( std :: vector< unsigned int > &simplex, std :: vector< double > ¶m ); }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/dim.cc000066400000000000000000000022501511655130300231700ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // DimBlock // -------- DimBlock :: DimBlock ( std :: istream &in ) : BasicBlock ( in, "Dimensions" ) { if (isempty()) { DUNE_THROW(DGFException, "no dimension of world specified!"); } else { getnextline(); line >> _dim; if (_dim<1) { DUNE_THROW(DGFException, "negative dimension of world specified!"); } else { if (noflines()==1) _dimworld=_dim; else { getnextline(); line >> _dimworld; if (_dimworld < _dim) { DUNE_THROW(DGFException, "negative dimension of world smaller than dim!"); } } } } } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/dim.hh000066400000000000000000000017531511655130300232110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_DIMBLOCK_HH #define DUNE_DGF_DIMBLOCK_HH #include #include namespace Dune { namespace dgf { class DimBlock : public BasicBlock { int _dimworld; // dimension of world int _dim; // dimension of grid public: const static char* ID; // initialize block and get dimension of world DimBlock ( std :: istream &in ); // get dimension of world found in block int dim() { return _dim; } int dimworld() { return _dimworld; } // some information bool ok() { return true; } }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/general.cc000066400000000000000000000107411511655130300240400ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // GeneralBlock // --------- GeneralBlock :: GeneralBlock ( std::istream &in, int pnofvtx, int pvtxoffset, int &pdimgrid ) : BasicBlock( in, "General" ), nofvtx(pnofvtx), dimgrid( pdimgrid ), goodline(true), map(0), nofparams(0), vtxoffset(pvtxoffset) { if( !isactive() ) return; if( findtoken( "parameters" ) ) { int x = 0; if( getnextentry( x ) ) { if( x > 0 ) nofparams = x; } if( x <= 0 ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Key 'parameters' found with no or non-positive value." ); } } if( dimgrid < 0 ) dimgrid = getDimGrid(); pdimgrid = dimgrid; map.resize( 1 << dimgrid ); for( size_t i = 0; i < map.size(); ++i ) map[ i ] = i; if( findtoken( "map" ) ) { for( size_t i = 0, count = 0; i < map.size(); ++i , ++count ) { int x; if( !getnextentry( x ) ) { // if we don't find another entry that's it map.resize( count ); break ; } map[ i ] = x; } } } int GeneralBlock :: getDimGrid () { reset(); while( getnextline() ) { int count = 0; double x; while( getnextentry( x ) ) ++count; if( count > nofparams ) { count -= nofparams; // int dim = (int)(log( count ) / M_LN2); int dim = 1; while (1< > &elements, std :: vector< std :: vector< double > > ¶ms, int &nofp ) { nofp = nofparams; reset(); std :: vector< unsigned int > element( 1 << dimgrid ); std :: vector< double > param( nofparams ); int nofcubes = 0; for( ; next( element, param ); ++nofcubes ) { elements.push_back( element ); if( nofparams > 0 ) params.push_back( param ); } return nofcubes; } bool GeneralBlock :: next ( std :: vector< unsigned int > &element, std :: vector< double > ¶m ) { assert( ok() ); if( !getnextline() ) return (goodline = false); for( std :: size_t n = 0; n 0 // just resize the element vector if( n > 0 ) { element.resize( n ) ; } } if( (vtxoffset > idx) || (idx >= int(nofvtx + vtxoffset)) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Invalid vertex index " << "(" << idx << " not in [" << vtxoffset << ", " << (nofvtx + vtxoffset) << "[)" ); } element[ map[ n ] ] = idx - vtxoffset; } std :: size_t np = 0; double x; for( ; getnextentry( x ); ++np ) { if( np < param.size() ) param[ np ] = x; } if( np != param.size() ) { DUNE_THROW ( DGFException, "Error in " << *this << ": " << "Wrong number of simplex parameters " << "(got " << np << ", expected " << param.size() << ")" ); } return (goodline = true); } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/general.hh000066400000000000000000000030461511655130300240520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_DGFPARSER_BLOCKS_GENERAL_HH #define DUNE_GRID_IO_FILE_DGFPARSER_BLOCKS_GENERAL_HH #include #include #include namespace Dune { namespace dgf { // GeneralBlock // --------- class GeneralBlock : public BasicBlock { unsigned int nofvtx; int dimgrid; bool goodline; // active line describes a vertex std :: vector< unsigned int > map; // active vertex int nofparams; int vtxoffset; public: GeneralBlock ( std :: istream &in, int pnofvtx, int pvtxoffset, int &pdimgrid ); int get ( std :: vector< std :: vector< unsigned int> > &simplex, std :: vector< std :: vector< double > > ¶ms, int &nofp ); // some information bool ok () { return goodline; } int nofsimplex () { return noflines(); } private: // get the dimension of the grid int getDimGrid (); // get next simplex bool next ( std :: vector< unsigned int > &simplex, std :: vector< double > ¶m ); }; } // end namespace dgf } // end namespace Dune #endif // #ifndef DUNE_GRID_IO_FILE_DGFPARSER_BLOCKS_GENERAL_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/gridparameter.cc000066400000000000000000000046671511655130300252630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // GridParameterBlock // ------------------ GridParameterBlock::GridParameterBlock ( std :: istream &in ) : BasicBlock( in, "GridParameter" ), foundFlags_( 0 ), name_( "Unnamed Grid" ), // default value (used if name is empty) dumpFileName_( "" ), markLongestEdge_( false ), // default value bisectionCompatibility_( false ) // default value { if( isempty() ) return; // check name if( findtoken( "name" ) ) { std::string entry; if( getnextentry( entry ) ) name_ = entry; else dwarn << "GridParameterBlock: Found keyword 'name' without value." << std::endl; foundFlags_ |= foundName; } // get file name if ( findtoken( "dumpfilename" ) ) { std::string entry; if( getnextentry( entry ) ) dumpFileName_ = entry; else dwarn << "GridParameterBlock: Found keyword 'dumpFileName' without value." << std::endl; foundFlags_ |= foundDumpFileName; } // check for markLongestEdge if( findtoken( "refinementedge" ) ) { std::string entry; if( getnextentry( entry ) ) { makeupcase( entry ); if( entry == "LONGEST" ) markLongestEdge_ = true; else if( entry != "ARBITRARY" ) dwarn << "GridParameterBlock: Invalid value for keyword 'refinementedge': " << entry << std::endl; } else dwarn << "GridParameterBlock: Found keyword 'refinementedge' without value." << std::endl; foundFlags_ |= foundLongestEdge; } // check for bisectioncompatibility if( findtoken( "bisectioncompatibility" ) ) { int entry; if( getnextentry( entry ) ) { bisectionCompatibility_ = bool(entry); } else dwarn << "GridParameterBlock: Found keyword 'bisectioncompatibility' without value." << std::endl; foundFlags_ |= foundCompatible; } } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/gridparameter.hh000066400000000000000000000072131511655130300252630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_GRIDPARAMETERBLOCK_HH #define DUNE_DGF_GRIDPARAMETERBLOCK_HH #include #include #include namespace Dune { namespace dgf { /** \brief Common Grid parameters \ingroup DGFGridParameter For each grid implementation there is a set of parameters that can be passed via the GridParameter block to the momment of grid construction. Currently implemented common parameters are: \n\n 1. \b name: The name of the grid ( later returned by the method grid.name() ). \n 2. \b refinementedge: parameter to specify the refinement edge in simplices. Valid values are \b arbitrary (which is the default value) and \b longest which marks the longest edge/face of each simplex to be the refinement edge. \n See also the \b examplegrid5.dgf file for examples. */ class GridParameterBlock : public BasicBlock { public: typedef unsigned int Flags; static const Flags foundName = 1 << 0; static const Flags foundDumpFileName = 1 << 1; static const Flags foundLongestEdge = 1 << 5; static const Flags foundCompatible = 1 << 13; protected: Flags foundFlags_; // supportFlags, this block was created with std::string name_; // name of the grid std::string dumpFileName_; // name of the grid bool markLongestEdge_; // Mark longest edge for AlbertaGrid or ALUGrid bool bisectionCompatibility_; // true if grid is compatible (bisection refinement works) private: // copy not implemented GridParameterBlock(const GridParameterBlock&); public: //! constructor: read common parameters GridParameterBlock ( std::istream &in ); //! return the name of the grid const std::string &name ( const std::string &defaultValue ) const { if( (foundFlags_ & foundName) == 0 ) { dwarn << "GridParameterBlock: Parameter 'name' not specified, " << "defaulting to '" << defaultValue << "'." << std::endl; return defaultValue; } else return name_; } const std::string &dumpFileName ( ) const { if( (foundFlags_ & foundDumpFileName) != 0 ) { dwarn << "GridParameterBlock: found Parameter 'dumpfilename', " << "dumping file to `" << dumpFileName_ << "'" << std::endl; } return dumpFileName_; } //! returns true if longest edge should be marked for AlbertaGrid bool markLongestEdge () const { if( (foundFlags_ & foundLongestEdge) == 0 ) { dwarn << "GridParameterBlock: Parameter 'refinementedge' not specified, " << "defaulting to 'ARBITRARY'." << std::endl; } return markLongestEdge_; } //! returns true if grid is compatible for bisection refinement bool bisectionCompatibility() const { if( (foundFlags_ & foundCompatible) == 0 ) { dwarn << "GridParameterBlock: Parameter 'bisectioncompatibility' not specified, " << "defaulting to '0' (false)." << std::endl; } return bisectionCompatibility_; } // some information bool ok() { return true; } }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/interval.cc000066400000000000000000000132161511655130300242470ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // IntervalBlock // ------------- IntervalBlock::IntervalBlock ( std::istream &in ) : BasicBlock( in, "Interval" ), intervals_( 0 ), map_(), good_( false ), dimw_( 0 ) { if( !isactive() ) return; const bool hasMapping = findtoken("map"); if( hasMapping ) { int x; map_.clear(); while( getnextentry( x ) ) { map_.push_back( x ); } } else { reset(); } getnextline(); for( double x; getnextentry( x ); ++dimw_ ) ; if( dimw_ == 0 ) { DUNE_THROW( DGFException, "Too few coordinates for point p0 in IntervalBlock" ); } // reset stream reset(); // skip first line if mapping was found if( hasMapping ) getnextline(); while( next() ) ; // set default map if( map_.empty() ) { map_.resize( dimw_ ); for( int i=0; i= dimw_ ) DUNE_THROW( DGFException, "Error in " << *this << ": ijk mapping is not a permutation of {0,...," << dimw_-1 << "}"); } } int IntervalBlock::getVtx ( int block, std::vector< std::vector< double > > &vtx ) const { dverb << "reading vertices for interval " << block << "... "; Interval interval( get( block ), map_ ); size_t old_size = vtx.size(); vtx.resize( old_size + nofvtx( block ) ); for( size_t i = old_size; i < vtx.size(); ++i ) vtx[ i ].resize( dimw() ); size_t m = old_size; std::vector< int > i( dimw() ); const int end = dimw()-1; int k = end; for( i[ end ] = 0; i[ end ] <= interval.n[ end ]; ) { // go all the way down for( ; k > 0; --k ) i[ k-1 ] = 0; assert( m < vtx.size() ); for( int j = 0; j < dimw(); ++j ) { // apply mapping to get correct coordinates vtx[ m ][ map_[ j ] ] = interval.p[ 0 ][ j ] + double(i[ j ])*interval.h[ j ]; } ++m; // increase i[ k ] and go up for all finished loops for( ; (++i[ k ] > interval.n[ k ]) && (k < end); ++k ) ; } assert( m == vtx.size() ); dverb << "[done]" << std::endl; return m - old_size;; } int IntervalBlock::getHexa ( int block, std::vector< std::vector< unsigned int > > &cubes, int offset ) const { dverb << "generating cubes for interval " << block << "... "; Interval interval( get( block ), map_ ); const int verticesPerCube = 1 << dimw(); size_t old_size = cubes.size(); cubes.resize( old_size + nofhexa( block ) ); for( size_t i = old_size; i < cubes.size(); ++i ) cubes[ i ].resize( verticesPerCube ); size_t m = old_size; std::vector< int > i( dimw() ); const int end = dimw()-1; int k = end; for( i[ end ] = 0; i[ end ] < interval.n[ end ]; ) { // go all the way down for( ; k > 0; --k ) i[ k-1 ] = 0; assert( m < cubes.size() ); for( int j = 0; j < verticesPerCube; ++j ) { cubes[ m ][ j ] = offset; int factor = 1; for( int d = 0; d < dimw(); ++d ) { cubes[ m ][ j ] += factor*(i[ d ] + ((j >> d) & 1)); factor *= interval.n[ d ]+1; } } ++m; // increase i[ k ] and go up for all finished loops for( ; (++i[ k ] >= interval.n[ k ]) && (k < end); ++k ) ; } assert( m == cubes.size() ); dverb << "[done]" << std::endl; return m - old_size; } template< class T > void IntervalBlock::parseLine ( std::vector< T > &v ) { getnextline(); v.resize( dimw_ ); for( int i = 0; i < dimw_; ++i ) { if( !getnextentry( v[ i ] ) ) DUNE_THROW( DGFException, "ERROR in " << *this << ": Not enough values." ); } } bool IntervalBlock::next () { if (linenumber()==noflines()-1) { good_=false; return good_; } Interval interval; parseLine( interval.p[ 0 ] ); parseLine( interval.p[ 1 ] ); parseLine( interval.n ); //find real upper and lower edge and calculate cell width interval.h.resize( dimw_ ); for( int i = 0; i < dimw_; ++i ) { double &left = interval.p[ 0 ][ i ]; double &right = interval.p[ 1 ][ i ]; const int &n = interval.n[ i ]; if( left > right ) { double dummy = left; left = right; right = dummy; } interval.h[ i ] = (right - left) / double( n ); assert( interval.h[ i ] > 0); } intervals_.push_back( interval ); dverb << interval << std::endl; good_ = true; return good_; } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/interval.hh000066400000000000000000000101051511655130300242530ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_INTERVALBLOCK_HH #define DUNE_DGF_INTERVALBLOCK_HH #include #include #include #include namespace Dune { namespace dgf { struct IntervalBlock : public BasicBlock { struct Interval { Interval() {} Interval( const Interval& interval, const std::vector& map ) { copy( interval, map ); } void copy(const Interval& interval, const std::vector& map ) { const int size = map.size(); p[0].resize( size ); p[1].resize( size ); n.resize( size ); h.resize( size ); assert( size == int(interval.n.size()) ); for( int i=0; i, 2 > p; // lower and upper boundary points std::vector< double > h; // width of the cells in each direction std::vector< int > n; // number of cells in each direction }; private: std::vector< Interval > intervals_; std::vector< int > map_; bool good_; //data read correctly int dimw_; //dimension of world public: explicit IntervalBlock ( std::istream &in ); void get ( std::vector< std::vector< double > > &vtx, int &nofvtx, std::vector< std::vector< unsigned int > > &simplex, int &nofsimpl ) { for( size_t i = 0; i < intervals_.size(); ++i ) { int oldvtx = nofvtx; nofvtx += getVtx( i, vtx ); nofsimpl += getHexa( i, simplex, oldvtx ); } } void get ( std::vector< std::vector< double > > &vtx, int &nofvtx ) { for( size_t i = 0; i < intervals_.size(); ++i ) nofvtx += getVtx( i, vtx ); } const Interval &get ( int block ) const { return intervals_[ block ]; } int numIntervals () const { return intervals_.size(); } int dimw () const { return dimw_; } int getVtx ( int block, std::vector< std::vector< double > > &vtx ) const; int getHexa ( int block, std::vector< std::vector< unsigned int > > &cubes, int offset = 0 ) const; int nofvtx ( int block ) const { const Interval &interval = get( block ); int n = 1; for( int i = 0; i < dimw_; ++i ) n *= (interval.n[ i ] + 1); return n; } int nofhexa ( int block ) const { const Interval &interval = get( block ); int n = 1; for( int i = 0; i < dimw_; ++i ) n *= interval.n[ i ]; return n; } private: template< class T > void parseLine ( std::vector< T > &v ); bool next (); }; inline std::ostream & operator<< ( std::ostream &out, const IntervalBlock::Interval &interval ) { if( interval.p[ 0 ].empty() || interval.p[ 1 ].empty() || interval.n.empty() ) return out << "Interval {}"; out << "Interval { p0 = (" << interval.p[ 0 ][ 0 ]; for( size_t i = 1; i < interval.p[ 0 ].size(); ++i ) out << ", " << interval.p[ 0 ][ i ]; out << "), p1 = (" << interval.p[ 1 ][ 0 ]; for( size_t i = 1; i < interval.p[ 1 ].size(); ++i ) out << ", " << interval.p[ 1 ][ i ]; out << "), n = (" << interval.n[ 0 ]; for( size_t i = 1; i < interval.n.size(); ++i ) out << ", " << interval.n[ i ]; return out << ") }"; } } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/periodicfacetrans.cc000066400000000000000000000035101511655130300261040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // PeriodicFaceTransformationBlock // ------------------------------- PeriodicFaceTransformationBlock ::PeriodicFaceTransformationBlock ( std::istream &in, int dimworld ) : BasicBlock( in, "PeriodicFaceTransformation" ) { while( getnextline() ) { AffineTransformation trafo( dimworld ); for( int i = 0; i < dimworld; ++i ) { if( i > 0 ) match( ',' ); for( int j = 0; j < dimworld; ++j ) { if( !getnextentry( trafo.matrix( i, j ) ) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Not enough entries in matrix row " << i << "." ); } } } match( '+' ); for( int i = 0; i < dimworld; ++i ) { if( !getnextentry( trafo.shift[ i ] ) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Not enough entries in shift." ); } } transformations_.push_back( trafo ); } } void PeriodicFaceTransformationBlock::match ( char what ) { char c; if( !getnextentry( c ) || (c != what) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << what << "expected." ); } } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/periodicfacetrans.hh000066400000000000000000000055031511655130300261220ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_PERIODICFACETRANSBLOCK_HH #define DUNE_DGF_PERIODICFACETRANSBLOCK_HH #include #include #include namespace Dune { namespace dgf { // PeriodicFaceTransformationBlock // ------------------------------- struct PeriodicFaceTransformationBlock : public BasicBlock { template< class T > class Matrix { int rows_; int cols_; std::vector< T > fields_; public: Matrix ( int rows, int cols ) : rows_( rows ), cols_( cols ), fields_( rows * cols ) {} const T &operator() ( int i, int j ) const { return fields_[ i * cols_ + j ]; } T &operator() ( int i, int j ) { return fields_[ i * cols_ + j ]; } int rows () const { return rows_; } int cols () const { return cols_; } }; struct AffineTransformation { Matrix< double > matrix; std::vector< double > shift; explicit AffineTransformation ( int dimworld ) : matrix( dimworld, dimworld ), shift( dimworld ) {} }; private: std::vector< AffineTransformation > transformations_; // copy not implemented PeriodicFaceTransformationBlock ( const PeriodicFaceTransformationBlock & ); public: // initialize block and get dimension of world PeriodicFaceTransformationBlock ( std::istream &in, int dimworld ); const AffineTransformation &transformation ( int i ) const { assert( i < numTransformations() ); return transformations_[ i ]; } int numTransformations () const { return transformations_.size(); } private: void match ( char what ); }; // PeriodicFaceTransformationBlock::AffineTransformation // ----------------------------------------------------- inline std::ostream & operator<< ( std::ostream &out, const PeriodicFaceTransformationBlock::AffineTransformation &trafo ) { for( int i = 0; i < trafo.matrix.rows(); ++i ) { out << (i > 0 ? ", " : ""); for( int j = 0; j < trafo.matrix.cols(); ++j ) out << (j > 0 ? " " : "") << trafo.matrix( i, j ); } out << " +"; for( unsigned int i = 0; i < trafo.shift.size(); ++i ) out << " " << trafo.shift[ i ]; return out; } } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/polygon.hh000066400000000000000000000027711511655130300241300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=2 sw=2 sts=2: #ifndef DUNE_POLYGON_HH #define DUNE_POLYGON_HH #include #include #include #include namespace Dune { namespace dgf { // PolygonBlock // ------------ struct PolygonBlock : public BasicBlock { PolygonBlock ( std::istream &in, int numVtx, int vtxOfs ) : BasicBlock( in, "Polygon" ), vtxBegin_( vtxOfs ), vtxEnd_( vtxOfs + numVtx ) {} int get ( std::vector< std::vector< int > > &polygons ) { reset(); std::vector< int > polygon; while( getnextline() ) { polygon.clear(); for( int vtxIdx; getnextentry( vtxIdx ); ) { if( (vtxBegin_ > vtxIdx) || (vtxIdx >= vtxEnd_) ) DUNE_THROW( DGFException, "Error in " << *this << ": Invalid vertex index (" << vtxIdx << " not int [" << vtxBegin_ << ", " << vtxEnd_ << "[)" ); polygon.push_back( vtxIdx - vtxBegin_ ); } polygons.push_back( polygon ); } return polygons.size(); } protected: int vtxBegin_, vtxEnd_; }; } // namespace dgf } // end namespace Dune #endif // #ifndef DUNE_POLYGON_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/polyhedron.hh000066400000000000000000000036401511655130300246200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=2 sw=2 sts=2: #ifndef DUNE_POLYHEDRON_HH #define DUNE_POLYHEDRON_HH #include #include namespace Dune { namespace dgf { // PolyhedronBlock // --------------- struct PolyhedronBlock : public BasicBlock { explicit PolyhedronBlock ( std::istream &in, int numPolys ) : BasicBlock( in, "Polyhedron" ), numPolys_( numPolys ) {} int get ( std::vector< std::vector< int > > &polyhedra ) { reset(); std::vector< int > polyhedron; int minPolyId = 1; while( getnextline() ) { polyhedron.clear(); for( int polyIdx; getnextentry( polyIdx ); ) { if( (polyIdx < 0) || (polyIdx > numPolys_) ) DUNE_THROW( DGFException, "Error in " << *this << ": Invalid polygon index (" << polyIdx << " not int [0, " << numPolys_ << "])" ); minPolyId = std::min( minPolyId, polyIdx ); polyhedron.push_back( polyIdx ); } polyhedra.push_back( polyhedron ); } // subtract minimal number to have 0 starting numbering if( minPolyId > 0 ) { const size_t polySize = polyhedra.size(); for( size_t i=0; i #include namespace Dune { namespace dgf { namespace Expr { struct ConstantExpression : public ProjectionBlock::Expression { explicit ConstantExpression ( const Vector &value ) : value_( value ) {} explicit ConstantExpression ( const double &value ) : value_( 1, value ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: Vector value_; }; struct VariableExpression : public ProjectionBlock::Expression { virtual void evaluate ( const Vector &argument, Vector &result ) const; }; struct FunctionCallExpression : public ProjectionBlock::Expression { FunctionCallExpression ( const ProjectionBlock::ExpressionPointer& function, const ProjectionBlock::ExpressionPointer& expression ) : function_( function ), expression_( expression ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer function_; ProjectionBlock::ExpressionPointer expression_; mutable Vector tmp_; }; struct VectorExpression : public ProjectionBlock::Expression { explicit VectorExpression ( const std::vector< ProjectionBlock::ExpressionPointer >& expressions ) : expressions_( expressions ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: std::vector< ProjectionBlock::ExpressionPointer > expressions_; }; struct BracketExpression : public ProjectionBlock::Expression { BracketExpression ( const ProjectionBlock::ExpressionPointer& expression, size_t field ) : expression_( expression ), field_( field ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer expression_; size_t field_; }; struct MinusExpression : public ProjectionBlock::Expression { explicit MinusExpression ( const ProjectionBlock::ExpressionPointer& expression ) : expression_( expression ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer expression_; }; struct NormExpression : public ProjectionBlock::Expression { explicit NormExpression ( const ProjectionBlock::ExpressionPointer& expression ) : expression_( expression ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer expression_; }; struct SqrtExpression : public ProjectionBlock::Expression { explicit SqrtExpression ( const ProjectionBlock::ExpressionPointer& expression ) : expression_( expression ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer expression_; }; struct SinExpression : public ProjectionBlock::Expression { explicit SinExpression ( const ProjectionBlock::ExpressionPointer& expression ) : expression_( expression ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer expression_; }; struct CosExpression : public ProjectionBlock::Expression { explicit CosExpression ( const ProjectionBlock::ExpressionPointer& expression ) : expression_( expression ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer expression_; }; struct PowerExpression : public ProjectionBlock::Expression { PowerExpression ( const ProjectionBlock::ExpressionPointer& exprA, const ProjectionBlock::ExpressionPointer& exprB ) : exprA_( exprA ), exprB_( exprB ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer exprA_; ProjectionBlock::ExpressionPointer exprB_; mutable Vector tmp_; }; struct SumExpression : public ProjectionBlock::Expression { SumExpression ( const ProjectionBlock::ExpressionPointer& exprA, const ProjectionBlock::ExpressionPointer& exprB ) : exprA_( exprA ), exprB_( exprB ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer exprA_; ProjectionBlock::ExpressionPointer exprB_; mutable Vector tmp_; }; struct DifferenceExpression : public ProjectionBlock::Expression { DifferenceExpression ( const ProjectionBlock::ExpressionPointer& exprA, const ProjectionBlock::ExpressionPointer& exprB ) : exprA_( exprA ), exprB_( exprB ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer exprA_; ProjectionBlock::ExpressionPointer exprB_; mutable Vector tmp_; }; struct ProductExpression : public ProjectionBlock::Expression { ProductExpression ( const ProjectionBlock::ExpressionPointer& exprA, const ProjectionBlock::ExpressionPointer& exprB ) : exprA_( exprA ), exprB_( exprB ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer exprA_; ProjectionBlock::ExpressionPointer exprB_; mutable Vector tmp_; }; struct QuotientExpression : public ProjectionBlock::Expression { QuotientExpression ( const ProjectionBlock::ExpressionPointer& exprA, const ProjectionBlock::ExpressionPointer& exprB ) : exprA_( exprA ), exprB_( exprB ) {} virtual void evaluate ( const Vector &argument, Vector &result ) const; private: ProjectionBlock::ExpressionPointer exprA_; ProjectionBlock::ExpressionPointer exprB_; }; void ConstantExpression::evaluate ( const Vector & /* argument */, Vector &result ) const { result = value_; } void VariableExpression::evaluate ( const Vector &argument, Vector &result ) const { result = argument; } void FunctionCallExpression::evaluate ( const Vector &argument, Vector &result ) const { expression_->evaluate( argument, tmp_ ); return function_->evaluate( tmp_, result ); } void VectorExpression::evaluate ( const Vector &argument, Vector &result ) const { result.resize( 0 ); Vector r; const auto end = expressions_.end(); for( auto it = expressions_.begin(); it != end; ++it ) { (*it)->evaluate( argument, r ); for( size_t i = 0; i < r.size(); ++i ) result.push_back( r[ i ] ); } } void BracketExpression::evaluate ( const Vector &argument, Vector &result ) const { expression_->evaluate( argument, result ); if( field_ >= result.size() ) DUNE_THROW( MathError, "Index out of bounds (" << field_ << " not in [ 0, " << result.size() << " [)." ); result[ 0 ] = result[ field_ ]; result.resize( 1 ); } void MinusExpression::evaluate ( const Vector &argument, Vector &result ) const { expression_->evaluate( argument, result ); const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) result[ i ] *= -1.0; } void NormExpression::evaluate ( const Vector &argument, Vector &result ) const { using std::sqrt; expression_->evaluate( argument, result ); double normsqr = 0.0; const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) normsqr += result[ i ] * result[ i ]; result.resize( 1 ); result[ 0 ] = sqrt( normsqr ); } void SqrtExpression::evaluate ( const Vector &argument, Vector &result ) const { using std::sqrt; expression_->evaluate( argument, result ); if( result.size() != 1 ) DUNE_THROW( MathError, "Cannot calculate square root of a vector." ); result[ 0 ] = sqrt( result[ 0 ] ); } void SinExpression::evaluate ( const Vector &argument, Vector &result ) const { expression_->evaluate( argument, result ); if( result.size() != 1 ) DUNE_THROW( MathError, "Cannot calculate the sine of a vector." ); result[ 0 ] = sin( result[ 0 ] ); } void CosExpression::evaluate ( const Vector &argument, Vector &result ) const { expression_->evaluate( argument, result ); if( result.size() != 1 ) DUNE_THROW( MathError, "Cannot calculate the cosine of a vector." ); result[ 0 ] = cos( result[ 0 ] ); } void PowerExpression::evaluate ( const Vector &argument, Vector &result ) const { exprA_->evaluate( argument, result ); exprB_->evaluate( argument, tmp_ ); if( (result.size() == 1) && (tmp_.size() == 1) ) result[ 0 ] = std::pow( result[ 0 ], tmp_[ 0 ] ); else DUNE_THROW( MathError, "Cannot calculate powers of vectors." ); } void SumExpression::evaluate ( const Vector &argument, Vector &result ) const { exprA_->evaluate( argument, result ); exprB_->evaluate( argument, tmp_ ); if( result.size() == tmp_.size() ) { const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) result[ i ] += tmp_[ i ]; } else DUNE_THROW( MathError, "Cannot sum vectors of different size." ); } void DifferenceExpression::evaluate ( const Vector &argument, Vector &result ) const { exprA_->evaluate( argument, result ); exprB_->evaluate( argument, tmp_ ); if( result.size() == tmp_.size() ) { const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) result[ i ] -= tmp_[ i ]; } else DUNE_THROW( MathError, "Cannot sum vectors of different size." ); } void ProductExpression::evaluate ( const Vector &argument, Vector &result ) const { exprA_->evaluate( argument, result ); exprB_->evaluate( argument, tmp_ ); if( result.size() == tmp_.size() ) { double product = 0.0; const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) product += result[ i ] * tmp_[ i ]; result.resize( 1 ); result[ 0 ] = product; } else if( tmp_.size() == 1 ) { const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) result[ i ] *= tmp_[ 0 ]; } else if( result.size() == 1 ) { std::swap( result, tmp_ ); const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) result[ i ] *= tmp_[ 0 ]; } else DUNE_THROW( MathError, "Cannot multiply non-scalar vectors of different size." ); } void QuotientExpression::evaluate ( const Vector &argument, Vector &result ) const { exprB_->evaluate( argument, result ); if( result.size() != 1 ) DUNE_THROW( MathError, "Cannot divide by a vector." ); double factor = 1.0 / result[ 0 ]; exprA_->evaluate( argument, result ); const size_t size = result.size(); for( size_t i = 0; i < size; ++i ) result[ i ] *= factor; } } // namespace Expr // ProjectionBlock // --------------- ProjectionBlock::ProjectionBlock ( std::istream &in, int dimworld ) : BasicBlock( in, blockId() ), defaultFunction_() { // for backup and load balancing registerProjectionFactory( dimworld ); while( getnextline() ) { std::string thisLine = line.str(); nextToken(); if( token.type == Token::functionKeyword ) { nextToken(); parseFunction( thisLine ); // std::cout << "Projection line: '" << thisLine << "'" << std::endl; } else if( token.type == Token::defaultKeyword ) { nextToken(); parseDefault(); } else if( token.type == Token::segmentKeyword ) { nextToken(); parseSegment(); } else if( token.type != Token::endOfLine ) DUNE_THROW( DGFException, "Error in " << *this << ": Invalid token (" << token << ")." ); matchToken( Token::endOfLine, "trailing tokens on line." ); } } void ProjectionBlock::parseFunction ( const std::string& exprname ) { if( token.type != Token::string ) DUNE_THROW( DGFException, "Error in " << *this << ": function name expected." ); const std::string functionName = token.literal; if( functions_.find( functionName ) != functions_.end() ) DUNE_THROW( DGFException, "Error in " << *this << ": redeclaration of function " << functionName << "." ); nextToken(); matchToken( Token::openingParen, "'(' expected." ); if( token.type != Token::string ) DUNE_THROW( DGFException, "Error in " << *this << ": variable name expected." ); const std::string variableName = token.literal; nextToken(); matchToken( Token::closingParen, "')' expected." ); matchToken( Token::equals, "'=' expected." ); ExpressionPointer expression = parseExpression( variableName ); //std::cout << std::endl << "Declaring function: " << functionName << "( " << variableName << " )" << std::endl; functions_[ functionName ] = std::make_pair( expression, exprname ); } ProjectionBlock::ExpressionPointer ProjectionBlock::parseBasicExpression ( const std::string &variableName ) { ExpressionPointer expression; // parenthesized expression if( token.type == Token::openingParen ) { nextToken(); expression = parseExpression( variableName ); matchToken( Token::closingParen, "')' expected." ); } // vector constant else if( token.type == Token::openingBracket ) { std::vector< ExpressionPointer > expressions; nextToken(); while( token.type != Token::closingBracket ) { expressions.push_back( parseExpression( variableName ) ); if( (token.type != Token::comma) && (token.type != Token::closingBracket) ) { std::cerr << "Warning: Components of vector expressions should be " << "separated by ','." << std::endl; std::cerr << " This separation will be mandatory in future " << "versions." << std::endl; } if( token.type == Token::comma ) nextToken(); } nextToken(); expression.reset( new Expr::VectorExpression( expressions ) ); } // norm expression else if( token.type == Token::normDelim ) { nextToken(); expression.reset( new Expr::NormExpression( parseExpression( variableName ) ) ); matchToken( Token::normDelim, "'|' expected." ); } // number else if( token.type == Token::number ) { expression.reset( new Expr::ConstantExpression( token.value ) ); nextToken(); } // pi else if( token.type == Token::piKeyword ) { expression.reset( new Expr::ConstantExpression( MathematicalConstants< double >::pi() ) ); nextToken(); } else if( token.type == Token::string ) { if( token.literal != variableName ) { FunctionMap::iterator it = functions_.find( token.literal ); if( it == functions_.end() ) DUNE_THROW( DGFException, "Error in " << *this << ": function " << token.literal << " not declared." ); nextToken(); matchToken( Token::openingParen, "'(' expected." ); expression.reset( new Expr::FunctionCallExpression( it->second.first, parseExpression( variableName ) ) ); matchToken( Token::closingParen, "')' expected." ); } else { expression.reset( new Expr::VariableExpression ); nextToken(); } } else DUNE_THROW( DGFException, "Error in " << *this << ": " << "basic expression expected." ); return expression; } ProjectionBlock::ExpressionPointer ProjectionBlock::parsePostfixExpression ( const std::string &variableName ) { ProjectionBlock::ExpressionPointer expression = parseBasicExpression( variableName ); if( token.type == Token::openingBracket ) { nextToken(); if( (token.type != Token::number) || (double( int( token.value ) ) != token.value) ) DUNE_THROW( DGFException, "Error in " << *this << ": integral number expected." ); expression.reset( new Expr::BracketExpression( expression, int( token.value ) ) ); nextToken(); matchToken( Token::closingBracket, "']' expected." ); } return expression; } ProjectionBlock::ExpressionPointer ProjectionBlock::parseUnaryExpression ( const std::string &variableName ) { ProjectionBlock::ExpressionPointer expression; // unary minus if( (token.type == Token::additiveOperator) && (token.symbol == '-') ) { nextToken(); expression.reset( new Expr::MinusExpression( parsePostfixExpression( variableName ) ) ); } // sqrt else if( token.type == Token::sqrtKeyword ) { nextToken(); expression.reset( new Expr::SqrtExpression( parseUnaryExpression( variableName ) ) ); } // sin else if( token.type == Token::sinKeyword ) { nextToken(); expression.reset( new Expr::SinExpression( parseUnaryExpression( variableName ) ) ); } // cos else if( token.type == Token::cosKeyword ) { nextToken(); expression.reset( new Expr::CosExpression( parseUnaryExpression( variableName ) ) ); } else expression = parsePostfixExpression( variableName ); return expression; } ProjectionBlock::ExpressionPointer ProjectionBlock::parsePowerExpression ( const std::string &variableName ) { ProjectionBlock::ExpressionPointer expression = parseUnaryExpression( variableName ); while( token.type == Token::powerOperator ) { nextToken(); expression.reset( new Expr::PowerExpression( expression, parseUnaryExpression( variableName ) ) ); } return expression; } ProjectionBlock::ExpressionPointer ProjectionBlock::parseMultiplicativeExpression ( const std::string &variableName ) { ProjectionBlock::ExpressionPointer expression = parsePowerExpression( variableName ); while( token.type == Token::multiplicativeOperator ) { const char symbol = token.symbol; nextToken(); if( symbol == '*' ) expression.reset( new Expr::ProductExpression( expression, parsePowerExpression( variableName ) ) ); else if( symbol == '/' ) expression.reset( new Expr::QuotientExpression( expression, parsePowerExpression( variableName ) ) ); else DUNE_THROW( DGFException, "Error in " << *this << ": Internal tokenizer error." ); } return expression; } ProjectionBlock::ExpressionPointer ProjectionBlock::parseExpression ( const std::string &variableName ) { ProjectionBlock::ExpressionPointer expression = parseMultiplicativeExpression( variableName ); while( token.type == Token::additiveOperator ) { const char symbol = token.symbol; nextToken(); if( symbol == '+' ) expression.reset( new Expr::SumExpression( expression, parseMultiplicativeExpression( variableName ) ) ); else if( symbol == '-' ) expression.reset( new Expr::DifferenceExpression( expression, parseMultiplicativeExpression( variableName ) ) ); else DUNE_THROW( DGFException, "Error in " << *this << ": Internal tokenizer error." ); } return expression; } void ProjectionBlock::parseDefault () { if( token.type != Token::string ) DUNE_THROW( DGFException, "Error in " << *this << ": function name expected." ); const std::string functionName = token.literal; nextToken(); //std::cout << std::endl << "Default function: " << functionName << std::endl; FunctionMap::iterator it = functions_.find( functionName ); if( it == functions_.end() ) DUNE_THROW( DGFException, "Error in " << *this << ": function " << functionName << " not declared." ); defaultFunction_ = it->second; } void ProjectionBlock::parseSegment () { std::vector< unsigned int > faceId; while( token.type == Token::number ) { if( double( (unsigned int)token.value ) != token.value ) DUNE_THROW( DGFException, "Error in " << *this << ": integral number expected." ); faceId.push_back( (unsigned int)token.value ); nextToken(); } if( token.type != Token::string ) DUNE_THROW( DGFException, "Error in " << *this << ": function name expected." ); const std::string functionName = token.literal; nextToken(); //std::cout << std::endl << "Boundary projection for face"; //for( size_t int i = 0; i < faceId.size(); ++i ) // std::cout << " " << faceId[ i ]; //std::cout << ": " << functionName << std::endl; FunctionMap::iterator it = functions_.find( functionName ); if( it == functions_.end() ) DUNE_THROW( DGFException, "Error in " << *this << ": function " << functionName << " not declared." ); boundaryFunctions_.push_back( std::make_pair( faceId, it->second ) ); } void ProjectionBlock::matchToken ( const Token::Type &type, const std::string &message ) { if( token.type != type ) DUNE_THROW( DGFException, "Error in " << *this << ": " << message ); if( type != Token::endOfLine ) nextToken(); } void ProjectionBlock::nextToken () { int c; // eat white space while( ((c = line.peek()) == ' ') || (c == '\t') || (c == '\r') ) line.get(); // parse string literals if( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ) { token.type = Token::string; token.literal = ""; while( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ) { token.literal += lowerCase( line.get() ); c = line.peek(); } if( token.literal == "default" ) token.type = Token::defaultKeyword; else if( token.literal == "function" ) token.type = Token::functionKeyword; else if( token.literal == "segment" ) token.type = Token::segmentKeyword; else if( token.literal == "sqrt" ) token.type = Token::sqrtKeyword; else if( token.literal == "sin" ) token.type = Token::sinKeyword; else if( token.literal == "cos" ) token.type = Token::cosKeyword; else if( token.literal == "pi" ) token.type = Token::piKeyword; } // parse numeric constant else if( (c >= '0') && (c <= '9') ) { token.type = Token::number; token.value = 0; while( (c >= '0') && (c <= '9') ) { token.value = 10*token.value + double( c - '0' ); token.literal += char( line.get() ); c = line.peek(); } if( c == '.' ) { token.literal += line.get(); c = line.peek(); double factor = 0.1; while( (c >= '0') && (c <= '9') ) { token.value += factor * double( c - '0' ); token.literal += line.get(); factor *= 0.1; c = line.peek(); } } } // parse single character tokens else if( c == ',' ) token.setSymbol( Token::comma, line.get() ); else if( c == '=' ) token.setSymbol( Token::equals, line.get() ); else if( c == '(' ) token.setSymbol( Token::openingParen, line.get() ); else if( c == ')' ) token.setSymbol( Token::closingParen, line.get() ); else if( c == '[' ) token.setSymbol( Token::openingBracket, line.get() ); else if( c == ']' ) token.setSymbol( Token::closingBracket, line.get() ); else if( c == '|' ) token.setSymbol( Token::normDelim, line.get() ); else if( (c == '+') || (c == '-') ) token.setSymbol( Token::additiveOperator, line.get() ); else if( c == '*' ) { c = line.get(); if( (line.peek() == '*') ) { token.type = Token::powerOperator; line.get(); } else token.setSymbol( Token::multiplicativeOperator, c ); } else if( c == '/' ) token.setSymbol( Token::multiplicativeOperator, line.get() ); // parse end of line else if( c == std::stringstream::traits_type::eof() ) token.type = Token::endOfLine; else DUNE_THROW( DGFException, "Invalid character parsed: code=0x" << std::hex << c << "." ); //std::cout << " " << token << std::flush; } std::ostream &operator<< ( std::ostream &out, const ProjectionBlock::Token &token ) { typedef ProjectionBlock::Token Token; switch( token.type ) { case Token::string : return out << "string [" << token.literal << "]"; case Token::number : return out << "number [" << token.value << "]"; case Token::defaultKeyword : return out << "default"; case Token::functionKeyword : return out << "function"; case Token::segmentKeyword : return out << "segment"; case Token::sqrtKeyword : return out << "sqrt"; case Token::sinKeyword : return out << "sin"; case Token::cosKeyword : return out << "cos"; case Token::piKeyword : return out << "pi"; case Token::equals : return out << "'='"; case Token::openingParen : return out << "'('"; case Token::closingParen : return out << "')'"; case Token::openingBracket : return out << "'['"; case Token::closingBracket : return out << "']'"; case Token::normDelim : return out << "'|'"; case Token::additiveOperator : return out << "addop [" << token.symbol << "]"; case Token::multiplicativeOperator : return out << "mulop [" << token.symbol << "]"; case Token::powerOperator : return out << "powerop" << std::endl; case Token::endOfLine : return out << "eol"; default : return out << "invalid [" << token.type << "]"; } } } // namespace dgf } // namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/projection.hh000066400000000000000000000166021511655130300246130ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_PROJECTIONBLOCK_HH #define DUNE_DGF_PROJECTIONBLOCK_HH #include #include #include namespace Dune { namespace dgf { // ProjectionBlock // --------------- class ProjectionBlock : public BasicBlock { struct Token { friend std::ostream &operator<< ( std::ostream &, const Token & ); enum Type { string, number, defaultKeyword, functionKeyword, segmentKeyword, sqrtKeyword, sinKeyword, cosKeyword, piKeyword, comma, equals, openingParen, closingParen, openingBracket, closingBracket, normDelim, additiveOperator, multiplicativeOperator, powerOperator, endOfLine }; Type type; char symbol; std::string literal; double value; void setSymbol ( const Type &t, char c ) { type = t; symbol = c; } }; friend std::ostream &operator<< ( std::ostream &, const Token & ); public: struct Expression; typedef std::shared_ptr< Expression > ExpressionPointer; typedef std::pair< ExpressionPointer, std::string > ExpressionPair ; private: template< int dimworld > class BoundaryProjection; void registerProjectionFactory( const int dimworld ); static const char* blockId() { return "Projection"; } public: ProjectionBlock ( std::istream &in, int dimworld ); template< int dimworld > const DuneBoundaryProjection< dimworld > *defaultProjection () const { if( defaultFunction_.first ) { return new BoundaryProjection< dimworld >( defaultFunction_ ); } else return 0; } size_t numBoundaryProjections () const { return boundaryFunctions_.size(); } const std::vector< unsigned int > &boundaryFace ( const size_t i ) const { assert( i < numBoundaryProjections() ); return boundaryFunctions_[ i ].first; } template< int dimworld > const DuneBoundaryProjection< dimworld > *boundaryProjection ( const size_t i ) const { assert( i < numBoundaryProjections() ); return new BoundaryProjection< dimworld >( boundaryFunctions_[ i ].second ); } ExpressionPointer function ( const std::string &name ) const { const FunctionMap::const_iterator it = functions_.find( name ); return (it != functions_.end() ? it->second.first : 0); } ExpressionPair lastFunctionInserted () const { assert( ! functions_.empty() ); return functions_.begin()->second; } static ProjectionBlock::ExpressionPair createExpression( const std::string& funcexpr, const int dimworld ) { std::stringstream str; str << blockId() << std::endl; str << funcexpr << std::endl; str << "#" << std::endl; ProjectionBlock problock( str, dimworld ); return problock.lastFunctionInserted(); } private: void parseFunction ( const std::string& exprname ); ExpressionPointer parseBasicExpression ( const std::string &variableName ); ExpressionPointer parsePostfixExpression ( const std::string &variableName ); ExpressionPointer parseUnaryExpression ( const std::string &variableName ); ExpressionPointer parsePowerExpression ( const std::string &variableName ); ExpressionPointer parseMultiplicativeExpression ( const std::string &variableName ); ExpressionPointer parseExpression ( const std::string &variableName ); void parseDefault (); void parseSegment (); void matchToken ( const Token::Type &type, const std::string &message ); void nextToken (); static char lowerCase ( char c ) { return ((c >= 'A') && (c <= 'Z') ? c + ('a' - 'A') : c); } protected: typedef std::map< std::string, ExpressionPair > FunctionMap; typedef std::pair< std::vector< unsigned int >, ExpressionPair > BoundaryFunction; using BasicBlock::line; Token token; FunctionMap functions_; ExpressionPair defaultFunction_; std::vector< BoundaryFunction > boundaryFunctions_; }; std::ostream &operator<< ( std::ostream &out, const ProjectionBlock::Token &token ); struct ProjectionBlock::Expression { typedef std::vector< double > Vector; virtual ~Expression () {} virtual void evaluate ( const Vector &argument, Vector &result ) const = 0; }; template< int dimworld > class ProjectionBlock::BoundaryProjection : public DuneBoundaryProjection< dimworld > { typedef DuneBoundaryProjection< dimworld > Base; typedef BoundaryProjection < dimworld > This; typedef typename Base :: ObjectStreamType ObjectStreamType; public: typedef typename Base::CoordinateType CoordinateType; BoundaryProjection ( const ExpressionPair& exprpair ) : expression_( exprpair.first ), expressionName_( exprpair.second ) {} BoundaryProjection( ObjectStreamType& buffer ) { int size = 0; buffer.read( (char *) &size, sizeof(int) ); expressionName_.resize( size ); buffer.read( (char *) expressionName_.c_str(), size ); expression_ = ProjectionBlock::createExpression( expressionName_, dimworld ).first; } virtual CoordinateType operator() ( const CoordinateType &global ) const override { std::vector< double > x( dimworld ); for( int i = 0; i < dimworld; ++i ) x[ i ] = global[ i ]; std::vector< double > y; expression_->evaluate( x, y ); CoordinateType result; for( int i = 0; i < dimworld; ++i ) result[ i ] = y[ i ]; return result; } // backup name of expression that should allow to recreate this class virtual void backup( std::stringstream& buffer ) const override { buffer.write( (const char *) &key(), sizeof( int )); int size = expressionName_.size(); buffer.write( (const char *) &size, sizeof(int) ); buffer.write( expressionName_.c_str(), size ); } static void registerFactory() { if( key() < 0 ) { key() = Base::template registerFactory< This >(); } } protected: static int& key () { static int k = -1; return k; } ExpressionPointer expression_; std::string expressionName_; }; inline void ProjectionBlock::registerProjectionFactory( const int dimworld ) { if( dimworld == 3 ) { BoundaryProjection< 3 > :: registerFactory(); } else if ( dimworld == 2 ) { BoundaryProjection< 2 > :: registerFactory(); } else if ( dimworld == 1 ) { BoundaryProjection< 1 > :: registerFactory(); } else { DUNE_THROW(NotImplemented,"ProjectionBlock::registerProjectionFactory not implemented for dimworld = " << dimworld); } } } } #endif // #ifndef DUNE_DGF_PROJECTIONBLOCK_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/simplex.cc000066400000000000000000000171771511655130300241160ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // SimplexBlock // ------------ SimplexBlock :: SimplexBlock ( std :: istream &in, int pnofvtx, int pvtxoffset, int &pdimgrid ) : BasicBlock( in, "Simplex" ), nofvtx( pnofvtx ), vtxoffset( pvtxoffset ), dimgrid( pdimgrid ), goodline( true ), nofparams( 0 ) { if( !isactive() ) return; if( findtoken( "parameters" ) ) { int x = 0; if( getnextentry( x ) ) { if( x > 0 ) nofparams = x; } if( x <= 0 ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Key 'parameters' found with no or non-positive value." ); } } if( dimgrid < 0 ) dimgrid = getDimGrid(); pdimgrid = dimgrid; } int SimplexBlock :: getDimGrid () { reset(); while( getnextline() ) { int count = 0; double x; while( getnextentry( x ) ) ++count; if( count > nofparams ) return (count - nofparams) - 1; } return 0; } int SimplexBlock :: get ( std :: vector< std :: vector< unsigned int > > &simplices, std :: vector< std :: vector< double > > ¶ms, int &nofp) { nofp = nofparams; reset(); std :: vector< unsigned int > simplex( dimgrid+1 ); std :: vector< double > param( nofparams ); int nofsimpl = 0; for( ; next( simplex, param ); ++nofsimpl ) { simplices.push_back( simplex ); /* for( size_t j = 0; j < simplex.size(); ++j ) simplices[ nofsimpl ][ j ] = simplex[ j ]; */ if( nofparams > 0 ) params.push_back( param ); } return nofsimpl; } bool SimplexBlock :: next ( std :: vector< unsigned int > &simplex, std :: vector< double > ¶m ) { assert( ok() ); if( !getnextline() ) return (goodline = false); for( std :: size_t n = 0; n < simplex.size(); ++n ) { int idx; if( !getnextentry( idx ) ) { if( n > 0 ) { DUNE_THROW ( DGFException, "Error in " << *this << ": " << "Wrong number of vertex indices " << "(got " << idx << ", expected " << simplex.size() << ")" ); } else return next( simplex, param ); } if( (vtxoffset > idx) || (idx >= int(nofvtx + vtxoffset)) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Invalid vertex index " << "(" << idx << " not in [" << vtxoffset << ", " << (nofvtx + vtxoffset) << "[)" ); } simplex[ n ] = idx - vtxoffset; } std :: size_t np = 0; double x; for( ; getnextentry( x ); ++np ) { if( np < param.size() ) param[ np ] = x; } if( np != param.size() ) { DUNE_THROW ( DGFException, "Error in " << *this << ": " << "Wrong number of simplex parameters " << "(got " << np << ", expected " << param.size() << ")" ); } return (goodline = true); } int SimplexBlock :: cube2simplex ( std :: vector< std :: vector< double > > &vtx, std :: vector< std :: vector< unsigned int > > &elements, std :: vector< std :: vector< double > > ¶ms ) { static int offset3[6][4][3] = {{{0,0,0},{1,1,1},{1,0,0},{1,1,0}}, {{0,0,0},{1,1,1},{1,0,1},{1,0,0}}, {{0,0,0},{1,1,1},{0,0,1},{1,0,1}}, {{0,0,0},{1,1,1},{1,1,0},{0,1,0}}, {{0,0,0},{1,1,1},{0,1,0},{0,1,1}}, {{0,0,0},{1,1,1},{0,1,1},{0,0,1}} }; static int offset2[2][3][2] = {{{0,0},{1,0},{0,1}}, {{1,1},{0,1},{1,0}}}; if (elements.empty()) return 0; const int dimworld = vtx[ 0 ].size(); int dimgrid = 0; for( size_t n = elements[ 0 ].size(); n > 1; ++dimgrid, n /= 2 ) ; if( size_t( 1 << dimgrid ) != elements[ 0 ].size() ) DUNE_THROW( DGFException, "cube2simplex: all elements must be cubes." ); dverb << "generating simplices..."; dverb.flush(); if( dimgrid == 1 ) return elements.size(); std::vector< std::vector< unsigned int > > cubes; std::vector< std::vector< double > > cubeparams; elements.swap( cubes ); params.swap( cubeparams ); if( dimgrid == 3 ) { elements.resize( 6*cubes.size() ); if( cubeparams.size() > 0 ) params.resize( 6*cubes.size() ); for( size_t countsimpl = 0; countsimpl < elements.size(); ++countsimpl ) elements[ countsimpl ].resize( 4 ); for( size_t c = 0; c < cubes.size(); ++c ) { for( int tetra = 0; tetra < 6; ++tetra ) { for( int v = 0; v < 4; ++v ) { elements[ c*6+tetra ][ v ] = cubes[ c ][ offset3[ tetra ][ v ][ 0 ] +2*offset3[ tetra ][ v ][ 1 ] +4*offset3[ tetra ][ v ][ 2 ] ]; } if( cubeparams.size() > 0 ) params[ c*6+tetra ] = cubeparams[ c ]; } } } else if( dimgrid == 2 ) { elements.resize( 2*cubes.size() ); if( cubeparams.size() > 0 ) params.resize( 2*cubes.size() ); for( size_t countsimpl = 0; countsimpl < elements.size(); ++countsimpl ) elements[ countsimpl ].resize( 3 ); for( size_t c = 0; c < cubes.size(); ++c ) { int diag = 0; double mind = 0; for( int d = 0; d < 2; ++d ) { // let's cut the longer diagonal double diaglen = 0; for( int i = 0; i < dimworld; ++i ) { const double dist = vtx[ cubes[ c ][ d ] ][ i ] - vtx[ cubes[ c ][ 3-d ] ][ i ]; diaglen += dist*dist; } if( diaglen < mind ) { mind = diaglen; diag = d; } } if( diag == 0 ) { int tmp0 = cubes[ c ][ 0 ]; cubes[ c ][ 0 ] = cubes[ c ][ 1 ]; cubes[ c ][ 1 ] = cubes[ c ][ 3 ]; cubes[ c ][ 3 ] = cubes[ c ][ 2 ]; cubes[ c ][ 2 ] = tmp0; } for( int triangle = 0; triangle < 2; ++triangle ) { for( int v = 0; v < 3; ++v ) { elements[ c*2+triangle ][ v ] = cubes[ c ][ offset2[ triangle ][ v ][ 0 ] + 2*offset2[ triangle ][ v ][ 1 ] ]; } if( cubeparams.size() > 0 ) params[ c*2+triangle ] = cubeparams[ c ]; } } } return elements.size(); } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/simplex.hh000066400000000000000000000032761511655130300241230ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_SIMPLEXBLOCK_HH #define DUNE_DGF_SIMPLEXBLOCK_HH #include #include #include namespace Dune { namespace dgf { // SimplexBlock // ------------ class SimplexBlock : public BasicBlock { unsigned int nofvtx; int vtxoffset; int dimgrid; bool goodline; // active line describes a vertex int nofparams; // nof parameters public: SimplexBlock ( std :: istream &in, int pnofvtx, int pvtxoffset, int &pdimgrid ); int get ( std :: vector< std :: vector< unsigned int > > &simplex, std :: vector< std :: vector< double > > ¶ms, int &nofp ); // cubes -> simplex static int cube2simplex ( std :: vector< std :: vector< double > > &vtx, std :: vector< std :: vector< unsigned int > > &elements, std :: vector< std :: vector< double > > ¶ms ); // some information bool ok () { return goodline; } int nofsimplex () { return noflines(); } private: // get the dimension of the grid int getDimGrid (); // get next simplex bool next ( std :: vector< unsigned int > &simplex, std :: vector< double > ¶m ); }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/simplexgeneration.cc000066400000000000000000000032471511655130300261630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // SimplexGenerationBlock // ---------------------- SimplexGenerationBlock :: SimplexGenerationBlock ( std :: istream &in ) : BasicBlock(in,"Simplexgenerator"), area_(-1), angle_(-1), display_(false), haspath_(false), filetype_(), parameter_(), dumpfilename_(), hasfile_(false), dimension_(-1) { double x; bool b; int i; std::string p; if (findtoken("max-area")) if (getnextentry(x)) area_=x; if (findtoken("min-angle")) if (getnextentry(x)) angle_=x; if (findtoken("display")) if (getnextentry(b)) display_=b; if (findtoken("path")) if (getnextentry(p)) { path_=p; haspath_=true; } if (findtoken("file")) { if (getnextentry(p)) { filename_=p; hasfile_=true; } if (getnextentry(p)) { filetype_=p; } if (findtoken("dimension")) if (getnextentry(i)) { dimension_=i; } gettokenparam("parameter",parameter_); } if (findtoken("dumpfilename")) if (getnextentry(p)) { dumpfilename_=p; } } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/simplexgeneration.hh000066400000000000000000000032661511655130300261760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_SIMPLEXGENERATIONBLOCK_HH #define DUNE_DGF_SIMPLEXGENERATIONBLOCK_HH #include #include namespace Dune { namespace dgf { class SimplexGenerationBlock : public BasicBlock { double area_; double angle_; bool display_; std::string path_; bool haspath_; std::string filename_; std::string filetype_; std::string parameter_; std::string dumpfilename_; bool hasfile_; int dimension_; public: SimplexGenerationBlock ( std :: istream &in ); double maxArea () { return area_; } double minAngle () { return angle_; } bool display () { return display_; } bool haspath () { return haspath_; } std :: string path () { return path_; } bool hasfile () { return hasfile_; } std :: string filename () { return filename_; } std :: string filetype () { return filetype_; } int dimension () { return dimension_; } std :: string parameter () { return parameter_; } const std::string dumpFileName ( ) const { return dumpfilename_; } }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/vertex.cc000066400000000000000000000075431511655130300237460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include namespace Dune { namespace dgf { // VertexBlock // ----------- VertexBlock :: VertexBlock ( std :: istream &in, int &pdimworld ) : BasicBlock( in, "Vertex" ), dimvertex( -1 ), dimworld( pdimworld ), goodline( true ), vtxoffset( 0 ), nofParam( 0 ) { if (!isactive()) return; if( findtoken( "firstindex" ) ) { int x; if( getnextentry( x ) ) vtxoffset=x; } if( findtoken( "parameters" ) ) { int x; if( getnextentry( x ) ) nofParam=x; } dimvertex = getDimWorld(); if( pdimworld < 0 ) pdimworld = dimvertex; dimworld = pdimworld; if( dimworld < dimvertex ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Vertex dimension greater than world dimension." ); } if( dimworld > dimvertex ) { dwarn << id() << " block: Embedding " << dimvertex << "-dimensional vertices into " << dimworld << "-dimensional space." << std::endl; } } int VertexBlock :: get ( std :: vector< std :: vector< double > > &points, std :: vector< std :: vector< double > > ¶ms, int &nofp ) { nofp = nofParam; reset(); std::vector< double > point( dimworld ); std::vector< double > param( nofParam ); while( next( point, param ) ) { points.push_back( point ); if( nofParam > 0 ) params.push_back( param ); } return points.size(); } int VertexBlock :: getDimWorld () { if( findtoken( "dimension" ) ) { int dimworldFromVertex; if( !getnextentry( dimworldFromVertex ) || (dimworldFromVertex <= 0) ) { DUNE_THROW( DGFException, "Error in " << *this << ": " << "Invalid value given for 'dimension'." ); } return dimworldFromVertex; } reset(); while( getnextline() ) { int dimworldFromVertex = -nofParam; double x; while( getnextentry( x ) ) ++dimworldFromVertex; if( dimworldFromVertex > 0 ) return dimworldFromVertex; } DUNE_THROW( DGFException, "Error in " << *this << ": " << "Unable to determine dimension of vertices." ); } bool VertexBlock :: next ( std :: vector< double > &point, std :: vector< double > ¶m ) { assert( ok() ); if( !getnextline() ) return (goodline = false); int n = 0; double x; for( ; getnextentry( x ); ++n ) { if( n < dimvertex ) point[ n ] = x; else if( n-dimvertex < nofParam ) param[ n-dimvertex ] = x; } if( n == 0 ) return next( point, param ); else if( n != dimvertex + nofParam ) { DUNE_THROW ( DGFException, "Error in " << *this << ": " << "Wrong number of coordinates and parameters " << "(got " << n << ", expected " << (dimvertex + nofParam) << ")" ); } for( int i = dimvertex; i < dimworld; ++i ) point[ i ] = double( 0 ); return (goodline = true); } } // end namespace dgf } // end namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/blocks/vertex.hh000066400000000000000000000027001511655130300237460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_VERTEXBLOCK_HH #define DUNE_DGF_VERTEXBLOCK_HH #include #include #include namespace Dune { namespace dgf { class VertexBlock : public BasicBlock { int dimvertex; // the dimension of the vertices (determined from DGF file) int dimworld; // the dimension of the world (either dimvertex or given by user) bool goodline; // active line describes a vertex int vtxoffset; int nofParam; public: // initialize vertex block VertexBlock ( std :: istream &in, int &pdimworld ); int get ( std :: vector< std :: vector< double > > &vtx, std :: vector< std :: vector< double > > ¶m, int &nofp ); // some information bool ok () const { return goodline; } int offset () const { return vtxoffset; } private: // get dimworld int getDimWorld (); // get next vertex bool next ( std :: vector< double > &point, std :: vector< double > ¶m ); }; } // end namespace dgf } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfexception.hh000066400000000000000000000010041511655130300236270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_DGFEXCEPTION_HH #define DUNE_GRID_DGFEXCEPTION_HH #include namespace Dune { //! \brief exception class for IO errors in the DGF parser class DGFException : public IOError {}; } #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfgeogrid.hh000066400000000000000000000155411511655130300232640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGFGEOGRID_HH #define DUNE_DGFGEOGRID_HH #include #include #include #include #include #include #include namespace Dune { /************************************************************************ * Warning: * Reading DGF files directly into a GeometryGrid is a dirty hack for * two reasons: * 1) The host grid and coordinate function are never deleted (dangling * pointers). * 2) The coordinate function has to provide a default constructor ************************************************************************/ // External Forward Declarations // ----------------------------- template< class GridImp, class IntersectionImp > class Intersection; // DGFCoordFunction // ---------------- template< int dimD, int dimR > class DGFCoordFunction : public AnalyticalCoordFunction< double, dimD, dimR, DGFCoordFunction< dimD, dimR > > { typedef DGFCoordFunction< dimD, dimR > This; typedef AnalyticalCoordFunction< double, dimD, dimR, This > Base; public: typedef typename Base::DomainVector DomainVector; typedef typename Base::RangeVector RangeVector; typedef dgf::ProjectionBlock::Expression Expression; DGFCoordFunction ( const Expression *expression ) : expression_( expression ) {} void evaluate ( const DomainVector &x, RangeVector &y ) const { std::vector< double > vx( dimD ); std::vector< double > vy; for( int i = 0; i < dimD; ++i ) vx[ i ] = x[ i ]; expression_->evaluate( vx, vy ); assert( vy.size() == size_t( dimR ) ); for( int i = 0; i < dimR; ++i ) y[ i ] = vy[ i ]; } private: const Expression *expression_; }; // DGFCoordFunctionFactory // ----------------------- template< class HostGrid, class CoordFunction, bool discrete = GeoGrid::isDiscreteCoordFunctionInterface< typename CoordFunction::Interface >::value > struct DGFCoordFunctionFactory; template< class HostGrid, class CoordFunction > struct DGFCoordFunctionFactory< HostGrid, CoordFunction, false > { static CoordFunction *create ( std::istream &, const HostGrid & ) { return new CoordFunction; } }; template< class HostGrid, class CoordFunction > struct DGFCoordFunctionFactory< HostGrid, CoordFunction, true > { static CoordFunction *create ( std::istream &, const HostGrid &hostGrid ) { return new CoordFunction( hostGrid ); } }; template< class HostGrid, int dimD, int dimR > struct DGFCoordFunctionFactory< HostGrid, DGFCoordFunction< dimD, dimR >, false > { typedef DGFCoordFunction< dimD, dimR > CoordFunction; static CoordFunction *create ( std::istream &input, const HostGrid &hostGrid ) { dgf::ProjectionBlock projectionBlock( input, dimR ); const typename CoordFunction::Expression *expression = projectionBlock.function( "coordfunction" ); if( expression == 0 ) DUNE_THROW( DGFException, "no coordfunction specified in DGF file." ); return new CoordFunction( expression ); } }; // DGFGridFactory for GeometryGrid // ------------------------------- template< class HostGrid, class CoordFunction, class Allocator > struct DGFGridFactory< GeometryGrid< HostGrid, CoordFunction, Allocator > > { typedef GeometryGrid< HostGrid, CoordFunction, Allocator > Grid; const static int dimension = Grid::dimension; typedef MPIHelper::MPICommunicator MPICommunicator; typedef typename Grid::template Codim<0>::Entity Element; typedef typename Grid::template Codim::Entity Vertex; typedef DGFCoordFunctionFactory< HostGrid, CoordFunction > CoordFunctionFactory; explicit DGFGridFactory ( std::istream &input, MPICommunicator comm = MPIHelper::getCommunicator() ) : dgfHostFactory_( input, comm ), grid_( 0 ) { auto hostGrid = std::shared_ptr(dgfHostFactory_.grid()); assert( hostGrid != 0 ); auto coordFunction = std::shared_ptr(CoordFunctionFactory::create( input, *hostGrid )); grid_ = new Grid( hostGrid, coordFunction ); } explicit DGFGridFactory ( const std::string &filename, MPICommunicator comm = MPIHelper::getCommunicator() ) : dgfHostFactory_( filename, comm ), grid_( 0 ) { auto hostGrid = std::shared_ptr(dgfHostFactory_.grid()); assert( hostGrid != 0 ); std::ifstream input( filename.c_str() ); auto coordFunction = std::shared_ptr(CoordFunctionFactory::create( input, *hostGrid )); grid_ = new Grid( hostGrid, coordFunction ); } Grid *grid () const { return grid_; } template< class Intersection > bool wasInserted ( const Intersection &intersection ) const { return dgfHostFactory_.wasInserted( HostGridAccess< Grid >::hostIntersection( intersection ) ); } template< class Intersection > int boundaryId ( const Intersection &intersection ) const { return dgfHostFactory_.boundaryId( HostGridAccess< Grid >::hostIntersection( intersection ) ); } template< int codim > int numParameters () const { return dgfHostFactory_.template numParameters< codim >(); } // return true if boundary parameters found bool haveBoundaryParameters () const { return dgfHostFactory_.haveBoundaryParameters(); } template< class GG, class II > const typename DGFBoundaryParameter::type & boundaryParameter ( const Dune::Intersection< GG, II > & intersection ) const { return dgfHostFactory_.boundaryParameter( HostGridAccess< Grid >::hostIntersection( intersection ) ); } template< class Entity > std::vector< double > ¶meter ( const Entity &entity ) { return dgfHostFactory_.parameter( HostGridAccess< Grid >::hostEntity( entity ) ); } private: DGFGridFactory< HostGrid > dgfHostFactory_; Grid *grid_; }; // DGFGridInfo for GeometryGrid // ---------------------------- template< class HostGrid, class CoordFunction, class Allocator > struct DGFGridInfo< GeometryGrid< HostGrid, CoordFunction, Allocator > > { static int refineStepsForHalf () { return DGFGridInfo< HostGrid >::refineStepsForHalf(); } static double refineWeight () { return -1.0; } }; } #endif // #ifndef DUNE_DGFGEOGRID_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfgridfactory.hh000066400000000000000000000123101511655130300241500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_GRIDFACTORY_HH #define DUNE_DGF_GRIDFACTORY_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { // External Forward Declarations // ----------------------------- template < class GridImp, class IntersectionImp > class Intersection; // DGFGridFactory // -------------- template < class G > struct DGFGridFactory { typedef G Grid; const static int dimension = Grid::dimension; typedef MPIHelper::MPICommunicator MPICommunicatorType; private: typedef typename Grid::template Codim< 0 >::Entity Element; typedef typename Grid::template Codim< dimension >::Entity Vertex; public: explicit DGFGridFactory ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : macroGrid_( filename.c_str(), comm ) { grid_ = macroGrid_.template createGrid< Grid >(); if( macroGrid_.nofelparams > 0 ) { const size_t nofElements = macroGrid_.elements.size(); for( size_t i = 0; i < nofElements; ++i ) { std::vector< double > coord; DomainType p(0); const size_t nofCorners = macroGrid_.elements[i].size(); for (size_t k=0; k 0 ) { const size_t nofVertices = macroGrid_.vtx.size(); for( size_t i = 0; i < nofVertices; ++i ) { std::vector< double > coord; DomainType p; for( int k = 0; k < DomainType::dimension; ++k ) p[ k ] = macroGrid_.vtx[i][k]; vtxInsertOrder_.insert( std::make_pair( p, i ) ); } } } Grid *grid() { return grid_; } template bool wasInserted(const Intersection &intersection) const { return intersection.boundary(); } template int boundaryId(const Intersection &intersection) const { return (intersection.boundary()) ? int(intersection.indexInInside()+1) : int(0); } template< int codim > int numParameters () const { if( codim == 0 ) return macroGrid_.nofelparams; else if( codim == dimension ) return macroGrid_.nofvtxparams; else return 0; } template < class Entity > int numParameters ( const Entity & ) const { return numParameters< Entity::codimension >(); } std::vector& parameter(const Element &element) { const typename Element::Geometry &geo = element.geometry(); DomainType coord( geo.corner( 0 ) ); for( int i = 1; i < geo.corners(); ++i ) coord += geo.corner( i ); coord /= double( geo.corners() ); InsertOrderIterator it = elInsertOrder_.find( coord ); if( it != elInsertOrder_.end() ) return macroGrid_.elParams[ it->second ]; assert(0); return emptyParam; } std::vector& parameter(const Vertex &vertex) { const typename Vertex::Geometry &geo = vertex.geometry(); DomainType coord( geo.corner( 0 ) ); InsertOrderIterator it = vtxInsertOrder_.find( coord ); if( it != vtxInsertOrder_.end() ) return macroGrid_.vtxParams[ it->second ]; return emptyParam; } // return true if boundary parameters found bool haveBoundaryParameters () const { return false; } template< class GG, class II > const typename DGFBoundaryParameter::type & boundaryParameter ( const Intersection< GG, II > & /*intersection*/ ) const { return DGFBoundaryParameter::defaultValue(); } private: typedef FieldVector DomainType; struct Compare { bool operator() ( const DomainType &a, const DomainType &b ) const { // returns true, if a < b; c[i] < -eps; const DomainType c = a - b; const double eps = 1e-8; for( int i = 0; i < DomainType::dimension; ++i ) { if( c[ i ] <= -eps ) return true; if( c[ i ] >= eps ) return false; } return false; } }; typedef std::map< DomainType, size_t, Compare > InsertOrderMap; typedef typename InsertOrderMap::const_iterator InsertOrderIterator; MacroGrid macroGrid_; Grid *grid_; InsertOrderMap elInsertOrder_; InsertOrderMap vtxInsertOrder_; std::vector emptyParam; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfidentitygrid.hh000066400000000000000000000056731511655130300243500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGFPARSER_DGFIDENTITYGRID_HH #define DUNE_DGFPARSER_DGFIDENTITYGRID_HH #include #include #include #include namespace Dune { // DGFGridFactory for IdentityGrid // ------------------------------- template< class HostGrid > struct DGFGridFactory< IdentityGrid< HostGrid > > { typedef IdentityGrid< HostGrid > Grid; const static int dimension = Grid::dimension; typedef MPIHelper::MPICommunicator MPICommunicator; typedef typename Grid::template Codim<0>::Entity Element; typedef typename Grid::template Codim::Entity Vertex; explicit DGFGridFactory ( std::istream &input, MPICommunicator comm = MPIHelper::getCommunicator() ) : dgfHostFactory_( input, comm ), grid_( 0 ) { HostGrid *hostGrid = dgfHostFactory_.grid(); assert( hostGrid != 0 ); grid_ = new Grid( *hostGrid ); } explicit DGFGridFactory ( const std::string &filename, MPICommunicator comm = MPIHelper::getCommunicator() ) : dgfHostFactory_( filename, comm ), grid_( 0 ) { HostGrid *hostGrid = dgfHostFactory_.grid(); assert( hostGrid != 0 ); std::ifstream input( filename.c_str() ); grid_ = new Grid( *hostGrid ); } Grid *grid () const { return grid_; } template< class Intersection > bool wasInserted ( const Intersection &intersection ) const { return dgfHostFactory_.wasInserted( HostGridAccess< Grid >::hostIntersection( intersection ) ); } template< class Intersection > int boundaryId ( const Intersection &intersection ) const { return dgfHostFactory_.boundaryId( HostGridAccess< Grid >::hostIntersection( intersection ) ); } template< int codim > int numParameters () const { return dgfHostFactory_.template numParameters< codim >(); } template< class Entity > std::vector< double > ¶meter ( const Entity &entity ) { return dgfHostFactory_.parameter( HostGridAccess< Grid >::hostEntity( entity ) ); } private: DGFGridFactory< HostGrid > dgfHostFactory_; Grid *grid_; }; // DGFGridInfo for IdGrid // ---------------------- template< class HostGrid > struct DGFGridInfo< IdentityGrid< HostGrid > > { static int refineStepsForHalf () { return DGFGridInfo< HostGrid >::refineStepsForHalf(); } static double refineWeight () { return DGFGridInfo< HostGrid >::refineWeight(); } }; } #endif // #ifndef DUNE_DGFPARSER_DGFIDENTITYGRID_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfoned.hh000066400000000000000000000136571511655130300225770ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_FILE_IO_DGFPARSER_DGFONED_HH #define DUNE_GRID_FILE_IO_DGFPARSER_DGFONED_HH //- C++ includes #include #include #include #include #include //- dune-common includes #include //- dune-grid includes #include #include //- local includes #include "dgfparser.hh" namespace { // helper method used below double getfirst ( std::vector< double > v ) { return v[ 0 ]; } } // end anonymous namespace namespace Dune { // DGFGridInfo // ----------- template< > struct DGFGridInfo< OneDGrid > { static int refineStepsForHalf () { return 1; } static double refineWeight () { return 0.5; } }; // DGFGridFactory< OneDGrid > // -------------------------- template< > struct DGFGridFactory< OneDGrid > { /** \brief grid type */ typedef OneDGrid Grid; /** \brief grid dimension */ const static int dimension = Grid::dimension; /** \brief MPI communicator type */ typedef MPIHelper::MPICommunicator MPICommunicatorType; /** \brief constructor taking istream */ explicit DGFGridFactory ( std::istream &input, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : grid_( 0 ), emptyParameters_( 0 ) { generate( input, comm ); } /** \brief constructor taking filename */ explicit DGFGridFactory ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : grid_( 0 ), emptyParameters_( 0 ) { std::ifstream input( filename.c_str() ); generate( input, comm ); } /** \brief get grid */ Grid *grid () const { return grid_; } /** \brief always returns false */ template< class GG, class II > bool wasInserted ( const Dune::Intersection< GG, II > &intersection ) const { return false; } template< class GG, class II > int boundaryId ( const Dune::Intersection< GG, II > &intersection ) const { // OneDGrid returns boundary segment index; // we return the index as the method boundaryId is deprecated return intersection.boundarySegmentIndex(); } /** \brief OneDGrid does not support parameters, returns 0 */ template< class Entity > int numParameters ( const Entity & ) const { return 0; } /** \brief OneDGrid does not support parameters, returns 0 */ template< int codim > int numParameters () const { return 0; } template< class Entity > std::vector< double >& parameter ( const Entity &entity ) { return parameter< Entity::codimension >( entity ); } /** \brief return empty vector */ template< int codim > std::vector< double > ¶meter ( [[maybe_unused]] const typename Grid::Codim< codim >::Entity &element ) { return emptyParameters_; } /** \brief OneDGrid does not support boundary parameters */ bool haveBoundaryParameters () const { return false; } /** \brief return invalid default value */ template< class GG, class II > const DGFBoundaryParameter::type &boundaryParameter ( [[maybe_unused]] const Dune::Intersection< GG, II > &intersection ) const { return DGFBoundaryParameter::defaultValue(); } private: // generate grid void generate ( std::istream &input, MPICommunicatorType comm ); Grid *grid_; std::vector< double > emptyParameters_; }; // Implementation of DGFGridFactory< OneDGrid > // -------------------------------------------- inline void DGFGridFactory< OneDGrid >::generate ( std::istream &input, [[maybe_unused]] MPICommunicatorType comm ) { // try to open interval block dgf::IntervalBlock intervalBlock( input ); // try to open vertex block int dimensionworld = Grid::dimensionworld; dgf::VertexBlock vertexBlock( input, dimensionworld ); // check at least one block is active if( !( vertexBlock.isactive() || intervalBlock.isactive() )) DUNE_THROW( DGFException, "No readable block found" ); std::vector< std::vector< double > > vertices; // read vertices first if( vertexBlock.isactive() ) { int nparameter = 0; std::vector< std::vector< double > > parameter; vertexBlock.get( vertices, parameter, nparameter ); if( nparameter > 0 ) std::cerr << "Warning: vertex parameters will be ignored" << std::endl; } // get vertices from interval block if ( intervalBlock.isactive() ) { if( intervalBlock.dimw() != dimensionworld ) { DUNE_THROW( DGFException, "Error: wrong coordinate dimension in interval block \ (got " << intervalBlock.dimw() << ", expected " << dimensionworld << ")" ); } int nintervals = intervalBlock.numIntervals(); for( int i = 0; i < nintervals; ++i ) intervalBlock.getVtx( i, vertices ); } // copy to vector of doubles std::vector< double > vtx( vertices.size() ); transform( vertices.begin(), vertices.end(), vtx.begin(), getfirst ); // remove duplicates std::sort( vtx.begin(), vtx.end() ); std::vector< double >::iterator it = std::unique( vtx.begin(), vtx.end() ); vtx.erase( it, vtx.end() ); if( vertices.size() != vtx.size() ) std::cerr << "Warning: removed duplicate vertices" << std::endl; // create grid grid_ = new OneDGrid( vtx ); } } // end namespace Dune #endif // #ifndef DUNE_GRID_FILE_IO_DGFPARSER_DGFONED_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfparser.cc000066400000000000000000001013051511655130300231200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include // HAVE_MKSTEMP #include #if HAVE_MKSTEMP #include #endif #include #include #include #include namespace Dune { static const std::string dgfid( "DGF" ); class DGFPrintInfo { std::ofstream out; public: DGFPrintInfo( const std :: string &name ) : out( (name+".log").c_str() ) { // out << "Grid generated from file " << name << std::endl; out << "DGF parser started" << std::endl; } void finish () { out << "Successful" << std::endl; } template< class Block > void block( const Block& printBlock ) { out << "Using " << printBlock.id() << " block" << std::endl; } void print( const std :: string &message ) { out << message << std::endl; } void step1(int dimw,int nofvtx,int nofel) { out << "Step 1 finished: " << std::endl; out << " " << dimw << "d" << std::endl; out << " " << nofvtx << " vertices" << std::endl; out << " " << nofel << " elements" << std::endl; } void step2(int bndseg,int totalbndseg, int bnddomain,int defsegs,int remaining) { out << "Step 2 finished: " << std::endl; out << " " << bndseg << " bnd-segs read in BoundarySegment block" << std::endl; out << " " << totalbndseg << " bnd-segs in grid" << std::endl; out << " " << bnddomain << " bnd-segs in a boundary domain" << std::endl; out << " " << defsegs << " bnd-seg assigned default value" << std::endl; out << " " << remaining << " bnd-segs have not been assigned an id!" << std::endl; } void cube2simplex(DuneGridFormatParser::element_t el) { if (el == DuneGridFormatParser::General) out << "Simplex block found, thus converting " << "cube grid to simplex grid" << std::endl; else out << "Element type should be simplex, thus converting " << "cube grid to simplex grid" << std::endl; } void automatic() { out << "Automatic grid generation" << std::endl; } }; // DuneGridFormatParser // -------------------- DuneGridFormatParser :: DuneGridFormatParser ( int rank, int size ) : dimw( -1 ), dimgrid( -1 ), vtx(0), nofvtx(0), vtxoffset(0), minVertexDistance(1e-12), elements(0) , nofelements(0), bound(0) , nofbound(0), facemap(), haveBndParameters( false ), element(General), simplexgrid(false), cube2simplex(false), nofvtxparams(0), nofelparams(0), vtxParams(), elParams(), info(0), rank_(rank), size_(size) { if( (rank_ < 0) || (rank_ >= size_) ) DUNE_THROW( DGFException, "Invalid rank: " << rank << " (not in [ 0, " << size_ << " [)." ); } // Output to Tetgen/Triangle poly-file void DuneGridFormatParser ::writeTetgenPoly ( const std::string &prefixname, std::string &extension, std::string ¶ms ) { std::string name = prefixname; params = ""; if( dimw == 2 ) { if (facemap.size()+elements.size()>0) { extension = ".poly"; params += " -Ap "; } else extension = ".node"; name += extension; info->print("writing poly file "+name); std::ofstream polys(name.c_str()); writeTetgenPoly(polys); } else { if( facemap.size() > 0 && elements.size() == 0 ) { extension = ".poly"; name += extension; info->print("writing poly file "+name); std::ofstream polys(name.c_str()); writeTetgenPoly(polys); params += " -p "; } else { extension = ".node"; std::ofstream nodes( (name + extension).c_str() ); writeTetgenPoly( nodes, false ); { std::ofstream out( (name + ".ele").c_str() ); dverb << "Writing elements..."; out << elements.size() << " 4 " << nofelparams << std::endl; for (size_t n=0; nfirst.size(); i++) out << pos->first.origKey(i) << " "; out << pos->second.first; out << std::endl; } } if( elements.size() > 0 ) params += " -r "; } } } // Output to Tetgen/Triangle poly-file void DuneGridFormatParser::writeTetgenPoly ( std::ostream &out, bool writeSegments ) { dverb << "Writing vertices..."; out << nofvtx << " " << dimw << " " << nofvtxparams << " 0" << std::endl; for( int n = 0; n < nofvtx; ++n ) { out << n << " "; for( int j = 0; j < dimw; ++j ) out << " " << vtx[ n ][ j ]; for( int j = 0; j < nofvtxparams; ++j ) out << " " << vtxParams[ n ][ j ]; out << std::endl; } dverb << "done" << std::endl; if( writeSegments ) { dverb << "Writing Segments..."; out << facemap.size() + elements.size()*3 << " 1 " << std::endl; int nr = 0; // write out triangle faces (this code is purely 2d, but also used for tetgen) for( size_t i = 0; i < elements.size(); ++i ) { for( int k = 0; k < 3; ++k ) out << nr++ << " " << elements[ i ][ (k+1)%3 ] << " " << elements[ i ][ (k+2)%3 ] << " 0" << std::endl; } // write out boundary segments for( facemap_t::iterator pos = facemap.begin(); pos != facemap.end(); ++pos, ++nr ) { if( dimw == 3 ) { out << "1 0 " << pos->second.first << std::endl; out << pos->first.size(); } else out << nr; for( int i = 0; i < pos->first.size(); ++i ) out << " " << pos->first.origKey( i ); if( dimw == 2 ) out << " " << pos->second.first; out << std::endl; } out << "0" << std::endl; // write out element parameters (2d only) if( nofelparams > 0 ) { if( dimw != 2 ) DUNE_THROW( InvalidStateException, "Element parameters are not supported by tetgen." ); out << elements.size() * nofelparams << std::endl; int outputLineNum = 0; for( size_t i = 0; i < elements.size(); ++i ) { double coord[ 2 ] = { 0, 0 }; for( int j = 0; j < 3; ++j ) { coord[0] += vtx[ elements[ i ][ j ] ][ 0 ]; coord[1] += vtx[ elements[ i ][ j ] ][ 1 ]; } coord[0] /= 3.; coord[1] /= 3.; for( int j = 0; j < nofelparams; ++j ) out << outputLineNum++ << " " << coord[ 0 ] << " " << coord[ 1 ] << " " << elParams[ i ][ j ] << std::endl; } } else out << 0 << std::endl; dverb << "done" << std::endl; } } bool DuneGridFormatParser::isDuneGridFormat ( std::istream &input ) { input.clear(); input.seekg( 0 ); if( !input ) return false; std::string idline; std::getline( input, idline ); dgf::makeupcase( idline ); std::string id; std::istringstream idstream( idline ); idstream >> id; // compare id to DGF keyword return (id == dgfid); } bool DuneGridFormatParser::isDuneGridFormat ( const std::string &filename ) { std::ifstream input( filename.c_str() ); return isDuneGridFormat( input ); } bool DuneGridFormatParser::readDuneGrid ( std::istream &gridin, int dimG, int dimW ) { if( !isDuneGridFormat( gridin ) ) { std::cerr << "Couldn't find '" << dgfid << "' keyword." << "File is not in DuneGridFormat. Exiting parser..." << std::endl; return false; } // not a DGF file, perhaps native file format // initialize variables cube2simplex = false; simplexgrid = false; dimgrid = dimG; dimw = dimW; vtxoffset = 0; nofvtx=0; nofelements=0; info = new DGFPrintInfo( "dgfparser" ); dgf :: IntervalBlock interval( gridin ); dgf :: VertexBlock bvtx( gridin, dimw ); // generate cartesian grid? if ( interval.isactive() ) { info->automatic(); if( bvtx.isactive() ) { nofvtx = bvtx.get( vtx, vtxParams, nofvtxparams ); info->block( bvtx ); } info->block( interval ); if( dimw >= 0 ) { if( dimw != interval.dimw() ) { DUNE_THROW( DGFException, "Error in " << interval << ": Wrong coordinate dimension " << "(got " << interval.dimw() << ", expected " << dimw << ")" ); } } else dimw = interval.dimw(); if( (dimgrid >= 0) && (dimgrid != dimw) ) { DUNE_THROW( DGFException, "Error in " << interval << ": Coordinate dimension differs " << "from grid dimension." ); } else dimgrid = dimw; cube2simplex = true; simplexgrid = (element == Simplex); if( element == General ) { dgf :: SimplexBlock bsimplex( gridin, -1, -1, dimgrid ); simplexgrid = bsimplex.isactive(); if (simplexgrid) info->cube2simplex( element ); } interval.get( vtx, nofvtx, elements, nofelements ); // nofelements=interval.getHexa(elements); if( simplexgrid ) nofelements = dgf :: SimplexBlock :: cube2simplex( vtx, elements, elParams ); // remove copies of vertices if ( bvtx.isactive() || interval.numIntervals()>1) removeCopies(); } else { if( bvtx.isactive() ) { nofvtx = bvtx.get( vtx, vtxParams, nofvtxparams ); info->block( bvtx ); vtxoffset = bvtx.offset(); } dgf :: SimplexBlock bsimplex( gridin, nofvtx, vtxoffset, dimgrid ); dgf :: CubeBlock bcube( gridin, nofvtx, vtxoffset, dimgrid ); dgf :: GeneralBlock bgeneral( gridin, nofvtx, vtxoffset, dimgrid ); if( bcube.isactive() && (element != Simplex) ) { info->block( bcube ); nofelements = bcube.get( elements, elParams, nofelparams ); if( bsimplex.isactive() && (element == General) ) { size_t nofsimplex = bsimplex.get( elements, elParams, nofelparams ); // if no simplices found but simplex block active, convert cubes to simplices if( nofsimplex == 0 ) { // make simplex grid info->cube2simplex( element ); nofelements = dgf :: SimplexBlock :: cube2simplex( vtx, elements, elParams ); simplexgrid = true; nofelements += bsimplex.get( elements, elParams, nofelparams ); } } } else if( bgeneral.isactive() ) { info->block(bgeneral); nofelements += bgeneral.get( elements, elParams, nofelparams ); } else { simplexgrid = true; if( bcube.isactive() ) { info->block( bcube ); info->cube2simplex( element ); nofelements = bcube.get( elements, elParams, nofelparams ); // make simplex grid nofelements = dgf :: SimplexBlock :: cube2simplex( vtx, elements, elParams ); } if( bsimplex.isactive() ) { info->block(bsimplex); nofelements += bsimplex.get( elements, elParams, nofelparams ); if( dimgrid == 2 && dimw == 2) { for( size_t i = 0; i < elements.size(); ++i ) testTriang( i ); } } } } info->step1( dimw, vtx.size(), elements.size() ); // test for tetgen/triangle block (only if simplex-grid allowed) if( (element != Cube) && dgf :: SimplexGenerationBlock( gridin ).isactive() ) { if( !interval.isactive() ) generateBoundaries( gridin, true ); info->automatic(); simplexgrid = true; nofelements = 0; generateSimplexGrid( gridin ); } generateBoundaries( gridin, !interval.isactive() ); if( nofelements<=0 ) { std::cerr << "No suitable element block found in dgf file " << "for the chosen grid type - " << "perhaps you are building a grid supporting cube elements " << "from a dgf file containing only a simplex block?" << std::endl; DUNE_THROW( DGFException, "Error: No usable block to construct elements found." ); } info->finish(); delete info; info = 0; // we made it - // although perhaps a few boundary segments are still without id :-< return true; } void DuneGridFormatParser :: removeCopies () { std::vector map(vtx.size()); std::vector shift(vtx.size()); for (size_t i=0; iblock(segbound); nofbound=segbound.get(facemap,(nofelements>0),vtxoffset); // check whether we have boundary parameters facemap_t :: iterator pos = facemap.begin(); for( ; pos != facemap.end(); ++pos ) { if( !pos->second.second.empty() ) break; } haveBndParameters = ( pos != facemap.end() ); } } // if no boundary elements, return if (nofelements==0) return; dgf :: BoundaryDomBlock dombound(gridin, dimw); if ( !dombound.isactive() && facemap.empty() ) return; // now add all boundary faces { facemap_t :: iterator pos; for(int simpl=0; simpl < nofelements ; simpl++) { const int nFaces = ElementFaceUtil :: nofFaces( dimw, elements[ simpl ]); for( int i =0 ; i < nFaces; ++i ) { //DGFEntityKey< unsigned int > key2 facemap_t :: key_type key2 = ElementFaceUtil :: generateFace( dimw, elements[ simpl ], i ); pos=facemap.find(key2); if(pos == facemap.end()) { auto& entry = facemap[key2]; entry.first = 0; entry.second = DGFBoundaryParameter::defaultValue(); } else if (pos->second.first==0 || pos->first.origKeySet()) { // face found twice facemap.erase(pos); } else { // use original key as given in key2 const auto value = pos->second; facemap.erase(pos); facemap[key2] = value; } } } } // remove unused boundary faces added through boundaryseg block or cube2simplex conversion { facemap_t :: iterator pos = facemap.begin(); while( pos != facemap.end() ) { if( !pos->first.origKeySet() ) { facemap_t :: iterator pos1 = pos; ++pos; facemap.erase( pos1 ); } else ++pos; } } // now try to assign boundary ids... int remainingBndSegs = 0; int defaultBndSegs = 0; int inbnddomain = 0; if ( dombound.isactive() ) { info->block( dombound ); std::vector < std::vector < double > > v; for (auto& pos : facemap) { if( pos.second.first != 0 ) continue; v.resize( pos.first.size() ); for( int i = 0; i < pos.first.size(); i++ ) v[ i ] = vtx[ pos.first[ i ] ]; const dgf::DomainData * data = dombound.contains( v ); if ( data ) { pos.second.first = data->id(); pos.second.second = data->parameter(); data->isDefault() ? defaultBndSegs ++ : inbnddomain++; } } } for (const auto& pos : facemap) { if( pos.second.first == 0 ) remainingBndSegs++; } haveBndParameters = ( haveBndParameters || dombound.hasParameter() ); info->step2(nofbound,facemap.size(),inbnddomain,defaultBndSegs,remainingBndSegs); } /************************************************************* caller to tetgen/triangle ****************************************************/ void DuneGridFormatParser :: generateSimplexGrid ( std :: istream &gridin ) { dgf :: SimplexGenerationBlock para(gridin); info->block(para); // check whether a dump file name was provided std::string name = para.dumpFileName(); const bool tempFile = name.empty(); if( para.hasfile() ) // a triangle/tetgen file is provided name = para.filename(); else if( tempFile ) // we have no dump file name and no triangle/tetgen file -> use temporary file name = temporaryFileName(); std::string suffix; std::string params; if( para.hasfile() ) { if (para.filetype().size()==0) { readTetgenTriangle(name); return; } dimw = para.dimension(); if (dimw!=2 && dimw!=3 && dimw!=-1) { DUNE_THROW(DGFException, "SimplexGen can only generate 2d or 3d meshes but not in " << dimw << " dimensions!"); } else if (dimw==-1) { DUNE_THROW(DGFException, "SimplexGen: cannot determine dimension of grid," << " include parameter DIMENSION in the " << "Simplexgeneration-Block"); } } else writeTetgenPoly( name, suffix, params ); int call_nr = 1; if( dimw == 2 ) { std::stringstream command; command << std::fixed; if (para.haspath()) command << para.path() << "/"; command << "triangle -ej " << params; if(para.hasfile()) { // name = para.filename(); suffix = "."+para.filetype(); command << " " << para.parameter() << " "; } else { suffix = ""; } if (para.minAngle()>0) command << "-q" << para.minAngle() << " "; if (para.maxArea()>0) command << "-a" << para.maxArea() << " "; command << name << suffix; dverb << "Calling : " << command.str() << std::endl; info->print("Calling : "+command.str()); const int status = system( command.str().c_str() ); if( status != 0 ) { if( status < 0 ) DUNE_THROW( SystemError, "Unable to call '" << command.str() << "'." ); else DUNE_THROW( DGFException, "Triangle finished unsuccessfully (Command: '" << command.str() << "')." ); } if (para.display()) { std::stringstream paraCommand; if (para.haspath()) paraCommand << para.path() << "/"; paraCommand << "showme " << name; // << ".1.ele"; dverb << "Calling : " << paraCommand.str() << std::endl; if( system( paraCommand.str().c_str() ) < 0 ) DUNE_THROW( SystemError, "Unable to call " << paraCommand.str() << "." ); } } else if( dimw == 3 ) { { // first call std::stringstream command; command << std::fixed; // std::string suffix; if (para.haspath()) command << para.path() << "/"; command << "tetgen " << params; if( para.hasfile() ) { suffix = "." + para.filetype(); command << " " << para.parameter() << " "; } command << name << suffix; dverb << "Calling : " << command.str() << std::endl; info->print("Calling : "+command.str()); const int status = system( command.str().c_str() ); if( status != 0 ) { if( status < 0 ) DUNE_THROW( SystemError, "Unable to call '" << command.str() << "'." ); else DUNE_THROW( DGFException, "TetGen finished unsuccessfully (Command: '" << command.str() << "')." ); } } if (para.minAngle()>0 || para.maxArea()>0) { // second call info->print("Quality enhancement:"); call_nr = 2; std::stringstream command; command << std::fixed; if (para.haspath()) command << para.path() << "/"; command << "tetgen -r"; if (para.minAngle()>0) command << "q" << para.minAngle(); if (para.maxArea()>0) command << "a" << para.maxArea(); command << " " << name << ".1"; dverb << "Calling : " << command.str() << std::endl; info->print("Calling : "+command.str()); if( system(command.str().c_str()) < 0 ) DUNE_THROW( SystemError, "Unable to call " << command.str() << "." ); } if (para.display()) { std::stringstream command; if (para.haspath()) command << para.path() << "/"; command << "tetview-linux " << name << "." << call_nr << ".ele"; dverb << "Calling : " << command.str() << std::endl; if( system(command.str().c_str()) < 0 ) DUNE_THROW( SystemError, "Unable to call " << command.str() << "." ); } } std::stringstream polyname; polyname << name << "." << call_nr; readTetgenTriangle(polyname.str()); if ( tempFile && name.compare(0,12,"TMPDGFParser")==0 ) { /* std::stringstream command; command << "rm -f " << prefixname << "*.ele " << prefixname << "*.edge " << prefixname << "*.node " << prefixname << "*.poly "; if( system(command.str().c_str()) < 0 ) DUNE_THROW( SystemError, "Unable to call " << command.str() << "." ); */ } info->print("Automatic grid generation finished"); } void DuneGridFormatParser :: readTetgenTriangle ( const std :: string &name ) { int offset,bnd; std::string nodename = name + ".node"; std::string elename = name + ".ele"; std::string polyname = name + ((dimw==2) ? ".edge" : ".face"); dverb << "opening " << nodename << "\n"; std::ifstream node(nodename.c_str()); if (!node) { DUNE_THROW(DGFException, "could not find file " << nodename << " perhaps something went wrong with Tetgen/Triangle?"); } dverb << "opening " << elename << "\n"; std::ifstream ele(elename.c_str()); if (!ele) { DUNE_THROW(DGFException, "could not find file " << elename << " perhaps something went wrong with Tetgen/Triangle?"); } { dverb << "calculating offset from " << name << " .... offset = "; node >> nofvtx >> dimw >> nofvtxparams >> bnd; // offset is 0 by default // the offset it the difference of the first vertex number to zero node >> offset; dverb << offset << " \n"; node.seekg(0); } { int tmp; // first token is number of vertex which should equal i node >> nofvtx >> dimw >> nofvtxparams >> bnd; vtx.resize(nofvtx); if (nofvtxparams>0) vtxParams.resize(nofvtx); for (int i=0; i> nr; // first token is number of vertex which should equal i assert(nr-offset==i); for (int v=0; v> vtx[i][v]; if (nofvtxparams>0) { vtxParams[i].resize(nofvtxparams); for (int p=0; p> vtxParams[i][p]; } for (int p=0; p> tmp; } } { int tmp; ele >> nofelements >> tmp >> nofelparams; elements.resize(nofelements); if (nofelparams>0) elParams.resize(nofelements); for (int i=0; i> nr; assert(nr-offset==i); for (int v=0; v> elno; elements[i][v] = elno - offset; } if (nofelparams>0) { elParams[i].resize(nofelparams); for (int p=0; p> elParams[i][p]; } } } dverb << "opening " << polyname << "\n"; std::ifstream poly(polyname.c_str()); if (poly) { /* if (dimw==2) { poly >> tmp >> tmp >> tmp >> tmp; } */ { int noffaces,params; poly >> noffaces >> params; if (params>0) { assert(params==1); facemap.clear(); for (int i=0; i p( dimw ); int nr; poly >> nr; for (size_t k=0; k> p[k]; poly >> params; if (params!=0) { facemap_t :: key_type key( p, false ); // read bnd id as positive value (tetgen uses negative values) facemap[key].first = std::abs(params); facemap[key].second.clear(); } } } } } } /*************************** Helper methods mostly only for simplex grids ***************************/ void DuneGridFormatParser :: setOrientation ( int use1, int use2, orientation_t orientation ) { if (element == Cube) { std::cerr << "Reorientation is only implemented for simplex grid!" << std::endl; return; } if( dimgrid == 2 ) { for (int i=0; i::simplex(); for (int i=0; i& p0 = vtx[elements[i][1]]; std::vector& p1 = vtx[elements[i][2]]; std::vector& p2 = vtx[elements[i][3]]; std::vector& q = vtx[elements[i][0]]; double n[3]; n[0] = -((p1[1]-p0[1]) *(p2[2]-p0[2]) - (p2[1]-p0[1]) *(p1[2]-p0[2])) ; n[1] = -((p1[2]-p0[2]) *(p2[0]-p0[0]) - (p2[2]-p0[2]) *(p1[0]-p0[0])) ; n[2] = -((p1[0]-p0[0]) *(p2[1]-p0[1]) - (p2[0]-p0[0]) *(p1[1]-p0[1])) ; double test = n[0]*(q[0]-p0[0])+n[1]*(q[1]-p0[1])+n[2]*(q[2]-p0[2]); bool reorient = (test*int(orientation)<0); if (reorient) { // reorient element first int tmp=elements[i][use1]; elements[i][use1] = elements[i][use2]; elements[i][use2] = tmp; // for all faces, check reorient for(int k=0; k face( numVerts ); // get face vertices for(int j=0; jsecond; facemap.erase(bndFace); facemap[key] = bndId; } } } } } } } void DuneGridFormatParser::setRefinement ( int use1, int use2, int is1, int is2 ) { if( use1 > use2 ) std::swap( use1, use2 ); if( is1 > is2 ) std::swap( is1, is2 ); if( element != Cube ) { for( int i = 0; i < nofelements; ++i ) { if( elements[ i ].size() != size_t( dimgrid + 1 ) ) continue; double maxlen = 0.0; int vtx1 = is1; int vtx2 = is2; if( (vtx1 == -1) || (vtx2 == -1) ) { for( int l = 0; l <= dimgrid; ++l ) { const int idxl = elements[ i ][ l ]; for( int k = l+1; k <= dimgrid; ++k ) { const int idxk = elements[ i ][ k ]; double len = 0.0; for( int p = 0; p < dimw; ++p ) { const double dist = vtx[ idxk ][ p ] - vtx[ idxl ][ p ]; len += dist * dist; } if( len > maxlen ) { vtx1 = l; vtx2 = k; maxlen = len; } } } } int swapped = 0; if( vtx1 != use1 ) { std::swap( elements[ i ][ vtx1 ], elements[ i ][ use1 ] ); ++swapped; } if( vtx2 != use2 ) { std::swap( elements[ i ][ vtx2 ], elements[ i ][ use2 ] ); ++swapped; } if( swapped == 1 ) std::swap( elements[ i ][ use1 ], elements[ i ][ use2 ] ); } } else std::cerr << "Computing refinement edge is only implemented for 2d simplex grids." << std::endl; } double DuneGridFormatParser :: testTriang ( int snr ) { double o = (vtx[elements[snr][1]][0]-vtx[elements[snr][0]][0])* (vtx[elements[snr][2]][1]-vtx[elements[snr][1]][1])- (vtx[elements[snr][1]][1]-vtx[elements[snr][0]][1])* (vtx[elements[snr][2]][0]-vtx[elements[snr][1]][0]); if (fabs(o)<1e-10) { DUNE_THROW(DGFException, "Simplex number " << snr << " with vertex numbers " << "(" << elements[snr][0] << "," << elements[snr][1] << "," << elements[snr][2] << ")" << " has zero volume!"); } return o; } std :: vector< double > & DuneGridFormatParser :: getElParam ( int i, std::vector< double > &coord ) { coord.resize(dimw); for (int j=0; j & DuneGridFormatParser :: getVtxParam ( int i, std :: vector< double > &coord ) { coord.resize(dimw); for (int j=0; j #include #include #include #include #include #include #include #include #include //- Dune includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /*! @brief Some simple static information for a given GridType */ template struct DGFGridInfo { //! number of globalRefine steps needed to refuce h by 0.5 static int refineStepsForHalf(); //! relation between volume of children to volume of father. //! If this is not a constant the return value is -1 static double refineWeight(); }; /** @addtogroup DuneGridFormatParser @brief Classes for reading a macrogrid file in the dune macrogrid format (dgf) @section General The DGF format allows the simple description of macrogrids, which can be used to construct Dune grids independent of the underlying implementation. Due to the generality of the approach only a subset of the description language for each grid implementation is available through this interface. @section Usage There are two ways of constructing Dune grids using DGF files: -# By defining one of the symbols \c ALBERTAGRID , \c ALUGRID_CUBE , \c ALUGRID_SIMPLEX , \c ALUGRID_CONFORM , \c UGGRID , or \c YASPGRID and the integer \c GRIDDIM one obtains a definition of the type \c GridType and the required header files for the desired grid and the macrogrid parser are included. -# By directly including one of the files dgf*.hh from the dune/grid/io/file/dgfparser directory: \n in this case only the required header files for the desired grid and the macrogrid parser are included but no typedef is made. After a grid type (denoted with \c GridType in the following) is selected in some way, the grid can be constructed either by calling @code Dune::GridPtr gridptr(filename, mpiHelper.getCommunicator() ); @endcode or @code Dune::GridPtr gridptr(filename); @endcode or @code Dune::GridPtr gridptr; ... gridptr=Dune::GridPtr(filename); @endcode where in the second and third example \c MPIHelper::getCommunicator() is selected as default value; \c filename is the name of the dgf file. This creates an auto pointer like object \c Dune::GridPtr holding a pointer to a the grid instance described through the dgf file. Access to the grid is gained by calling the operator * of \c GridPtr. @code GridType & grid = *gridptr; @endcode Like in all unique_ptr like objects the grid instance is destroyed if the GridPtr goes out of scope. To be able to destruct the GridPtr object without losing the grid call the release method: @code GridType *grid; { GridPtr< GridType > gridPtr( filename.c_str(), mpiHelper.getCommunicator() ); grid = gridPtr.release(); } @endcode Remarks: -# The last argument in the constructor of the GridPtr should be of the type \c Dune::MPIHelper::MPICommunicator which defaults to \c MPI_COMM_WORLD for parallel runs or some default value for serial runs. -# If the file given through the first argument is not a dgf file a suitable constructor on the \c GridType class is called - if one is available. @section FORMAT Format Description We assume in the following that the type \c GridType is suitably defined, denoting a dune grid type in \c dimworld space dimension. A point in dimworld space is called a vector. In general dgf files consists of one or more blocks, each starting with a keyword and ending with a line starting with a # symbol. In a block each full line is parsed from the beginning up to the first occupance of a \% symbol, which can be used to include comments. Trailing whitespaces are ignored during line parsing. Also the parsing is not case sensitive. Some example files are given below (\ref EXAMPLES). @subsection START First line DGF files must start with the keyword \b DGF. Files passed to the grid parser not starting with this keyword are directly passed to a suitable constructor in the GridType class. @subsection BLOCKS Blocks In the following all blocks are briefly described in alphabetical order. The construction of the grid is detailed below. In general lines are parse sequentially, with the exception of lines starting with a special keyword which are treated separately. - \b Boundarydomain \n Each line consists of an integer greater than zero and two vectors describing an interval in \c dimworld space. The first entry of the line is a boundary identifier. - A special keyword is \b default followed by a positive integer which is to be used as a default boundary identifier. - \b Boundarysegments \n Each line consists of a positive integer denoting a boundary id and a set of vertex indices (see \b Vertex block) describing one boundary patch of the macrogrid. Note that a special ordering of the vertex numbers is not required. - \b Cube \n Each line consists of \c dimworld2 vertex indices (see \b Vertex block) describing one cube of the macrogrid. - If the ordering of the local vertices of the cube elements does not follow the %Dune @link GeometryReferenceElements reference element@endlink then the mapping between the local numbering used and the dune reference cube has to be prescribed by a line starting with the keyword \b map followed by the permutation of the numbers \c 0...2dimworld describing the mapping from the local vertex numbers in the reference elements used in the dgf file to the local vertex numbers in dune reference element. - By means of the special keyword \b parameters followed by a positive integer \c n it is possible to add \c n parameters to each element of the grid. These double valued parameters then have to be added to the definition lines for the elements behind the vertex numbers. - \b Interval \n Each interval is described by three lines in this block: the first two lines give the lower and upper vector of an interval, the third line consists of \c dimworld integers. used to determine the initial partition of the interval into equal sized cubes. More than one interval can be described in this fashion. Optional a reordering of the i-j-k logic can be added as a first line of the Interval block. The reordering is indicated by the keyword map followed by the permutation of the coordinates {0,...,d} (which is the default ordering). - \b Simplex \n Each line consists of \c dimworld+1 vertex indices (see \b Vertex block) describing one simplex of the macrogrid. - Note that no ordering of local vertices is required. - Parameters can be added to each element using the \b parameters keyword as described for cube elements. - \b Simplexgenerator \n Using this block a simplex grid can be automatically generated using one of the freely available grid generation tools Tetgen (http://tetgen.org) for \c dimworld=3 or Triangle (http://www.cs.cmu.edu/~quake/triangle.html) for \c dimworld=2. For more detail see \ref Simplexgeneration. - \b Vertex \n Each line consists of a vector representing a vertex of the macrogrid. The vertices are consecutively numbered. leading to vertex indices which can be referenced in the \b Simplex, \b Cube, and \b Boundarysegment blocks. - By default the numbering starts from zero; to change this behaviour the keyword \b firstindex followed by a positive integer denoting the number of the first vertex can be used. - Using the \b parameters keyword it is possible to add a set of parameters to each vertex of the grid. - \b GridParameter \n For each grid implementation there is a set of parameters that can be passed via the GridParameter block to the momment of grid construction. For the specific parameters see the \ref DGFGridParameter section. See also the \b examplegrid5.dgf file for examples. - \b PeriodicFaceTransformation \n Each line describes an affine transformation that shall be used to glue grid boundaries together. The transformation is denoted as \em matrix + \em shift. The following 2d example describes a shift by the first unit vector: \code 1 0, 0 1 + 1 0 \endcode - \b Projection \n Each line either declares a function or it assigns one a boundary segment. Functions are declared as follows:\n function function ( variable ) = expression\n The following expressions are currently implemented: - constant - variable - ( expression ) - function ( expression ) - expression [ constant ] - - expression - | expression | - expression + expression - expression - expression - expression * expression - expression / expression - expression ** expression - sqrt expression - sin expression - cos expression . Functions are assigned to boundary segments as follows:\n segment vertex ... vertex function\n Here, the given vertices identify the boundary segment.\n Another possibility is to set a default, assigned to all non-listed boundary segments:\n default function\n Note: Currently, the attached functions map global coordinates to global coordinates. This feature is only available with AlbertaGrid or with dune-ALUGrid. . @section CONSTR The Grid Construction Process For simplicity we first describe how the grid is manually constructed, i.e., if no \b Simplexgenerator block is found. Details on how Tetgen/Triangle can be used is detailed below (see \ref Simplexgeneration). How to access the element and vertex parameter is detailed in Section \ref PARAMETERS. The details of the construction are logged in the file \b dgfparser.log. The construction of the grid depends on the type of elements the given by \c GridType can handle. @subsection CONSTRCART Cartesian grids (Dune::YaspGrid ) The grid is constructed using only the information from the first three lines of the \b Interval block. @subsection CONSTRSIMPL Simplex grids (Dune::AlbertaGrid, or Dune::ALUGrid<3,3,simplex,nonconforming>, and Dune::ALUGrid<2,2,simplex,nonconforming>) The vertices and elements of the grid are constructed in the following three steps: -# The file is parsed for an \b Interval block; if present a Cartesian grid is build for each interval defined in this block and each element is partitioned either into two triangles or into six tetrahedron. The user has to make sure that this process leads to a conforming grid. -# If no \b Interval block is found, the grid is generated using the information from the \b Vertex and the \b Simplex or \b Cube blocks. If a non-empty \b Simplex block is found the element information is only taken from there; in the case where no \b Simplex block is found or in the case where it is empty, the \b Cube block is read and each cube is partitioned into simplex elements - in 3d this process will not always lead to a correct macro triangulation! Note that no specific ordering of the local numbering of each simplex is required but the cubes must either conform with the Dune reference element or the mapping must be prescribed using the map keyword. . If the simplex generation process was successful, boundary ids are assigned to all boundary faces of the macrogrid. -# If the macrogrid was constructed in the third step of the generation process detailed above (i.e. using the vertex block), then the file is first parsed for \b Boundarysegment block. Here boundary ids can be individually assigned to each boundary segment of the macrogrid by specifying the vertex ids. Boundary segments can either be described as simplex elements or as cube elements. -# All Boundary segments which have not yet been assigned an identifier and lie inside the interval defined by the first line of the \b Boundarydomain block are assigned the corresponding id. This process is then repeated with the remaining boundary segments using the following intervals defined in the \b Boundarydomain block. If after this process boundary segments without id remain, then the default id is used if one was specified in the \b Boundarydomain block - if no default was given, the behavior of the parser is not well defined. . \b Remark: -# \c Bisection: \n the refinement edge is always chosen to be the longest edge. @subsection CONSTRCUBE Cube grids (Dune::ALUGrid<3,3,cube,nonconforming>) The grid is constructed using the information from the \b Interval block, if present; otherwise the \b Vertex and \b Cube blocks are used. The boundary ids are assigned in the same manner as for simplex grids described above. @subsection CONSTRMIXED Mixed grids (\c Dune::UGGrid ) Note that in this version only grids consisting of one element type are constructed even if the implemented grid allows for mixed elements. The vertices and elements of the grid are constructed in one of the following stages: -# The file is first parsed for an \b Interval block; if present a Cartesian grid is build; a simplex grid is generated if a \c Simplex block is present otherwise a cube grid is constructed. -# If no \b Interval block is found, the grid is generated using the information from the \b Vertex block; cube elements are constructed if the \b Cube block is present otherwise the \b Simplex blocks is read. If both a \b Cube and a \b Simplex block is found, then only the element information from the \b Cube block is used and each cube is split into simplex elements so that a simplex grid is constructed. . Boundary ids are assigned in the same manner as described for simplex grids. @section PARAMETERS Accessing parameters In addition to the element and vertex information it is possible to add a set of parameters through the DGF file. Using the construction mechanism via the Dune::GridPtr class these parameters can be accessed using the Dune::GridPtr::parameters(const Entity& en) method. Depending on the codimentsion of \c en the method returns either the element or vertex parameters of that entity in the DGF file. The number of parameters for a given codimension can be retrieved using the method Dune::GridPtr::nofParameters. In the case of parallel runs only the process with rank zero reads the dgf file and thus the parameters are only available on that processor. Do not call loadBalance (or for that matter globalRefine, adapt) on the grid instance before retrieving the parameters. To simplify the handling of parameters in a parallel run the Dune::GridPtr::loadBalance method can be used to distribute the macro grid and the parameters. Afterwards the parameters can be extracted on each processor using the method GridPtr::parameters. \section Simplexgeneration Using Tetgen/Triangle The freely available simplex grid generators are directly called via system call through the dgfparser. Therefore one should either add the path containing the executables of Triangle and/or Tetgen to the environment variable PATH or use the path option described below. One can either use a file in Tetgen/Triangle format to directly generate a macro grid or one can prescribe vertices and boundary faces which will be used to generate the grid directly in the DGF file: -# For the first approach use the token \b file to give a filename and the type of the file (e.g. node, mesh, ply...). Example: \code file name mesh \endcode If the filetype is given, it will be appended to \b name and this will be passed to Tetgen/Triangle. Additional parameters for the grid generators can be given by the \b parameter token. If no file type is given it is assumed that in a previous run of Tetgen/Triangle files name.node and name.ele were generated and these will be used to describe the vertices and elements of the Dune grid. -# In the second approach the \b vertex and the \b interval blocks (if present) are used to generate the vertices of the grid; the \b Cube and \b Simplex blocks are used for element information in the interior and the \b boundarysegment block is used for boundary information: - If only a \b vertex and/or \b interval block is found the resulting .node file is passed directly to Tetgen/Triangle and a tessellation of the convex hull of the points is generated. - A more detailed description of the domain is possible by using the \b Boundarysegment block together with the \b vertex block. Planar polyhedral boundary faces of the domain can be prescribed in this way. Note that in this case the whole domain boundary has to be defined (see the description of the .poly files in the Tetgen documentation). In 3d each polyhedral face (p0,..,pn) is automatically closed by adding the segment between p0 and pn. To define the whole boundary of a 2d domain using only one polyhedron the closing segment has to be added, i.e., (p0,..,pn,p0). - If a \b cube or \b simplex block is found the element information is also passed to tetgen/triangle together with the parameters - if given. Note that a triangle can only handle one region attribute in its .poly files so that only the first parameter is the \b simplex or \b cube block can be retrieved. . Some identifiers can be used to influence the quality of the generated mesh: - \b max-area followed by a positive real number used as an upper bound for the area of all simplicies of the mesh. - \b min-angle followed by a positive number. In 2d this limits the angles in the resulting mesh from below; in 3d this bounds the radius-edge ratio from above. . In this case the grid is constructed using two calls to Tetgen/Triangle. The details of the call are logged in the \b dgfparser.log file. \e Note: vertex parameters are interpolated in triangle but tetgen assigns a zero to all newly inserted vertices; therefore quality enhancement and vertex parameters should not be combined in 3d. On the other hand element parameters and boundary ids can be used together with quality enhancement. The remaining identifiers are - The identifier \b path (followed by a path name) can be used to give a search path for Triangle/Tetgen. - The identifier \b display followed by 1 can be used to get a first impression of the resulting mesh using the visualization tools distributed with Triangle/Tetgen. . \e Note that parameters can be attached to the vertices and elements of the grid as described in the Triangle/Tetgen manual. Then can be retrieved as described in Section \ref PARAMETERS. Download - Tetgen http://tetgen.org - Triangle http://www.cs.cmu.edu/~quake/triangle.html @section OPEN Work in progress -# There should be a mechanism to fix the desired refinement edge for simplex grids. An automatic selection is performed using the longest edge, but it should be possible to turn off this automatic selection. -# A callback to the user between parsing the DGF file and the construction of the dune grid; here e.g. a post-processing of the vertex coordinates could be included. @section EXAMPLES Examples In two space dimensions: - \ref dgfexample1 - \ref dgfexample2 - \ref dgfexampleParam - \ref dgfexample3 - \ref dgfexample6 In three space dimensions: - \ref dgfexample4 - \ref dgfexample5 \section dgfexample1 Manual Grid Construction A tessellation of the unit square into six simplex entities. Some boundary segments on the lower and right boundary are given their own id the remaining are given a default id. @include examplegrid1s.dgf \image html examplegrid1s.png "The resulting grid" A tessellation into cubes using the same vertices as before, @include examplegrid1c.dgf \image html examplegrid1c.png "The resulting grid" Using the last input file with a simplex grid or by adding an empty \c Simplex block @code Simplex # @endcode leads to the following macro triangulation \image html examplegrid1cs.png "The resulting grid" \section dgfexample2 Automated Grid Construction Automatic tessellation using Triangle, with vertices defined as in the example \ref dgfexample1 : @include examplegrid1gen.dgf \image html examplegrid1gen.png "The resulting grid" The quality of the grid can be enhanced by adding the line @code min-angle 30 @endcode in the \c Simplexgenerator block \image html examplegrid1genangle.png "The resulting grid" Automatic tessellation using Triangle, with vertices are defined on a Cartesian grid with two additional vertices in the top right corner and one vertex outside the unit square. All boundary are given a default id. @include examplegrid2a.dgf \image html examplegrid2a.png "The resulting grid" Adding some quality enhancement. The boundaries are numbered counterclockwise starting at the left boundary from one to four. @include examplegrid2b.dgf \image html examplegrid2b.png "The resulting grid" Using both quality enhancement and a maximum area restriction. The bottom boundary is given the id 1 all other boundaries have id 2; here we do not use a default value. @include examplegrid2c.dgf \image html examplegrid2c.png "The resulting grid" A similar grid is generated by prescribing the boundary of the domain: @include examplegrid2d.dgf \image html examplegrid2d.png "The resulting grid" \section dgfexampleParam Using Parameters We use the same domain as in the previous example but include vertex and element parameters: @include examplegrid2e.dgf The results in piecewise constant data on the elements and piecewise linear date using the vertex parameters: \image html examplegrid2e.png "The resulting grid with element and vertex parameters" \section dgfexample3 Interval Domain A automatic tessellation of the unit square using a Cartesian Grid. All boundaries have id 1. @include examplegrid5.dgf \image html examplegrid5c.png "The resulting grid using YaspGrid<2>" \image html examplegrid5s.png "The resulting grid using AlbertaGrid<2,2>" If UGGrid<2,2> is used the result would be the same as for YaspGrid<2>. If an empty \c Simplex Block @code Simplex # @endcode is added than the same simplex grid as for AlbertaGrid<2,2> would be constructed. \section dgfexample6 Boundary Projections The following example shows a DGF file that projects 3 sides of a quadrilateral onto the surrounding circle: @include example-projection.dgf \image html example-projection.png "The resulting grid using AlbertaGrid<2>" \section dgfexample4 Grid Generation in 3d An automatic tessellation of the unit square using a Cartesian Grid is shown. All boundaries have id 1 except boundary segment on the lower boundary which have value 2. First we use only the interval block: @include examplegrid6.dgf \image html examplegrid6c.png "The resulting grid using ALUGrid<3,3,cube,nonconforming>" \image html examplegrid6s.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" Now the vertices are still defined through the interval block; the simplicies are constructed using Tetgen (note the comment symbol \% in the \b Simplexgenerator block): @include examplegrid7.dgf \image html examplegrid7.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" Note that in the grid would be the same as in the above example if ALUGrid<3,3,cube,nonconforming> where used. Now we can also include some quality enhancement: First: \b min-angle = 1.2 (remove the first \% in the \b Simplexgenerator block) \image html examplegrid7angle.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" Second: \b min-angle = 1.2 and \b max-area = 0.1 (remove both \% in the \b Simplexgenerator block) \image html examplegrid7area.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" This examples show different ways to define a grid for the following domain and boundary ids: \image html examplegrid10.png "An example domain" \e Manual grid construction: Note that the reference element used to define the cube is not the one used in dune so that the mapping has to be given; furthermore the vertex index are numbered starting with 1. If a simplex grid is to be constructed some care must be taken in the numbering of the nodes so that a conforming grid is constructed. @include examplegrid10.dgf \image html examplegrid10c.png "The resulting cube grid" \image html examplegrid10s.png "The resulting simplex grid" \e Using multiple intervals: Here the boundary ids are not set correctly; this could be done using different boundarydomains. @include examplegrid11.dgf \image html examplegrid11a.png "The resulting cube grid" \image html examplegrid11b.png "The resulting simplex grid" \e By only defining the boundary faces and using Tetgen: @include examplegrid12.dgf Without the \b max-area and \b min-angle keywords the following grid is constructed: \image html examplegrid12_1.png "The resulting grid" With the quality enhancement active: \image html examplegrid12_2.png "The resulting grid" Finally we demonstrate the use of parameters. With a simple modification of the above example @include examplegrid10a.dgf we can define parameters on each element: \image html examplegrid10a.png "The resulting grid with element parameters" The following example @include examplegrid10b.dgf defines parameters for each vertex of the grid, leading to a piecewise linear function \image html examplegrid10b.png "The resulting grid with vertex parameters" \section dgfexample5 Importing Grids written in a Tetgen/Triangle format Here a .mesh file used to generate a 3d simplex grid through Tetgen. The mesh file is taken from http://www-c.inria.fr/Eric.Saltel/download/download.php @include examplegrid9.dgf \image html BBEETH1M.d_cut.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" \image html Orb_cut.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" \image html bunny.p65.param_skin.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" \image html pmdc.png "The resulting grid using ALUGrid<3,3,simplex,nonconforming>" **/ /* Dune::Alberta with \c dimworld=3: \n if Tetgen is used to construct a tetrahedral grid for Dune::Alberta then the bisection routine does not necessarily terminate. This problem does not occur if the grid is constructed using the \b Interval block. */ } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfug.cc000066400000000000000000000070611511655130300222430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include // HAVE_DUNE_UGGRID #include namespace Dune { namespace dgf { // Implementation of UGGridParameterBlock // -------------------------------------- UGGridParameterBlock::UGGridParameterBlock ( std::istream &input ) : GridParameterBlock( input ), noClosure_( false ), // default value noCopy_( true ) // default value { // check closure if( findtoken( "closure" ) ) { std::string closure; if( getnextentry( closure ) ) { makeupcase( closure ); if( closure == "NONE" ) noClosure_ = true ; else if( closure != "GREEN" ) { dwarn << "UGGridParameterBlock: Parameter 'closure' has invalid value: " << closure << ", using default: 'GREEN'." << std::endl; } } } else { dwarn << "UGGridParameterBlock: Parameter 'closure' not specified" << ", using default: 'GREEN'." << std::endl; } if( findtoken( "copies" ) ) { std::string copies; if( getnextentry( copies ) ) { makeupcase( copies ); if( copies == "YES" ) noCopy_ = false; else if( copies != "NO" ) { dwarn << "UGGridParameterBlock: Parameter 'copies' has invalid value: " << copies << ", using default: 'NO'." << std::endl; } } } else { dwarn << "UGGridParameterBlock: Parameter 'copies' not specified" << ", using default: 'NO'." << std::endl; } } } // namespace dgf // Implementation of DGFGridFactory< UGGrid > // ------------------------------------------- #if HAVE_DUNE_UGGRID template< int dim > void DGFGridFactory< UGGrid< dim > >::generate ( std::istream &input ) { dgf_.element = DuneGridFormatParser::General; if( !dgf_.readDuneGrid( input, dim, dim ) ) DUNE_THROW( DGFException, "Error: Failed to build grid"); dgf_.setOrientation( 0, 1 ); // get grid parameter block dgf::UGGridParameterBlock gridParam( input ); // create grid factory (passed grid is returned by createGrid method) for( int n = 0; n < dgf_.nofvtx; n++ ) { FieldVector< double, dim > v; for( int j = 0; j < dim; j++ ) v[ j ] = dgf_.vtx[ n ][ j ]; factory_.insertVertex( v ); } std::vector< unsigned int > el; for( int n = 0; n < dgf_.nofelements; n++ ) { el.clear(); for( size_t j = 0; j < dgf_.elements[ n ].size(); ++j ) el.push_back( ( dgf_.elements[ n ][ j ] ) ); factory_.insertElement( geometryTypeFromVertexCount( dim, el.size() ), el ); } // create grid grid_ = factory_.createGrid().release(); // set closure type to none if parameter say so if( gridParam.noClosure() ) grid_->setClosureType( UGGrid< dim >::NONE ); if ( !gridParam.noCopy() ) grid_->setRefinementType( UGGrid< dim >::COPY ); } template void DGFGridFactory< UGGrid< 2 > >::generate ( std::istream &input ); template void DGFGridFactory< UGGrid< 3 > >::generate ( std::istream &input ); #endif // #if HAVE_DUNE_UGGRID } // namespace Dune dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfug.hh000066400000000000000000000151721511655130300222570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_DGFPARSER_DGFUG_HH #define DUNE_GRID_IO_FILE_DGFPARSER_DGFUG_HH //- C++ includes #include #include #include #include //- dune-common includes #include #include #include //- dune-grid includes #include // HAVE_DUNE_UGGRID #include #include //- local includes #include "dgfparser.hh" #include "blocks/gridparameter.hh" namespace Dune { namespace dgf { // UGGridParameterBlock // -------------------- struct UGGridParameterBlock : public GridParameterBlock { /** \brief constructor taking istream */ explicit UGGridParameterBlock ( std::istream &input ); /** \brief returns true if no closure should be used for UGGrid */ bool noClosure () const { return noClosure_; } /** \brief returns true if no copies are made for UGGrid elements */ bool noCopy () const { return noCopy_; } /** \brief returns heap size used on construction of the grid */ size_t heapSize () const { return heapSize_; } protected: bool noClosure_; // no closure for UGGrid bool noCopy_; // no copies for UGGrid size_t heapSize_; // heap size for UGGrid }; } // namespace dgf #if HAVE_DUNE_UGGRID template< int dim > struct DGFGridInfo< UGGrid< dim > > { static int refineStepsForHalf () { return 1; } static double refineWeight () { return -1.; } }; // DGFGridFactory< UGGrid< dim > > // ------------------------------- template< int dim > struct DGFGridFactory< UGGrid< dim > > { /** \brief grid type */ typedef UGGrid< dim > Grid; /** \brief grid dimension */ static const int dimension = dim; /** \brief MPI communicator type */ typedef MPIHelper::MPICommunicator MPICommunicatorType; /** \brief constructor taking istream */ explicit DGFGridFactory ( std::istream &input, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : grid_( 0 ), factory_(), dgf_( rank( comm ), size( comm ) ) { generate( input ); } /** \brief constructor taking filename */ explicit DGFGridFactory ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : grid_( 0 ), factory_(), dgf_( rank( comm ), size( comm ) ) { std::ifstream input( filename.c_str() ); if ( !input ) DUNE_THROW( DGFException, "Error: Macrofile " << filename << " not found" ); generate( input ); } /** \brief return grid */ Grid *grid () { return grid_; } /** \brief please doc me */ template< class GG, class II > bool wasInserted ( const Dune::Intersection< GG, II > &intersection ) const { return factory_.wasInserted( intersection ); } /** \brief will return boundary segment index */ template< class GG, class II > int boundaryId ( const Dune::Intersection< GG, II > &intersection ) const { return intersection.boundarySegmentIndex(); } /** \brief return number of parameters */ template< int codim > int numParameters () const { if( codim == 0 ) return dgf_.nofelparams; else if( codim == dimension ) return dgf_.nofvtxparams; else return 0; } /** \brief return number of parameters */ template< class Entity > int numParameters ( const Entity & ) const { return numParameters< Entity::codimension >(); } /** \brief return parameter for codim 0 entity */ std::vector< double > ¶meter ( const typename Grid::template Codim< 0 >::Entity &element ) { if( numParameters< 0 >() <= 0 ) { DUNE_THROW( InvalidStateException, "Calling DGFGridFactory::parameter is only allowed if there are parameters." ); } return dgf_.elParams[ factory_.insertionIndex( element ) ]; } /** \brief return parameter for vertex */ std::vector< double > ¶meter ( const typename Grid::template Codim< dimension >::Entity &vertex ) { if( numParameters< dimension >() <= 0 ) { DUNE_THROW( InvalidStateException, "Calling DGFGridFactory::parameter is only allowed if there are parameters." ); } return dgf_.vtxParams[ factory_.insertionIndex( vertex ) ]; } /** \brief UGGrid does not support boundary parameters */ bool haveBoundaryParameters () const { return dgf_.haveBndParameters; } /** \brief return invalid value */ template< class GG, class II > const DGFBoundaryParameter::type &boundaryParameter ( const Dune::Intersection< GG, II > &intersection ) const { typedef Dune::Intersection< GG, II > Intersection; typename Intersection::Entity entity = intersection.inside(); const int face = intersection.indexInInside(); auto refElem = referenceElement< double, dimension >( entity.type() ); int corners = refElem.size( face, 1, dimension ); std::vector< unsigned int > bound( corners ); for( int i = 0; i < corners; ++i ) { const int k = refElem.subEntity( face, 1, i, dimension ); bound[ i ] = factory_.insertionIndex( entity.template subEntity< dimension >( k ) ); } DuneGridFormatParser::facemap_t::key_type key( bound, false ); const DuneGridFormatParser::facemap_t::const_iterator pos = dgf_.facemap.find( key ); if( pos != dgf_.facemap.end() ) return dgf_.facemap.find( key )->second.second; else return DGFBoundaryParameter::defaultValue(); } private: // create grid void generate ( std::istream &input ); // return rank static int rank( MPICommunicatorType MPICOMM ) { int rank = 0; #if HAVE_MPI MPI_Comm_rank( MPICOMM, &rank ); #endif return rank; } // return size static int size( MPICommunicatorType MPICOMM ) { int size = 1; #if HAVE_MPI MPI_Comm_size( MPICOMM, &size ); #endif return size; } Grid *grid_; GridFactory< UGGrid< dim > > factory_; DuneGridFormatParser dgf_; }; #endif // #if HAVE_DUNE_UGGRID } // namespace Dune #endif // #ifndef DUNE_GRID_IO_FILE_DGFPARSER_DGFUG_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfwriter.hh000066400000000000000000000370111511655130300231540ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_DGFPARSER_DGFWRITER_HH #define DUNE_GRID_IO_FILE_DGFPARSER_DGFWRITER_HH /** \file * \brief write a GridView to a DGF file * \author Martin Nolte */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \class DGFWriter * \ingroup DuneGridFormatParser * \brief write a GridView to a DGF file * * The DGFWriter allows create a DGF file from a given GridView. It allows * for the easy creation of file format converters. * * \tparam GV GridView to write in DGF format */ template< class GV > class DGFWriter { typedef DGFWriter< GV > This; public: /** \brief type of grid view */ typedef GV GridView; /** \brief type of underlying hierarchical grid */ typedef typename GridView::Grid Grid; /** \brief dimension of the grid */ static const int dimGrid = GridView::dimension; private: typedef typename GridView::IndexSet IndexSet; typedef typename GridView::template Codim< 0 >::Entity Element; typedef typename GridView::Intersection Intersection; typedef typename Element::EntitySeed ElementSeed; typedef typename IndexSet::IndexType Index; public: /** \brief constructor * * \param[in] gridView grid view to operate on */ DGFWriter ( const GridView &gridView ) : gridView_( gridView ) {} /** * \brief write the GridView into a std::ostream * * \param gridout std::ostream to write the grid to * \param[in] newElemOrder vector providing a new ordering for the elements in the given GridView * \param[in] boundaryData callable attaching boundary data to each intersection * \param[in] addParams additional data to write to dgf file, such as projections etc. * (defaults to an empty data stream) **/ template< class BoundaryData > void write ( std::ostream &gridout, const std::vector< Index > &newElemOrder, BoundaryData &&boundaryData, const std::stringstream &addParams = std::stringstream() ) const; /** * \brief write the GridView to a file * * \param gridout std::ostream to write the grid to * \param[in] boundaryData callable attaching boundary data to each intersection * \param[in] addParams additional data to write to dgf file, such as projections, etc. * (defaults to an empty data stream) **/ template< class BoundaryData > void write ( std::ostream &gridout, BoundaryData &&boundaryData, const std::stringstream &addParams = std::stringstream() ) const; /** * \brief write the GridView into a std::ostream * * \param gridout std::ostream to write the grid to * \param[in] newElemOrder vector providing a new ordering for the elements in the given GridView * \param[in] addParams additional data to write to dgf file, such as projections etc. * (defaults to an empty data stream) **/ void write ( std::ostream &gridout, const std::vector< Index > &newElemOrder, const std::stringstream &addParams = std::stringstream() ) const { write( gridout, newElemOrder, [] ( const Intersection &i ) -> int { return boundaryId( i ); }, addParams ); } /** * \brief write the GridView into a std::ostream * * \param gridout std::ostream to write the grid to * \param[in] addParams additional data to write to dgf file, such as projections, etc. * (defaults to an empty data stream) **/ void write ( std::ostream &gridout, const std::stringstream &addParams = std::stringstream() ) const { write( gridout, [] ( const Intersection &i ) -> int { return boundaryId( i ); }, addParams ); } /** * \brief write the GridView to a file * * \param[in] fileName name of the write to write the grid to * \param[in] args arguments for the write method with istream **/ template< class... Args > auto write ( const std::string &fileName, Args &&... args ) const -> std::void_t< decltype( this->write( std::declval< std::ostream & >(), std::declval< Args >()... ) ) > { std::ofstream gridout( fileName ); if( gridout ) write( gridout, std::forward< Args >( args )... ); else std::cerr << "Couldn't open file `"<< fileName << "'!"<< std::endl; } protected: auto elementsSeeds ( const std::vector< Index > &newElemOrder ) const -> std::vector< ElementSeed >; void writeHeader ( std::ostream &gridout ) const; void writeFooter ( std::ostream &gridout ) const; auto writeVertices ( std::ostream &gridout ) const -> std::vector< Index >; void writeElement ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const Element &element, const GeometryType &elementType ) const; void writeSimplices ( std::ostream &gridout, const std::vector< Index > &dgfIndices ) const; void writeSimplices ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const std::vector< ElementSeed > &elementSeeds ) const; void writeCubes ( std::ostream &gridout, const std::vector< Index > &dgfIndices ) const; void writeCubes ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const std::vector< ElementSeed > &elementSeeds ) const; template< class... Args > void writeElements ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const Args &... args ) const; private: template< class I > static auto boundaryId ( const I &i, PriorityTag< 1 > ) -> std::enable_if_t< std::is_convertible< std::decay_t< decltype( i.impl().boundaryId() ) >, int >::value, int > { return i.impl().boundaryId(); } template< class I > static int boundaryId ( const I &i, PriorityTag< 0 > ) { return 1; } protected: static int boundaryId ( const Intersection &i ) { return boundaryId( i, PriorityTag< 42 >() ); } private: static int boundaryId ( const Intersection &, int bndId ) { return bndId; } static int boundaryId ( const Intersection &i, const std::string & ) { return boundaryId( i ); } static int boundaryId ( const Intersection &i, const std::pair< int, std::string > &data ) { return boundrayId( i, data.first ); } static void appendBoundaryData ( std::ostream &gridout, int ) { gridout << std::endl; } static void appendBoundaryData ( std::ostream &gridout, std::pair< int, std::string > &data ) { appendBoundaryData( gridout, data.second ); } static void appendBoundaryData ( std::ostream &gridout, const std::string &s ) { gridout << " : " << s << std::endl; } protected: template< class BoundaryData > void writeBoundaries ( std::ostream &gridout, const std::vector< Index > &dgfIndices, BoundaryData &&boundaryData ) const; void writeBoundaries ( std::ostream &gridout, const std::vector< Index > &dgfIndices ) const { writeBoundaries( gridout, dgfIndices, [] ( const Intersection &i ) -> int { return boundaryId( i ); } ); } protected: GridView gridView_; }; template< class GV > inline auto DGFWriter< GV >::elementsSeeds ( const std::vector< Index > &newElemOrder ) const -> std::vector< ElementSeed > { const IndexSet &indexSet = gridView_.indexSet(); const std::size_t orderSize = newElemOrder.size() ; std::vector< ElementSeed > elementSeeds( orderSize ); for( const Element &element : elements( gridView_ ) ) { assert( newElemOrder[ indexSet.index( element ) ] < orderSize ); elementSeeds[ newElemOrder[ indexSet.index( element ) ] ] = element.seed(); } return elementSeeds; } template< class GV > inline void DGFWriter< GV >::writeHeader ( std::ostream &gridout ) const { // set the stream to full double precision gridout.setf( std::ios_base::scientific, std::ios_base::floatfield ); gridout.precision( 16 ); const IndexSet &indexSet = gridView_.indexSet(); // write DGF header gridout << "DGF" << std::endl; gridout << "%" << " Elements = " << indexSet.size( 0 ) << " | Vertices = " << indexSet.size( dimGrid ) << std::endl; } template< class GV > inline void DGFWriter< GV >::writeFooter ( std::ostream &gridout ) const { gridout << std::endl << "#" << std::endl; } template< class GV > inline auto DGFWriter< GV >::writeVertices ( std::ostream &gridout ) const -> std::vector< Index > { const IndexSet &indexSet = gridView_.indexSet(); const Index vxSize = indexSet.size( dimGrid ); std::vector< Index > dgfIndices( vxSize, vxSize ); // write all vertices into the "vertex" block gridout << std::endl << "VERTEX" << std::endl; Index vertexCount = 0; for( const Element &element : elements( gridView_ ) ) { for( auto i : range( element.subEntities( dimGrid ) ) ) { const Index vxIndex = indexSet.subIndex( element, i, dimGrid ); assert( vxIndex < vxSize ); if( dgfIndices[ vxIndex ] == vxSize ) { dgfIndices[ vxIndex ] = vertexCount++; gridout << element.geometry().corner( i ) << std::endl; } } } gridout << "#" << std::endl; if( vertexCount != vxSize ) DUNE_THROW( GridError, "IndexSet reports wrong number of vertices." ); return dgfIndices; } template< class GV > inline void DGFWriter< GV >::writeElement ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const Element &element, const GeometryType &elementType ) const { // if element's type is not the same as the type to write the return if( element.type() != elementType ) return; // write vertex numbers of the element const IndexSet &indexSet = gridView_.indexSet(); for( auto i : range( element.subEntities( Element::dimension ) ) ) gridout << (i > 0 ? " " : "") << dgfIndices[ indexSet.subIndex( element, i, dimGrid ) ]; gridout << std::endl; } template< class GV > inline void DGFWriter< GV >::writeSimplices ( std::ostream &gridout, const std::vector< Index > &dgfIndices ) const { // write all simplices to the "simplex" block gridout << std::endl << "SIMPLEX" << std::endl; // write all simplex elements for( const Element &element : elements( gridView_ ) ) writeElement( gridout, dgfIndices, element, GeometryTypes::simplex( dimGrid ) ); // write end marker for block gridout << "#" << std::endl; } template< class GV > inline void DGFWriter< GV >::writeSimplices ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const std::vector< ElementSeed > &elementSeeds ) const { // write all simplices to the "simplex" block gridout << std::endl << "SIMPLEX" << std::endl; // write all simplex elements for( const ElementSeed &seed : elementSeeds ) writeElement( gridout, dgfIndices, gridView_.grid().entity( seed ), GeometryTypes::simplex( dimGrid ) ); // write end marker for block gridout << "#" << std::endl; } template< class GV > inline void DGFWriter< GV >::writeCubes ( std::ostream &gridout, const std::vector< Index > &dgfIndices ) const { // write all cubes to the "cube" block gridout << std::endl << "CUBE" << std::endl; // write all cube elements for( const Element &element : elements( gridView_ ) ) writeElement( gridout, dgfIndices, element, GeometryTypes::cube( dimGrid ) ); // write end marker for block gridout << "#" << std::endl; } template< class GV > inline void DGFWriter< GV >::writeCubes ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const std::vector< ElementSeed > &elementSeeds ) const { const IndexSet &indexSet = gridView_.indexSet(); // write all cubes to the "cube" block gridout << std::endl << "CUBE" << std::endl; // write all cube elements for( const ElementSeed &seed : elementSeeds ) writeElement( gridout, dgfIndices, gridView_.grid().entity( seed ), GeometryTypes::cube( dimGrid ) ); // write end marker for block gridout << "#" << std::endl; } template< class GV > template< class... Args > inline void DGFWriter< GV >::writeElements ( std::ostream &gridout, const std::vector< Index > &dgfIndices, const Args &... args ) const { const IndexSet &indexSet = gridView_.indexSet(); if( (dimGrid > 1) && (indexSet.size( GeometryTypes::simplex( dimGrid ) ) > 0) ) writeSimplices( gridout, dgfIndices, args... ); if( indexSet.size( GeometryTypes::cube( dimGrid ) ) > 0 ) writeCubes( gridout, dgfIndices, args... ); } template< class GV > template< class BoundaryData > inline void DGFWriter< GV >::writeBoundaries ( std::ostream &gridout, const std::vector< Index > &dgfIndices, BoundaryData &&boundaryData ) const { using std::max; const IndexSet &indexSet = gridView_.indexSet(); // write all boundaries to the "boundarysegments" block gridout << std::endl << "BOUNDARYSEGMENTS" << std::endl; for( const Element &element : elements( gridView_ ) ) { if( !element.hasBoundaryIntersections() ) continue; const auto &refElement = ReferenceElements< typename Grid::ctype, dimGrid >::general( element.type() ); for( const Intersection &intersection : intersections( gridView_, element ) ) { if( !intersection.boundary() ) continue; const auto data = boundaryData( intersection ); const int bndId = max( boundaryId( intersection, data ), 1 ); const int faceNumber = intersection.indexInInside(); const unsigned int faceSize = refElement.size( faceNumber, 1, dimGrid ); gridout << bndId << " "; for( auto i : range( faceSize ) ) { const int j = refElement.subEntity( faceNumber, 1, i, dimGrid ); gridout << " " << dgfIndices[ indexSet.subIndex( element, j, dimGrid ) ]; } appendBoundaryData( gridout, data ); } } gridout << "#" << std::endl; } template< class GV > template< class BoundaryData > inline void DGFWriter< GV >::write ( std::ostream &gridout, const std::vector< Index > &newElemOrder, BoundaryData &&boundaryData, const std::stringstream &addParams ) const { writeHeader( gridout ); auto dgfIndices = writeVertices( gridout ); writeElements( gridout, dgfIndices, elementSeeds( newElemOrder ) ); writeBoundaries( gridout, dgfIndices, std::forward< BoundaryData >( boundaryData ) ); gridout << addParams.str(); writeFooter( gridout ); } template< class GV > template< class BoundaryData > inline void DGFWriter< GV >::write ( std::ostream &gridout, BoundaryData &&boundaryData, const std::stringstream &addParams ) const { writeHeader( gridout ); auto dgfIndices = writeVertices( gridout ); writeElements( gridout, dgfIndices ); writeBoundaries( gridout, dgfIndices, std::forward< BoundaryData >( boundaryData ) ); gridout << addParams.str(); writeFooter( gridout ); } } // namespace Dune #endif // #ifndef DUNE_GRID_IO_FILE_DGFPARSER_DGFWRITER_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/dgfyasp.hh000066400000000000000000000355601511655130300226230ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGFPARSERYASP_HH #define DUNE_DGFPARSERYASP_HH #include #include #include "dgfparser.hh" namespace Dune { // External Forward Declarations // ----------------------------- template< class GridImp, class IntersectionImp > class Intersection; namespace dgf { /** \brief Grid parameters for YaspGrid * \ingroup DGFGridParameter * * The YaspGridParameter class is in charge of passing parameters specific * to YaspGrid to the grid construction. * Current parameters are: * -# \b overlap defining the overlap of the grid (default value is zero) * . * See the \b examplegrid5.dgf file for an example. * * \note The \b periodic parameter has been replaced by the * \b PeriodicFaceTransformation block. */ class YaspGridParameterBlock : public GridParameterBlock { protected: int _overlap; // overlap for YaspGrid public: //! constructor taking istream YaspGridParameterBlock( std::istream &in ) : GridParameterBlock( in ), _overlap( 0 ) // default value { // check overlap if( findtoken( "overlap" ) ) { int x; if( getnextentry(x) ) _overlap = x; else { dwarn << "GridParameterBlock: found keyword `overlap' but no value, defaulting to `" << _overlap <<"' !\n"; } if (_overlap < 0) { DUNE_THROW(DGFException,"Negative overlap specified!"); } } else { dwarn << "YaspGridParameterBlock: Parameter 'overlap' not specified, " << "defaulting to '" << _overlap << "'." << std::endl; } } //! get dimension of world found in block int overlap () const { return _overlap; } }; } /*! * \brief Grid factory for YaspGrid with equidistant coordinates. */ template struct DGFGridFactory< YaspGrid > > { typedef YaspGrid > Grid; const static int dimension = Grid::dimension; typedef MPIHelper::MPICommunicator MPICommunicatorType; private: typedef FieldVector< ctype, dimension > Point; typedef dgf::BoundaryDomBlock BoundaryDomainBlock; public: explicit DGFGridFactory ( std::istream &input, MPICommunicatorType comm = MPIHelper::getCommunicator() ) { generate( input, comm ); } explicit DGFGridFactory ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ) { std::ifstream input( filename.c_str() ); if( !input ) DUNE_THROW( DGFException, "Error: Macrofile '" << filename << "' not found" ); generate( input, comm ); } ~DGFGridFactory () { delete boundaryDomainBlock_; } Grid *grid() const { return grid_; } template bool wasInserted(const Intersection &intersection) const { return false; } template int boundaryId(const Intersection &intersection) const { if( boundaryDomainBlock_->isactive() ) { std::vector< Point > corners; getCorners( intersection.geometry(), corners ); const dgf::DomainData *data = boundaryDomainBlock_->contains( corners ); if( data ) return data->id(); else return intersection.indexInInside(); } else return intersection.indexInInside(); } template< int codim > int numParameters () const { return 0; } // return true if boundary parameters found bool haveBoundaryParameters () const { return boundaryDomainBlock_->hasParameter(); } template< class GG, class II > const typename DGFBoundaryParameter::type & boundaryParameter ( const Intersection< GG, II > & intersection ) const { if( haveBoundaryParameters() ) { std::vector< Point > corners; getCorners( intersection.geometry(), corners ); const dgf::DomainData *data = boundaryDomainBlock_->contains( corners ); if( data ) return data->parameter(); else return DGFBoundaryParameter::defaultValue(); } else return DGFBoundaryParameter::defaultValue(); } template< class Entity > std::vector ¶meter ( const Entity & ) { return emptyParam; } private: void generate( std::istream &gridin, MPICommunicatorType comm ); template< class Geometry > static void getCorners ( const Geometry &geometry, std::vector< Point > &corners ) { corners.resize( geometry.corners() ); for( int i = 0; i < geometry.corners(); ++i ) { const typename Geometry::GlobalCoordinate corner = geometry.corner( i ); for( int j = 0; j < dimension; ++j ) corners[ i ][ j ] = corner[ j ]; } } Grid *grid_; dgf::BoundaryDomBlock *boundaryDomainBlock_; std::vector emptyParam; }; // generate YaspGrid from the provided DGF template< typename ctype, int dim > inline void DGFGridFactory< YaspGrid< dim , EquidistantCoordinates > > ::generate ( std::istream &gridin, MPICommunicatorType comm ) { using std::abs; dgf::IntervalBlock intervalBlock( gridin ); if( !intervalBlock.isactive() ) DUNE_THROW( DGFException, "YaspGrid can only be created from an interval block." ); if( intervalBlock.numIntervals() != 1 ) DUNE_THROW( DGFException, "YaspGrid can only handle 1 interval block." ); if( intervalBlock.dimw() != dim ) { DUNE_THROW( DGFException, "Cannot read an interval of dimension " << intervalBlock.dimw() << " into a YaspGrid< " << dim << " >." ); } const dgf::IntervalBlock::Interval &interval = intervalBlock.get( 0 ); FieldVector lang; std::array anz; for( int i = 0; i < dim; ++i ) { // check that start point is 0.0 if( abs( interval.p[ 0 ][ i ] ) > 1e-10 ) { DUNE_THROW( DGFException, "YaspGrid cannot handle grids with non-zero left lower corner." ); } lang[ i ] = interval.p[ 1 ][ i ] - interval.p[ 0 ][ i ]; anz[ i ] = interval.n[ i ]; } typedef dgf::PeriodicFaceTransformationBlock::AffineTransformation Transformation; dgf::PeriodicFaceTransformationBlock trafoBlock( gridin, dim ); std::bitset< dim > per; const int numTrafos = trafoBlock.numTransformations(); for( int k = 0; k < numTrafos; ++k ) { const Transformation &trafo = trafoBlock.transformation( k ); bool identity = true; for( int i = 0; i < dim; ++i ) for( int j = 0; j < dim; ++j ) identity &= (abs( (i == j ? 1.0 : 0.0) - trafo.matrix( i, j ) ) < 1e-10); if( !identity ) DUNE_THROW( DGFException, "YaspGrid can only handle shifts as periodic face transformations." ); int numDirs = 0; int dir = -1; for( int i = 0; i < dim; ++i ) { if( abs( trafo.shift[ i ] ) < 1e-10 ) continue; dir = i; ++numDirs; } if( (numDirs != 1) || (abs( abs( trafo.shift[ dir ] ) - lang[ dir ] ) >= 1e-10) ) { std::cerr << "Transformation '" << trafo << "' does not map boundaries on boundaries." << std::endl; } else per[ dir ] = true; } // get grid parameters dgf::YaspGridParameterBlock grdParam( gridin ); grid_ = new YaspGrid< dim , EquidistantCoordinates >( lang, anz, per, grdParam.overlap(), comm ); boundaryDomainBlock_ = new dgf::BoundaryDomBlock( gridin, dimension ); } /*! * \brief Grid factory for YaspGrid with equidistant coordinates. */ template struct DGFGridFactory< YaspGrid > > { typedef YaspGrid > Grid; const static int dimension = Grid::dimension; typedef MPIHelper::MPICommunicator MPICommunicatorType; private: typedef FieldVector< ctype, dimension > Point; typedef dgf::BoundaryDomBlock BoundaryDomainBlock; public: explicit DGFGridFactory ( std::istream &input, MPICommunicatorType comm = MPIHelper::getCommunicator() ) { generate( input, comm ); } explicit DGFGridFactory ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ) { std::ifstream input( filename.c_str() ); generate( input, comm ); } ~DGFGridFactory () { delete boundaryDomainBlock_; } Grid *grid() const { return grid_; } template bool wasInserted(const Intersection &intersection) const { return false; } template int boundaryId(const Intersection &intersection) const { if( boundaryDomainBlock_->isactive() ) { std::vector< Point > corners; getCorners( intersection.geometry(), corners ); const dgf::DomainData *data = boundaryDomainBlock_->contains( corners ); if( data ) return data->id(); else return intersection.indexInInside(); } else return intersection.indexInInside(); } template< int codim > int numParameters () const { return 0; } // return true if boundary parameters found bool haveBoundaryParameters () const { return boundaryDomainBlock_->hasParameter(); } template< class GG, class II > const typename DGFBoundaryParameter::type & boundaryParameter ( const Intersection< GG, II > & intersection ) const { if( haveBoundaryParameters() ) { std::vector< Point > corners; getCorners( intersection.geometry(), corners ); const dgf::DomainData *data = boundaryDomainBlock_->contains( corners ); if( data ) return data->parameter(); else return DGFBoundaryParameter::defaultValue(); } else return DGFBoundaryParameter::defaultValue(); } template< class Entity > std::vector ¶meter ( [[maybe_unused]] const Entity &entity ) { return emptyParam; } private: void generate( std::istream &gridin, MPICommunicatorType comm ); template< class Geometry > static void getCorners ( const Geometry &geometry, std::vector< Point > &corners ) { corners.resize( geometry.corners() ); for( int i = 0; i < geometry.corners(); ++i ) { const typename Geometry::GlobalCoordinate corner = geometry.corner( i ); for( int j = 0; j < dimension; ++j ) corners[ i ][ j ] = corner[ j ]; } } Grid *grid_; dgf::BoundaryDomBlock *boundaryDomainBlock_; std::vector emptyParam; }; // generate YaspGrid from the provided DGF template< typename ctype, int dim > inline void DGFGridFactory< YaspGrid > > ::generate ( std::istream &gridin, MPICommunicatorType comm ) { using std::abs; dgf::IntervalBlock intervalBlock( gridin ); if( !intervalBlock.isactive() ) DUNE_THROW( DGFException, "YaspGrid can only be created from an interval block." ); if( intervalBlock.numIntervals() != 1 ) DUNE_THROW( DGFException, "YaspGrid can only handle 1 interval block." ); if( intervalBlock.dimw() != dim ) { DUNE_THROW( DGFException, "Cannot read an interval of dimension " << intervalBlock.dimw() << " into a YaspGrid< " << dim << " >." ); } const dgf::IntervalBlock::Interval &interval = intervalBlock.get( 0 ); FieldVector lower; FieldVector upper; std::array anz; for( int i = 0; i < dim; ++i ) { lower[ i ] = interval.p[ 0 ][ i ]; upper[ i ] = interval.p[ 1 ][ i ]; anz[ i ] = interval.n[ i ]; } typedef dgf::PeriodicFaceTransformationBlock::AffineTransformation Transformation; dgf::PeriodicFaceTransformationBlock trafoBlock( gridin, dim ); std::bitset< dim > periodic; const int numTrafos = trafoBlock.numTransformations(); for( int k = 0; k < numTrafos; ++k ) { const Transformation &trafo = trafoBlock.transformation( k ); bool identity = true; for( int i = 0; i < dim; ++i ) for( int j = 0; j < dim; ++j ) identity &= (abs( (i == j ? 1.0 : 0.0) - trafo.matrix( i, j ) ) < 1e-10); if( !identity ) DUNE_THROW( DGFException, "YaspGrid can only handle shifts as periodic face transformations." ); int numDirs = 0; int dir = -1; for( int currentDir = 0; currentDir < dim; ++currentDir ) { if( abs( trafo.shift[ currentDir ] ) > 1e-10 ) { dir = currentDir; ++numDirs; } } if ( (numDirs != 1) || (abs( abs( trafo.shift[ dir ] ) - abs( upper[ dir ] - lower[ dir ] ) ) >= 1e-10) ) { std::cerr << "Transformation '" << trafo << "' does not map boundaries on boundaries." << std::endl; } else { periodic[ dir ] = true; } } // get grid parameters dgf::YaspGridParameterBlock grdParam( gridin ); grid_ = new YaspGrid< dim, EquidistantOffsetCoordinates > ( lower, upper, anz, periodic, grdParam.overlap(), comm ); boundaryDomainBlock_ = new dgf::BoundaryDomBlock( gridin, dimension ); } /*! * \brief Placeholder for grid factory for YaspGrid with tensor product coordinates. * * currently tensor product coordinates are currently not supported. Triggers a run time error. */ template< class ctype, int dim > class DGFGridFactory< Dune::YaspGrid > > { using Grid = Dune::YaspGrid >; public: template< typename In > DGFGridFactory ( const In & ) {} Grid *grid() { throw std::invalid_argument( "Tensor product coordinates for YaspGrid are currently not supported via the DGFGridFactory" ); } }; template struct DGFGridInfo< YaspGrid > { static int refineStepsForHalf() {return 1;} static double refineWeight() {return std::pow(0.5,dim);} }; } #endif // #ifndef DUNE_DGFPARSERYASP_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/entitykey.hh000066400000000000000000000065151511655130300232110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGFEnTITYKEY_HH #define DUNE_DGFEnTITYKEY_HH #include #include #include namespace Dune { // DGFEntityKey // ------------ template< class A > struct DGFEntityKey { DGFEntityKey ( const std :: vector< A > &key, bool setOrigKey = true ); DGFEntityKey ( const std::vector< A > &key, int N, int offset, bool setOrigKey = true ); DGFEntityKey ( const DGFEntityKey< A > &k ); DGFEntityKey< A > &operator= ( const DGFEntityKey< A > &k ); inline const A &operator[] ( int i ) const; inline bool operator < ( const DGFEntityKey< A > &k ) const; void orientation ( int base, std :: vector< std :: vector< double > > &vtx ); void print( std :: ostream &out = std :: cerr ) const; inline bool origKeySet () const; inline const A &origKey ( int i ) const; inline int size () const; private: std :: vector< A > key_, origKey_; bool origKeySet_; }; template< class A > inline const A &DGFEntityKey< A > :: operator[] ( int i ) const { return key_[ i ]; } template< class A > inline bool DGFEntityKey< A > :: operator< ( const DGFEntityKey< A > &k ) const { // assert(k.key_.size()==key_.size()); return key_ < k.key_; } template< class A > inline bool DGFEntityKey< A > :: origKeySet () const { return origKeySet_; } template< class A > inline const A &DGFEntityKey< A > :: origKey ( int i ) const { return origKey_[ i ]; } template< class A > inline int DGFEntityKey< A > :: size () const { return key_.size(); } // ElementFaceUtil // --------------- struct ElementFaceUtil { inline static int nofFaces ( int dim, const std::vector< unsigned int > &element ); inline static int faceSize ( int dim, bool simpl ); static DGFEntityKey< unsigned int > generateFace ( int dim, const std::vector< unsigned int > &element, int f ); private: template< int dim > static DGFEntityKey< unsigned int > generateCubeFace( const std::vector< unsigned int > &element, int f ); template< int dim > static DGFEntityKey< unsigned int > generateSimplexFace ( const std::vector< unsigned int > &element, int f ); }; inline int ElementFaceUtil::nofFaces ( int dim, const std::vector< unsigned int > &element ) { switch( dim ) { case 1 : return 2; case 2 : switch( element.size() ) { case 3 : return 3; case 4 : return 4; default : return -1; } case 3 : switch( element.size() ) { case 4 : return 4; case 8 : return 6; default : return -1; } default : return -1; } } inline int ElementFaceUtil::faceSize( int dim, bool simpl ) { switch( dim ) { case 1 : return 1; case 2 : return 2; case 3 : return (simpl ? 3 : 4); default : return -1; } } } //end namespace Dune // include inline implementation #include "entitykey_inline.hh" #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/entitykey_inline.hh000066400000000000000000000122001511655130300245330ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ENTITYKEY_INLINE_HH #define DUNE_ENTITYKEY_INLINE_HH #include #include #include namespace Dune { // DGFEntityKey // ------------ template< class A > inline DGFEntityKey< A > :: DGFEntityKey ( const std :: vector< A > &key, bool setOrigKey ) : key_( key.size() ), origKey_( key.size() ), origKeySet_( setOrigKey ) { for (size_t i=0; i inline DGFEntityKey< A > :: DGFEntityKey ( const std :: vector< A > &key, int N, int offset, bool setOrigKey ) : key_( N ), origKey_( N ), origKeySet_( setOrigKey ) { for (size_t i=0; i inline DGFEntityKey< A > :: DGFEntityKey ( const DGFEntityKey< A > &k ) : key_( k.key_.size() ), origKey_( k.key_.size() ), origKeySet_( k. origKeySet_ ) { for (size_t i=0; i inline DGFEntityKey< A > &DGFEntityKey< A > :: operator= ( const DGFEntityKey< A > &k ) { assert(key_.size()==k.key_.size()); for (size_t i=0; i inline void DGFEntityKey< A > :: orientation ( int base, std::vector< std :: vector< double > > &vtx ) { if (key_.size()==3) { assert( (size_t) origKey_[0] < vtx.size() ); std::vector& p0 = vtx[origKey_[0]]; assert( (size_t) origKey_[1] < vtx.size() ); std::vector& p1 = vtx[origKey_[1]]; assert( (size_t) origKey_[2] < vtx.size() ); std::vector& p2 = vtx[origKey_[2]]; assert( (size_t) base < vtx.size() ); std::vector& q = vtx[base]; double n[3]; n[0] = (p1[1]-p0[1])*(p2[2]-p0[2])-(p2[1]-p0[1])*(p1[2]-p0[2]); n[1] = (p1[2]-p0[2])*(p2[0]-p0[0])-(p2[2]-p0[2])*(p1[0]-p0[0]); n[2] = (p1[0]-p0[0])*(p2[1]-p0[1])-(p2[0]-p0[0])*(p1[1]-p0[1]); double test = n[0]*(q[0]-p0[0])+n[1]*(q[1]-p0[1])+n[2]*(q[2]-p0[2]); bool reorient = (test>0); if (reorient) { A key1=origKey_[1]; origKey_[1]=origKey_[2]; origKey_[2]=key1; } } } template< class A > inline void DGFEntityKey< A > :: print ( std :: ostream &out ) const { for( size_t i = 0; i < key_.size(); ++i ) out << key_[ i ] << " "; out << std :: endl; } // ElementFaceUtil // --------------- template< int dim > inline DGFEntityKey< unsigned int > ElementFaceUtil::generateCubeFace ( const std::vector< unsigned int > &element, int f ) { auto refCube = ReferenceElements< double, dim >::cube(); const unsigned int size = refCube.size( f, 1, dim ); std::vector< unsigned int > k( size ); for( unsigned int i = 0; i < size; ++ i ) k[ i ] = element[ refCube.subEntity( f, 1, i, dim ) ]; return DGFEntityKey< unsigned int >( k ); } template< int dim > inline DGFEntityKey< unsigned int > ElementFaceUtil :: generateSimplexFace ( const std :: vector< unsigned int > &element, int f ) { auto refSimplex = ReferenceElements< double, dim >::simplex(); const unsigned int size = refSimplex.size( f, 1, dim ); std :: vector< unsigned int > k( size ); for( unsigned int i = 0; i < size; ++i ) k[ i ] = element[ refSimplex.subEntity( f, 1, i, dim ) ]; return DGFEntityKey< unsigned int >( k ); } inline DGFEntityKey< unsigned int > ElementFaceUtil::generateFace ( int dim, const std::vector< unsigned int > &element, int f ) { if( element.size() == size_t(dim+1) ) { // Simplex element switch( dim ) { case 3 : return generateSimplexFace< 3 >( element, f ); case 2 : return generateSimplexFace< 2 >( element, f ); case 1 : return generateSimplexFace< 1 >( element, f ); default : DUNE_THROW( NotImplemented, "ElementUtil::generateFace not implemented for dim = " << dim << "." ); } } else { // Cube element switch( dim ) { case 3 : return generateCubeFace< 3 >( element, f ); case 2 : return generateCubeFace< 2 >( element, f ); case 1 : return generateCubeFace< 1 >( element, f ); default : DUNE_THROW( NotImplemented, "ElementUtil::generateFace not implemented for dim = " << dim << "." ); } } } } // end namespace Dune #endif // DUNE_ENTITYKEY_INLINE_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/gridptr.hh000066400000000000000000000644621511655130300226440ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_GRIDPTR_HH #define DUNE_DGF_GRIDPTR_HH #include #include #include #include #include #include #include #include #include //- Dune includes #include #include #include #include #include #include #include #include #include #include #include namespace Dune { // External Forward Declarations // ----------------------------- template < class G > struct DGFGridFactory; template< class GridImp, class IntersectionImp > class Intersection; // GridPtr // ------- //! \brief Class for constructing grids from DGF files. //! //! The constructor of the class is given the filename of the DGF file. //! From that file a pointer to an instance of type GridType is created by reading //! the given file which is translated to the specific format of the given //! GridType. The GridPtr class behaves like an auto pointer of GridType. //! An auto pointer to a grid of type GridType is constructed //! as follows: //! @code //! GridPtr gridptr(filename, MPI_COMM_WORLD ); //! GridType & grid = *gridptr; //! @endcode template< class GridType > struct GridPtr { class mygrid_ptr : public std::shared_ptr< GridType > { typedef std::shared_ptr< GridType > base_t ; // empty deleter to avoid deletion on release typedef null_deleter< GridType > emptydeleter_t ; void removeObj() { // if use count is only 1 delete object if( use_count() == 1 ) { // delete point here, since we use the empty deleter GridType* grd = release(); if( grd ) delete grd ; } } void assignObj( const mygrid_ptr& other ) { removeObj(); base_t :: operator = ( other ); } public: using base_t :: get ; using base_t :: swap ; using base_t :: use_count ; // default constructor mygrid_ptr() : base_t( ( GridType * ) 0, emptydeleter_t() ) {} // copy constructor mygrid_ptr( const mygrid_ptr& other ) : base_t(nullptr) { assignObj( other ); } // constructor taking pointer explicit mygrid_ptr( GridType* grd ) : base_t( grd, emptydeleter_t() ) {} // destructor ~mygrid_ptr() { removeObj(); } // assignment operator mygrid_ptr& operator = ( const mygrid_ptr& other ) { assignObj( other ); return *this; } // release pointer GridType* release() { GridType* grd = this->get(); base_t ptr(( GridType * ) 0, emptydeleter_t() ); this->swap( ptr ); return grd ; } }; protected: std::string getFileExtension( const std::string& filename ) const { // extract file extension auto extpos = filename.find_last_of("."); std::string ext; if( extpos != std::string::npos) ext = filename.substr( extpos + 1 ); // convert all letters to lower case for( auto& item : ext ) item = std::tolower( item ); return ext; } // read gmsh file if dimension world <= 3 void readGmsh( const std::string& filename, std::integral_constant< bool, true > ) { GridFactory gridFactory; std::vector boundaryIDs; std::vector elementsIDs; GmshReader::read(gridFactory,filename,boundaryIDs,elementsIDs); initialize( gridFactory, boundaryIDs,elementsIDs); } // if dimension world > 3 throw GridError void readGmsh( const std::string& /*filename*/, std::integral_constant< bool, false > ) { DUNE_THROW(GridError, "GmshReader requires dimWorld <= 3." ); } public: typedef MPIHelper::MPICommunicator MPICommunicatorType; static const int dimension = GridType::dimension; //! constructor given the name of a DGF file explicit GridPtr ( const std::string &filename, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : gridPtr_(), elParam_(), vtxParam_(), bndParam_(), bndId_(), emptyParam_(), nofElParam_( 0 ), nofVtxParam_( 0 ), haveBndParam_( false ) { std::string fileExt = getFileExtension( filename ); if( fileExt == "dgf" ) { DGFGridFactory< GridType > dgfFactory( filename, comm ); initialize( dgfFactory ); } else if( fileExt == "msh" ) { // Gmsh reader only compiles for dimworld <= 3 readGmsh( filename, std::integral_constant< bool, GridType::dimensionworld <= 3 > () ); } else if( fileExt == "amc" || fileExt == "2d" || fileExt == "3d" ) { // TODO: AlbertaReader DUNE_THROW( NotImplemented, "GridPtr: file format '" << fileExt << "' not supported yet!" ); } else if( fileExt == "vtu" ) { // TODO: vtu/vtk reader DUNE_THROW( NotImplemented, "GridPtr: file format '" << fileExt << "' not supported yet!" ); } else { DUNE_THROW( NotImplemented, "GridPtr: file format '" << fileExt << "' not supported yet!" ); } } //! constructor given a std::istream explicit GridPtr ( std::istream &input, MPICommunicatorType comm = MPIHelper::getCommunicator() ) : gridPtr_(), elParam_(), vtxParam_(), bndParam_(), bndId_(), emptyParam_(), nofElParam_( 0 ), nofVtxParam_( 0 ), haveBndParam_( false ) { // input stream only works for DGF format right now DGFGridFactory< GridType > dgfFactory( input, comm ); initialize( dgfFactory ); } //! Default constructor, creating empty GridPtr GridPtr() : gridPtr_(), elParam_(), vtxParam_(), bndParam_(), bndId_(), emptyParam_(), nofElParam_(0), nofVtxParam_(0), haveBndParam_( false ) {} //! Constructor storing given pointer to internal auto pointer explicit GridPtr( GridType *grd ) : gridPtr_(grd), elParam_(), vtxParam_(), bndParam_(), bndId_(), emptyParam_(), nofElParam_(0), nofVtxParam_(0), haveBndParam_( false ) {} //! Copy constructor, copies internal auto pointer GridPtr( const GridPtr &org ) = default; //! assignment of grid pointer GridPtr& operator= ( const GridPtr &org ) { gridPtr_ = org.gridPtr_; elParam_ = org.elParam_; vtxParam_ = org.vtxParam_; bndParam_ = org.bndParam_; bndId_ = org.bndId_; emptyParam_ = org.emptyParam_; nofElParam_ = org.nofElParam_; nofVtxParam_ = org.nofVtxParam_; haveBndParam_ = org.haveBndParam_; return *this; } //! assignment of pointer to internal auto pointer GridPtr& operator = (GridType * grd) { gridPtr_ = mygrid_ptr( grd ); elParam_.resize(0); vtxParam_.resize(0); bndParam_.resize(0); bndId_.resize(0); emptyParam_.resize(0); nofVtxParam_ = 0; nofElParam_ = 0; haveBndParam_ = false; return *this; } //! return reference to GridType instance GridType& operator*() { return *gridPtr_; } //! return pointer to GridType instance GridType* operator->() { return gridPtr_.operator -> (); } //! return const reference to GridType instance const GridType& operator*() const { return *gridPtr_; } //! return const pointer to GridType instance const GridType* operator->() const { return gridPtr_.operator -> (); } //! release pointer from internal ownership GridType* release () { return gridPtr_.release(); } //! get number of parameters defined for a given codimension int nofParameters(int cdim) const { switch (cdim) { case 0 : return nofElParam_; break; case GridType::dimension : return nofVtxParam_; break; } return 0; } //! get parameters defined for given entity template int nofParameters ( const Entity & ) const { return nofParameters( (int) Entity::codimension ); } //! get number of parameters defined for a given intersection template< class GridImp, class IntersectionImp > int nofParameters ( const Intersection< GridImp, IntersectionImp > & intersection ) const { return parameters( intersection ).size(); } //! get parameters defined for each codim 0 und dim entity on the grid through the grid file template const std::vector< double > ¶meters ( const Entity &entity ) const { typedef typename GridType::LevelGridView GridView; GridView gridView = gridPtr_->levelGridView( 0 ); switch( (int)Entity::codimension ) { case 0 : if( nofElParam_ > 0 ) { assert( (unsigned int)gridView.indexSet().index( entity ) < elParam_.size() ); return elParam_[ gridView.indexSet().index( entity ) ]; } break; case GridType::dimension : if( nofVtxParam_ > 0 ) { assert( (unsigned int)gridView.indexSet().index( entity ) < vtxParam_.size() ); return vtxParam_[ gridView.indexSet().index( entity ) ]; } break; } return emptyParam_; } //! get parameters for intersection template< class GridImp, class IntersectionImp > const DGFBoundaryParameter::type & parameters ( const Intersection< GridImp, IntersectionImp > & intersection ) const { // if no parameters given return empty vector if ( !haveBndParam_ ) return DGFBoundaryParameter::defaultValue(); return bndParam_[ intersection.boundarySegmentIndex() ]; } void communicate () { if( gridPtr_->comm().size() > 1 ) { DataHandle dh(*this); gridPtr_->levelGridView( 0 ).communicate( dh.interface(), InteriorBorder_All_Interface,ForwardCommunication ); } } void loadBalance () { if( gridPtr_->comm().size() > 1 ) { DataHandle dh(*this); gridPtr_->loadBalance( dh.interface() ); gridPtr_->levelGridView( 0 ).communicate( dh.interface(), InteriorBorder_All_Interface,ForwardCommunication ); } } protected: template< class Range > static bool isEmpty ( Range &&range ) { return range.begin() == range.end(); } void initialize ( DGFGridFactory< GridType > &dgfFactory ) { gridPtr_ = mygrid_ptr( dgfFactory.grid() ); const auto gridView = gridPtr_->levelGridView( 0 ); const auto &indexSet = gridView.indexSet(); nofElParam_ = dgfFactory.template numParameters< 0 >(); nofVtxParam_ = dgfFactory.template numParameters< dimension >(); haveBndParam_ = dgfFactory.haveBoundaryParameters(); std::array< int, 3 > nofParams = {{ nofElParam_, nofVtxParam_, static_cast< int >( haveBndParam_ ) }}; gridView.comm().max( nofParams.data(), nofParams.size() ); // empty grids have no parameters associated if( isEmpty( elements( gridView, Partitions::interiorBorder ) ) ) { nofElParam_ = nofParams[ 0 ]; nofVtxParam_ = nofParams[ 1 ]; } // boundary parameters may be empty haveBndParam_ = static_cast< bool >( nofParams[ 2 ] ); if( (nofElParam_ != nofParams[ 0 ]) || (nofVtxParam_ != nofParams[ 1 ]) ) DUNE_THROW( DGFException, "Number of parameters differs between processes" ); elParam_.resize( nofElParam_ > 0 ? indexSet.size( 0 ) : 0 ); vtxParam_.resize( nofVtxParam_ > 0 ? indexSet.size( dimension ) : 0 ); bndId_.resize( indexSet.size( 1 ) ); if( haveBndParam_ ) bndParam_.resize( gridPtr_->numBoundarySegments() ); for( const auto &element : elements( gridView, Partitions::interiorBorder ) ) { if( nofElParam_ > 0 ) { std::swap( elParam_[ indexSet.index( element ) ], dgfFactory.parameter( element ) ); assert( elParam_[ indexSet.index( element ) ].size() == static_cast< std::size_t >( nofElParam_ ) ); } if( nofVtxParam_ > 0 ) { for( unsigned int v = 0, n = element.subEntities( dimension ); v < n; ++v ) { const auto index = indexSet.subIndex( element, v, dimension ); if( vtxParam_[ index ].empty() ) std::swap( vtxParam_[ index ], dgfFactory.parameter( element.template subEntity< dimension >( v ) ) ); assert( vtxParam_[ index ].size() == static_cast< std::size_t >( nofVtxParam_ ) ); } } if( element.hasBoundaryIntersections() ) { for( const auto &intersection : intersections( gridView, element ) ) { // dirty hack: check for "none" to make corner point grid work if( !intersection.boundary() || intersection.type().isNone() ) continue; const auto k = indexSet.subIndex( element, intersection.indexInInside(), 1 ); bndId_[ k ] = dgfFactory.boundaryId( intersection ); if( haveBndParam_ ) bndParam_[ intersection.boundarySegmentIndex() ] = dgfFactory.boundaryParameter( intersection ); } } } } void initialize ( GridFactory< GridType > &factory, std::vector& boundaryIds, std::vector& elementIds ) { gridPtr_ = mygrid_ptr( factory.createGrid().release() ); const auto& gridView = gridPtr_->leafGridView(); const auto& indexSet = gridView.indexSet(); nofElParam_ = elementIds.empty() ? 0 : 1 ; nofVtxParam_ = 0; haveBndParam_ = boundaryIds.empty() ? 0 : 1 ; std::array< int, 3 > nofParams = {{ nofElParam_, nofVtxParam_, static_cast< int >( haveBndParam_ ) }}; gridView.comm().max( nofParams.data(), nofParams.size() ); // empty grids have no parameters associated if( isEmpty( elements( gridView, Partitions::interiorBorder ) ) ) { nofElParam_ = nofParams[ 0 ]; } // boundary parameters may be empty haveBndParam_ = static_cast< bool >( nofParams[ 2 ] ); // Reorder boundary IDs according to the insertion index if(!boundaryIds.empty() || !elementIds.empty() ) { bndParam_.resize( boundaryIds.size() ); elParam_.resize( elementIds.size(), std::vector(1) ); for(const auto& entity : elements( gridView )) { elParam_[ indexSet.index( entity ) ][ 0 ] = elementIds[ factory.insertionIndex( entity ) ]; if( haveBndParam_ ) { for(const auto& intersection : intersections( gridView,entity) ) { if(intersection.boundary()) { // DGFBoundaryParameter::type is of type string. bndParam_[intersection.boundarySegmentIndex()] = std::to_string(boundaryIds[factory.insertionIndex(intersection)]); } } } } } } template std::vector< double > ¶ms ( const Entity &entity ) { const auto gridView = gridPtr_->levelGridView( 0 ); switch( (int)Entity::codimension ) { case 0 : if( nofElParam_ > 0 ) { if ( gridView.indexSet().index( entity ) >= elParam_.size() ) elParam_.resize( gridView.indexSet().index( entity ) ); return elParam_[ gridView.indexSet().index( entity ) ]; } break; case GridType::dimension : if( nofVtxParam_ > 0 ) { if ( gridView.indexSet().index( entity ) >= vtxParam_.size() ) vtxParam_.resize( gridView.indexSet().index( entity ) ); return vtxParam_[ gridView.indexSet().index( entity ) ]; } break; } return emptyParam_; } void setNofParams( int cdim, int nofP ) { switch (cdim) { case 0 : nofElParam_ = nofP; break; case GridType::dimension : nofVtxParam_ = nofP; break; } } struct DataHandle : public CommDataHandleIF< DataHandle, char > { explicit DataHandle ( GridPtr &gridPtr ) : gridPtr_( gridPtr ), idSet_( gridPtr->localIdSet() ) { const auto gridView = gridPtr_->levelGridView( 0 ); const auto &indexSet = gridView.indexSet(); for( const auto &element : elements( gridView, Partitions::interiorBorder ) ) { if( gridPtr_.nofElParam_ > 0 ) std::swap( gridPtr_.elParam_[ indexSet.index( element ) ], elData_[ idSet_.id( element ) ] ); if( gridPtr_.nofVtxParam_ > 0 ) { for( unsigned int v = 0, n = element.subEntities( dimension ); v < n; ++v ) { const auto index = indexSet.subIndex( element, v, dimension ); if ( !gridPtr_.vtxParam_[ index ].empty() ) std::swap( gridPtr_.vtxParam_[ index ], vtxData_[ idSet_.subId( element, v, dimension ) ] ); } } if( element.hasBoundaryIntersections() ) { for( const auto &intersection : intersections( gridView, element ) ) { // dirty hack: check for "none" to make corner point grid work if( !intersection.boundary() || intersection.type().isNone() ) continue; const int i = intersection.indexInInside(); auto &bndData = bndData_[ idSet_.subId( element, i, 1 ) ]; bndData.first = gridPtr_.bndId_[ indexSet.subIndex( element, i, 1 ) ]; if( gridPtr_.haveBndParam_ ) std::swap( bndData.second, gridPtr_.bndParam_[ intersection.boundarySegmentIndex() ] ); } } } } DataHandle ( const DataHandle & ) = delete; DataHandle ( DataHandle && ) = delete; ~DataHandle () { const auto gridView = gridPtr_->levelGridView( 0 ); const auto &indexSet = gridView.indexSet(); if( gridPtr_.nofElParam_ > 0 ) gridPtr_.elParam_.resize( indexSet.size( 0 ) ); if( gridPtr_.nofVtxParam_ > 0 ) gridPtr_.vtxParam_.resize( indexSet.size( dimension ) ); gridPtr_.bndId_.resize( indexSet.size( 1 ) ); if( gridPtr_.haveBndParam_ ) gridPtr_.bndParam_.resize( gridPtr_->numBoundarySegments() ); for( const auto &element : elements( gridView, Partitions::all ) ) { if( gridPtr_.nofElParam_ > 0 ) { std::swap( gridPtr_.elParam_[ indexSet.index( element ) ], elData_[ idSet_.id( element ) ] ); assert( gridPtr_.elParam_[ indexSet.index( element ) ].size() == static_cast< std::size_t >( gridPtr_.nofElParam_ ) ); } if( gridPtr_.nofVtxParam_ > 0 ) { for( unsigned int v = 0; v < element.subEntities( dimension ); ++v ) { const auto index = indexSet.subIndex( element, v, dimension ); if( gridPtr_.vtxParam_[ index ].empty() ) std::swap( gridPtr_.vtxParam_[ index ], vtxData_[ idSet_.subId( element, v, dimension ) ] ); assert( gridPtr_.vtxParam_[ index ].size() == static_cast< std::size_t >( gridPtr_.nofVtxParam_ ) ); } } if( element.hasBoundaryIntersections() ) { for( const auto &intersection : intersections( gridView, element ) ) { // dirty hack: check for "none" to make corner point grid work if( !intersection.boundary() || intersection.type().isNone() ) continue; const int i = intersection.indexInInside(); auto &bndData = bndData_[ idSet_.subId( element, i, 1 ) ]; gridPtr_.bndId_[ indexSet.subIndex( element, i, 1 ) ] = bndData.first; if( gridPtr_.haveBndParam_ ) std::swap( bndData.second, gridPtr_.bndParam_[ intersection.boundarySegmentIndex() ] ); } } } } CommDataHandleIF< DataHandle, char > &interface () { return *this; } bool contains ( int dim, int codim ) const { assert( dim == dimension ); // do not use a switch statement, because dimension == 1 is possible return (codim == 1) || ((codim == dimension) && (gridPtr_.nofVtxParam_ > 0)) || ((codim == 0) && (gridPtr_.nofElParam_ > 0)); } bool fixedSize (int /* dim */, int /* codim */) const { return false; } template< class Entity > std::size_t size ( const Entity &entity ) const { std::size_t totalSize = 0; // do not use a switch statement, because dimension == 1 is possible if( (Entity::codimension == 0) && (gridPtr_.nofElParam_ > 0) ) { assert( elData_[ idSet_.id( entity ) ].size() == static_cast< std::size_t >( gridPtr_.nofElParam_ ) ); for( double &v : elData_[ idSet_.id( entity ) ] ) totalSize += dataSize( v ); } if( (Entity::codimension == dimension) && (gridPtr_.nofVtxParam_ > 0) ) { assert( vtxData_[ idSet_.id( entity ) ].size() == static_cast< std::size_t >( gridPtr_.nofVtxParam_ ) ); for( double &v : vtxData_[ idSet_.id( entity ) ] ) totalSize += dataSize( v ); } if( Entity::codimension == 1 ) { const auto bndData = bndData_.find( idSet_.id( entity ) ); if( bndData != bndData_.end() ) totalSize += dataSize( bndData->second.first ) + dataSize( bndData->second.second ); } return totalSize; } template< class Buffer, class Entity > void gather ( Buffer &buffer, const Entity &entity ) const { // do not use a switch statement, because dimension == 1 is possible if( (Entity::codimension == 0) && (gridPtr_.nofElParam_ > 0) ) { assert( elData_[ idSet_.id( entity ) ].size() == static_cast< std::size_t >( gridPtr_.nofElParam_ ) ); for( double &v : elData_[ idSet_.id( entity ) ] ) write( buffer, v ); } if( (Entity::codimension == dimension) && (gridPtr_.nofVtxParam_ > 0) ) { assert( vtxData_[ idSet_.id( entity ) ].size() == static_cast< std::size_t >( gridPtr_.nofVtxParam_ ) ); for( double &v : vtxData_[ idSet_.id( entity ) ] ) write( buffer, v ); } if( Entity::codimension == 1 ) { const auto bndData = bndData_.find( idSet_.id( entity ) ); if( bndData != bndData_.end() ) { write( buffer, bndData->second.first ); write( buffer, bndData->second.second ); } } } template< class Buffer, class Entity > void scatter ( Buffer &buffer, const Entity &entity, std::size_t n ) { // do not use a switch statement, because dimension == 1 is possible if( (Entity::codimension == 0) && (gridPtr_.nofElParam_ > 0) ) { auto &p = elData_[ idSet_.id( entity ) ]; p.resize( gridPtr_.nofElParam_ ); for( double &v : p ) read( buffer, v, n ); } if( (Entity::codimension == dimension) && (gridPtr_.nofVtxParam_ > 0) ) { auto &p = vtxData_[ idSet_.id( entity ) ]; p.resize( gridPtr_.nofVtxParam_ ); for( double &v : p ) read( buffer, v, n ); } if( (Entity::codimension == 1) && (n > 0) ) { auto &bndData = bndData_[ idSet_.id( entity ) ]; read( buffer, bndData.first, n ); read( buffer, bndData.second, n ); } assert( n == 0 ); } private: template< class T > static std::enable_if_t< std::is_trivially_copyable< T >::value, std::size_t > dataSize ( const T & /* value */ ) { return sizeof( T ); } static std::size_t dataSize ( const std::string &s ) { return dataSize( s.size() ) + s.size(); } template< class Buffer, class T > static std::enable_if_t< std::is_trivially_copyable< T >::value > write ( Buffer &buffer, const T &value ) { std::array< char, sizeof( T ) > bytes; std::memcpy( bytes.data(), &value, sizeof( T ) ); for( char &b : bytes ) buffer.write( b ); } template< class Buffer > static void write ( Buffer &buffer, const std::string &s ) { write( buffer, s.size() ); for( const char &c : s ) buffer.write( c ); } template< class Buffer, class T > static std::enable_if_t< std::is_trivially_copyable< T >::value > read ( Buffer &buffer, T &value, std::size_t &n ) { assert( n >= sizeof( T ) ); n -= sizeof( T ); std::array< char, sizeof( T ) > bytes; for( char &b : bytes ) buffer.read( b ); std::memcpy( &value, bytes.data(), sizeof( T ) ); } template< class Buffer > static void read ( Buffer &buffer, std::string &s, std::size_t &n ) { std::size_t size; read( buffer, size, n ); s.resize( size ); assert( n >= size ); n -= size; for( char &c : s ) buffer.read( c ); } GridPtr &gridPtr_; const typename GridType::LocalIdSet &idSet_; mutable std::map< typename GridType::LocalIdSet::IdType, std::vector< double > > elData_, vtxData_; mutable std::map< typename GridType::LocalIdSet::IdType, std::pair< int, DGFBoundaryParameter::type > > bndData_; }; // grid auto pointer mutable mygrid_ptr gridPtr_; // element and vertex parameters std::vector< std::vector< double > > elParam_; std::vector< std::vector< double > > vtxParam_; std::vector< DGFBoundaryParameter::type > bndParam_; std::vector< int > bndId_; std::vector< double > emptyParam_; int nofElParam_; int nofVtxParam_; bool haveBndParam_; }; // end of class GridPtr } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/macrogrid.hh000066400000000000000000000055321511655130300231310ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_MACROGRID_HH #define DUNE_DGF_MACROGRID_HH #include #include #include namespace Dune { // forward declarations // -------------------- class DuneGridFormatParser; class MacroGrid : protected DuneGridFormatParser { template< class GridType > friend struct DGFGridFactory; public: typedef MPIHelper::MPICommunicator MPICommunicatorType; protected: //! constructor given the name of a DGF file MacroGrid(const char* filename, MPICommunicatorType MPICOMM = MPIHelper::getCommunicator()) : DuneGridFormatParser( rank(MPICOMM), size(MPICOMM) ) , filename_(filename) , MPICOMM_(MPICOMM) {} //! constructor given the name of a DGF file MacroGrid(MPICommunicatorType MPICOMM = MPIHelper::getCommunicator()) : DuneGridFormatParser( rank(MPICOMM), size(MPICOMM) ) , filename_(0) , MPICOMM_(MPICOMM) {} //! returns pointer to a new instance of type GridType created from a DGF file template inline GridType * createGrid () { return Impl::generate(*this,filename_,MPICOMM_); } private: static int rank( [[maybe_unused]] MPICommunicatorType MPICOMM ) { int rank = 0; #if HAVE_MPI MPI_Comm_rank( MPICOMM, &rank ); #endif return rank; } static int size( [[maybe_unused]] MPICommunicatorType MPICOMM ) { int size = 1; #if HAVE_MPI MPI_Comm_size( MPICOMM, &size ); #endif return size; } /** \brief container for the actual grid generation method * * For each grid implementation to be used with the DGF parser, this class * has to be specialized. It has to contain one static method of the * following prototype: \code static GridType * generate ( MacroGrid ¯oGrid, const char *filename, MPIHelper :: MPICommunicator comm = MPIHelper :: getCommunicator() ); \endcode */ template< class GridType > struct Impl { static GridType* generate(MacroGrid& /*mg*/, const char* /*filename*/, [[maybe_unused]] MPICommunicatorType MPICOMM = MPIHelper::getCommunicator() ) { // make assertion depend on the template argument but always evaluate to false static_assert( GridType::dimension<0,"DGF grid factory missing. Did you forget to add the corresponding dgf header?"); } }; const char* filename_; MPICommunicatorType MPICOMM_; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/parser.hh000066400000000000000000000120151511655130300224500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_DGF_DUNEGRIDFORMATPARSER_HH #define DUNE_DGF_DUNEGRIDFORMATPARSER_HH #include #include #include #include #include namespace Dune { class DGFPrintInfo; /*! @brief Contains types for additional features */ struct DGFBoundaryParameter { //! type of additional boundary parameters typedef std::string type; //! default constructor static const type &defaultValue () { static type value; return value; } //! copy from string static type convert ( const std::string & parameter ) { return parameter; } //! delimiter static const char delimiter = ':'; }; //! \brief The %DuneGridFormatParser class: reads a DGF file and stores //! build information in vector structures used by the MacroGrid class. class DuneGridFormatParser { public: typedef enum {Simplex,Cube,General} element_t; typedef enum {counterclockwise=1,clockwise=-1} orientation_t; //! constructor DuneGridFormatParser ( int rank, int size ); /** \brief check whether a stream is in DUNE grid format * * Actually checks whether the stream starts with the keyword 'DGF'. * * \param input std::istream to check * * \note The stream must support seeking. * * \return whether the keyword 'DGF' was found */ static bool isDuneGridFormat ( std::istream &input ); /** \brief check whether a file is in dune grid format * * This is just a convenience method. It calls isDuneGridFormat * with a std::ifstream. * * \param filename file to check * * \return whether the keyword 'DGF' was found */ static bool isDuneGridFormat ( const std::string &filename ); /** \brief parse dune grid format from stream * * This method actually fills the vtx, element, and bound vectors. * * \param input std::istream to read the grid from * \param[in] dimG dimension of the grid (i.e., Grid::dimension) * \param[in] dimW dimension of the world (i.e., Grid::dimensionworld) * * \note The stream must support seeking. * * \returns whether reading succeeded */ bool readDuneGrid( std::istream &input, int dimG, int dimW ); //! method to write in Tetgen/Triangle Poly Format void writeTetgenPoly ( const std::string &, std::string &, std::string & ); void writeTetgenPoly ( std::ostream & out, const bool writeSegments = true ); protected: void generateBoundaries ( std::istream &, bool ); // call to tetgen/triangle void generateSimplexGrid ( std::istream & ); void readTetgenTriangle ( const std::string & ); // helper methods void removeCopies (); void setOrientation ( int use1, int use2, orientation_t orientation=counterclockwise ); void setRefinement ( int use1, int use2, int is1=-1, int is2=-1 ); double testTriang ( int snr ); std::vector< double > & getElParam ( int i, std::vector< double > & coord ); std::vector< double > & getVtxParam ( int i, std::vector< double > & coord ); static std::string temporaryFileName (); // dimension of world and problem: set through the readDuneGrid() method int dimw, dimgrid; // vector of vertex coordinates std::vector < std::vector < double > > vtx; int nofvtx; int vtxoffset; double minVertexDistance; // min. L^1 distance of distinct points // vector of elements std :: vector< std :: vector< unsigned int > > elements; int nofelements; // vector of boundary segments + identifier std::vector < std::vector < int > > bound; int nofbound; // map to generate and find boundary segments typedef DGFBoundaryParameter::type BoundaryParameter; typedef std::pair < int, BoundaryParameter > BndParam; typedef std::map< DGFEntityKey< unsigned int >, BndParam > facemap_t; facemap_t facemap; // true if parameters on a boundary found bool haveBndParameters; // set by generator depending on element type wanted element_t element; // set by the readDuneGrid method depending // on what type the elements were generated bool simplexgrid; // true if grid is generated using the interval Block bool cube2simplex; // parameters on elements int nofvtxparams,nofelparams; std::vector< std::vector< double > > vtxParams,elParams; // write information about generation process DGFPrintInfo * info; std::vector < double > emptyParam_; private: int rank_; int size_; template< class GridType > friend struct DGFGridFactory; template< class GridType > friend struct DGFBaseFactory; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/000077500000000000000000000000001511655130300216135ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/BBEETH1M.d_cut.png000066400000000000000000006133111511655130300245520ustar00rootroot00000000000000PNG  IHDR@IDATxgey~#<;]Ad9lk|x={L9l.p˲`YZRP9];Z3x]m]mwO5Xs|"2}>; >Db=[۝Qo51.8 bD;L!D1 3۲wL_M0_ |WB-C^"  0BlŀFaIe!L`0Gfgϝ:;~^7o}Í7D rdc B@)% ,J)Bj Z+AEض7PB(b`޷||[ 7]޸y8|[r5[hMYɄDZa`D6+!d 'eyڔ2!$1(bFH!DA`VJ" a貜n1L֥ʹA%w}wW Ox":!` .Mu#!4Hì˲ B(c)H ТT@ɘ6F Q&I1[YŋZZ.A#B`!ECZQpnI~R~ӟuRf(y`\sl7Rƀ0 |,RgBHk@XCEHcв| Fa]A,r A)M21lLʽ~0qo:_'.BlzD)1߄ͽLkǘ] c ! NFZ` 0Msm FLwJJB/ hoD e#H$!dE-6%ZE;<R!) w F^?hO7??NŞ77ebo&K-ؐߪjpRgݞ~|.+o\5;fB\T72wm6W;}ˢe)Ry*c ZcR!|hܢcy DF' *)luZ}qo _Ѕ qM0\4iU+$7+Ƭ)=‰syѺ0:;1Kc<qs7ϸ@p1QL) FFHS)4/W \2!-!Uq1aQiz+Na`7H1R(8̶4>1~?W摧Gi) ➃N.toȝof냤Thg?p<T2F |%+WBjZڶL%_T>0VO&uVh-2UkI>$09!y*۱p)H)CO6[h0bA}3G3՛:uqu˲: NJ 1*~03si#- $"l#X4 b7J)NJIZIA|լ0Wٻfj0Xks(U_VHF,gaVs2j^Ljz-w+bS,7_'$MF3uҚiTwڽǸO{sO'slpjP5'fԒ4/c lKٖeYQ%)s-:J򃯀ccˁǒQm9g\/!Vdchmlfά~]Br01ƔP SB֎ɞˊQ^$/{jy$TJej*1,f7+/՝Fŗ!;9cYsSw35T^gTZJ4!l[T ai &hj=;Z&0c,'QBm8!fc[ E$RsKo9sgM]g?"4,XZv*Bf[J#VKA)Z[Ir.BHV(ʼ Bk-6k &.|.TdʽfTN2%)K)S16صlx!/rȸ!pl(hj QknrZ>BgW,d BC 72ƘRj3Ԍ۽agT1ƨc'NO-'/A>c Te9_>[Zl[F^,-/ڛp!ַ}H07O8`>\]΍I Fcc .p17uZ'\^3v_L')%VIQSǩioacHrt^5+q ٷ+U# Aф T`p:fDϿ{= c?ᏼ?a\J-mFTxonu[]E]Vfci~K:û櫾,6΄wN-e<6w,\OF䖭Jq|~Ч!cݜ .F#&Glx1pBɇG^ռHkxWuym1ضaߵq8T$rStVyWkUQZfֶEd\Yau,,bB3Ff+ Z\j Yj)@mw0ʼ`423@76FXx'yq$V!#/R @ # 4c!IJLs1%XA7JiiQ"~޺Q ?SdԁLֲǯmtj{}7;KQV8Fm[qu{ʩ* q2Gh ,c ʣsEVv 9$[ DbQ%4-1q1#E+r  0! jG R(m2ƵI&+6ά%Vj8S5|s,2wK]-k~p3zKc2Zc J=0ҲT^woZ_vg>iob3""@Sc ƷK7vSv~䅅ԕ\wDIw%p==DtDDY´Bх`GJ (%!!$#%DJ8[Bct}340YiLRIGkE)!}VCJq!d7nI uH !X"R*QۃhJ*\'OOg>wmcz|%fKfÀMl16e1<^?)ݏVZH!DhMڄ TK.1cm!dFygzgd;Jy5ܮJiFIow6J Fy>ֺD3IYj-5sqZGj`Y"Zn"cfd¯XK2+h6#$7í[.E>2^?x1Fkɘ裭OL,Fnv/\A=:I0(AqE{+ul@E` eF,xf/42PqM0J՚Ar^vm0ZolvnƇng ۟!s5қy5ܩ,2x;jS8R\]|/b(0ZߩʘcYvYf#d;}DL=@5)r.JmFI)|{s$Yla]8{|$y8(%V, Bh]hy@icR !Ql\Spamyn[Nb9 !e% kci-9O`~#;Wvo,f$ǤLij BBX?ע{bw⃬.%oT(Jq0F6-@3*#Ƙy> Q[h`b!5nUB)˄^ mm[lQ,O.M6ӴBW6_l䔠q$/Y)PJ9{EMp_ pRB)n((=(UyN]؍#nTv1v ۶Imc)e EÒKS)¬71wlh|ecaFYPabD?{- GO O *L# *,k.9:y.Ji1NIZhcDk5r(I!SNo{zY3u21RX{ )1&pYh.1-O)R˱Y5@-F6JrYWn|Y,m춥TLCP(!R&R)߯ٛRbdN/IRji^yYr1I9e;Gi]1F1TJ+F6 \%XԲF%F2pqJҸQ{-&O6ďK1jX B#.!af?„EӃaBnQۅm#!HT(CU)SBN,zx齗Zi-gJɩ˘cREZU#Bcf D.oa||Zrs9hd wl(%BPXpwֆ"Q IVN暧/w+=w\#Xi{nАXWv"+K9$niX!6xv̷?qw ?/ Eam)K2+͸inw«sޠ(y`,bY\N<a.B@4ˆW+8 mIc4٫BH@{Z J/{";>8t୥E,e/{K\aL9js%Q`)!B(qf4ɒ(-pƂ0"m&1[zVrM(BJ#)c)3`ہV P*:_l 6TR>j&+\^/wJDZK/v8=x!(dp؂k/`C1SY^xe<3.`ikU*5k}6;G[J59{!0IH),p,!$s,nijZ"I\wf(w2FHe PJW|2SLR0Ҝ J'/ojIx/Dv^†Us#fE{ J"FYu}{{*b\ 4QQ1L+3Q_w?U?/'wwF`VXuJH$0zh0j7vY=5F~If:`-{cH >u6]jrBжk$gZ&\*(-=-Rix~V"/JrV64a]Ѻ<܁W\ f[.4s&68J>U V3YgcgbQr;MaԂ"G] ✺>REuk?t0Ga,Ԅ`m;&1aԜ\V˞( Nmۙ$+OAϟxdss^!R*$B!Z 87?w7Oӛ[\FrQb,M^XU `-L[xCf^Wc?RJuٗ=BG!iVaK>RfBvzcg2=o`7n%]+&>2C%(XiV+sg̈́vc!e7/b]/U;Bp,(eJqjvK7șUPn쿚;+ZT=}T ,H2=SI5] 7J԰p38ڜdEJqІk[?{Z~Wp_.]A#4Fh-4hچcp!A$[o^(zG m!3Mܓ2' ƥw!¤ın 8+r۲]LRg7Lf"ߥQFlZkm[ZT?{MiloZsa2Nt$e9 =B9~e|[ stv< `bB"ccA&I,;[6uע훕E`:gW&$OXd+NZgT^Y(0FK>~Wk >;[?w ]5^1;JD ^Z3燓]!KP L%^Xo^t1Z+Jifj4Fէ{R*s!=U-~K᪏pR( `a` Dž·UK-{ ǟں&)v;-S1 f}uvsmiRYٕtQ'׫z[ŮV|U)t|cH3SN 4xJ1Ƶ~v=ۥtL\ =JhmisΟFY3FYQJk %'\oܲ,/>ye+CGdv@?݉mqRGzum~ڥۢϴnl%i+[)=qX @T2j+/\!u)H5 g­KߌªQLT;qQSz?8 9{\W`e~񣏝={n(GK8 JA9UX<DqF)tu鎍Ê+lb?ee湐Bj5W_X߹B0˲rltR+Qz*4[oq%YbnV%ǵ-!\y2 2!zs?'/-O[ŕ<0:FzO.P!!OI1yuPAQ*YҬzwҼN Gɟw+MNJT&{ זwٍ :B5_"6v8Й]-9wr2݌KGiB4AB wztooz& °╛3IA5kw TF*#z ^]Gy,D5"[߲魝,Ս.Oz }^4&Vg0Zxlkʩc4ơTc ="WZ'91 va~?/twmBpR BJɕ"kl/M ضTSt9ɠ?Uk(v;PQqB 'tέ~Wyk >c zW^;~ IU U=z.P0N^]ԗDv\uzwLɹZTR)?2ҾôWXUx+=jP3 ڛLⲱcB; JkdGO]S Rc6?kigM$zHhШU4B-֤Y)2$c h-->t;_i6[ ۤ;ݞ056MRz[vGmD3KͫZ}=lrؘӴ،[ՄRdnF)Ƶ$0K?X[4Eo"oEຕ_//.;zY;6a?J[@{8ϊqg`6;lN}˗)GO=d JNo3!D#-PJR+DaRrX8\)m!DHܵ[N7/V_䉬` "bl74Px9Gt#qF(%Bc'.FƦjѕE~(u *aXr! 1b5h9I=nlZ rL($.*RƀBit;ZU:[,*~iκ\ )4kc j( eȢ6Yܶ\.X(6(Zkv_Gy瓎6͇ 0u?fʞn\72Z$if1s zs/^9F^k:Nx tPն,XLcR0JtcBq;$; /XfA$JcęMϱ_+h#?|\lYOm$%!F8bhBǢ-O50I[ʬ|b1ѪGA^ϵ*|_;]>Cmrc3\* ZKa^n7mԣ8@ňfU3V#g2[Zb`18N^`)B885U/k8!y.OJM8+M;;ؼ(B' Fa5%U n̙;vqy~8feffm06B(ϝt3I%(+8Vų B9*+2'߶UuuVJ#\dQLƙ#ˊV#5#hS!y.TJJIZQJ}A `Q?Όcw z}xIJܲ@`0m  /rh#*|tM"D(  jV2jE8.둪)_G>q~L*zo >{,zuV*3u۵֥P/vagxRSF#\rZ# vz~q|mM.\ޒJj%3O_^];u1F+\J4$-\;TE'XY.^OBe@IIe 'Ҙc! Y;_FOUg?}?~-ܿJ}+*$D=hKNͲ@Hq7n\ZK(0W ;ƃ44kՏ~N*`kzg>WI^Ĕ. x{a pYkH:r=;Y1H5NX9+WlmgLkc08$Q'^FAQNN,fIôzsV)v~|L^=}G?_6S ol*iYS&(sl"+!`644+1w{2xZ63W}JlrWk=i s4=[ B{KMx|S@W䢐ҩ}# WC8OnN2vZh䮄.bTK)E|=w&dY_uYpi 7Q5$OΜ>0?e /}co0?W*GvwxEJ)E ~Eje~pdM,y^q+\!ضhZ "ň䃅V75&L`yj!)Q0[F^$qa#8?C>zR^>oH5ﲴm]w};$Lc{m:_iN<ua&-)$#Q5}G.ܭ<^Q[՝7]!yA&Y[]zmKuG Sg{zkܠꢝ'qgiI ADqV=w4.@ ?pM8ӡBU'DѥY?2|uUBBj폮¾~&y`O3Rvf[Ա(jn(,tE`f{EĦ;*j3Jby>lױ(%tr4k@P^ Q FƱ>pJq3iI+#3ԯ>^k>~g~f{cs<7I{Bc4qRtrˎXTPrp]2Zp:[Q/=X.H)2Z^&"q[1󗽜/;Ƕp^j?)8&lv ,#cL&CRqQYZZw*if %JHttsj@aZIYjlfk yDxrkw&~?6{7_k\mV gQjIZ8):CIP)TPEQbq(N +0;NTie):;8d^ B(B*tv%k#C&M4K.+K)zi1W?xo_)(%Џ\"FLSJ6!Rk'  !TB.TB*޷}$Jibl:wJe.ٟoF\3_ǣq_*~օf?AOk`1 n,+L@!?n7ŹĶ.JM?6ۊ<֛ͽmmP[R9 .m!yQuB11LE4Fp\xG޶t;{;9}jaeeqnnnܻTдc<[ ;C3H0nWDt`Gs{SHkg\;x+]k-  0qPёOm,;Lv*Q!l5¼&M;}|^o?OnyV.jbd`Rm*f!TqVjm1owww _,ϰq@.Vb1z6fzMڬWwb+ԛhw?¹Qp:t!oТ]zKltyQ4nfSNḨk'Bd1ߌE9:dN.{fahug̼(v {JID7E̱hb1Vilˍi+EI2,_}W޿}5u5{N2qi/x7wU-7n65JxBRaNښ~ N$ &JHsW7l@Zjז\U!foQmqFx@5a,N,6Sx8O =9f팓F7?X N qɝbєڌ2GJ -$Ꚃ˕F˕Mco2 o;obi:J8HJB,;nJ?e7*Vȧ^gLp|!>u?Vի;̥ +9nvKgң 6| )2osזfw'i:ϽsW#k' j/fJ3BFX'o_Z(Aڕ+n=GVP1!eR_$cL術s*\KW#յ77zve0¤V K̓|;me61I-piԑitwz0Qɥk>W>"2[+" ^&EӊuPɥ!ՈYĵsFHj5Z]^/T#v(}U c4AҳKi % hմL%'d`!Y KUwfA)#ŵm2IT8qHNYqpme[Σ'i57agm8E3;N$krZY% |foZufr7rajsrs7jc0TSit ^\rdeFxgBӂpYxIF%/v;RKV6golOB\bU?\*emxsN_^!ƙ8Iej+FL](A@@kZ !FEm 47\=QY$s(+DHzk%SӖ2hal 5rm#KMi=XI& F<xa?vϺy,'H*G>;{:D7S׃f,V3#>`dZNϡQԒrƧ_z6l)d5zFG?2;yQoE6fG4`Y˛sy03-Gg/Gp/X%'hP 왚(1_uV[S jlu++=J0HE<}^vnZ5Q7{ߒz,>J)H8aP 2Z*0Z,GZk4eU!8wR/![m,`0 <͊2pqQJ 6BRRH}/69__/26F=p@>q/ϑVcIg珹`sV"A-!$vwSE?cOD#<,v{ ZT'=ꔒ҉2SBϋeW ssk?my3sΉuPe䒋뒱#Cp>W+jqYum<8d/NXcV}!vĬ\&m:).y.E0&)Jq-tWg7=+aYɇYAzTӛoiS0Ji{` I e@˕RIe(JT!M0'KOO0#;h66*f}\)SR1H ٴ.o0BF=کxSO$h<{mKqs!Gw?0fk<-\nƸYG/2.xd̅(,ťU,7V}[/5mTc_z`M}70'Ms!d|+f?׫1F}xRI`6`ݎ|itw^]9-{7t;L*ڟVcFFc h> L>U|#@ i}lqw+Gfd[Z_ Fr0qӄ0qQ(OH CXNHFRѳkN!0Hj@tFi@*v*/K8 ȳJkNwd$^~h-$HmYN|=\HR6GޤYw?a|~mۘwFIz~8=D*[i.OKN 9i6`OK Tg_O=:(sbkowxaSw/R mp%O gk컬:&~u.gv6@(OWG9ztnxα1eVh&ضiÎTrmu|'K3:)`-M[/Fض 2`!h#>e/BY 6Ӗ(*ƕ$7Z09kla͈K!70Ug/ Z!sym]gr~e`p~lCu~֮K0^h$@/\ zp7{Qn_Qc|xܶAID_|88$oU$I=cAs>5Po.nߺbw`=us,eluGՖTC_B+b-m/~ᕟ'9:kMk%˒ҭUm-Xo;3p5  c :9 b1YjݯGEɵ5Wg% d3T_̌ި> ƘIWZ״!l4,U wv:bH o D2^g;920?ﵴx_ڶimuێ@+<6T\ qlqlTp#Ԃ1}Q*A-- iV(%=L!b:&B3ʊo4UE,d< ߺQ qJ|e5 #Jc`kU ?y=Ñ_}y:H1XDǔ֗ꑇ4oD 37$8}ws_vo>ǜ#WOy7'GZ3 fsf/Xs[²IfIM _dkֲ3JK*[;ǗD|JDs|tYs(Z+ۖ'hH+{Į%vstfZ_o]wzFf9fRimY:W\ k+!QZH۶ۗ 1J2PScr a2eyY⩽ HaRZHԶEصi'4 =]8lP8V<ɻm-MonIбmITk}W_Vl-!.oUu8bbGfwϭƣ{-ޢ+2l1fG,y vy8\-!|գ>_U|ZhNgl[o+\TƵE8/})Jϱ(9g^DSPEGSӍ \` S7)=~Ĉxit#5Y]t،˻-xi/ZB)&G ʹln*ܡxpY΋~.jʠ{Uv4~'؈Co<>6[=hL qN `3A[@*Oܕ06?sL<4II#'8me )ͺ5S9]~BsdB5 -!lY |/iqV}}k'/5ޛw gDɕR!LXZMU'yp񖸱]r1mzWF,nPZk!+8βV݌6b,4qfF *(ƀ$V=i !.Q\: 󹣼;s0W)d9% &ЂC50 S[^Ts?zc!}Ge碼Є@ 5Zm=xG4 |jvLg/F^ ˲l;l^|nVkKsSW,̿Mf5T +a'p2_Ed䄁T0OSjZR;>L[ڌðms]V]',⌸K*Rۯm? |@=aoQg\zH a6S%Wӷ!%{{}```/߬5a5%}b l~j[a3(gQ-z_#vRy<Б¼Z4' ڭ6.jc_3<Ԣ8,Fg>-Ę-{-)ފ=7,+$Y ROX}:g`s)ڮ%cg/\`BIABzmkTp=.Ki3 gbg8!M-<RVgkN-io N83[ sevLRc'W %zXhntO~vuj^#h<^\kW>[$/m2ʈRm̴zRڬU"cRadqfo޸:$wLfY˦K,DG|}뺕:5hwvi^(8+҇ Z] SSr$E gZOј¾_pPhZm$sPZoc)FδBYRm"g8QTBg$%,w^WNm6{+1TsqO|)%D dexFiVZ5!,OF3=H+@\i@Ms+;N0ZJw)/]?'61,!||֎-I=[B @c?/N7Kk (ՍsshN_O]5=83ل|z̑??JӴJ5У1X@o,obpu|zu{ B/(L2 ׫[@SnTxspelТHj7l5s ~~52kaO#md|qǽ3|~D6wJmB~llyOV.$NW{[Ӛ{LƯ>}m>e[έkVvXW_x#'$+x31(* i± ɵcL^e8m>| sh8m}flS}ud̝$oxs#ȉ{T+[ohʷ"'khًMvcGbdFmi~,Yx[G=;RG-JT2^[9RJg^6R{hkaJOO< _H:ٶ 4 =9 'Dp4eѵͅj:#˟%A&ҩjYX|)e~\EphgwO"Tccx 3-.stXm8\9[ Lt!hYm2>LݍQrzxgMRth>K׃Wkν o9?=*mR-4~ek!w: olgE1 rm%v1 ׷ΝX\ӡ;%+QVIԲ7ۉ,h~P;rZOgT³N,7)n aӧW0G'J(_ӏHu^:xܮ4:=z|҃w9B()McQuo8>87IhH\)5OՊ|M,"F;J;@gl-[?Hm+/=;Ϝɰe[⛿FXX'z 3-=_'2͑;qxDآ* kUOęlc3؝5ZOݎ",ng7BA0З]qdNBCgj"mӈP7ҐN3ۻ?̸owO>TvcLMB uЬ[kMώ-YA$&qȦ8u\Z<>ϴPh j3fq<6t@g6F#q~i{e6>>?#ہ௭{w<֜#pmfm-F~98=wrQw;Ÿj ^>|@ݞ k}5um%e1T[;7GYq6ڂЊ7 ܹ|YF~ Zicj~<ز3 st)񯝳-es$`36(z?TeE)0҃ak ~kkgVu.HkM*.%8ңx G!eL 㒛 7ɅI5lvc Y>V v'Wa@ ~KҩȁfT:ƜB]0 `YNϸR0 Kq/~,k鵹Db 1FuF'NLfcuo"/^ZcL{`:; I./]^KײK!ݞ~TK^X Jn(i־vmfD=DiGO[؀NruL *4"rԙ0"[dQ a3)0˶ev b:IN-rIHja;;[=j9?3l1+6cxvq\EʶJy)\9ǵ[HI Dj֋31LjDvh3- j4J^jm`̮l"  |?UfvӰgRf==$)\۽h i?]J,Q,iw,DV OqSr}}WԜ3mWrm+MEyIUTto(e%P~3YAuz\FRNت׭{EBMZu`2z#rVE/o;%[SvNz+++z/Z\ni\*//V*&\3ү{t!'0fdz}پg3s( I#%CHipMقQ2pzBO>3qA'Ea4M*znzYoJ#5<=zXdZJ1QFZ˃|Ͻo-'ـ diN5c.ɘȱ8-7]uruVGH5 ^ ~8Kp.6@y%%@k͋i #FƁ[.׻sAI PlT;E=˳MW<) !s^"70 Xh { U|{{'8q=ed3ZJ)U Pl( z$-| G}b47Z@Bz^o2W[mt-Ș% (d[td3~zս-IKi3[l]cll" O48@:5QDQ,G M/`J4m'3ɹ$0![eas}ޤϬUU==`b`@@ B CI$@("I )HH0L.{~ܗ͑FN|~眻^{0`58ܩki<9Bt-O 5 y.B_Rؙ:zq:ӥ0YY [9|B{ǡ#UI)mk[@e'{ʣ"F[m0L m%j`5R|VNR#\TrPZG~{OK yBah:}sN&{nCBwCwSD#X]kͽݏz_C0u\.op }>*m{St\(`,@ee\EpGHY WUusFY]綈Ad,eai՝=j#7y2^\@͊\Ȓ,hל^03hmZ:}N ݻP[Lz2=0LiqR3Kv{c'Y=m%ty>x!X]~-r Z39JDgWlyɠt8 h cBs Qћ6LE ֘0hώw)u6Tc}YNqe^)f<~Wv@-`xzM#Dj hT i>F0k zWALO?KqG)"pQ$RӲ<\%}qmw+:gWmUn1jxhpR^S q)QZ+3=N0S.!ZDQgۇ"  v?l3W'ZEW/y-![v}Bu0r2-ۄ!+v^:z(uoN/.Қ.wrz=g8ǓHgyYkVWqi:L dkNW0rC@icY߫ÉSӵ>aZ KB;yeZg+}W\:Y. Q@6Zԗ,2N5gXj7G״;$~b<$G:2t6pv>@>sqfi{nRТ*[Q H2wrcqdu@8rB7vȅ8~=,cPHk13@ mPfHҬrByq7#_?.ƜPY-tke09 E^'i=KR)sN?2:j{ᙅgdoL0iÿsP>Hrgxp'/,r'c`FGp?Fi-YSkjG1Eqέ/[ Vs~ O76U@H S}1cp-hB^s'P|8`l2< 9BBqKɥ1G`c>1#Hh@(~}N\[V:UJA?2޽h1KmDB`#D MiZ~g 1 {! 89ukQf(!@Y+kydfeYc=ML`"N ,4#!B>8Mfy;<>?Nm0X(=F#2w@$ <ƙ}n. Dw8o5jH SϮ#w}p?vEZB/nI#u~Wh2g[ \̈{<{`CN ?|x/;/U-؇(fԺCHCuQUϝv ޴tFN76KF`x, $K“8kN3^ !ZP7i/^G5;J[26yʚBX% !^2뵻JvTJufRƺڤEE5Rɼ>wpc|U;wim16x7If GcovĎ&VlRLΗ$5B؝ZRNjci+n 8Ԫї߅7 tj.tIZ8%o^9wKrjmszMrqy{w {+pm>SD> jMbW y0 w>$J85ľ-* hB%4WE-/Oṿm^bFӦ5,.Oh1F-C Uw}2WBT I 򢌃@k]U,_xႛU3wvM-eެ=,9_  ՞ywze::3LG'4_$Cn.h@*mL[<@rD)nf36y4t‚f9b &Y+v㓓B |eJ2MR"[\ V:QuvLE/o˛p[5(P)"'2`ڂ1k h^#'(EUd:0|jшB`C0e3j`gsIäҶG㪬Sc셥`sߚxccߨwW) /׶}u@hw<ןAaGH9\` 7_~|5w^XwF5GiS 31IDATشFW@Vl*d,%,m'^'CW'ir]g ] #.ۻ;*h'~N<6B;˔֊3Rw23,8'do90KlE~fee06Zk׍RjS/CmpZևzЈbh9t:iɝ#r:y{lj->ݦ15Uj2犢rіY'8\X2F!օ)ZjGaOt~]{,tZ˽pl&tƷ%$,۳2^~Xd28M,ɇ@A!`)xf*XXEw|qqCZ|B0()2K e'*UϺn'ϫUZ (9~C7R[$W.0ms'փ'&: `:^V'`cyGJyۇfh?8Wk[@J<]$eڙ5+kZlͷu]PF hL6o彽Idhc\IeG#hszw>.[| ΒIT:$MAlZ4#h0sA)m7XfN`֭άc%caX0T޻߿~Q5yzU @1Fd-NoR~dHlWJyt[,1+POV(.8\"m'>hbaPڂſ\3KF]cܛ~"d 0BaЅ8*! ꪒ|s>c? eC[YN9iTՉ}y'?(R/i;^`RRKBi}Z?<>:Y>bj)w G0w9<- /??c44㏶XO>/߹rif*4 Ca+{i$`ҶdPA !2 >^Gdy>NZQ{;7xrJA]eQM;lp\ւ컎1v8U @~95Rʧ%*7W+HɣdsF<ʲBD .k"{J7CQd(%FK:w.g9**.w"ŸCw98)}T+s(jXc(=JK1Oֲڴk:j Yi}GGJO3AB7 og}\͕̪*9Vu0nEcfe,/R`P )oܽOݗ&lżN^S7 AݫwC͆{`@aPݴq'6y azb3cx,BŵLvbwT c:f=!k/;ZcOY,rxd|`ZɋkÑ?8䫋V=fr z|Q0$T"[iɌEumϞ%ZNum}vZ p:R%qfI}LV8q3 Ωt`d)!ڠqJAYT,dBlU+P> RQQS! ,!-伮!<1%E؅ `RfH3ynKkL9zxU4كw3Up.?1:`&+t-A*ՌG#p~;";by% FX(vm^VLRU_Fۍt>h^ ?oz<ZT"'e؊cný|0jd^ BrgsѴJGq+6KDheY6U}{wFRC?}yY(/6\fP>4f~hLZBʴܸ6 $p "2tz{m#{F n[q$fV3Jk 1SOn-!Z[&cT.P BGEl}7)'|Hi,00=H^{ /81 ŽG7[r/ PnI[!x|ZH+[w^H$e5B wTB![G^~FJҁw/={ngspj\PA_!VUW-GLhGWá;+m[kiʴJ9[X<3y^RzpH1nu`oZa8T[c#ǐee%ρ1+R-v{Vj;gVݭJLbBs?'7up>fykOQtqXX}\UKӌI"8s3cڽjnsp?.K05m| Z_MgC$KxUO!zfPd2Tu]mxU=r/W񸼼qw0O eRe%#e:6qJ~p Wo( e 7vE1p݆"+UvC4Cz20c쬊+$FG(_u0 -%̡;7+]Yл#߂ΨJie(BycB8Un']Qϋ@ifXٵN'xTqgVBdt`w9{r*=z՞V\\/sƊ:Jsh8|9NOGVjx'=cp%P;iicLomVshZIE- }Jn%?/u3|&_zS^(}ZTi6fs Z uBOfXv 7kᤳXVxލ0+wVo'_^i-sv̗.;"B@'J Bkԅ  ))1f,КhfJ/zX5#߼j4Ä )BcLkQZ5$RC^(PB)aa< h #[`X%MqsO2;Z_[jJh^ԜA#ticB6k<=!MYX\1A(5.,01ήEg`wWTtQmx*\{g" TVâvy8 `*O/_~ԒRbB') LPrcaTyijIjYp syc5H `}!#0Ɲfo|//%g*ix88Y2ck(QRrb_6э?B%N|#J,u6G$ NûN]Ia :Y90wW,O>m AF0Aljq2әt(ovL5"A"z =긐 `47fE~xiyD9B@p8b+_7ֵ[Ñ琓w'`S0;P.2kO B1ն `(FH?]\<M*fO3p,L$W2e=D(-8$n^7aEf_{4Bm2Z$$`Y+>zO0{B_*q6>̕w[3N+^n\ R)8$B,9c(!qYJ`>A@(H@Yp@kE1X1Cq3̞L-IһV~7bdԦHD,&ml"iuϾҞ[*&\{nΝ]Tfion{;<`msv8W ivX^hxf*;Ab:x)E͓Y-$Bʡ3:_d6@xX=0V]"iΈK: evRҺtF<fkc45V#{kRڵX $ 6n iP"LM+ų*J;r*Nޔb/QpR=}4uHJ{ S}O ',+`T:L#6Ҽh.!$4U֢F=ډ{8Q֔ge#vN>J5goDU%~䊐q@)s{@y2K͠*p ӆXkk1 (88s2% W3x1@vK+pF,,#/o7qW<-H??RJ4Q-78=J2S %NϥJ$,ƔQa>Iek`(jAY/7 !6XH\xϴHqJLznU\ČhЙ,F=2D"=q~.$J]]P[G/wZ3d%&)$SѫY RYi_N~L`HqzUB\K^ "$$?F1ܯe (i^8JRJʸS1Qdq8dByL| i3JY\oKcO}ҡ5B2Nqt0ZaɩdEl фl,άU=l׶s#;7?e?WuVΓ<5"5Yaӂ@Zi>.4WcύxZ,dYeI'&Mo0s Q*cl'UWa7M^َٯ^]J%OɌ; HP@ &Y!JC0:XJk-1aDm4&(r^p `RǓ 깍tk;],cuk#fL9۵]C)F(-`B,llΜf R Eq<KR nd-$cX+z-bϻ XH%AD:JB"!E\ughXJ64IEñTZN#޾oC{~%sCav(AEEoV|ꅘ1@pQYibwo]>, ;f>Qſ_?uPUJuc8ZOEkAipD4#v nkJw&i5L`#^9}rVfDSh1%CNeat7*O a8[7#B׹E|&8xAz<K!A&.wsg=j1m~ŒZJ3}<ۜNQ1ab[bVkYp =,WGe3[zU[@%֩TkV1X SzFHtۚ#u4`i1| uGQ_[胝c(qas;8dί:g[k:aDRB)iF:/fY6T?Bԍ??S`hS_^f9JRZ+.D*E^'bsV6yM.t6xj_x9xk߭,[3 8`,jHJε/k I?aS{u4R׃I1ν+ %i{|7u^}_'>ٸ!1'yWmxRIՙNw[~tl3KNywwߺef7[!7*j*A(,Jb,@2)Q !k9Tat mu"szt#0V"17fu5E?eX?_x{ϮY^58f6;L"`j!p|3LݔJ)_-XIG&`>iHlKF{;^X^/ *޽Kh:lm,'Ű0K_Z?CY32K"湤7.;@7ms{/v#vXj¾j)gɌ#x\b@Q#Y^x~ǰO3^!' COZ}OwfWX!oľK0j}dC;UE-8]\|"vc`:hiuDv{6Uú_緌 3n<`BNZ?~n>vCe(u>pQ Z*YUJZi)VμſqG<<YO98+b4t#*cHY#6J]:NAI-zyFnUZkȢP@G9t>eqEl9 1v?w*o,|9 wg_9rM=y_|xMy,.mzֈ4MũW/PBaJ@3B'xEq=.ǣ cBRYڍq:7sm k1={Y ӣۇ{.,H!^2,+#·W(c@ 07E1k͜QҊ-RD%+Eu~8 )+gcX+򍫀mIpqYw-gXVK;#wLZAgG]~-s;W+KEO?궮0JZhmN Fsǐd*=ÌE!kQ%},lriUlq(ғ"ʝ>7} |{Pqc=hOW$lZbh?3*si-2SGRq:2<|f^Kuq@YJT5B (.GqQQm*`G[kFjr{, +GB`XZhb-8V4?t2x*bla8jEiZocV.^5{Nz]ΈS p0ij@u#6-c@HM3ųd$t-@;?*?[ݝ쩟5R)#)QEU+}c%m3x$ЈVQ܍۞Oj-I0Qݏr)q*;a^S/.?b$WBZkV͎ ta42?T/Ch^&SN)heR\"3B` F#Z{c6( (4;RXǙC 9JGIUև灋J}ez;Hx*Q 'ry pIi;sFV7Nŗk{,'ЭO/SxʿN}! ӡ@@KnڄPmUZ`mOA#jhk` 5Eg^smhiGuԼÉ<kRd|`bt Y;_ ]8hM(y0RURh>/WJqZ u`%}vH[!9N$sd NӚewgG]SphlxJ@ŵbnFfj0R88@ZCʥgwbVҍtn>g3}Z3k'cHwp(u_}Y3@"Dt~ϻfFjێ؟ExYHbʅ')F.;7Qm$tx<8ӱBw0^w/9{ϟ̊WHi5ƶ"1FNJ`Rz8TU:cfii:ԗ bq޺qKcOTgB)k]_3x$<`+~݇'#BSuvΉ~swfzy1ҏ|.0!BЅs&,DF!T(C5(8 `V ő#[KgYQ2Lvӳ![_ޘ gFH3`'Zezk-13H=6nV3{Qh9wvxO^:[_[]X.] )B^Iu%_mg{n޻y. 2Z-yj 3+E[&{+BɷoJQoqTc$Լ4q|*o>#oo1y2ネEc(b]:.hx*~!䝰w{Vs~ߥZkB|p^-??٭ц>ؽ*dj g Pu?tܺ&'ajPLBPXi3MV)7/LwPL`7]mZٴh,mZ-m('ײ¡*ŏ6[=A-}id!iƝiRf$% [n?jo!}X_ !NY7ZyiA95(p BeVTJZHBJ sBHZexpUXg^ذ(J)0s @\{V#$P[@dxYE9{L*3_s݇m ByÚ|:|ȧ2;7n]_kp(ϡ֒[/\r#*hwbK :*[s ح{U Ba- &Y'cqAufԆ~C>).QȊ!r4&>v|/~풻SZkBI:Mw?_qGk[:x4JÅ(CHW&Ţ"W֗/˄7z%)No,Wen}_^>{]0$U9F.G|GB|n k(ٵJh\T U`8 ̌-k\!꼜9.`p*5a6yeI&[lZ8)!qH!vDF)D vA¨;JJo 'Rke&#r0PK k/J]މ[/:Jofu|dd`F߶L'6XȲ>iݱ9e”`sƤvnj޹LNsZ*l cRZi`l7R-MIp%$JNV PTǾ`J q0Z@ rju^/7ߟF.Bh:S+en)"FQZ~rƬcY+4sB<`NG;޿QJ@!Qʥ) wlg3iÃB5 }m>pptHɌQqqn!8)ƣOuiNNL_8/̌ ס ~?G /Zrk-BP( " Fs=ZS`M!DBʙB0ڽ$_}/ }'?b+XK P"1}'E xB(lإxu-g i_ o0 UyUU2PBބ(kbqb$#m0X T^}{|P\%-B\ZEMRr'm-:$/T3 @^fBBSJ:@Y& B0Mܱl >ڭ% cyYgs Qe[TVUԌdS~{Ʌdef%sUBTi ?/B@0rXx<,ry}L8]6\3w)dq/G gyݍ2^^d봤XOsad>`E1LgVGs1R0ƽg7Kí2-󡧷v$BTpXJpsޝPa֓ [CuRf&v{M)&(%HEF +iK7_wxG{(@>uҲ5fzbI0!P,2S3Kٻ~0֊<"j0Ei?0tvq7έ\j>hС̵壬3s׾;{'PT9f{Ùra'G@+mL]K[{ɪ]μ70#e#h0LZ cQ3"p.(5XݼEVC)yV%WF+[d5 \q) ;T@0:K˜ rs!",<CV$Zp.plB)IYc&-swyˢcRl8eS/4d!Nsrk6x0-s탖PwsZ^$s)ܘZ鴈)JH7q~9;V҆CEWʆNO_ -CN!2bdʙ͕( vR[bKR8`A4ͬPڢ=N-ƌГ4=O۳w/vbw @WbڽS0oyYoF چEXK LZg RJ!kL^6LXmk0`LzZqg^`;u^jV`gWR?ОĬDq:_oRC "e +q9PI/-ptzq0LgPIArq0EnFl\וZk՞fߣ\-"W%݆J37ivZJsg#w5kJ;ZG5~8Xa0ؿ;6o#>9w1 W J*B{_saVmB]i@'6zڥFHwѬ#!pnZ7nO'g濾j؈vܗS*IZZjY@bw9UZ[1)R-Q&0^49jJЋKJt2˻M!\'E?\~NWs/FΪ+lm 5s< pD4b5ckڡ>B8 8 EY^xD =VuVʭC1Hھ Ϝ&InKmdA%M'V̚`]F/>uż{7e~C*]JcLU(` al{~ijgΝ582 #F$Ut:ҦE6i!:HZô%M9a~cY"URl8z[xjDha^[|vř }|?_A:;&h&t(BY)#hpo}@$?Ur/z|Zi@)wb>RVfrZh0MǮR@=Xѓ^q5U?B=UzCWVMLXqwo5HFs(V)Jhx8aQŜ`4޿O{1AFJM}TnFlZchpvt J鵞MǯR$˦y1=enમMZ[8u-NQ0'ÄuE%8bGͦ*]豝#xuhu0 ^lk9fK͉&/3 =g aLn5^6q·ji3ZCƨiU$8pJΰl^~OQ{}/n<( ۩˹:: ,hsĈ9JF,ߝl,7mwGpLۼ9x\cךQSJ~hEV-D߻VP~(b0FF[1.ea+#ʚ Ϭ^TNp8)0 _ydY.5(b4}]eYBHWY5^SKqF Wj<[ϹQh`#fڐLc4e"td!EV0L^=Z`#_,r)ӦDNLWM B_WXkΓ߾??ˌ06pAfМC?I,7Jrd.CSUì A6LߥNRQ=veslqs>EЎfژF]ezI`Roi\X޳@. sAIcm..̲rZ8vABMmJP0 k,F`N `1ΝIy~"QUNeUf6CDլs1'Zf, lQ$U`BNem1BkU3 #/JM|LXlM65. aBѰzloucw%3g<>I>\I7c@l`)ghQYciDyήE+Ei,yhcIzg۔ytVYW^:MUѳvWɬFWi+J&Y[Yg cB9[[ ſqmEVc@ ip4"J07ʳ0h%YZfV62uꍋȥ;ݥs^™g?qO`ȫ`7Ϊ<@cWڇʃtڥV&r^xhϯ?qfSAW;ؾʹAZkViy<[44IqU Ҟ[{7ʮ6scVE'YfNsbUqޝ0RxN1&BBōh4f㍵%XS R&Q~wHr-عD`0thTQ*UF0 N먱$bYnhW7O(il4+z^;=ZGp8|w4L,KK?4Qkk\eqQe!>.5l,R^Fa…(!Z (G-J[0u00K-[K'wp EЏRbְФSgxqT;?W:/+2)y~棖b{n#+c4w39sVߙ ZJ,s[=Q@,`\?Y,޹73aa-(;72ӽb}]~erU&4`c)LYecF@'iY_tg30~/v!15#XV+S֬r/*r Bf# 1 @,B#>xmt8R0΂7Ek)@ Z*H iy4jOdvSb1 4rDyRZH+#mP^vT7{J/)Ekd10AȢ3፯ϖ#R fCtx0`cfkbApD|^4Z8oX6Ʃ8n45`"jί/=ϜC' \iʼ4yID6 %AYB"+Rc2/z_i!p-!p!̩QK-E>׺$݇J/,Fi-p |1F;L+1dN$K2vH0%Ƒ:=MW^:QɍeimR)FSuV'6> M^8醷Ѝnm$3.k:(=bp"ӵ̊IwO5Z3b> oPm#8ij7J xQxt" ~Vfn8TqЯ\9NQӣqT6ryޗ'N-/19<: BarRi@*98B}ʵt8§VǓ"å^5i:GxjGݏi!p3RJFEipai@o+g"BXh7SFj?Ѻ*%FhVQ{o47*g֤3*(/UT/%$$8zfpѴ^9⤅bŒGK,ӒG!E gg +` CMQV~ح˫h]\W8\};f%9=Iig9yiқb: ΩQ8AlHu@TPOiD;ahõYn/Z@; %z6Q0: YPW9Ϛ.y-0[MhX4V䂅SưZC`_PWlfOp'qg[ȍLQ>;ٜغejrW4|O}:ݛ:|QВ=gV(mmɬkZ"tP' 3Bsפq`dz,mz 0fh~8f?\tū V_: k N:{$NEfע k`4!zf\3&<1{w:Npv{pFkǩD8rG(hQ8l<(1֘/~GwR˼YR D =luH5juqӴTo 5Mwr(ѶeY8Wӟs_Df*RHtF(eJ6v]e\vaBQB2QGx}v ^dF~9n}{5\߼~a$/&av+cZ e^-7:|CY7iD;~hk]7u0e~'7xVr-Ȫ8`4+yk K3 ymrQlE>iy6V;?,r5A'(fim`x&yy~n1)NSȕ k0Q/ZaAC_jkKzsdBO9qim.mP`Cٸs{,9h yJ.h|x`ltMVEF'd#ւx5X0}SNSxnƯ!\s8&g:U":$.SD?W4J3~<٧/x oK/l̏ \#EF_U7S=1iwX[ cͦw+pa^PUn`yU!|fίIs> F qD!Q%rX̙xquB1r]m~uq!_\9'ȵVsh2~CV960:B6 qQ Ay.֛ f8Jr=>]rNV_R>pzC/2C0FƭvAL7>-Bu=?8]ɶS&In1\Eh5 a#cE??+@!hjի{_ãᰓ[֪\*AY D+jiAæһ O %&x9>uyVh"^Zj{3vKz5hڬ!!]Ylm9FylѼt Jn*u?4 eY[Ƙe5HiU>>$()أbdMÂ+R#z>u?q;g0|j`4 i|{!$EU=׵lyEiV ݈H^`||8h4pZE MJh%$^xdжID"e5knaZ{TZ[?^x1f#_&FoGYԡ4XdH:?Yja3{ Szǿ?|x '듩Cą8]lOG_b.RunLcNma(xӊu%1' J|ҦU^O !$ZSv}o8*VߟNTh#k04 l_D)%{tT{Ƨ'!DKZIJP9΁y +;!d)cu-m-*1OMw+#pᅭʜʛO=mn$㥚efي N?xppZ-4Pª1ff6.XTՕ(Drq{F~pNKF8hc:wN8%02{JȜ6oO8RZJjUxH )@%pd9 p~Xm_.?0>geqc9l8Mg3G( ێY]yeƬV Ξ8i]VG{[U9aCΖ@3 z:gңѻ7$4Iyg`;cB{548U; ^Z9BOa;㐂x^G37fˏ zXӟɫ7(IX^_}ݶ(g!뜵Zh%V{ə#WJnl]xʎ!B-h /g/.lJ <3/1@2ڃ Lw_ }0Q 8s(X, ewlc+A2C2g kgR< 1BX<_ө跼$!&"VĢ>x =KfX6e,_vCx8Pu=iĉG>wOTچAl2VLaܯ~5YO_\Vz8Js+ }c(( ꅛzw_+`Xc'Ry]'RIm,%X(eI"#jMQj14`X> m9>m[ՃEvp`X}ׇGcs`u(k7D5zä)9Uy@eE ;Ru0+DyJ;-'Rh_kѝs[?hXUUfP8AH/V6W4Z_jaB,evdze͋@ѻw<%. %JmբBfKswE9J<yTE/Bj{n)9ox#NM3 xE?}awU֚E qFGr4g#Je_ȪAYtp`v@1&ژw(9'?=*c$m^KJ[Z2pS‡]zS-3/5Ji5g>x7͍ |bxE8+b-"/92-CQ)J3ZE+E>|ʪ;̈́1>[-1ZA8:1IVd[}Pw)4X+< \;(fK7vKlY;X ^Ѡkcʁ[~W#[k4dv׽/{ču%taX)]jL`aح%;BpN=N 'Cx-j c|5o%I-D'.mTvR9BIwt6\{( /P-VG۱tF*2=_%Qh} )<^Xp= B9z+@a}@E1 !V ]>Ii)ȇ|>mg4dDxenӢl5bk5AsN[19ø\f{wa݈J!8'3kCm5/ ՍC:QrX:7ZeO_B0'qs5>4<0_]B<^_ tVYr[/ /\"BT[RLJ*h?WkҊ(?A4[Z7JH9'.s-RS?)7??|g:}Nܟg[=uq-Q^B=A)*X9]٢6Fsq2kw24_mkR3 īja,)d,D۠~W&0|Sx/ beO=)K"^vgE0 .lxG߸s4o^27jQAj|3#oW$d ^;_ hc\_ۺ??#M c\ ?y`WFS9= l#źvQV2Jߙ()U6g>mgy0VH1J ]uNO2NWߠJ( S6* a"YOF}:O'F2yzص4-,'6 ȳg;vJ a.:7#_t̙ ov46ܞiWXy^Ym'>9<|n!o~YIM0UWBOqIyZ5lsӔ⸬Ť.}|Y%Jr *A:N-aBxhKm?ruZw/i3Ja]IJ1r:wC/ r.^xWvVߧhI0!(aMcYQql^͙w@hUW3v;k>:6-xPYjjw5u۱wH0ӡjE ƔbN$QTz䴔-SXxV>)kZD^ꗕo~ ~P.˻=0 YL#O]|oh em28٫[*/5Ջ'w^tV߸{܉YVhDkwXk* p՝S!xa>dsn,c_97Y@J:Yv<I^i ]e{֡Z BCBLEUDAM"~֑”R`+FVڳ$#D v`V$c{hBY0z ˰AVwow}^vjz {'tQpƐS#=/)yM7:b(;Q1.jŵ54Nn6Ј 9|q8Zaj9BKMrZ`Qӛ,2s^~~y=$`?_̅rC#R'd(otLhZEຜ~a^+v9͚7Te/۝90[]; BrZF~V#g%0B8`ƾ,cacszv@B3CT0mQ2XL_ū *,Y7[y_DeVu# (qn_ꙴB c{qNH@Q "O9r, :]kaH9ƽj=!QK +{!̌WV^+H-y#JV~ߵwas]PkRI8P`V?} |[z\| U^,O:c9*c c: c뷫eVaB9`oX:(am=@kS A,UpH1D(~{DTx>&&\4 Hmҥ)o~;G'"9JM/gYf ƁGijeT6z9Wo*߾ !Dk7, N,yF1rι*87eYoΆ Z)U5?||y=*3ͯG;.1"PKsA}˜=>0ljugC"]N/jkLQu!]B1rv"R(69kkhcI`5g9LWӲg߆(P?hG8!VCOuXl{wIy hW/v,JY=) W7oetdDG&+[+=؅Ҵ-yVYwXP^z^\5#{uZȭ9qVv:'8NW9_|4yW=-3c< hAO{Q~V[k(k/5FkRgϏ.|o)X0Xct1 _*qVMG1j& Bm +辴mw ճ;g,!@ЈaQ6۶ϕkk_ 0{AwECDq/JSrqZ1k &AڳUY9˜e!@i m<ӈBL(TsJx1"1,E8enq?/͇Mw5[k9tzO}~MNÉObL_dWE2F+ǘv1ϥvB?vXf%>XL9'Mߙ0#[JDӟ[ fyY@^APh"kb-``Vt{FY @1,ދ&yyE8'^xo6aBrRh0%(+E)4_ xV6cgR'FuuHq:hӢ N.c E&7mZ԰n aRWKqOIXȗEZkoo? j+K7!pg0[ټfwOObǣ.i'6v^x˙qj܌ ˆ@(˝\+'sWI\ʦ\^֢ZRF+7(k߻ ?~y7;mKgUZoBS[fjQ9#pLܪ._qJJBMD?si4Ν:˼J+/8]e Fqq&4tn muU5" ΁6d8!]2w(@!D3{(skt$u:w9ALtF&Gy0o:ԍ!H|&]?=_zLQQ Ӭ@Y9I!9F3wh'LHll!jj[WNFwbuo AfQqZ*"G}"d4@Ҡ3+s~k\oC|GƵ?9,n 68_y1?(wYfJ%:2E靴×Gݽ;AHm6]tyu4OŇHA4 z~;?z\x^|>֡Lyfa C֛.yָ}:o16|彍23F+9$JƮcRV20!֑$~ROI#90Zpst&`[)Jq!^"@Ymv`ԈLe{ȭ@1jlIc aW}qt٢RtAH0O? ;w;+NLZ1{IowkYKv1Dh9ȳ҆MAHΓ,6|6G痶TUHjɾ}G۝&˻߉B?¸HZӟnʕ }SQ#|a1g%vU|}KHFa[B2FT*cq I E@5|<9.k%dV6.*1E7{@w(Slot*Lon{>ǡ9؏- `1KMOl0'RltGRɪL'MeΎ1Rjj,})tQA-*F<JìL1olW_}Zvz{\F/qa݂'.UB=6m<5'ލAAp)fPJ;?> AX9Pڸq?B(z J!dBc1`R ;$X{sB#@:wH%—4_ 4DC o. c9vXG(ьNg}e7FЌ-.jQS/9P=: L8}iwʏ}5VیOi{=z@ <.J(JZ>Ds̼|UvcϞ_}ؔyW;ShM?<8EiԤLH`$-֔Kr0UkrY`vqY%V̋*SdV0N)LQ!L~`-p^"tf8 ςRFٶfB.r|@:OWsD'RiemQCȝ%8~S)CCp4Wث>O=mx)[N!}zW5tzgqAsX'%etwbЄ@#P-e+8)> ->ghZтxo!R1B!*E9]/:{] . 6{!FXddl18N6!!B`1&{ᦘeJ(g< peR=( x65"QB'ՠ( &B X^K[ѠL3QL zuvBNft(ϹzQP pgkaF[mkpQ\ {xI; 'w/a'lS-UH.%9k)=8-IDAT+gѠug,BۀA{cqgpel,Z߉#lń9 }"n}o!3q΄tվ !"iso5NaVR JFjF8 $Q(b_vI 齓<췣akmՂW/J^ %a_BdzIpt[{5{t|vUUxL,3XZ$xK5uakfcYk5|Q1@3 89]R"׼v\Y=71nRֹq]"bdgR9creBcYDE/WD]̟37©G߸D9jo8=ܺ?~4] QYJ8g xs>sֵ04%GA"rscDi~g^pHHJp\ c)1v9U'z!o,EgB^.HF9Zd!bڝ6[3zSk@+t2>J=z*@yBv[7 7Z[(f{xA7(.f.-FMh^7XZѭz9$5%cTɅsk̲?g0k:B8taڗRt~/JXsֈZb 22F砨,!lj)s/GEǶ_}l'6Wϭ}K!nW`paykFvkE:3aZL ~-g!^v^a- xK~CS& !V$]˩ykJC(ݲPߡǯ'u* εLSz̧+w/'<1L5C: ď;c*%K@P󷎌6\$>;> ͦx6G߬UoֵC,:֑}CYa')BRZJƕUѰ]S"_KIMU(='yvt<;'svo C!{k.L2 |ZT dsgsPF4: m#/^Q]WƳ @-`}CO 8{6kmҺH}! ɼ=?ҝͷ.E "_?-`}m=F1,S/` k,v%Gw7s6/FVFb - Q/V! (_;%dRIÄ=7KKv!)chت;bt-$\5_yNMaQ`r-9W NZ[8K  ct6[#ПBFնZN2!>㴽$$EZ6Q^hBi(;7]*^:7(Sl{E RSPD7_ܫt[ck9(.jZ,elDp-UBVq@s 5ͅo,L8!L8h,=#+O+|vj4=sЏ8EIq*RՃn`,UH3oԥZQ|UR`LX3ETjK}(J190"o\f7SE-"LB!vr`/?ŋ:EBaNMW/ }zF*DMtbU$lck L;Zȭ dWgUVO&Ah/Xnl2+*O( .צیJTupVsɼ&c ?G&ڿm'~~nFH!IA< Ëf$E[ RQB"<ʍ):D[XǴ {s/5\aյ;W>;ZS؟&'s{z.OT76wڠ텴ڥ'->{FGI?+C''cp8J0D\I͈KTEh2ͫ&>n6"4Vj+YElʢ4`8 Btmr#nVbޟ7jT\&;'.OdNʼ*U-cu8w,}BSF Y!ܾUmp<ݣ:[IHk_9-0w}8ң{ZP?o Nj ƒy;aӥ$$ʞLӺ>nc}"n8dG::U;Oluj^48&^RuȎ?t=A?\OBgxF1dvwi5c%:ǫÓbU'Y5ʬr8 @Y1FR[.QXjf5ƶ|몮~c?_n7ֶK߾]Q#n[UBwMcFve(Q!c$!,V!s:Jִ:v#*1ZJvWEpvDv.0rugEj%ިѢdku(#.>w{{VٍbQk]t5#4YnĹ$+Ӻ26y qG(RpΣ孕hUx|rV~F%DoQ)olJE5Z}&ꩧ|ؼos֗4.4'HZ H%9CXgZ㜫ݗč3Nݽ;oqX[nhӈHQVRbsa<9IdI(MsLtYG3`{@N:a8TZ'ʪ&4&%}/>F osqf ;bOeg!Y a [aQ3c*ߋ~xQ]FU!dq{^:b+=kaVIme6&>%Mє?Gw<.7]BUug,gQU:;Aii6ZqhJU bHܾ̅`TDLA09ޙN|^.2 ⨨XNMm1tv:ؾm+jg}ӉacԠMȇ;4J%1k€b rՌC,ʪr0(ΥiSWD;Ūo~]|}f,wMp H`LEm1&RbcӗB|=[!=|OXM 湧E0ֽ~7!!vRʀe1lhfoFSzbx2Ƨuq>Sd5j7[`DiFEzaκ,W FV }/&8 e~ BG7w[~Ba!d[r5eUcDK*###Kk ;)tu^*KJe:W(`T/tכ=-}i^x~N0&N1ygt6_ήFvUY+!'p#dR BFY ;G>6 Vo~QJpV50fjJx^dBӗB Z+bkn)>Y6sW24 :U4 īUx?Q"m5y*NÛWv;Fe2 U>μ"C$\I*V^RT5ʁ;8ɺIiz'!|5f6E5 Zm'[uTs( H[ɽ78ؽ ;c!aVe-Ӽ*]F+~[&-)2N;;wS{~!*yE\02qDbNL%Rq eaGC]=H%k]L͎d?緺YQ!8b_I&4tU<_Ї?æ| `q#!bBUVxD c'+;^FƑY٪'5F9 @bl 4`GM4*WT+@~/nEsmJNV.%FolwK84Wupy EYАpa PTuGف} C!WylvgA#= eZ|톏 -NɣXy-$~Y'I_Bǧw1yePr5#9yɹ ^hU%R{VP*W^_<{z=cG15iˋ@)lebSnz 81TeKQ^cCIʴA/ݬ*!!pVRa ] 3rcBG>§$-e%х1gJEC[N-E8-c!Q gя?oC'~Kc8 1\y)P:,BI@2{hb!D%^DT d(궺~@@-"t>@uucqo:4]̈51&'ύۭ7!y e=e"DDq=r!ʳS4g4 bH'f}e6x}.E; (1FgJyu_Ɨ.sNoG +8Rwx^l*E5[&]Bڀ#ӄg;cPq<#0RyV". OpBbo,lj).+e!Ju!8琵Nr 0fHm/{ekBkEJ(geU;`ξ/}v/??3bv~XW/ <(%'#qT<b9n)H^67{rl%r|p߄E~P)*inR!M6vd:]y7yz߾U,,KK 4[믵rLPeO>,/þ#}/ZNC/L6ƳrшHbt?E}|=0͟yI;o+3[B@k"ceE3J֬إboaJ@dbB{c4#,g}ւrkeh1RZH˺w2ƅEZEXN\8(=2GyeTsJZoBR/ƾUj A(XJwa#A3[:r{7ov#i4䢮"Ft)yC[gNPPJa:.&J+c|a-Rݓ"ʽ4MB\h\>yq=/V8SEkJi{$?#tЁJXw?7C:~^#Jd!kdF8WϿ8TGq V MUCoLe9gtvnkm w;/W^y!g(,!ĭva\.&=q٢wF̏Hi?QI+kw AT\ڊgX"_99]܊11PAD0Eh;KK0 PJzUvxw){p:&!=lGQH"d돽̂z6B­_D0X_bU r0=9IpBfUYZۑ`ru~s0]E^ mH?ު ~$nt;Mr8iNjO1RJֆR(?/'z,·v£ǿ_ +`IK խv-1B cz1:FKLOEhq+la`3NU^#4lDwkwYV̊Z]hE3BvwoMBC,4SeQ賭Eڲ꺪Es b~ :Q` kNW-z&#Ot! Q$$(ͳ8h>qsnFx#`*M}+z`~0$ٻƍ{<ӥ$r?ˍ[mY)8ޤU] WH"$J# %\mܹ?9J5ZAi# u#;\1&D'QImZi>X0j_"`Gmve)#Ug?& G7d.{Q絖JI)LFZ`ɠ%*)MZߏʡ9,]\L}iU"dGC<[T6*s 1mx^J ̭m8F^xcQ?24( p[l&Q/WV_kCآ*kQic|~Y.W8೔<6;OLE@03J[wǘF3>]N 4SzE'M x(3/Y2V'[V>/~dD>EI umZ1"-AwX g pr^G>A{#KiQ8!l}6uoV۽AQ&8 Brˢh8E!,9°'_}z#?>M31Zc0ydF#m|cX"XqшߊY,R8+e2yKWm7[ RTk[Gn_ ysJY-Jy{x7[\HwhֲgMB!ֆe4M`j<}XeYY8$ȭEk1ζݟçä:mE!B@jy*gRk (IUK|/JQ>vqQ a~{pI9Xeu'a1k`ƫ>@I妋noA(+T! ĤFHuf)<:5!4(*&8g8mt5Ҭ86:ҵ7__o?oOÏ8V!ۅki҄~TԜR |je$mh˄8?Cq%~gxZ$1CT[ZI{ƪf7SB8c(Y:o;kn<]R*J;iZyWԝt5$@ZG[?W^-?6F.^Ǐs ;f>8ʄ Ba{CKژSЖ,Rh4db>N Qhc 1!6t5#We ,YZ}9FuKBz < _He[_D_QcUF/kQMDbd,OK^Vi M 9qJc !T5g J1F\*3w}Ek|RA, V9c+!֔P2Zkmq^ԛ!%+U vDW7+{>3!tg ! *ZdB1?SsΗP{ߍPhxdqo?m'"C;mʲB6cbG Ødy*v<)8'd, l/h]Be] %VӃ^3/ʐHW^`rum#4<=d5$~̓{O[N+"}c*X|Qb1B͗Sdћ[V`%WGU.YGJ|ƫ{QYNB%F?+ậ .oVT~cޜ, l'%xt6& cUcDQFUN&K7/}m wioצYcp5d=RT1!9vJL!&XvU*t ձ8:lxh㌵Hj⑕ufgBMFjTuy:;Ϗ`:i^Nؐч|r:{e}#[b3WLJR1ByY{"`^^ZSkxZđG)U*AGJ.Q\[bp!!8܌Q Îug`Vㅬf˪.SAkUatNP)%B!o }uo2Fi@zk]JbTT9AVd$FazX1cIڍoDPGU0.tRꁶFceVnO c末ls0X%V M(1VB2.lhz](o<P'k/h6a"XI^X8ڵ3F~dYrY 7$!J7rR~9eEٰ=3[}aUB֘mAY?p~27W+/5՜W"w8P5B1;h9Z4Xמ?4 7YsZj7w'Jyw7:VsPL)͋S vkpW:^Ti?%ceu&F%N%oOVƦ M\6V*tc_iP6"ŘnGI6 Ğh_]kÙL[9[wzx]-__۟¤ɹީ:$(]sk"7`>0`IEg5G3cPhE79uRi1I[T4c Km\Qa"̍1ȏʺPZ;^^;{Ol;FPy3X4_ejeV͖F>7_o=LY~|o~i/$˜5fFv# iIBV"7,.<ЉU笒jг=XMsS}*NM0ŦV}{^ͮrѧ!єuDîE!-0΋* l2 hbeUy/`su񥓅vQb)fCTF*Bv~AZRkYW_FHҢ(hQVGb?,gc."FOO&9;hR{/\gօNK Ivc ;DۧcP,eɾJz~0̈vb]Pp\{E|c*ԒZa"/2k- ik0g(ck-5B^誓nOFصUnWٴ|bo|?*jbkEe=GR?>'pe.]?1 (+'u`L)] *g+c8<ڑ<@`i!F̜s$XQCcTIS&sx;I#i,hg_4ʶ4= ogy7|s*TRiIV۽^WۍѨ{uӘ B(Ք5de|)q=o'ͬ$ ?q>;}j [wEFc)tr`)I%;uI#JJ{/?|'oono^='Ku_$Cohѯ?t1J>}i=]GK(l+]W}QI&$(Ygjo^@Z`c+m=X۬|5^rAͤjFo'zicj?j܉[1svO}c^UslsݘRCI16F DB]ZPO)(W>2.D:+/}:n_ZoV|; %ݿ3r3cO?͝7nSus i)Z[[6ydxu+V .G%hM'^&9eUޞSIu06MGc!(kUX2KZp<p$OTSWeѦ0[ic&rla;<4yܿCmhx_-A#TUC!$t[iVM-̚zr:%0BR1QB#\NyY>/k"c1y(FnS/( OKBcd<OG^y,f!6!!l-4h6ǘPz&%KESj"j-e X # $÷ #]8fsUtqhIk 9Z!+FFkkΗk77 o}z~'y],$Lf:oVz {㽻\R kQ#28]Qϯ^YZz}1g6+]FIEQoai6؀{nZx0آD=})(*JsZa˛aY\kj%NLKg̣fpٰd~|; {NeE(cDjrx+WsK3Ki1wֵ?>ъ"d鞿3zwzp|lg<+y3O'e9Y`LQ`Rd SZc([~>/Y;/7ѥussW&aw/׽x +",?2>+)P+-jA{`/dD[`ɹM;k-FI`ќMs:/HZ3^5=;YQ6Mq }0ʊ\^9z0\La I)QTQ4l~IQ#-!Tʴnd7S&\=3+pn9Q_5}]]O><)of]Eq1PBj6Jq y׶T?i }6r-D{ЪQ`$J;:S`8ya(;j`(C 85 C4"K!z{on.GB{1zgy^|Gw\*o$Om{'N+lgLy7SV)cyϐ?Ko6j~g//?5f.exWkq>~s4i-BOD@iU]3B>}bV+c3@: 9Yk0+ݧjYENH=}pdڬ/ K_3O>pM^)+ejW|;=Tx:(jkBvk$Vu/2z+Vֆw\gd?g{VA<'UDSU#қ[ݷ0 Y&ބUK nk^F^SkSt ;WZ+v2}󙱞R!;1;ءw,OϯiCk |{sih|V y3;MmYq8i sAq};}/PJa`Zϯ]qƣ6p:&L\7U. Ɛ)Ԃ#rti=\;erۇ˾1ۊcmقG@eU1 x+MA%C XƜcoblۢ;O ! ROJ4U+2!&-kgro0Z#Rk7hVuwр,K,3bD 2akM'ٙ:̰xQkVsjrz4K:Cta|:KṶwFNs9OC~AT3%Fy4ރ^y~_zia۞ƄtyEʋҰ@( 4=Wjיwp-l'Fzl*![Y4W WU%v2 ~;eX7 oOç3xlۙ#>8=ci8GڊS_f¨ێ'_=ouaΏ_U;/+I'v+B( bRcK{4ev>5b{Xt]cpj"iw"ue|ѶjM ^_'?;߶ᬬocNTmW|;7Lpq˜`P\w{Og$>!i!X2x< cڈ1'LՌ 5RNO9!hgE%YNfn^#%PXȓ$l/JJVLBh@Wo黲>0z8-?\φf+?YyF߶˿z܆xecra~o/ޣx7pm\t(Vk)5Efo\0y=5+ɜ188ͶWc B噴$@ݘynGZkU< |gG뺨Iyǻս2syy;|zRZhY[J9|ҲAiԒ7کUBQuSׯ\u=ƺ7_2mg4"pGӢ?+cB3oy.3Ffd"dc*tA)\3M=?1jRHc`L a^F`#G/;9s!=x2??XK02(/\.x^e^HbLs\,tA!SE7O[wm3Q)R%ƕh%+%6BR;ӻQ8׍8\n8ɳ,;WV0?b{܏c`,9ǃ~֏sׯ},j]n3C/كs|s۽;o |_گWMv%۾B0aGmǣԟ5i3|eԶ4ͼjZ25nv=B<Ԩ Z+(FY:YYY YE,z.{@VWͦ3+xkzm@ CΡRٰc҈f8';V@k,*/ ڔ~zݜFDjjIFYtq@vva#L|݊hYZPksC;ꢶU8p$$MrV8eUX[!TXz?,ܯ_yW?#blk?F>z~[O,ܲd[sLPm, Jkj'1dVyp^&~Is:gc NA.,肔FP :I"w6ƌR0І]YzDt01 YמFh.rPZ4Gz/`YBi|xk (5|SW~RlF++\Zmo?w2xp {GJ- R!6Qao~ӅBd/lȳݾN=/sY_-YZsRMzp6CG1X'R˭2y^ڼi &5]Ot^Zc1KςgJˢJb0v^`!f!aY0Ck:q#Cӟ}K1%jtۉ,seck <ŨMƘTiIRk(^V*L<)ݬ|6%:gz i3FW N;{w>Kh@_]"#^Bm]bu]-klry=6:  {':|BG÷ o?-8?unr,+ٍ/v) hW1'Ƀ{=[nnHi慥Dj0Y֗Z`-ZWa?ep&8su;F[|i?sFO;n%aR'L*w&WbvXg|;ݙ^]wW_{P5(ЎV;{Ρ *8=X"{vYT]7Y7iOl0BP#UȊx\a/+rZdFHT{VѴeH1ZJ`Jƨ]qHݿ#=X"=?{l\j z5 ˵Th֖1I ˽^+10ޑƳƁGSrF- 0?w 'ϼ~s?>iI2JFJAsTB{l'ǧw@78싸㍵Z `1&4+NJ+kKҞpc1sclFQPůvfoGnOo0`~{.{a[ݸ~r|+f!c#,;l6W7&:On룃8m=2E7߾pr~镇bU(AeC9GkmVv[Ro[ [ժGGfYx:qZ*+3+X5#,N'6*QlV)sd@;97D,EdZhOZwV(=G>w|sO?}R ͇/={weke54F"!v&^gIk5hSWՆDO@*< θTȡ p0!vaL!X PtE Fw5?~~6;}πjO'[WfVf׺4[}o=;"(ǝhSJrme33",W^Ƙ[ ҈]{̗ŏK#U`k8籡5XJpA[[}C s2I:H }O5db vk̨e!eh6hڭU_o;9z5pG_9%q/gȕҭw>?GӒ77z1KԼB50K$CG1Ȼ8I/_s<[}Z϶C{bjCb8GRBQ$t5}puldq,8w$L/EY]<< EP/}}_juB{ƥjh-BHӊ" ѪxZZ2chxl^<=y$^xn͎V;6}boey`t @q:m o)]uC\&FrF6ԮYkRJa_`w es!Vk8F`7vc(it"јyg_Tׇ?}X5W 5#F/IŘŒ9V,wGQZn8Y :Ӽ,xci!XF}Jcrv@>5hp^˯mZ`2PR jaR47v.PVewoeٙxKI~_r뒾Z8NrT!zyi, %謈` izsuk`z;PRIrNūx.Ofni㹎e#=v׸Q&-A<"KB4lKD0kmbP*9Q*DfL^ky> }`UK-u.kC>,/Q9tޣ|?sƖ(BPcMQ@Uu]&AT k4 O?{:sNj|C]7=`tC'۱;lTK{e;Wϐ4Hnxy卲jqzyP업5:Ó0Bhc?4;B 9 z?pGKa_g>}?ƛd?~vţA PuRB&߸=Sjk$sUfƝZgդ++# v'h걉K'FwF攆nnD{\!+P0C8cY&yO6A9Vx;2A#zQ.*cMu+nbˆ ?rO]kaEsVA@ZO]P{`ȔiѬ4|8ɴa:xg'ЍK Ʋ?BaϑFFJ [ 1c'Dyc}E7[?'7v幤J:3 c;+$ O\ˋSE#*؇R\ii!@J5]muξeFuˬ0FQIs2N+p֨ǣòCq6q}j\մ MVazN[5NU5Wn0lmv7Vl旾D|/, u3Ӫ)*iEލr nNqf7<9E X%#]I7k18J`F*iJDkIfl5iIHc 4r"/(y;I0"s<+f۫q'+]L` msg1(eb{aT5gL8kqU+3jJӣ! pTM՞s0{<>%YZԾ˥ԌyEqXSMs^A3)l8~zp88{36rd-)^3~ӳO50 b$(;˔vfTwma;.[a d#ǪB 5:rJ+cҹYzl< W [kQ-''k8ko,}̄\W'1h'/lleC6㺚Z:l;GG37rk_۞pvT|{ʺۘx~u{>)(m4-Gŋ!7>O/^yן5F5JjޫڥΪP@C7[ (1JRiVTͣxIeW?SdT~"°0-Esxp]{z `yv8t)BhRDծVkg0s} (@Y['-r2nmp4B{yKŵ ֈQv~[A;ѝ֊aՈ8 G0J 9#(4-꥖ E=NώǨW{$J[.VeNN!ZjuQ e&X[}ƽᴸ.RpbcL)iYQekV /} 0b2/8*` /!`"n ]t cB"R(Bwz_D.7^տ>wx B{L?p"V6H޸G] 0BZY0 dYQ";wA/M%Bȥ̕vI 9pJ1[s+KՑxd}8YN6~0^,jy/Uʹێ`YHPWc4R&PȒ5]5 s젯L!Bokkz~w|~BHJ߿]]av0,p$׮y(;OPq*;4-[8p.,L$F@hޕ#ME=tJ7Q|1K1PZ#cJ0P DƠEߥaJ1ح,~wNb t#Q襖GYJiղ mZ7k%ؗ~2{8NgGh•[뫝4HrSxK P68xG5> Ƣr^ )qNk,n4{9CLսGOufY_3?ON9'dVm#g˭u'eIHD qyyZadH-WQ)H5MS#H78Ğ%4>R#qZ4RW5^^ԶDGco4n&h@H:UJR} YYE|BrҝR 5jku1B+,4Rw0*@UՏ˼>ľ L)`Qm|_s˓iڊ/ͯ~JA>9Q9DF^=kW^O+}"'fs,J5ݽ&SV1d"_XS*f@qm-}pH &sd~_jJ#4i˪uvµҴ']yZ[OU=?w^ЮCzQkӎf <^ p~<@se3ضCtk=eq+aM]Q#㄄AkbxbMd0" X #ka|0X5`A Yٍ̐UW# m6x cA`г]_c Y=q{˞sNqqZap )}kRꈒqU5y3F(;9K-<㱰Bztr8A2+Yv2'{j} qF#OWo:eߚgy/uB59!xR#(1%l-K5Y#dⰧIj?3N1|t5Z^ɇs1F"ߞ{3/UA?WIPeUy1]릔7tZYR^A1̞`1xKy` 7*R uasEqR :ӭE}cJBs0XKYzw[=2*s8J/4I0#2NGS_ٝNS4 4Fd B󲓖T$ZZnT.qCjt+0y c7wfPHIZn7-Rg_ yi4[4wF厵PՒRSX,TYV,_yYj k8˺ײSyncZ@hqLQ?ˏ%XB(ņ{\$ԎLd#5!^Nǭ9_{hw9s8b_YQaaäԢjG셋ټJ݃hXtYt"(UZLkc-)4J:TK;NYV9I d.)EˌJC/3J("ݼ.Y B,B(oڕ7 e!FI0JLKy}[NB*n~ק_,_?\HtBBHUW E2Y՝DkE0kpFi^nLЂteR*qjU"/R|1&/RKM9Y]1YױwQk`|hfT9Jyh{~LA&MM&cgq Ykco{u#+iV,'΁MJkyzD ~b͙NiTh0!|7RO7y"V[ۮ,Z7RzOv4##-tWI5sJHi!w*f<@&!15Hi~kEU㗞T 0F*D3"ϯ~9@F'7)I{-wܕGn@jCvh:/c,CȎvQClF)٦%ۘ76!+Ovo]Ҝbkxһq c|n}o$1"yN^IZ0B^FV;12YwYy<XmԜ< '2s5R=:UmޱSK/o~#-bu!zjIE ʸxMƵ8 (YQkp$ |k`(%hc!քΝ>BX9;SEqxzߎI0 L-%[;ݒyU#Bp1䥾z-`%B*qQ n2FULk{ ;E~m}i|8U+{h+FYJkL g0+7{T-ZW[VQF˱sw?hc|wX`{!xnޕo$dy'X6|bTj^0J)3:J0ʤ%K,r6OW%; !_ݴLj0m@^;<= sxlRoYV0 j]'//&ix:㟹fɮ6:9w>;{xԒׂ*0FjS_,!N]ebik-gʹ " ZM*UFTyoj /h(=Kxt*$^oq*kJZ|Cӧ((ZMSk~n_zZNuM]ÍsZ[ly SWiмiά-q*{I &hNigyr3s ƅ?(sQi.%Q#;UcS֍t'y[*-3U)XypIR( [2sUZs_o{JZI9~{auy?8l[ p:@J;Jx i1*-őOb_|>[fg,%"j9 ;ȝL>[4@l\7Ze5;Ô3+'EZ|oU] UYkA,8bSa֖4i-:UL[qiTW 9\n=]hKhT)2eNUF{wYd0o^8DTLz5.OթŽ5MhCBL#eA*pƙjmZi/%kV%іSym wb|JI # ZN9[6}a("d%aPx=LRC "!y6wjXӍ^sem٫i ]{v'?'q=L~22M]cKJ^ksN\SYB_ݨjqgsԕcѧ@k):Q# %g3!cG_S}~6{kan, cԸ UśM3|h46y}xBt`Y[#]ҎniQ~|8IA#lӬDbjd^u^8/Dh,=e>ص701X+fe9'^8;96*Qڽ楞$B@𢷆Q <-jY_zCoLT^ic66 B"J;A"Y'(1;"D`,(QO8KJ8pucovӭ~򫬨V4TTHX`)xTb wxka!5֎G|ek!LqPFx&Fm `Vukn@1\s^Fpt#YIH T W6//";|K8ٴ[BZ;odj]v7Bc7-++?XF(V;Ӳ<mH^snzky8(Ԏdq1jQ &Дk:-e,^Z;8r#[/~oF/iy( 7 I.0AhmFU@'; H 4:"M{bPoܲ2sM`VJvdP`ɴid.WScҤ`p/PX'Z*EG=eV *rLl҉()v`0SCy"Xv(ۡpYzF8+JʬR.6FεaJB}LbhDsqeV)M砏?#fqV9Ӝ6g7NͽՊ^g3p)C^Nj><.fO:K0g{{X ټPy>\%XyTqORZb)e%Fy#6p Fر@-*tQd4FO.c gw^0 :6^ۻXhm!v BZ,c,8肸<_mȪ?d 6=Y '=J;y0bb6*ÍCa jJoEsŰ8BxL]:T&^N^u?0-}F3ViQkJk<BQqBZK08Z\[|V xoŸǛ;W?#BP {R+vgJhF %TiE[E; Bs!DZ)aOk)<+!TY˄DVJ(B3 JFRFt^1O0qQIrZ7 Oj"uS{4Эi"te`6)_!ʐfU^V Wz&@!b}#Ƣe1ghܼf ]YGصoBOgN2y7[3g#@#qB`k?:Y;B(cax2Id-,1FTgew^X߯ i<'lE|?X)12ӉZ@iswwZSBUa^,KsziG&3R 6ͽI[𘻲{`F?=-4 wR^t:`EZ(.뼬åGMY+SJyxml]k`p6\^NJϼ:(l6e0JPY4m4p),S}i"ByUS!d=<b90p0q bȌ8X㢬gN74m%Sȭ$ZUY(%禹*NF^]=u8bQk^}0zg1jiS1dřInWÁu]w_FZ*T(4^$5!c#ƚ a*k1E14`,i-&z.ZkiAU<3x$Xj!Qt49UkEmW[o;iג-诵i,JƠ-j2T󛭋W6['_?hζIP<6EPPq m 0] 80Z+B|AQ"/1m0PIa dVRi #UԧF#$X+y1궞$[foo۫!ZYEeHNAPK0!`|];\V(X Eć{V#ˍVkKǍPgՎ$}uB)4Y-ְ8"Wpfzxy><zcAbno}A𽪝Lu8 (*E4X!)txX0ž;ˬ5jAaL1ҌԉW .g]=_;#X0<˄T3H3={QTԡD"pjB3qavFn+P`lmd֙#ቂJ`1(-E}{<1 #CE `xNC0`0Ά#JaҪY #YeCrIDAT7̖ k-,])UґYń:Ѫ&gJtJb@L"IR45)MѦIo=~?])I;lg BRwQZ`s0MY2׻rL`ˆ1nw3FbL2ƈ3#k-G7h"k@=).sܬ ՕdU*mnKZ7]f^U719_yQ# y!h$˪Xs&@P$lEcc.U pP7bs뽃- 4R9t+l[ q'-whdW$YE KB_.,е+K9ys~5\^^9=` BB?08 a;FU,x'R)y;r}+1 8>7I Gaۥ;#")5,U#ONUs IK(I-;"z8XjAY# i.'{}>Y:-JN:eqb0J!쟖eon{Am, ĨmEQ0U* GR"w\ VHy<ôϯTZu(AbGm/ i;L v9sXM4;"ihRôE˅1iW ox\M^~ ?A?-)ƄsZ 2:N; A"r']\J5qXȷb>10.~C٘5BZ8)m}OⳚfNHsٻRk1k/%_G6Uj5X0ء1YaB!9yE..ݸ38O0!Wp0 Xp޴(+MV4<3Y K~4 LyHgJ8Kg_h?\ݸss݅"D@kkj/ne Duxgi#UEi)Z2)Ug, |BfLkΨXV)V-\2\/\Q7b˧K:+,o$TcL ]5Bv8h 8+ Y@Mtm;i=$B)BbG㣧_w (cP(RV{6`kXI63T++(]')lg5XrNw$J0Peľg Xā:>3Mc/i1:BByutS@p}cʲvxRmrƒ!=1Pb:ŽEJc|pΜNXT2 '^:n?:>:IB|hy1Z[7kd<-+02?q%4s8^Z9:ޝFN6@{9~:H2v,ѡ.kp|8;]!DX-VCV@ZQ2:5q̤I?yopJ{r3O CP;M%M p׫]UvۜqeQ6EEe@H{c}iM\5T41R0/0!t8-vN-jivBhQ "[i蠨v'j{mU֍&1:)&qBwQL$%7ccZԕ  َP. xTa1KtH k˯.Y{ImR[-al䃃^+%tZ+A|&ѸS^R 4*aYiEAat! Xv,F1q/(n`58,p]UCkI }CYQ^Y0RJE/]nvѬs#d#72;/SGUoiZKpge׹>&{aB xP44-^zvܯzdbJY)Xj;m0ZL`>ӣL.5hCzSP4yncp iv@1alV7B(к XǁVkqJh FRsnE?v;w.1p #'x *h<) K9Y%dٹ\985=nL^H>UIL\[G=yEVn;`Yߥ M'y}?x9ns>}g.hr./̛4zNW*c-b\m1j)mIfũieX!~x_[((:VZ+6Z W]eei`q1v0i>ȵ諭eQbEri[>.(!OO5 GO`q-DyBd7EfAlz.\Vv1/i|QXiّy18LwbjkCz\ܲ0\Qogduh?]O奼gYڎ}ak !ZYS:o#i]-9pz'ao?NZ2㦓Oo*a˙8BQmL+dұ=#yδ&֔8xsc.{4=rUl0|fe~' *OJ($5"Ť+-jS p7'i56ͫR F {JN啵z'l8+ݭ^#TfMsu7F[C am-`YI=O_ ?_7娼ZTMZ1[k[+>y{.UZ`p?kLQgtR&>AU^-1PJT+VZYG"Ls׀QZa[NߌÈ`3+FHJG^+lrHTs eR#Fkv>"3o77'/Hv/.f+3%#25Cn JRp(ez=u<a^igZBKi#d Xj.P DN'{zQxu|%rnJ(Pg,2Jg]c*k-Rwz[~zxa+~RK6#l-CH%t,,](&}LRdҼok ) fkMZ%湝O4f;WL;xI Y><8w2Q5(cgz{/[ ׍$t%yQW Y޸VYio;c1kgŘ`L1K-_9=]W'IQ#[3ZM珤=#m>{cW.g="N\FGǣ9܀[Qo-TV֬XjJ}N'on%H#N{^ Y%ZkL[x4sB=9G{^Y,׍00ʸm B9kL]"J4`ljD;k") \;&nnīZ((@1i3i7*T&3%r9eDtMZhkN朷TUuzJk@΋`ཻofc|i|P<~k%ʆ QwKu~o^@]{_ueF[ i:]Q\: kTF[ Uݏ^%m En{/OK]6*+KfȬŧwVVy>? 6Bᲆ>Ӊ¶@_Ϝu=o7N'F5{+BH^IFSUXsNʺPL-D#D1քrL6eBwBPi\MF'&65꜌ˑzE!C?E'ZuyYi;G]YT}L̗{+6H yޅ;Rџ,{"ߩg/c)tBȪ^5m5WOjﹹ~Z`zkceJčgkv4`|{Ϋ^Va0Qtpؘsf.kD!h Nɕ=1,UR0o_N);}拯|at|i3J:FZoZ}#Ԏ{X5@p['czQRFZcR390^o-,faںoz=|g^?Ly^Oʹ+pG H8*Bv&otFs"Fs n51`6{u(T'Eݴ}$vJRMC5ױT/֭ŹC&yWv)c|ѷ BQZ i(E%&E96r;rZ#jSs F d(k$lNZ0+6Ɋa(w֨ Ծ חA޸qY_(1Bi^Z^|_ O-5Ҕ`=WaL#IDR6qe=u|84dQ8Z[;Y foc@EߥL< M^dQnc|R>^ԧdkom |!P:+ڄ/~@k˭٧pO )V0ν )CpY3J2OS˝JhHݖ?/=LrȲ5e,%)1Quwp}&ZW)RT6@cl@+de-Do5V 8TQ֒weoŋMUoկ 4^[B-H(J>9,B ٭%+57I{"]xlK'#s=XS/gCV(5voY9a=x.EyQ=ɲk3ڮL#^`Qѳ/+KIwl`k.N^.^e&'kR03UuJ4q_(o4G!D"ၴ3|KboG>1&4 #0F,H p!5WvY6ZXk޾}:|~9ϥEU3BmRj !sb,1 |ǡȢ8FKe@ cskhUcc@ZH0-tgU%$ȻwKz@ek9eh$G/\-~%\FyVJ`ǮJ%(/ݠpPհvJ[ f$Q+tv$29<!L{nt7"Ӛ㔊6! y/ֳ,i|įd`ś:BZuK\Mv1xڂ}v60p8:,#xIJ67oTU|(uS"8o/—_;EYQJŸvt$&`X 'IABBTQ{}a<@lYsvV)C1&0_5#Rs\c|( c/o]jg _OnrQbk+_Íp)qkLY]_`g?J 5uC??[B'>$-Z!Qt[qy'P#E"6Uy2ݣ84 m-x.}bx0/|KI=D O uFV !5P\P3ӊV/%0t' 4^a8:9Fyy5E4ԖjC!Va7 @܆FDIlĖYbUsͼs'μ臸yf KD>'/ ̊$|{WFGҙE}[BɫX7p tcJKcwb%j=%*Ņ+2BLߥ%EN8>f)MTØw9<LeDZtarp8#\kP cډ$_>dn^s{pԒ-RG %TaGi9L܆ōC捎QwoEZ,VFRu"_֯ ?gJy(/_n8==9Rty1RhC&iU T6Wbc`INfG*e(!| 4"/׶Eho7\?Z¸uxjJ7.6? 5pՐg(huNt-GZe'^ݒRͼN7rnPٺ>gxZ)irN'G/^xҪ{F?t݋=((+\g`u."!00RVFʂy+xfFJwE0hcTP.$[J;)  c;&ⳑ'8^:gˢa}jP^ٺ. 1cA(0 LN; "m.2J;dD$b(w_~JH0W O90"Mn;&vz RZϥ͹*DU*f;6% eU^q|{ٟ}Rou\)o \u!)E`>Ӹk+v9k#OF( "wPN1:"D,{]gc$UbFR9Ƹ.mGGoݍ.lj/XQ4;uƘr*atȂeV6dŤHN6 =Am.+[$JhF:v~4uuD#?76,`1>@%B(:!mDS͡ lz8Ԃeׯ>YU)]6;IQgn^OZF : _zǝlS*stcou^&KD˕FtQ+3r<:sv]נ'c,nա3b{V: @`%l6^*@nx=wv*BT1%RZ&2l㱬sJ JHJ]l $L\652 \VKG+xC?/}j0&R4uS(C p߅ZXNu^3eBFE Ff%5a##teZ2кD$Z鐵  !& H֦Z4\@s)b&\dz.AzF-d#BS uaYkOWMoϲ6kCx][5#:^on\Řk=1p9L7 i"OSTU]cA ,q=մ?h1g3M] i0j `i!koa+akeXa3R4 ֔DaVuXK%ZuVO8CO0ǘ&k;_Tzxw+[kYiXr%S2{5:r3o\jNy|Mᐟu+iE5Hk\o~󔪵6yMúMk~|ĔZ4_Zuv. {#a)4-։K[ebO~[jjuh! Ho[1em(tJ7 1|y4kgs/ԍu\11A[kVo|{27nhNd HPҞ(@n 4=&eZHE*3Ž_TB)71!!$[}vAPIw2lR..iX]k[<#_,E{[ѠU?wa~MRinE0)mRaPJA\v3Y$`DEm|NxR)>Ƙ3Vz2Uk yXYuk8jLPTIY @@8Z,bՂ=aFdtѵF>mV5ۯ+*b7o72ZkL3pN@l[m_ے99=4E1Z65B5W6vO&SB0L1d67) rvTh-&+c\َڑКbBatcHK0Ʌ`m<^l D[X.ښGi5_%/>X#4]NDGsW*; !u[ZKbƀZfoxgZ2#5҉aLEJBHfݓg7Zm̹4׫&L^QaGemthbMd 5zT`KPh"OvV`УeXb=F׌]c<+äK*9B(+\: D( y?4/_yiYO୘?Vw=>ak=|м*+Ghp2_ͰUpVuA>_ØQԚz9_u c$XjlҺAeqcńKE)l+n%8=.jXbY0p[k@|ō^ۯL8r 1SM#2Pt !pۊdqIfheo\Vcߚ^܈ deX-kA6"*H<5VSo;o![XJKXWz|{%WWM*  #(pZ YB~-Ҋ9!;kFihZR#1VwC4K ^81%a=˨a Y)ʪʿ7yY /_7ր9dBkNҟRU-kOT8 %!wJY߻ 9>_?7~ȸgQ{9㺙n4:TF q`f  ,CMc-)*U9J C_qa.׽)b+ Lž˳n "3w@.­FYvaKϠؑpOUd 0Zu# л O޾. E2>g_x8>{V„|bBZYQ$g!k)Ŝ19h魡|⸐.Yȧ6gn;'iK;Y^?^va>ˏD92~xp]7DNd YѾ{PðsJ+9/CWu8 iU.)u0viRD芽[rԸ49J.;zإЕ+O{M {ۏ6g|yz>BR0xm7/Eb[yftM!3YeOqѸpIqYΝ,10̛^./o@ZE=aׄ qqvOF#?]jlE }ܭͽc鹞4lvK=8ʚ(mbRiR_ڀ!\<+m]'V]P-E"%g2eϋ;]ok[[RiW"cccrR+1űP3Ca8s9<<@(ExM[Z8X|j8~\fTo#ƆڈFfHfwOF>{93Y赯:+'lQ`{[W~{ h4~v  B[36e9viDxnNi^Zahgm(y,ot1n0b6Bz&Qسq _#wreYr5jϿRaCc,@Ƃ&!^p2]^bf hZ5 a3ykLp2,,OCwPjW^*34'Usf`}$g΢O~Fa?͗Zkݏ~Clۗ9tϫa` ի`iamOZY m(Z8ۭGRKwHe0 y`d;! NQL7zEvRQ%_߽"蹱SLۋlmG0B,2dv\lӴP0Jy蓃.a9(O1pLb.UAqLݸsDYf&4p|xB4rJ770Fr*3GcI㺬u%ױ8w><;p9*Z#PqY8PRJ˪q%EHis5+K0؇?nݟEj]ֻRe`:Do\Dg8XP=iŁHM{um[GZ=^GChkX$iuCQכѿG/^6WW(.=Mb``X@4ol7-y0 n{V)AZRc2uw7\y^3PRz1DŽ`xxGfVuyE|g֎ 3ZfY$(%q6K9lٕ.ֺa)/wYs:>8R{V/G6߻{d&YPY;[mfkmu2.K4L29-iK*m]UGU1 8ɲ\}_O󿳨/J)wA}$ ~ g~u-8x%d2hgdredcjRZ0!icvha|JX=p{?ϻ/>U/B=;h=pY"c޲ r2t~EY=DhLH{ʅ/m>z嗖+].JOҴ4֒.s"4=vYյ YQ֬2Srr3;]rgt9Š8YA„.X,pER1ݍҚp < ,"eMc͏*[uZ"v{/]b}np5LSH"g,lKY>{5 Π]8:נgrnY%ͧ76Zw}hf/= sB[$u{ϸ"Ư+yרdmn{n-( Z,IώN =*+Îh Qsw(=TG/h{kg׶>rY2s4 PQ-Yk\;Kmv$LYOS 8dv\vm}xjEk)Go>ph^܈JaY7')E.Qi*x֍?*R!è6dʢ ܊ *t=דl|QB,k1UU墕UsŠZoFZeŋϷF@VxCkklO6q;T'yEYsz1F<_vK#@TQ̤x-m.Pj5/Q8ci"ʞSݲxKyp1ck-{FBvsgl hOuRiߎvQ̅!pv΁\"H8)x#vX- :P8 :L]$ɕvVSX8W7m 0jI(ŕ﬷ﭴfER{Z>Hֲ*DO>Ų ";UM~n:K?;eMo-TydkV׾e1BA B嗱W $ I.m[zr>88,9-_VRR/3i>FJa$%kuȃ8WM'W"8<; $= qH;SGN_VL~׫=wʲ.WV6IgYKS=l1leZ_~N˛~[r\ʆ5FHh,oϖk8W6ưw_z1pN9wcwv/10E~wtBʪϾn2 <i?riI\dZ>\,LK1ֈzlFhƨ 3W.?:엵 N{tn6R\H }_H5pRKDئkV:3:kIKqf{I锍4RZ{$]8Ue|1L6V-K煽i򏏽I֡%sh[K7rv9͋Űx.n{EݸKr&wʕwӪ*ڑ[UJlٙyy! Ie|=c(O8j;KD{^(j{\wvbm {/SsjҩEOw6P4>s.fQMʵv뻾xV*0R6 37eCI`mɨZd N(^&{y-c9{rhMBzmks}SRHj3T)pp=.\4W`:_ړy#k?kCnyr;JP⽪VZƳeUZd/\@h27̓2r ҕT#c@ \[ңyg.ץ-V@o;Y=zAR5͆ktBQ1ONwvf^]sJ5GjQ[nЎhNK7cZ߳`n*a`E!K@܈^~9yM-'s2X O^Ff%ˊɰgc4yaSkJ޾nȠCho^@ ,%aBwXZhc,X PE~{rXtSQ `H./ݨ Tԕdgv[ɬvvB(,qRVי?[32Ǚ*?}o_V\'yULS\$XV;lH{Z|=xkiͦzD*ƞ[;uZ+~B5l 'F:4 @&+N qϙ/ xtoVe]-2c`VtZϝ&f aV5/?,0,8R0ABNq;9:oM2(OS8b~W`cˬ4qw.'OLZ`%` \D^%mD9[H):e +ﭬ]gwN7t?o?<>/A,'M]>:B̠-NgrIQǷD~m{/GȋFy #j)_}Z FCՠ]j#^fΠ錔5DՍK[Q׷kU]qN]ΌCJ8(1#eSօӉJmqk6q0ua9FFGSƎ>U+z,gXm, UҍHٰe`-0Jfo7?IY:mY+ 4 >=kU=tw2l%uI+XdrHp y,yQ' o+bvw9Nl^&AӲhDϢ5dE{tsV;T"Bjc&N/N#-$w?:j]]^={0MFoҢi5juwt^j{ncml-dQ&,5tC#$^'Ƿ^힍4KĭgÝ=+!fD 0-bL6nxROX˯޺uu.zy}<]X^bNcfX:VB\M6;[kyW\)Fi_ ,]h^n{ɲT^:8-b/Cn$)ͅr\iqc VnYZGNib&4IN'ZÎ$q1Vię'R)"@O8jy_&M/$e[P P iް!b8M uN2UOgyMu*w ~#h=E@x,O76^%4ύO>tbߵP`ly9WemcX1Zb ۍ&FҸ!Gt G14ӝ[R ~Z`,g< CNYU8h_kOގp臁 m1ȅҥe#shMkLPzG_|zFɜ3,ʃe֎).P8{&IQTRu^V+$i (ZcG9[0p}_}5WM[PI#q?{7޳ՍZŒAƂ DiE ]_YN>̦4N|G|VsX `*Ҹz.oG.]8Kjw^OFPNIQ }~68v^t[m?=K6' Fs|N+aW6E9 ,q< îufzYyԁLae8r $fژ1vaNfn̗jmu.S>)W1jD1* BwJl-216lYW>`B&.]TrFCלL2o]Yx ]Q-!h8Ip1Gk>7Ob䓇ݘw!cNRRot1Cϭ=6V#=iV4%i:Y4QzʶrZn2B%je:! n?kNS4*O^ݻ/ve1Q% I%kd_{4 sdؚR8OB4DZvKqGO^>=V`.DE/Xw<{Ͼ|sh#q#vm<MHtI3xc0E%0w\k!%HgUTBԌ"B eV a:Veqv9+3}di'c ` NeQՔJxQUZRA;=*+9z_O >8|ъYYT:6}Be[kfK [sӤ47F之܎M^VN FO1o|Rg"V'e>"RLSaՒ'eUBaic# 2UKM:eD2eQ֖$E X J pF:,no]A[ƪ\.9 k?^$2TUٍbMv?z[UTJy1[e, z%p;wV[~jI L[a}yuձWE/ OzI>v A0-J]4ѢܐZI u*˜| 5jVbQv,\6b8ӮpothbNø!d$_ {;ny7VZ e+}zy7hx^/_rQEa+.DAF L\RXYKş, Uʶzx|6Offc ,P+zutCH& b|}ײW^˿uG8`IKn>NI$7aH ~Q> kZsaž W^/#Ҟ׹|y{!h-u햷~p6!ezTT&w?҇c^V2M_畩PȲnox.77ANa]EiWc{ڍ(rFZLaI1_VVE`yV IVr׾6\0Bk,QsZi}l-,d.w%yUTf<'=.ơja=n" zԉ}h-JٟeN gڢFJHՎxR)~8YTQ8$d6)R bkN޲-P#Vnm{A[~3NE^+0v' Fal04Zƨ1c)BSt.V%ĥ !;e-mKVgk}&_K?4}JhE{ǦiI8GmDqsTLɕݛ!/ t~¯:;$ nbZl]gK(:E. uݐ1\j˧Ó]h\213lWx6R.'Ep7kAv~[{">7~jfZ{k6*#hxc #R9cV/ex\+ʙvBG#[,֚FԜnp{ JB#0_hKkGǓ1B\ެ)r[=4Pk-ϋ'H2b)Qѣ p9˙ﱟ}{c{6oEao}8Yv7Q+x^Keq;˕ᥦwQ/Q:IB\ufӷ+]!0J/pu7 N+p@։2?:K9"Ƙ:/.!uSc ׺IRA5)e=94xI~Z䭴Ee֢a:x9UQ@^ѪEyWՔJLjm_Do>\iV~WkECNTAQe # f/n7: }׉98,ؕ^(egi'Hsۄ{p4Yܭ\IxQ#e?CS'KB2c{hdQKi4>^%US=ѓYTu4O,MZQ@BZ(׆* ri3 SOi{˓;( iqe|c Rt]iij!fn_uo{ LApvXku8=71\ |sՎ0V-\&`$s ]ԡb;I]I# kaYдj2 8lG Řsfiɕb#k@2\yWQd-cBe]Gn=H%%XZy _WonNUef:7'Ӆ1Izſ_n/v !ysff L+vQ\L{J8ep®JC$Ngq@]Z/^Kl(^r,zIaR^ x}(V"<6 (#D~QlV Ū V9G7(ŹrWm淋Ԩ(#(eYY=zqfomvn^&k'Q* B( wl/~n]e>LrFl:gXUS!T`ry1XgoR!7˸!D6P7Nk)%]cZ# -~w/+[+kG]fj/ޛe)0dIr;:Q#WKqlzlqSJ)uS1v! TN&6&>Bƭ~'jdrn^`DSx^zLNbk-}ϥZU:43.8leE9 5R&˪$ԏ<'eӹeUhV :nY k1e*t?h%%-܃1kαE*MF:0yIZ!Zp F-cDkK` 5#DO,]vZ(깄۪;*i!8sNA׷v.peewbhyMRtxt<^X~Y+{2+6>}óR+၃=g^z1{ m?X$;O^F0?>1Eo'8=Q&w:-@@6/bèǣɇW]FӼ|xBu:Q DͤzIS6I^JJ[DE\ _"2hѰjUl>B\\N.9?ʛ.V`G0|rB4b9YNP\hZ<&@ePRȏ|{eۿw$1h 06i/wBőy+;G=z 'b#J5UnNVїfIQ RBS wZvVGU.ׄQVgӺ^uшN|/nãYyBIBb̙SVVkX_&'8H* wl{a,3h <|w=h V4:8k5UMҊXެVB&_Q1!c50X7\䍏1` 80mC !sO0wxY&gTay]BݻSA| ow'\NBneenm{soRcoVd;"&7/Ɯ(Wo!Zx< *}ԺӎZOܟ>ZSvm: ccɏ;QZp~ג "O< !:Ƙ:_\Y}?'_ݿ箫ZkG'Y)EER{ގOĆr9oFYc hgM҉N( &&p Yl ,BnyEóG(tMj4ɛ$>;IswȬ8+7>ngp]ȕ&YyiyD 鷡\C/+IC?(KgY!Ö`c6lxp~pN#^\{!\PjS/"kE&u"{u72AkrKJׯ6՝G'4˜Z` uQ^6Ze#QyLMZyVke%#dPR0zpu@!Sю:'bwMRJ׿+D/_U:Rvw.3J+3y51ZڠSf( <.&^` ,߱FJ5ouKw+uuy*Z "<;k4a=tqލ }y6h-m+RJD?m jۜ6a/x&A)ϙWN7mkA?}9f{>h_yup'E9ch[{(7jhje 6X9贜y.hmtݭ< Yr]i wKMV^/AkNO߿02j -AkХ |yRƠBU @w#04Bir8ԚX$4ڹ(QʹV8Ow0EADX|nHHk:h^ ʲZ mt ɲ$IJ$ ?kT %6Z^hd}mtsZ Xkwတ5~J!k5K6Dw4u]ZBsǏ%}|>VVWqzpӇ֢qKv& "o8#/܂mk<{*("'MD_ɣ JOX?=QvpF~O{n+M[ 0=;~SJ2i Fw k/G!!YmIg[]-Y]ZϖCboimɂj> CFM)R>_LknVΌJ{q{pPO;{O\mܸLi1;[N%%uȝC"UU }r6hc6?:' ёW"ƽ8z#Y ;]LBckǓЧD.YdnfRnͣx0Y$q}_qXӋ˗*,FN|nPoF6\<*om%Y^6x8{V1Z @Uwt-s-VXIjy7TPJүxirv(=r܍C /Ycm$B6#5ۺl ڜ dlV{Qh!txR6E({QpU篸EԍHa{_`p[?Lʥ8+8ՕD󨨭4^pZZx\ L9yL5IJj H c  1Ur|xNJ~Gϝxΰ  Go;ˑ0#)g9w7ãN%{My>_ds׹^֏ymҪq^fPKog'jsk;`qލhN=׺L5 *- k{;q]&+i%(Țb ̾9zZ Ov ~~qfٷ^6$ 0g^ó9F~gcA@w;q^u!<[~|\ RZ$#n^t/>{clgEm {8![^[Ւβ.b'_~9%҄Q(:,D-J8LAg/\sR7Kߥg&͵2 ByJU#LECMeRp\CL0-@gY^aǭcfNY#ym =#kX0^ϩ{63JucUb/k73yLk7v.'8nTڊ'qM rm_`4.Rƾ#Gxܕc,Y% <ͭfoοi9;?u?oh4l%kO%(%8O2`gmv !:oU2~~u!Em:HKrޛ$bkvp::--ܪfs %m?faк/ގw}cj^H+xlE܍}gs])}q粚3FqqwcxZqbnͪ~x9+֚^n&*%gưs !۫Gs ߥ~w;pޡx J$k(vN>y LXGohP>Gn^mѨ0ޭ \8Y~^VG5.\P=wg23T8p g2+Un ٣a+;BH3M N\޽N2H+x>,}9Q0Z 6HpRIιBYֳTu[A'4/# @`oQ2_xX56+, kc4'y8!D ~︮`8ϫt$n h}kU}LS eh.sBO,zu'_$^ZӰ 'fR,[6;##`E01+kF.(fЏ|G?w)SƜL=\߱>=ƫxx>[B>o0n(Ein+ko4;rIDATxҝL~uRkL!twY97%ֺpBqK`ҡ]{6ۈVz< z7)FF^X)6M[cu8 +ZO;/_GeSBjL)Ic6ōkWb6}:<1'eci)|uU#;gGy,lM8UˬA6CvQ4emeVyn{&KxV޺ml"tN' ZwHC"w A<9D#֣e-6zu3RZ̖Eqұv96WKRV-m#T;գe($ P'ƒ01#sV֗ˊRpԖ YzèEV9u8]U!YS!e..54R%X 5UcM:pDNt>vem 'Nscd%M)'w?ze- iWEC< u}[$4 4o?vF P=w':wk+.c,Lj_F"_D=\xWX 2 O@6V[Gi[=d$ vGh9Rm)'Lש~Z>LV1^p>q/~x5dQ$zZ=T6gyQ3*9j!|%{a+Uۏ+Lm!$+sLN:ժB>eH).]k+=X4 ^Y n?5fe>FH}UʵrZǻ4 0P[, {9 2Iq QNA(]mE QH}*l]1 }r$B镮Ht9\/pl^R'!6#9D@|,qzy,Ғ3 "84Ʌ0BYk?fq_\{ڜk294vd0-8$/Sr%BZXpMsi4L;彺SFs0i%K{U$HQFP8=Ymߙ-0A,RDei;#%vudzlly9L^ᅦ0E Y7k8YbVf(FgYm6ҪaiVQҺlTea#φNZ*+m!idCɹ/KW )K|΋x,rdI)-ҍR4eo>?De7B>}>񝴖[\yx VBO(J}FƃD#U-oqO¿}lIa+;!sֈq3(BRB(ˬbӥ v9!:Rt3F#6^KoWuUjn40@BI)@RQ g&8#M̄44Q(&&HCh`F[twUKW3_>7ǟ}eE$ qy}}^k ũ!8ž|aBW`o﫝g1 0,z|=-ڮʴƳ4;:i^L.cpE,@ e2Rcl  ,2G;Kmy O  &o|?sP,CCO-E.ňΜ,'sSQ|᠍!d&!xhYu)'EbzП'54kЊ`{̎ޝG2ΐvg~ިJiFMǵнyW[DY2ZFys%J9Y{ s8$кQ#,Y-Q:Xn9לcrg1RHBzhmjc!mX\4 ?`(]x(6t0/,Z-RH)`Vw\ 5*<5`7p-c3kQ "L&2F.3>pK&k_XMlҷAkh"4bqIE0AaPy!('XeSw,ݩñ,bF \d[VYé<şjӧnO9Z`/"J Uf`1(@({U#/0&9ڔBRL,01JLݻ0&" _Zϔ)`U:gץ< **I򛠙7<в[^"()"bqhҕiJ 2Cz4C0,<j%zKTwL[j ʴ I<ŐBך *1vդ)hcUo_Z8[<,lvR(Vy8)ccsCIpB(ݣԹoI E&>ϋT 8GQ-dT `tYTE,eIl{9NfRje3qUJCS/\EܟfmcjH ڡ&F)nSz_J! 猐cC*t4;{?\ɐGC&Y5܉Eױ'Q6NQ`_* Tc {_q󙏽:Nzé8\ D4KR#|[HB h9rwfJ3%4. ELFzv1.{4CJH3Y>>s)fV$B)Tz8-83*jW(t3 @zj3Z(K[  !25y\˗66&`$`D݊K=:*70h ֜ZCs֣Q$BB`g$J{Pv~w]^#v{ 168LIbug Y}ed8M[)ܶ\m(5J҄[ĩz#/= ʷn=ydLi"LpFLZpQn[LTXJik9T({jGLIިV)SlޣI,N`o!dskГgX/68P} \߾Yf+=׼j w!İKBblJ\ UڮqI싯<hC?[/,PqB<楺l;LR~aYہz ZLy4-Jy{G{];_`hC4&<ͻG@߿}&Fl!}a1@Se"DjZ\#H|e\{8/_?es$k1dL{wb(0˃no?D,+C06;@!]'Hhv`XQknRR0gpg{[h+ y{sMku8zTu`u` Y{ lBgRlb0{s-8x\I4Bśo},Kdj lF ?efehmq;R#8VV`Tq< Uwo 4*f+<Diɫ^jMZvOY4|%ӟ=n{_n.54JI*> LC2iV %J#[ qBV(QȦ5FMk~Bi9G1ǂiqrJ06g F|aTE%2ƔҮ6>^o;YΙu惱A pc~Vt}Uejs*[MҸ֌1J0,MsVcFe0ŕ/uv%|ɡˢxnScc#F"Ē5&qy~\|$~*̷hGYY]c4ɸ|tpCOg؇hփ}q0x J032S'OE`&Wo~8: NNy.˨+NLVf;* /Z$OOtC3gGI&(!\`l3fJ 4Wͪ=3B Y]X-tX]0!7*3Z_yWvG;9᝭~ga{:,<4 < (1mz&Y;j)Jeg`.y\2mT22`;Np/Tww|\rLKK+FtV'liA gxxѶ-٬M)&ģLϝU?s8xJ7BER#R1qz [v(rThԘR K*mn0sp;è#ÁN#>;lՠؒko)`uٚ[]e Qtş-dokYg?xRjeFGׇ#vyxa! J^ҏb+a}D! fqTEPI܈;@^_ܾ٤kf"UX^)^]8f/4VqISldQ%ן~״6J2UB˻Y`L* Bb(kiF6Z}PG1 3@+E;Ѩ3bәuE8/KL3eS9eP#mAÑBajnCDo0jӰ``4351VK?T:Q2-EqUމIʻ뫛uG/UBeѣ^Mi JclJ\^*4(;oT“]#Bulqm_2`0f ͳ]=stomfF /7FTS#67is6Kuk!Yӈb,θw=Bp놞C#S,Kћ8 ]9<Ί/EЪLR˛~Y- XnkJ{Χo#FNF"3JKFm?{,<}]CO?,9~JekIެ<ꪬ˭0זjo4#ifL/4i+Farqs9;;Bi%z=v0FŮV"(ᚭom~eTUleARaq րql:AffY.ԠY oUt:Q1՟P M,۽ۃIҬY[h}?8 FRMR1(%`2M5BޡN{eS/lMRWx=:0 dIP?j&Ƥ?Jy߻ T+O1/0:3Kf'[][1տ[E3g/1!Ďlap<) JpuM+ڋ7_wiתk7*aKkӨmTJGaێg3iڏ8EZ%-pֵxZy!_(Xk d)FYB<}I5l!}GidY!A[rINy޽]>J)34hVR4s`kBg>߾r!Zw]稧>HiUVYxveiO Q$i,`<,%,U%leoY`4D[{VRߩX2ϷuBbw0)5{xܻX>޿ߩ&/h`(' ;Yzw~8v_ȳ-%"NQ2~=YDިR-ڱW 2q܉n4jwwG16XZh<c<[~LCXh0[A3BwlGO҄CdU [FuPK3a3.%Vj2l5[dV('OVuex1 0Lg1aAJPm?:s#w&ٸP ,-kFm[T9\2 J9dF4KҚ3$|e DHY`Li)Jpa3 mo`4,Tr}\"la$(>fRJ0Ri ̉΅Rdk L1B~8N>k]FqΫ_íN{[(Rd֫Nq9ԪRR6JCpf)#Wo:Q׻؈tQBs(poYέhc[A=d ZJmU!zkaP]Xyv~@hsu޽{hqf#L3+K;_{ޥbŲ-A%NldQjMsOh[-޹kf-`j>jSRb{}b3~ݹP.,=u$WF[ 06R4ίX>5WγxXuF)&`Rz{4<j`0r)'o?M1[wogBc?= ıU}yʝEQ, aR⻻,^8v8J TZ*diE2U)Yh4&9tY1Lrd%VB3J-v?h6M'/ܾ{oc} ^k$4:>㦐CBṋ4PBBzeȃAC3sIBy0Aj,|HƑ/ ar|I 6,NcJ)P pgVX@)6&`]_gCS 6`$Rȏ67lKݼ~%Tw,,يu Ev(Rc ƨѬ!B~oyi}w>DYvʲZ]NϞN5Aכ?}>}tye# =!BI1Y!mAR8j HIum!h{ЬN/xst62ze͗t;>}0X?&+F*Nfa?^S^CZóņ[("I;M2GYn /.4wFSiygg6! 8\4T.){skKy~$7k>#@E3wy˥#k֖Z8*$œ njw01*gw(cc!gNjbT|gr;XO16<,E3NlBZ[r8Y2g*ZZpJ4NXL Ji2jWZKX;duySub'0^}>}G_;La1|8C;+Ŧk (/-)Ng*FQ}BbRU}MV]t o~.=T.ۮܼ~ͧܰ~~|%SJmOi(0yQ1vA?b;GxyZ([I90i_ @`DM jypHkcRbyIdco:ZD.~,{AP'(i[__l޾+Vɮ->|G~!h|o*Bcͪ51nEQt:`ћP.]+~K_Ge?} K ek6* {JAjvJ(8+- $*qV#%Ʋm418r<[pF02 FRڲl0%ԫi6_4)`_Zτ, `sDA = t 漴Z!XZLH„oe^W;/^u˼9(ޞ< $&I‹"||EapgjZȪ4uuX7FF81mΔq)gCώR "*^P`6g8ql'/~/R fR.p-f<UT}bz\A(KuVRnH*\6.)%DeiصS=+c\ lgw{In3 '^mHT@0(MOi,Zj(e_'Y\l4 ~rν$^. U;yWRtiI`D\>?+\!vsV*OQk{5-]L"Z\b ml (o,wjP(q1 .O !=\&.cW({WFI1*hT/}LI$={8!= jGѕ+$cqRȋ֕yB'w,._B0XhyEDhBT fhm0O7/kcQ]ϡh[iRP8HS7E8J2άՄ2QFKɥlbo#YN.YÙ2Z)]^7yG`kytD/uT~Q$6s:/cP!oJ+n7|M{o|vy~."ЌL v޺r!"H)# F)f5 ;=e`1JMKGB};e[j?؊YQF,ɴ8"ILQ6A|NCqmQmZѫGyVi.PtxokW PkիinYdI/?kK;WB󢘏cUR%}"K\7fQ pgS^ʲ]cI^fd8opIPJNc# =h4|k68/ F"ˆsDM8rh6};ȅx->fRNʵg)mG%}*- HRYʳ>5ʰ'?  EV-;ڷFj'(7G;vv?lu/gqbYmQ!RPXY.1R8M,ӼV_r^$rl`hsmPbeqfqfq.V*sO8<䩓^wSʌ1 %Frr1(KŏF^$!r >şh,^y[Ie.ױe8<8\XY]=yj| rر2ns{m}饥`]yWN( ~ou~q<8VڀYf޲.M?ڠ8~ ?8]o)ve*[0FCvLB\ye)ObL }CZh~;BHcۦ4MmRusp-if3-LF3#5Nk4:n3t?y|2tY N+ZY^# R F?vvgqjqpM0E|ƥ$NBn1a?|FjU<]qkFVm'ktTbLk%s-Hpi6 iT9~J3H^L1 4iWSoUvokJș{SW!l<9L !pGE MkC0ƌ BScMk03d)6XBB(.8(JcsaXHi9(/ͼrPH8 2Kԥx%!qnB/6^8݅>?Fo|>Kt;Փn덦~wTVE`bO|y88XKB:)_kwOG܋?>U/=|zWן_{c/_~;,6T83uEiE`e9w VacPVcJk[k'ȶo .),~tx}gW \MzIܒTJӺpl;nF?xT1Oi~ÃbcT{@Qzhri#pUf/_nWdɫdkFp,e8Os!cR !de!֗ji4qSNQÏNюU6(-45>pjJ-NA^>?^h)m5Ne< ޼xЪV+uLx\xFXx]rbC"XϝN`0ߩ{0'>VdR{l9N=[yv-ht\ =דZ(ȶ3NFmw{YL`o}ymEՠB%ͪ{6ͪ1Z S, R31qs ro<.Ez7,p[[BmVu"I$Bb+{I"ِ &±,J,IG|G߰M$?TI  l=uaԬ0N۳,g8v']bnB<[JEn~ L9 Y$zBd6ŕxr{)gtRQ Vs4uﹷ_9g>غw  5-˦mQߕG7fPЯ!(Nbhc19iVHo=wl۝j0`Nf7rJ*='4BHÀ`}%WK12CEI.d?tK[3WGe[I6Eeyr_p`٘E ԗh ̪;+ P`eqai5i5pq ZC9:y&Wvc# \=w?*4ؖoq=W_{f g,/لaN!l2<94be*{B4JN-7$X[\N'"4H*j1:;qp!JmCzERܭرCd*j}{L)TUqkG} ϛTZM'c Jj67*ؕ;?~jJ6h$.L&O?Wo~Ns[v{E/= 2̅593!\I!13EDX#i.7f88">Z' I3IɄ )1Wp!Jc,TK{BeYQLVMTÑ~sλ~?v2_{{WUp8fPI\=΄be,E QbdBvL#0p";хPH)'~_W~1o<~Ss&`:݃1nN1م#$V0JB+!PnE7+;>/A̻@Y?3m _~ 4b.[kGw~uZw ?{jj@IuR .RkQ- pfYal&0FuL+\R4K8Nz[A蔜w4BJcl,b }pŧ*&>B<֜QeAEefȥӕl,.ZGф I0T^L,m-aMi4Mx^wXj-`E߻EǵeZm Ύ'_|w~~R9so?ON ګsO!DJmοv@D*FY/1cL0vPM+>04=.wBZkRmiZ?W3Z;Vc0@=ƅ3=Q=2(1.hGdmݽ:QhEyuxhsKO=uW Y0}6L;6(Ń7/ (挶,hpZNaub=E~Z7.Lz[a*@9'ih"aB8C()n7CadFyiNOb=jtVͼ,moSn+l:@ NldRi[m6Ñ(-VP **DQܨ2I DBbҬ= iD19O}kFk~$IsR1hVn²Xyi:U50Bs5hzp#^Wz}(gV=?,4ʝj>V~2K<)g h83J FB,>uڭB2fmhØhGe0FVOOf$q)JoQrX?1sӄV ~Z4 NfI:,Ok5rW9]:.^͆럲WxO2inZ8?ެwC靽( HͪE9My.sq,K Z0 my&NO*]K֥̫u! BbjA6iS4,,,o:s:'nT$1Z+@Q2)+Y;<`$ 0v|xv!$Qyt0:I!5XK6K҂bژL;ٌ@QN#|7&"|G1H(XbRisaN2]kNygΞm0xAշ0I<;TjEQܺ}ԙKZijHeBY,汩Ydx:BiRSE,j? ^ 3B]Qr0ŏ~+4 ~c~gu!T.51v~}qEIԮz^i=֜䜙 /RfRB;{a gSz&ϤF!eXhnc~{RBHQ@ 8@w-u٧<<(s/Iqx2/_]_ "l\ѧګmX޽{t%fc^XK]l4-.Ԛ͛h(G<\hբ9f`׃R*qBmQL޹$ull0U<3cQZKjj]*0KZgL3Mk;8k-8 h5(NǭDYs)b/7`fYLH !Y$ sfZyRZ$YYJ[MF`+M9I7ͧD4s %b$BvR4OGuwbTRiM83m,^X\u~ww6YkiZopjgL{5dbY~ ٟ0 o=7O̓Q]]Zr9Ns VORۥ⽁!$CJPQ"ց?K@AIa[^)V 7sllcB,%L96Kr)X vŎ, ;pp ^_Yv!`ZfcWC!xxH޹{6oW]*[tV`ƅŰ1DqY&R.TNM ']ڛH'"N+p,"bl1f,/c9p fjBJBYRf64+8LCDH9ϾZdpx+t(& TE:!QwU5 I2Nvk4:ЪPnwjoRBj X^BrK8vc:rT X$مk 5Vmb6bΈ/(Y4`p29޺rg$_V0;\prne @EV Ym{.i6;ߏW;uL\2\i"s]h\ }BX Rj ,"1P>&amtʕl\t{GO\tBĉ9ZrfO + T<ʈzqFnw"@8hRcVq=Vq*!AkmE9:/C5j-J( 18e HͲD9O j,,hX &v귯sSà *veINZ:ib3pniu-뭚 3O_[IG+_X&XՖλS8Ϟ_ sB,Kvs>yg6e0kh8rX{I !@PRy0Zo>Z}Vx}N={=3f%9#l#(E,>z@?k)%Xo+}dY4;m{nH 6Irl$?8,btjÒ"oW[F=!q^:7:uovCv:mqfeyҩoߩw<+:W1{c |^byn.:ab&I!2{Z5nseQvaL4~]7a Y0èӷm,m<ǁ) R^J"狫׋H*6Ӫg_uT*F1Hi0]n=\swc.ԃ{;2 [`lɠK-5S+Vw0B!ls #5I"8e69Uj EiY!XrtYsͯYx=_Zox@V0N6 HhMmfZ Qb0?@éZ~Wi;B ӸDe ƔLf*Ircsc.`ip#.k + ?P I~hO ||s?w?Z<9;;7{7ţLs?OK:[T0!#=^TܳGV[Ņ%NJ&Q;h:iU.W}f0"`TʽnZ[ɤ.ںd'g7J:ughϞ|*츔R;pFzܨX7o#¥xςH2ViSF0qJxh H%>LRÝ֡Gv?qnac%:o]ﰑūeĩ,ai1K֎E1sNBR2ȼ6ä҂B/4XxzOV$q*Rq07jaes3˄^oƯ$iqu{"qw:,\ۚ΢{R-]b CYMj{э{Z+~p&~8=e>·N]7=`؞^:q8__\z JfYm#no~еITf | 7m폦lgbˎҼj' 8)im2_jBe%RsfϓnߺR[h[% :ܲíágH״YYyz>"΂YBfLpVF#l|YZ10FOdR kE)MnxMfH1.+%!B! QjŔ3Ҷ1Ed0HVvY̖p8L ZE!pQplیŭxy,1d?$v_)1fSJ6wK-}OQD)A k%"{dD cqײ$6v50;aW(r:M,ϊdہ(CqrX RjJ1@q/?=VٵVsZ/8|7o=nzBMP $ Z,Tbx rxpxӄ^{NqNp 2ST= !W*4`E#fφGgbڱg 7 \2KtR;kE6@iCkc0ttk5΋y,|7|z Or=E 0z|M)ZPZ@F">K p`"?ޔl냟b2/XضŁ3W/4m/˓O=SOL̞ڴVګw>1I /`ezK 9B'k690Fq/?ߘ/Y.n}r- K`JN"LvN臻&,>{. ܮs rxB8e(Rɽwho_`+Y|ԇ~m4:x¿p (QP}Zk)B)) c׏.[.ERQji-GJSKsM0ﲑ@6+]d\)N<ۯ^o֛Ez KYwJ'@7hںƚT~[eƲ$rY`Q9ϝww,4$O}+Ƴ%1VPfQ7 $Julq1f_7juvr;/nS2;҂ ,ҷ޽f1jmѲ9+ƥo}_~ԕ79]s G7Ͽٻr QoYlߡ0Vsz>8d6鄓lC*#ݬ7.ںP'U%4,NsƜSj:~ʫ6֩D` RTM~)ypҩUg~hg'1c(P[ji>!v B>&te)0(UX+ƕEAYu펬\|j*8Egב<ڗևo@h@@)Y-F?g;ob E2vG b rV j6`DRK~1#o͵ngG91J t2%Я{Q8O>>mwn['G\.®q%hGgOdi޹8E]! I5{m==JY)R(XmU=<6&Z%,a?8aOm>I&͒jx<ۄ,`p]:CtbQ Pj8oT9:xVoZZ?(%Pƙd4 g](Otoy7[:ZI 4Ͱ51ܟTg@Cg;L̚; 7wTkZJ쩍ró3`\G)1K:Я c[d`RKJb Rzhn+|O#Ƙrn1EpQbS3vr{x"3zEnגTxyKl'1g"RJPjK@A950)=~~񿼻wI̍ß^lyo^/`V3Nf}RQq 0l&P+heqZFZ'y+į~?mT(: `aL& fC;i3&qJ(ҵR= ʮ}&|Dz_ޡ 4 AmH6))CJÑDFq$=DI#Q8ȡHJmU@J^y?"+PG7n8}^{mɷIݎ m=_m#i͍&*d J6v/,d-ҟO<zkɃh)٬b`L6I !J;;޺7~קGra*8vı'_?nz&7\s K1sylb j6~t=|}-/_ 5Ư>O=awu7`\Fqo}a.7vCs.0aKRB̻U_Sc3S.q#<^o,͍|wb ]7|XU35bnf}0Zuׁ1d<Kk`.Å4lq*YoH/2ǵVZ+y!  KgWF v4Ф):؉ 24M*(a[-bƁ mv+jnJT; C*]E~>RC6宝=5x9&gR!mQ, K7Z(+$ɸ[ 0V:m &bTJHի/j*D~/`t]΄7b ۙ<(0y96qQ Ss^1h0*`Vt,[C%Rifi[F@%s#! 3fx;ormdǺ{ڴ wͧ+w}|y/Cm-m}zܔ@yVݲ*B2 ;%8627HWmC-IQ NX5A:Y}`R ½aL:⚗ U(-Wo̽;+UL?5uΌef2Qge4a%THQ]Ho]ŽAO^b"&(5z$X8%RJ\(*Sݽ*tJ ]k4EqhWL# RN MFTYu~Q ȡ^n*Lz y1UU[=@(Ju,5 R$ @dOcsc٭nzqF0% )F*Wv/i-Mo0w y1C[*p~K+TW nE9 .k۵墝֛BՌ@dLHM)܋K7x\<2,ElXnHp[qnQQwܴ'5~qq<݌a8:p9/>_S:##/s. jv~bvd!%PT&$H WAIBxmELR݋@a]B8#Pm ză~|frOyﷃ(ojJ)4VhSmW߼my^XҼ8 m'촫~0rEJ*$)H4;;8_\W[,3Gwn+$LZo6jwQP"?º0y6'pA8i Y@cKW>05*JQ1]ϫVۑRGvsSJ )\8K[bHKI4kqlDivsGam^UiFn~b!$k]'kw):TlC F !6;aw?߽wD SqzީA;|k[}΍ԥiq''1F]vMXq;v8U]I'01V_qKev cnLmlޭmR/}ᙩ1Jy`{K6vL$WUGfdZ@V37VbФ!ԜKk3R|֡}[r3|13^܉!p)K)<jCEJAMkrX~{{_~wڠ%hc{!3;n\?mh4[51FC"!MQ4PB)c)mzUvw>; RRgzVTL®<$XJ "qػl嚵tnҬM ~.#QQ6W=jiS(E4EfDX8Nqϻ5IN(4QZ¼M}0u;AFZZBGm>`Q,+=sv1hޮ7z}VcuPnx ԱSpe=u ո4if⾅\xN<8om>}ޮ^yꉇup+;ҥ_?*o9$IxCW.~|zCG_a$izyk=liu!ı !@V+]nlmi`=qn4y茱f'X.B9%ԥk*YtX@{|流B3TUd4/EgͻUEltMO<ˎg+Kbey')#?[EӴAgmC  !Ld잗NVNㄛrY!`w,$aB ײJclh ,CzK8r!]SKaQPJp$\ *; /-9Մz%(VaۿYQTM%VTIDATJDS b% Eq)Lp Lň܏ KP!P' 1hsWi@mz}Sl` I:~xrfW{d c[_:,kb3 [RxNhbJD,kD@cLo\دj۝/RSֹKoo7'd߉0Fr'of! _K5'/ +㚝'AU; i腱V\/L `}k}sQ2L !T#B1hu1%yi L.?WGMjuUi*7%X LNюJB8 |i\̹w>[aV3tR Ҹy Rif'NQ "=E I$eE˺1ं -r&DGXy.%"(1b!dz~F :ҁ8᪪B8O|_!P1@5:QN5SG0VJY JM \UBr@Q&sѹ+Utw#Ҍ J(HFRU-& AYJ^QMa!/f) b6k'A%NU0t3 ]QKVg-Sݨ})"70<AGV2rۯ>wn0lJX[=_ͺ3cjPjvYGt]^=6(v4\X:2 "PڞdB˺v pRF2@k D0rN n'_}^ $TJXiqUclFQRzeq #݉ԃ{h"ZRX#UýJII=v,v7TJ0"@( "1RQVf["#d`vt%hBd %I#;hJqAt NiAx?1c}V ĩNC}[z9?Ta*$IxYGg"X[!1! M6GխOγ+%D $r0[3@NaEV(󭦕2LiJdoF?`sgLx3;>f7 +Ma112W9 M׶X~huZ|y }yۥ6͖MT5ccKխo A5n4:;ytG?+뫧/֨V\?6x0yc$11$~̅Ҙak+X11QtCSB.hXQ/BfONK^vPN׼ b 5J̘]o'2j.3cFLnne񁿘HPuίhk}sw?s+ mzj+0uDıJhd*%IqA0NR80. \mscRXɧr(]G[ɓ0k JVOh*^ȘK]/L*IR ϊ^@&c4d 6cP"$UUrd#\]+,8dDƵ 0dLҔ1M%&(:p? lXv{SV{FUĺ RCzOQ[Ē4 v>mҜi8˫gwDa)!9|S |W7/ Ka8vo?˟U3_x~7(~'|j<^aLNP^N[^Ю7^_(8Mx%lzbԼrfWPr.;3+9Tuμu;بj̍k IeXۼHZxtd&yךq֫v?qm`Ϙ>PyͩJ)MRV])r6u&|O`L )1xt JS5z]e֚}4;9O@\!ASP9;Zu't%PJ`9oyY zJ !(AkgźB Pgv/ݠfZO\zta)ɞIЬU4"L%;0v;_MP~Q <yAaEq|l20?;Wݼ0Z3lHٵ'#-ϫ 4^8t[bӇ̱IUW_W?쩟;n'SQ|}qm~:cS?c+koʭ'#c?S"\fDiq\O)Ǜ-]II ]zmy,p]wc[.@$,iūa䅋~p/zSvx6˾j[+o+|PURu>%dt QU}}N)%.-]0E`:BM>ZmK)EA #";ƥc (IM5ҕ4۶n$lgXmP^q3YQ=P] =n~HTJ0UWJpEKIhEWE$~бs%JcgJMvߘJ6. DH΅%ڟ=f7t t~IXxVxkGR!WQΔvnd}ࣧ< Iܹtw]| ZNO̹~?W~8:'W{@6W|ﺾ|Թk/j#̏H1i 4۰Jee]kgP{ Ir.tТ 'C 0 $<;ћg,^H.DIΨ NvHח:xदo~?;01׷Nt:cnQEB&)/娩r~vR a):7TYp0ƀo5Ӟb< /kc('D3=1 MRX &>W9?ݫ}Ak&v] G :T,y7u9Ip-,$KӸZ]Q J8"g qk)>r R.tu' i82y#۟=GOp^o{̈ce4 ~1*Ϸ}Փ]/%HKwkAu3{k\~XJAP)^\h-vi W׋]ohds;/`r/=:H]HӗT v1KҰ]ona7I;r۴5ǥDv#URBr-,+{c>N^t&6v -)65*/\fmn;zXeZH`\-5UA(v\ԹtKD N,VKJre wa!%8 (hQ3bl m+YH7w*3n{T7G5mʾ@ @!㢣n[QDQU.a(g1 ր0?/~cqQ},0B9O’ikc)$2A؛ `c{#Yy.b>KSԶx[U0L6kO<| COL?/~mk<{N|}[ iXb6V)ʘ]^O &\^ @` #t]j9Z`LFRI'ˊ:rʥso^[_$ w\KQF"7߶U\vfs#9|oW7G8"\$ 8u ܻYM޸OR+f&C(8)BbBV TnVIVUn&0@E0LlYJHkeQJlK7lA3z-# +ѱA󭥭H8;Ra@ BDJB HLF_%Od$2l74iTx!ALJ^8ka*VF떮ʄQ&H)KcJn<'_lZ_8W (q qQʰG4T?ogW+ό帣R۝'W7k=ԭ 7qݻU2IpxXoL9Z_>Y~w7|ٮurbY0CӥUGؑ qOO]BRl; %= yVdd@ȬMc3y7&V/AEq;R)NБf\|7:PRwmsGrS;JFoW"6QʍaٌzP=, \*)ib{(8w'핳Ad8i0`ѓ/S]kMp!5ňӄZP1Vqqk @R2ZҮ`kiE^F[b\`i©gwrT.TLmUw)%q؅!9N"Ȑ q L#ƍ̈́xD],e26`-aBAVTlvKy(*8e(M*rw1w _.dB n5M8LD1[MUE5)!Jښ[V._&mѬڞQױu])?zORF1N)%k(%;]gWd=!Jqo ~_*@fu|t\HG "Fj;in/~Ս<}?Iϓv$b"0׾- /nd#[W!2dˆr0tS3SjsvPRXsc'{t2\ٕ#\tK1mg;S^ō;0u !j3-:ywc㚦N).fiA6(!PzK”! s*aB"TWih73NV.,@DW:Є9;=##IP1ܴUsœ+@c┍W~*퇦V)!m(ꚲY\f`B+9As,\4i*oH6f)ӏSZk1`~).]e0$%f ~/-'ݥTolYV6_:+0t P̥UC۬dHM9̘:ɢ(nS/^۸箽ʰڦP>s|B /}艇v^Şyfӿw|*W/M foe7;v^ozb ;9':RyCH4F#Q-@of /VZ[n/KuB`gns @g{3m .t]AUV'XJeNSɅr8yu<9?8_ϽvٍS%)#'~p]d,7:Sg@MPx/U JWg׬ŷ{oa3\qy "L*adh^tM@$9Fqq)W$4$J8)tGc5!VzC[`a>Wh),<c{%t=c_4e򡜪 X@c7RPBں25xm*b|b!cSS3۵0'IQw{} ohɿ'&߶>W{; K~uum{x>>VFK}:cs3ȔөԩoL}s/'|#Y `<Ժ sI0Y<{e;\ > 8QG Pm麜qlj ,wl$rVٳ%6FÐb (勄hIr!m?g2A4U]Zo`3NR5Z`?8a!SP[ c?Tq3JRN_Gqc{̝{, IpK%%ce蘩2]i]U]4o& Bvϟ>wF lKf<;=uhaбc/W3W>|t8=yOCfe薦_ru}e c ?cG}{|)W]_Z2jSr|tjzox~q@:⡎~bj$M?J)f&yl|lwHILM֍sP::^x~6Pٍ &ÅRͻZcN5U(ל{H^1+?Ʌ8c#U%>MS QJ)4`JRJ), ٞbBFyiւfSI8g3eҭ}3G6~TDn #{G0F80m]PV7ꋫ)!2 ]VUXSBb8aQVӕz;I9J^- etsP cM-U.THB`hB%x(4%C7F'4J@/NJL =/:-cSf;M$L:&Ucu岮o|\v̙oxXݸ)V<1Z<&]?--}7_͗^?{b<}U(勥̞+WOm׃V_kIBIflue;c[ߏ(eriMIS RͶ޶Q)iN@+ sve79xқ Y &2BMU/]yqnjJhm78D13 9H=w}W_$>!@`ھm [X@'(ysU Txƚgi3Eme?픓J\i%/sloQGզyOAfj*kYRD Ӽuݑfp~. c(A S!3qsHpu,4vdƘ eG~'G'#oo]k.FvVg,Bޠf9tڮ567V_y>ѹQ ^MNM<ڶ^{\qzX\ZfReBC,e2cRPg*3V[s·f4={ӛ,u>APQ`+[_z>w'B |uBf6򢑾? ͶYm͕GmuF  2279ML(f FhȞt2P(4qM$:BtH0A(\{'%G1peǝDXFts졃ɫAZmŮ%#;'']%l'CYm`zPP2@fC1"Uu' ?K~ 6L0OcӺQɳ$';I8%tc0=;x0_ڧכVL^x}uq)Ҳ2==|]Z۪7:0<(F/Ǐk~ϼynkgߣ]=ug_''>_5ؼJ\};w_`dyejzomoK\J@k"PybJ0 KOߪifڙ0FV3*f'?!$̎Y #Be" [Y\QH#ׯ ڶP…44s5526R|–k{ƚRa?Y@cm7#%&yZddZ!$$k Lh7 hRJ& 5*?¥8 ljJʘҶ2\(H16=s0".x>Wtlw_G޵w\t򅱓Tܫ I]TL2U @B6DLBN[^3= CJJގᄩRىg$/stUUENɘDVyt>hUJr4mԏ- >aL R6S#ʽVbJ0>3n:Yg']o ~A8A$BqF(n0RHVj5l^B :-X;iBB>*XB 6G#;ƾJ1wo@Hj* ` "Jӆ@BDu45j%is8$)Vn ;z$@] O_ej )Q OXq*nU^&091s=WG?-y'\[<8>R*ڶ]G_?O>sܩ7sGZMU7Uu58r?g?Wm;{y640H3 x&%`" cn`awJR+ )%GڮL]UJ4dG^u8QDJ= 0A `ܑ񢒵n-fo]x9{2@i^80@QDouwp4)q(QlUx̽S.W^^r1Zc}lj,@Z}$mFT$]DJ,kӝ6q"J5K1s,N5]AC,aa7/ ,UVU#v~G޸ݾ?Xw}>|9oD! 0e AСTn(a\vQz_~{qo \m{}q2nTyͯ<935}ػl}_k^?7$ V~Q_]\g V)@67Z Ɵ~qfTJFa4Ž& c#EF MUe>Yf0STׇU y<|F O,بƪF޵v(6ӖxLl\:w*+vqgnH\Ȃ?8)ӰUMBv8eE)ds9cxy̘>V&B&ʵXUo>GS{9=1$6fV.Ik/0x*DQT|pQbESkicq@mBfg}IVp1!iȰ8B 配Lダ!+f#^X0[ɶ@nU5uZJme,l(AcV j7Fk,(m![Ց\2")ZEˊeBRSKwܱ8v|4΀!XJkZ1o~zұiqoЫk}?<|PA26"JEjVVH(*\U,Z۫2m$ {szjx/9q`\3PXF3odP̈́y˹2,mlHVkŵl]~RY%)Y' ,e0a q=|8X[yVD{ލ9$̕ެJiۻ)7%}q9ЉGm;~wu}%wqq8rt'7`ٙ$,'31++w_}yaJsrP$0r__#D*d IJS?JD+ԘS!@5d 7U"nt,% DQnJ5ER7kҦwrsi 7^0hQZ; C @Z}ӑbrpo,u^ʸ@6] ž$٬)DN1&(z 3 q*q!HOMzcrz}eIyG5S'dzNZ4Eu9!4lB6Uש IZmZW8&X~&Xvcb@!,; @L*;]tmi5c nLP!N򹅙Y]s84 glg5vF¤x+}.8GyǻOOoځ {@&=!=ôƙ/:VWBMO (j,d:vg?tv c&3B MS5u3{ hԱ@AٌTLr0`zOu Tgm:\~8arRqܬRʪ䞙Ɋi؄FvKӘRs4TQ%CC&4yjR<|(A(R k3pE~Rt>M0nF`8s:&`@h餌7&{+ON9x0 |V_jwB:e)cB(DjLqvgmm۪XtɪN?}\ÏJQ/eIףqۊhJ񰠅 !C]A~V2 }}ĺ~oWLIbL|`Dz^K׮-LL#mngnk$FL)o^|kIL6֟_Վl7#P'gvTw)X~V3;1fKY@ ?|#o^'☤5}@å 륣E#n}PGהL]HN f23ZJV\=k04a6N8Ya\/lOUyVm+ah%S<C՜Swcrjmjۭgj)h*ymx~Oh EqUq禋 # @bLm; MqJVM0<RJJ54zYZ:DF##4LZTkl唻0a 5lk'HƹT\ !$chio:3[t7QBƺTIRN?!vba K~4,L(jS{J}g3'+]QlwP}cx!:U7o[~+|]GOt+|ٯ>;qӿok/<>3ZkF!W(ʆ\]c|Dkq:3g/]azUAkzNH\%cqJGW]Ѿ$ҦLWoOAVF.7ϘN{Ffio,`(M vcI3žLF^bc7{Ov~⍴Aʔ9ZHBHwxf-a@0"F[H;B0=7jy=!8BHCE^HŀCDtR$LeMͅ(Zk`O^n8cŮܯu=5CyM A5D~Ħ<2лȵ eF)PjSB9D'&ܾJ)w^S޺`깕? (?跻j$ND (*!ddd_Oy|ԓꑙҡ=P]U60a76ɝg~tBSF1*lGͭO}ࠪ*\^\5<^nxh t 6{_GfY;B2rMW#C#`][]^鍗yWj+%Eq&=G~N ScNohѨQݔɱJL4,$B:K6 @,SFP~߽76ۅ\Vn\ͦWf\ Ƙ sU(ULB%tGH fr,eS/ I1QU`,o}J^@^?kE>csCM8,q@z_~T7LP~9aJ$d S@:|Teu=3^ /myډo~fmfN_2RJږsDA)UMl7_;1WRq(|F<|T_8zb|1J 6,7sK[(lpm'Iˋ7槧]@^P(udVq*/,Eq}pq K.Pc AsZ+<}^q6YBq Qh3n!!)t!]^)X4~`erq nCͫ,!|!X7*-cgG&B\ S0VfSH  )A$! 4[d94&9;"[70M+8Oerc&G6l,y۫W(mu?Øŭ뫛-S#>~VBh%M)=^_~7O_X\j"K 7bٍ_<׽pF+ѱ J}dOnfVȾeyV{'G"hw#^\88_4{\YF*WEz|/Zѻw _ZCZK @n~no4EK98.^ =2{ihsNby}ôw[-ު2$ c @ƝZm trR1% BBA> BQQ'tycsSo]n$6\0)3!(RbRJAR 5&1ڊp ϥ RDTwG5 cg Vb~bYa)Ok bnovsu8 Hu=Kil]I]mC_&1/Cw5w7՗\twBr/vnaO4I;F^eI7d,-scWjZAtUt.n2[z썕0^%ik߸k]6z`1oR*@\1.;jrR J֜ R}l/OjaCgFBD 9XFCh #yT5PYjQ?]/ެ{(8 cZFv'ƴٍY "ײR-١8!)t;364@A0DKm|d&&h |!Da}1Md1T8eLt2M=ۂFĄt4P(ƣ1QtاӢU-4q9}vqJzQRc?'oB(K Z>;EnDv`t[y::~gkJ˼{F3/e{!@UHed]'z+_;Mx\q/m̪I'D\jڏ~X^`Vח#%i2\Uq1:C c#ZwL-ֻxyyZ9K$ Xz3\()Z6Ah9[Ks _YWOŢ 0?hx^R~Ыw/\~#\UL0jlw]y352uJ~Nr9sz F|/hu|`h9B000g&9Y( @vfVo`[Q,Y)Py/RsvUxE bF n!v- 7٭B`H0ß+\ _! #V_b3K7$L Q'>g^^907:0Bs_::c>M.sƫO=eܤvC  ]smʃ7$(o ͌wQ3 ͠]kՇb!c[QjjC{j(㠅 ?q*;}y%L9w>bvL &ꡅ9S֥jѪr.x:1v3<$ZWaWJq$gyf˥W̗R&0J@k&hdn`oX׎ ^XwFrf/`1 yMKk&ٶ9)|nJ +[tEZ\`J;+J%Xt jLDJ\oRo1 8RZGGSξ[ӿ!(\|iWmfbµ B?yľ.z`aj#{B˳:'><5:|.z0+hyڅO  āflBHe)|$bZ>2LJWRI z^M]8VRG-]:?Of'eo+۪&˪BDU @4}TmdyjŜ9jQWvƕd=}A{kѥLbXzO˘Q檵-Y3N8(GqOzݺJdQz:z'8|dH=N9FG?5L2! bw3CHq{g*NX) (a$T-iƓɸ:`/3V4,'fAN{/^ަL;IMLgrl=}ƸRQn4o|ad|F+3w$Ik+ܵ0Ag/]~A7 ?:xf jKݞ[UM_>sum;5Lee}(>ݤ7}zk*#cBŗ"BU jo5EFGj'^WWysøU\n/Q@HV"$A qMUiT̺݁(N~7\3hBSm)W_mBQ{gv\.d(pV mdGNx8jNޭ#jfMiPR.=#kE~W;HtB&$xQ'*e-#_9wv Z-h`RmwUC<7@x{c1D 8ԮR] msf`b +D&8( K!)q!djC~J- be˛Y.KN$|( vZJif-no3cl&?ڞQp^Y4wq o?wT٭ھwyU52-q joկrǧP4cz}erknhuڕ].`uDmcD5Lp>c[bhMf~m%fOrPe8o}GG[GJp~l': 5=e(AVG)Ftzg?+dr]grzlfΥkBmpALRva R"7-$%B5̸)70YZĚ^_=_n?t ~e Eh92&Q fFZ]|%礦F `iVc %" bZkJ*rS]]{}3UXQDYJσ^s-ݨϾr}¡B&[WV^j=gLH4U"}n<#f|h};;䩗~Tb:~Lۦ3mȴo}uRը(8H p̛f@Tb;J٥#{Y+Օ[?&8f'PírqcPΊ-!Mj!tT׺#9Y_~)!?;S z57SqYvR"'?of\7 .yP>Fc2T4e 8OL*tlw):5}Hip4<^Cϵpt =ۀMb{K1t>E bN;/L tpF2;0&uqVopki4 $HU aZ)PYڟeڏOݟ=0};J&'mTGG8Kb}k7/LΏٷ⨛A{^msfTXOCaszW'|+ZT)gKB &!ݓ{=hٍ'x4fUZ7 [ C6A{-U)UE3 V0F+kBa.{{,djO0`XVG6{ay}T1 I0SX1q0 Aur攛jW~~ҳ;@J!Fq̥:<2X`) #Vn8W^ye,j4;à[Lh|q(F )C\fO %."it3$T u DeK]SAJ.@"aF1k[ ? \/5r)~RnF-]Myv&Sn=-g5=k;P($M<ƢNϟMBS Ͷ! &ch *唭:<*Io67t4iBJ٨j2p#e!xt1.1 [OWgOrA@J&ڱ=i”k@ cy^ QBRUKc(2t}{{IQ0R΍9S`맶IS&iuxߋ}}}EUaGlln"2DɒƜ#qf8>2-ٲF9^|m,ulM4ٍ4V{Ff#fdF"x7]hwzI#HFBi*.!.(ǧF{le~h +UZ حyfO3L>t];| /?hMs=VDkuG\qceE9/~d\߾y\*.,\ƭlnӂ X^L`HUDJӥ $9I˦۵N\W9vlU((%0VBQ18d`jسx1~>&y"&x>IIr6DZeߺ֞֗;~'9 f}KV{ONL/^\X$a`?h=z~}0xLR׫Wnzg^f8veq Ji778Dë7Vw茕cf~7. q{%rHK5{\ VK^GB?U7͝ZgabrC;|ȷ{"'#xN ~1bAO;> I18.>aX&c(D,44a2ix;*0٩j^RN位B/`>n/D❏$IC~K9.QćGe fO۵+W_J{*\B=ш[`sAt0 ҞѫxԨa;mⅈ 9Bqy'laYu"笶u~rG\| ml4[;YϪi{wvzh*,ʘ(H Vi6T5:&ui׳eZЈ*m7eU > @T"_i ?ѹ<1~{9;`t@hOFgZeP&B5Ea xџ~r\8}bpǓq\))…<c҃sW7~S=dgGJBE(Ǎ̉9/Ug6\8 @t2)0l% ]iqYE; ka eGcGҙ/CFD <'YS|)A\-+a9F"/FQh4;>^&ijۭFeKű[9Q]~qfrIŵ Ӛ=7pұaY1!O隞0W3)nKYDk;MUggI|db>0B@ƎeL/ta[ $c?ƛw[;4DZ]b(&@&0@y?80Л*oS.<ز00.1F,r5PB#6!ct _xxJ\Z?}|s'0?zm~rr GP땆Àir>'bc٫H1%NόƓ7;c HDAOQvh!]"Φ{C #ĩ=24DBV1c0dݤiZ^VSHB/n#3Z1p~rw*( SoE%; Ŵ mb{~dAB-"b*&!%& YK/-Mts[t(5L!#빞B A)ʥն,isz1,r6vcE4$58$|DF )QqE~-o_.dEwT\ #BxTs lVC<&ecl c8pfаT(<+_g_(O%A9v35X.I"~vb>ʦ˹L-fzϪgJ};+'E%6o)hn*nVwƊ(ɮn˥W/zO)j9Kؾouf]Z< y%aL8TJr)>'m3: MsKc B_yp]Gj0`šT(5;a,NR槧G7*Sک[N(=Q8s YYcӱ3EC!ז6#P8%e@"|}+ o[00hnhMgG+@ҞK0NgcVqd9hX(X5Rz̅Ggf739LnnkA\!(ՑCvDMUMG`t:46u{xW "NS㞽1p/PN+U~ "^>{f#Ro9[k>S _vo<$J{dJx/|ɹԄ(EmvsӮ%:B?_y~B,sƥ뭱!U۪3֢>EdR9BحũH,۔$# 1ZNJP!%0沙&nֻ̐ ȏ-tۊ)/+o_nUe13l rʧGݶSy0HOňK:-acy'QDvnC,,\mYz.^&t0D\PL]#^! jQRCBp0|A% [mqA:B(" ?H~v# Pf`< ZH =lǞ<$d;XxCڟQRkeL''q?U/ĴBU$Q @P1bH鸞*O"rRHiV#>IلRt= lvim졸\WEofbS> j! "\7q z$bDcaD)FtDv8`(]YI$\jP>?Ԇ}&w aBBBh9# aBiFwPsTvw-"E:vG,"Lg}(* |zvkb'IDӬ?¯jj* #aN?+޲]T ~/JxV*uҗr jpay=,$U-g僐hġdsWڵ]y2^.(P'_iw[Z"\'{Q?؏AV߸աt yXA맯"$(2$I|tg)*It&ۭ.ǎa~`0 @\S6Z;L8! @LW$ \QBz"Қ(sJ)y%1pĔ x2OeGknlhm9jk[+MnGVIٳϾK3`h7ҵI2yc&t;O?Wޮ.~>+ᅣ7.XK;*ҡ^~1L(4j Mbcjv(rf6s\<ͦ+mJHԉ^v"q ^zkPJ0^-I*4iPsz0~nBoQ{"͝ sW=,4`ZWDڹ?4Ne sbZ=#RB6jaDYڤA5~&!$*qA!7&fO Be!ia AQ8HՇ A^%߈E+дcI=(5"H84s'>;op>T&LJFs #lҋKDgpHD>+M]U$ ^|zi!A>τpQ=(ez,YϏeeZu;uĝ:wp*I{5Pj+C呻_ɐp[ʽkެ;tlXQ'r1#ݏQ*1ބL.\~^2e@(l<[QaJ0Q'ٸO%yvgOӶ*B 1U[(0Bf+"uzpN.&*!ʷ܁㓳>Kj1|OS㤡챯7E٭[xG2ʙ脌QT<ȊbLUc,{Xvf˱W-``IiosZ=0^˼ jJ/|mJw/t&U^bㄚ"3nnHù蝏1`qMreы t:ީ15- Ngmc>: 9Q^NVph2uosahWv"͝Z1i9y[#@qgtvkwe=e$҃7o<2v/1m aiŜk-/gJF=+Ng=8_>|Q1C@vg鄌P D1bWk{1{3oxJ׃(ks.BZVH{SLNȪI"r!ێ܈F@%Fydyv@լ̄\r Oh4-Lϝi&⺑A@&Qo,vݔǘnpk-׶Mx^. S?{xQ:K*%bʫ?!,^& ڗ)Mm_"ժI~(TN(q!V?t,>d$:\[h8ڵ]b1$B&a\ f{wj^08N^L34crr|vcWش,>301-"g$Ԑhv:7}(>%mǬML<xTv0y~fʼnyQo paY)֍52=w(D -mN #@Fm;U[0:9m?ȕe컠kҥ D^R{6 Ca|P]뷖q'?0rBJvp;T 40bNσa&2%ӣ׵e` <>_|v湐͓۹ܭp5%?o˷3ӖKSh9JaA4;1tѨYVũYtȁ7چ.Ai1IS~bLN,Y^32Ge9޷ٳR2(x~Ky2! 4k9$lu =Utöv9!R]o?ut>V^O{K7y4y*'I{bAҳ~z [ň@H+ʥַlQU^>4~͕Asj[GwJFWN}R[juZ]x0T9ux2inںʯl0]t)ʅBM$ @d<ҟqP*͌noZCvw FƜ|M켂0X7خQIe9v-?~븮 D]'PeZpeHE#|3Zv`>tQtek5JqlBI[k?<|_h:.]]AEXa@X 'OxM3 P NQ9r˗t/?{{F9w՛1X>MTe/4Ye,[k'GR\OFH)Bn#Jڷ"?$}t2Tfy}c6JB`ځɜ o ѹ⬨bc@Y7(NZ+}ʹ3 $B6D7= @WxDqv;"ۦi-/UĐ ON>[-)o"*SemQZ@. ~LT]H>6Xgn<5{I.1fZ_QK٢z5׺c҂/578"BIHNN$^MEABts[W`8/A8ռWu^}E]r8lWvv.%{,_r!& w`2w{yp{ ~&b29jZtf"zrD2qng_ |qRZ5<'dIR'՝W>̱18z~PF_e*/^t\XW IW!/X4Imw-m'fS< G*ho?QFY0JLR!I*qYĩx´KN;=2BVBJ4ޢ4udT"T5SI׎j,%XիDE7.%CeJjuq#qA=N3^? 72Fa+ DQO}τ"Ð:pfv xvo5K?uMpk+RjxgEut` a(cNע֡CYE#IYXn/t*߮YWU?4K嗗_Jv]J磝v C32{dk[}{I Ahj&tEbnj;8D9Py|hFc[Wu Ɔ )Ƙ0ck"gR(4ml7?!hA@ hN9 ( ?xMۄx^/ُ͉s#N)"պWۡ$nȏIӫ*{UXJFqp֢w!+7yxZ}'wkKټ{=~ YYjDO>1Ydxۦπ EUzvspkO(f㘪#7u\9ۋ1=f"IU"q܀e.^ob*1P4_ "z{?Cy[C/'Vu;zHUsϿ" k]{kvˎKCt+by'7YU)Qgl:Kv>b-.23ޮ][Nrq租~fZLp*1|Ѳ`{z1 zr³Fl>%4j6U."Ìt}Ȭ$a9lY-屡ٳUU ErINWL&OܼЄ~c崁zF#z{lp ,:]!8 DLI'% jjfF|apLP$Rg'S(qkBtP&~z"߫wōHA 2JXIǹBFuMs WW:pYVU/XZgvmtj9݈0Kj=B?2f w)~jx;G}[!(/XJF$Qs\rlv@GChPDܾIaz!9|$#7'T>/'z-?TYē3IDATxg%uHy-ۻ1#(DQ\iI[ٕ>#DjrIъ7.sVU`)O?ʌH7N8cq6srLhَR2,S+~?N__dƟ|b1_tk4pXlB#T.ё;K9ʈ"qLa:*nuN"Ѱ:>sw.33skQ4RQ QP ƞ\`yS[qfXO&&xMwdTFba(bvuӱ jiaı''[ _e^85͗Ku z(jMGP Śm;΃h Nhi .Q xD堍Rب)b<Li@?5=P$NП7_z镯?}ݴP('kF힚4U\k{BDUb;4"Z( Y h ah :k8,<=\!vRWP*(cU=fn חW6KmR :픉hI9 cY.'( k[<.m&3q`exIFhӾ`6BZq` 4Fs~ڨ)&f;?'V._d_xO պ}l,kmέn=]2ttk ?!QeB)Zܤvze/@vRpۤQ`mq@h^`r喿 V!|HQZ2OBg$n:do_zsXt(% q;D:s<:L)$k;Sc7fNw B1K_S ^m7U}G 0[E&jMrrϯ2)kM?N?40l׿H8{~G^6-ץ@>p!]iµVXך !`|=tTit{DٗOXHк/E"+ERrK}Ŧg|X";bv)ջ)aZHD7E`rH+W%xy>&>=G>O^7mǟ_zEUF-Mu"=e_$!5=^e<`fw<7@L ÛНh$On2C^ 5\k\]7PٝP',YLSxĄMJ)BDY<UH G[^n* 6u&ԵR>A7DX])mBdURXS?*JI׿P}?;0-fO}ѩ8.|ZUcgc8-MG1ajUk|**dPU꺠qcza~ =6&H.zY@ח+S>jRd[x:rc!?60f`P@,BA2KOEJK ջ ѶѕtA8b\mH8њF4|d,v.C#Z,^m;~RWrjH`n{ZPURCi$uk]7I:nxŹH@8"TSEiugLeix1nܡ6gW-dԸXwh VoVԽuGq@Bo85+$tw} Dj!`b4&G5-h:3^v2X@ÉRXC>JGr[̋wuoj/&4ZX-Hw}hc'QfG=:I+7_[:u|~߾w\yv˹.Ӎx[0qpTYɰQn7YBH"lL^Et2f\òYc-5uR^A6ۉ5IPr<x\ A9B4j -xh$>Ut|喻SD5q~QfcCզW/ #(vr.B?3}t~*={koGU&RS#bbzk+* .o,s]b"{ p0\Y mq1:ݨ)s~& V&4]a6ZGc0t2S1@"͐LfzVVKѶôrbRm  >ju`&a]987Ylw|>U ݇@jkdTό]_ܨ]k؏>;%|W0xmƧooh 0Xp]l*ErYhqH7{B<&r[}A=> v\3rK[>5k#CVP[Gh\;&U T^ȑ^;iY͡lJ)<`j9rcs Cc*n4F7r<9yG?xxǟ|FyfZ\-bn*`Pic"DC9RoxFN`)pރǴ]1_Fdq#^*hW6@<^ hzOֵ7齻T)8>běWԶune3v_8)wy^i0 QakS<,?Ħawm* '~G1|kx?_Y[ tzJqIC08D9;Ešv)/cE8t0w;HJ N4l}(օ; '΄n RiR)55 ؎4 ա;E*N_]j9)d$";zۤDLh34?7#Rb j;8KF!Ow~a-_nn(]&Q"U66x(i; Xx0w;zyUͱTXj9x&֐wrs|~8^DjQ(6kD$dG ;,*7͙1#[C/#-JF'l]|zo[ۯAB]ac._ 5esF-"rcϼQU&qTlp!?ZY9$/0M_bԄ4jli*#UtuHD䱬xғ'?ѿxg//>9?1VRG&,*cǶc M\paEA鈟 ėo<hۚlOnJ]BRZ{:&CřAc2tݧsUn)>pR`pZ Uj* PӐ`sp6>Wn񜯉vTBR+Ͻo|ansg02d|^Kg<*4MSWi+mrP:>܍||ihH, y wo ?_Ή>1TZ\&mZE'Ǣ@VĔjP4];k͟PS-Mj6}riNy-j=hUNj9Z>hZL#w!$pv0Ep2PxjҰpv$#*#͐ S5ah#-e?weŦ.-0*q:\◗GM6xXx</RCrO#;R/xGGOi@@m{7+x\n#/hbSu߸QMGVG,X!-VHjYzXG =o$r?5m[Djr|:O("#T75Ñ ϭ]'F[ݍ4,+@2(c26t;ZOE$%GuhnYlHM{ﮖ= cx1Tʿk7JH U+}{@evchB.R0G \Gе0XE(>\nF3 z."=0TLnx\kmP9$a0JLme"ʪM.2aÑ0 j4ZTp5gǛ^W[&ScaFC?H](̭6I Rmzwm/OLf~_pygA~~;pRo~?\̌a`3O=:uНX,,&3?Tlkw]JP z|(:E =x7GcP^}^Z`[ws~j^H? ;.u Vcѕ|9Tfc`4m>~Tl0i08nv-p-bn~ϲ]GŚwz̟sK]E߀ U#E_z|IFX#_|9s_< 厏TXZ$;]65'sI7J!3w-/rԖZ{EEV&u3Rhe68ye`G>}-&cj}<Z a:;&glTd%tm)`KteaC_y-G#hf GʉRJ܆0=@7zuWZ_n5|{m߫6쵂c92s#LS%ט8B԰)@q$#J[9]Du<(Dև-xuCr۱7Gw8ç|ۉ9Q0Oj*BlT057Y!-N/F3[3$֌px=Q~lϳD)خrHO9ٯy3|?P;6K<= <6L4{,q*5E&E&4_*㜦FcZ/ީ}}Ty2wtwŨ4|xwkMUs4{Xwf5lۈÊzvb+ @ ?7rntiij.?m1iNevRlhq FTz&40w@͎ނD6se; ׍͈bt'j`Y$Dž8qb^ v:$>; Ӷ<F㥦 . PіAdz(,'9wɳƬS!?뭖1ZL@{ґWna,͏~npO!9K#'ʐ6BF?gP'?mQ`~n_;vxymfFp.meBP%2}7;;~srlU§'$d@Uu;Nn\ZZ,fw-:9DV;&GC-OT7Dh˛VRFX,(srb8'2\0|r'CmcI:ȓUi IvQC(]Vj'aZe#wǪa%ӷS]ŵidv(er^ R ^xs [.f,n1c`2_;5Y]Μk;P62=x֍k^&f,58d@~A%u Ze4Y"dZfHZecj tWbdi}q>qэホ{)\-?ٌ\9*.DŦ3q8(4bsJ~UkN3 @ 8`..D<ƭ #E!Қ6߶vI\M82n,pd4Tn嶬p&~慧}63/^k '\ 験Y C(5Ķ\.'*P#dc,Hiw۷a xSL86*XjF A1f1HUiI9_91Y7qlq|Ph9c-g,,ƥ;Zjm1{C8: _&@DnBK䍐PxbJ#0 vwc< 7 ]c0 szuB$擀@AJuݳl hv~Leq$UZ|Z̋'ݵ  e\yuPp~;ݛ Sܑa$fEׄsQǩ ~UDmtGJƤ t_n{)@lT-Kb#h3j\ 0ˋ8ljL [6ޏ[*FGRƓo9c7ⳖV LNʪB3nIm6BBQpw|fujuK @qH1B CTۃ"ON25!f? ״W)%,6mcK q *ַ t\حDkkNb,zƒӅfv! *\C"u/E-?-8y1%ho<1`(аhHX;:0)"7{(kѲ9dMu+pwFcDtCkcD6x7 7 U,@T$5rJQ^)T~kۦ]7]K. 5m _/ne|KF}7h8XvydPpȕm;PaK6 Pԓ$uHW suK\#&mj1'und@u"e D6Lml?j\2M{8"mdB1}?^ulWnHiQ7>51?$%ETo9҉h3^Z#K٦{0Q0eaE~إ;gv 8F+R !h'H#}R-?f-Q87 [h6~k흯GY#`7$b),1WStѣ^*zܢGx. $NVgxİҴ'X=FDyTجʃX<\KEW˛0nz }tpmQ4]X=7ky>ܱ7m`k/ 5ι[l,JtZ#D)<Ӿ=o&RꛢoөJrv*"HJ%X;@eAAOEX %pi7DVtV*i/(iCb{_M{8X1T52A`MyR=<sGJ.GƉ{#Ę5Rzt8dQ ȥ9VOz.mx+_P;1ή/’OKzbBRr)r͖+x`pcHlf[>cj#m>$1iV #xn|_|#ޚ?3{f(t#b}h{e8, <_H މ5kBQL.S1DU ڶ)4FSlaJ-~@Wp^8.=-O_\_7Oߪ gۿZZftjmQͷwd-wt%g-6Eso~i'o <.<߳{%Cq('ml (Hn`dS &G1;;f0X_mq( 'a9 e\͚Q(U͑c!wD@P\nG2aՁSΛY҉k'<Β pTԜy |}zv&{m.}sSlf- (cvG @ Ik㮑92qU8U| H5:P<;_L»;l\WiӮU*ՉkñMG{׌8;4=@gy|A% ]z" !@g" U#23nwmt0;(Rž@"Q^uʏ@x_Uv|K q q$ոG+*`|CeM2 )iߨ{tb{zvgSCe'vA{ {sP$ p-p1vHHĎ St[n;Xs#saM,ڍ ܂&mk Ӧ^rM.z:>lVsg]x ~ }OBfO bOv F7JDQpOݕoc;g>r0=FNJz.`2YHT*^iJow*c9O9$o5OkwV*ԍehrĮrd) eKBC;3d{vX&ź:BOsy{$.b;lژ{cD_S2fnSF/JSRx>58D:m' m')K_9O#c>&lHR@{}.{=6[ۣ"EbF)ruPnGu߻V7S'@WKT1^eww.ϼv~x ~mɢE0Z>C\2M4]V;:]@_g.<̕9{7RU>ZcYbGǥȧ<5ȱڗ`-d=s.~U[鎋?^ʂj@HOJW7u~,d4 ǎueAh }(dyb<0GSO><n-4g"wgMz2ߕ:,qךdO(c ce9 'p+jeF&jhҶU|8'xW&^Yn#_9l父{v?̉GS^l_A"/UR}ϱYPtHχJv~WZ?͋UnaӕEyvH'n2m[^ߊB{&ޤ זYJ4k} B7.2^D\q];` TjHk>DEH\rњw 6l tL4Na~՟& >vpc~3[,- %QڧNG]E9 Fsh<,Px1d[SmIti  ˶+ `D%D;lj- RNm5'9$St Z mVevtA \_,}3o^z qT?3r;1c@x# FE Wg(c<0& 4ȗfU*HicԴoF59`!Q 7tpr6B CW ;=Bus[mB^?];c?_e*MK]7?no{EVҦX_okE>Ø=%Z󲸮M67r J"䥰״Il!;{;(4pl{3SIÉή:%(HF krXy*M \!ڰG==b4}񂊹kbmqдjہ(B)A]bʼay.s_=2(渾`›V@p76 #cԂ}ÄӡeU4VhmEoA 2dRa9ղ*۵̀(IUb>+7 V5^mcsZU|6|1u뱐;4!M=ȧAKdx @ZMOg-^~9@  8:ˢ_myMW髕>Qrdt ̬nyMެ5n!EhnIE7uSCpcYDTx'@aiE"lg'>~lh! /FWs:>@qp\}?w{̈́2ç p>:Jvg#Pptb@SĤ,uR'F"0TEϯ5kf!$B%&b#ѡL&9l߸sd┩_)^s4x<1哤 -[H9>Y7zʽ1j2?Gx_қwm+Rۅ@ͧR @QP.[ Sl &#m|}Gտ}r~?遻+5eqB '[w7wFnm[?txHl&-n\ՒU}Ž^˴D{.iK޶WSBӆA&"RSՖ#Hh|zcoTjwʵ;l:|IBDHKNmz.n+ "SO$wDږ<9z4_)o = Dmr⴦5qaB۶ׇjF+T>m-m;$lajey׿ KeP}a4 g83*RۨL\td}t "ØՓP}n3?;2^KLP۴"o+T8NYY,';莒 bla0葥9ѦG;Aa W%m~$i7uN7M]+lM~em}$ۅXY +47+mwn@=P~{`+}?{n|fhLN߂~(P{^ď] w} wt$sTw Cg֧>= GKM3yG}5`ʆa'|zDK=+Lol/P)sI ّŇO$BAɓ~law`@v/ (m[jp6y,;u03mS/r N`0E5it<5P_26_4Oΐy]g2+ 'k'{|q oŗyr6$-lڥ[ ,e r;ܞ-EUQ2mćBf}BHdIJ>n g,G 'd1 +`'8aiI}' )% F)Q DfFhqrdfAD:pۇC. &` BȎlWިO@0JߒߧM1HaJ8A}dv0*;B(;>4yWf^w\Y޸35K0bxl=[{jCpC}hj7枩Ė ƫ7ˍVet`8N}BhsFn ^(<Ҳtj}A9aH8@숺hɌA][ù)/Zqtc4p +<9FT SA)E ՗YJuGxץP#d +fVG4[n8[-Jjg&: ߲o:A+Y= scJiO:D($1D羆P u& Rz;aMSg'NSBB=HD'מgdžN{Vo3v:xaVIqXUL95}IVҭiV"0Cm7 V06h(B U A%_1"EU=mٌT7FMyH`7@&>68^.  $" H<:XǗkVd@H xb}V }Rx,Śc>hzn1%dI|ܲ&eLqljӆh4L\maN,> |W<خ}sv?7fq}{iA01U݈<ϱь:_D/7dX})?`[_$9uU/az~`` H⭔LȊ$k[?k:eG׿Q1}_gKz_Sʜp^kKW3EwG=9ze/]Cq;h1%JihS9˥+zjnC`##έe"(md = (caE_Yn$܀w}0Ȑ6"j m@j,_^ CmeTΗ*\!-x2uCiNL17Qpl?/<0R r`;c'v${JGMƊh2S#DSTFJi=v=bڤ ֚; gFNY-bbg~?֒N&=)lj;/,9kFfrٶ:CX`ErGdsH9z_{q}'n67g25zm0f)7#o-[AV d-69b1)Gxp"RQ"Sֿ)q0lg@-ɦh6eK |y1>D;D"`9^HM4ZsБ4~e0xke%nTzv >20p?26 d3M,)Q0DjГ Yd "=Pm{kab|1ȗׂ;.qBDK"e)m u(U.SɐHDtGˡiS߈#X_}f,2LkP6LKRug:`BpHIC^|1o)XCp@GؽW=$eU+7| qGt;ç$UKk(_rM3D K潩%0!DU='"*E=v$16JR!ξI g#Jeo ٸvOHGL7 m4~L(g)ӍBs"MR^uXcuS?~(&Ss7W.oVfFO&d`flYNNU }B=-E)3eT($-s"$,3ۥSDڮfngM[5-8<-z{3[ m}`daoxS Aߓ!:rv&9THxΚ( 3KZΌ <'{"k,GυFK_{ "?|O=Bȹj TA)H<?=3%,C&H&/HulĝW[n}ffRVs9@ѭIۅ-3)k/N<x>;292%JOmO]IL_> hheިe|hc}Sԭ홮a-QwA} u9`rG?lFزOyDD1Vr/^\O;_Cku`;ֵ;?3?Wg&^zP>\qTGbeRBqwѴt]UC3,j##'KR>'j4 Y njܔ?Y#؉S hykؗ'RDeX>=ֽ]+3MmO"/Zkec"<1fӗ knwԉRG?8XYmYbU Q;51.xυ'EASn;W<=^%S:84":;J| AcO:~˗?gM'?wmBڵT|{` Z<9WrpRV߯n.pDSYGWV(GzXEh9`omݑ0"bpC;/@51,|ے Uq_m7}Tƪ"ͮy5{@$ch:ug#r#~~> @bʵ]NͭSz 0P]=[k#^',AU"@;ź}l\IPz,K?gH&cZfv1=JN}D׿h+I߸>956m}[OMU'4&F`t&`^-S}tr\YعXU_YI4ŷ Z;pL0 $>gn?5=vDWVƾ ^XI-jMP337{ jBӿI (LVYOo^)$:-pl_*lT|gUjo+e磹պ!YyxƐg>RdmDbj.qt+k2(Bq{??pOHtp'- [  O.ćxZ:x'׮~gW^N6Ly߻p͍o/D 5$dl0Em/湾sKjfS x>J)k b9ï؎3ZXona950I5j)jILU9hM"w`R|ìDXj1 7h-mǓBzi눵/3c{F$W.hrHS¶F: :@hWM ~?g~kaUy75g_Z'DŽjf5BSv},pÛq(Xa3IKHI8tv(gF-h(TZ+Iכ#騳 mk jm)-Wa9+; o+RWigrS7(~6R-έzr8kviB/qD*MSf0ĚM62m/_<&M&DB22mr<Ơ;F{XbnU/?b: B_z㛯]YDxW1I eՂE,UѮab0$+M6rYp !pIA,^) ZyaNT!k'Gv/fW}|_n8+ !q.db9l: \@)5,MH{+TGmAw!g 0tq%~轚ܰD0stŧރn-t=i`'b.fs}i^jh.FK/]4Edt \Y,G(7saI|+%J_!Gw1?xi0)[ ۷?G^um!;hNJ 5V NOqbT8(iCkѓxMF[Gx4e3zQb!*]YC暿Ig[Ku6HIoԥG sd#N "ܞ{|<^VIQG#ٵ͕G gH}ʜ[g&Mt8~n7\y׷w;&aR~1/ʓDW|ฃܜߨD@!~HLv*wЈ U`\Bϭ oJuz_sRT,с߇Wf+!F ˅ x0&12I]np~wBgJt>M`Zwb  ne7'EcN+je?G8Vv90,6mNL ^#βub*Ņ򛗪Bvb>d }UAs}O~v~P-+Uux pe03岍O^1m(*s]r^{}l0W|tE}%J\RRgoKwo/Y6Di:׊v2ЧG$,\; Tǣ>[fm`]oc\tݕ~z S'O$j4"S!Vj' `#$'xOIYR;7[fMpk%3;=:Tolz6ZHw2żKyd|r07f_6s̗ܩ5wꇝxǦ>/` ާ[?߈Dz'Or$0ޭt&[]EqnEP/uKjj.u=>@U" z>-&aRu$ U[CBhۨ5bcKomQmڹbkvUn[L&J_0͚} px,5\X a|-<>dqr/zT#E-'>ֶ5WuS;e~GO׍O%T7>^zO={{J_-qk~qpP!-|H:b B~h\wtks NxU^muz%жAMY kJ9pc_+p<4 ^Wtg *G0*<6|_ buꇝO|g' i<%QzW:}-*_}aUW2 &U5 13'& -_q=^RX8GRd9c&͕]؀[xw]Y-H!nYh>t85QNhȑdۅݸ\}o3 8'$p(ԛn-jFik.e8/qR6sFD9BgJ7kFeCr>d:d !7Kݮ7]šfǵ?Eدb<,ۦSk4$Q&_r]?D>TCpWwbѭ]o^}K9Ѓ9>]sv0'KUJjʑѧ|Db8st 9hڤ jk~jYϛ2;+A 5fXc.lS]"ZCI+2T x["D"*_k6 >3MccȊi ` Xx$|DCaA)sɲ܆޶\y $r,".'9M'7 K Y$##fm؆ x򱑃랝]K$S\<?؉ҫgE|)ثv"'b>_—I yTyĭggb~wm%g| ~H'&2b *Fݏ@SZZ;sZs69U<5˭D#8‡4vb"Q* < m۱>$_&K<6Wm/~YQ"aNB29|mHH=s|ᡇ/?6k'β>ŕg_}c&G+vyz|r%wv(ډ8l;a7w}8|qRPz )8qY5!x<\ª)N4s"`’ٽ>J FH÷28]z>M&I'Hʊ(ZFޒf|/.f5x,eۋVD / ŴB>ʬٰ4I￸6O jdNRF&'V˹cԵ:#?S7N=/~ٳ.OtlT%>|sgob;c#35Qm^\'\*gԱNxi+NH9͖blӲ U 7!p9:>rN{Wb#HDC-a]"m Ib/+-G!i<[Tɥ>`@h;Ӂst5vYᘪv2Q4xEu//I-NF+⑱YOpyY -D+M3U5xⴟyDl+:Ss\\?f\Y-J+J}`D 0F :5B%ځ18ɇBݪTZ.\xc1v@ 1>iO>"ʐ[^y\1EdKs~@k Yi# wj*+P|Xȧ 8=L!Jˮ̙;32녍tX,< IچØгTFTI0]'6nXm> 2lh8HtЭp.^ݺ&Kkec/,'J`f$ʍաtB !(VRxY$]$đ=4s\xF(`hЦe ax #`K6[7ve<Ѡ//etյ;~!{Y\0Ydm[&{Q"B !`[Q*b`c1Bx- cNǣg 83S\Ckkyt*Wtc 0>(TkG'knL Z3mMޑvf9LZ"('x^Yd@EWHlNfěʻ`cT%kk[-kYP{r^ɒiͮ&NOUuGC}\ˁ4@6gZĮ[-_35ByVpE;ߒ$C @U$%kBb%1E$M[<#C\՛]OB뒲&GFVr%?ߺcFٞ?ed/kB`C̅osťj2vnCUX~*P"1/(VVg L< xUگ(@R9nrx0m>yvZ]w~ 1MʢY[x9OvH*2Ϙs"i'4EEA ˖):7}D@`*1UmoJ˰`5a)eɦ6cgF?y?Lѝ8WnL4.cזgXφRGOM#w:kjBgӉH2uIzѰ/.\2>btkxhůRNE;S#ف$dazVgmp6Ƈfzh9 27"]>.hSGgcaF?DA!p]f/?'wm1tzn6 P&2}p`|0=f-7lkwJ5`9.9E \nW0Ԛu*F#Ohɳ[/5ScGu檐 _{uu/.{vz]_Yo, ^c vhg{}3\(,y7O٩\MD\_q!SwnH!eg9F)vb;[b5FA(7cA=x O<JoL|Qޞ +-Áaf12n79 _];woz vȢ?R>֝CLom"'{7]IEJ~z6i-PKo݆r=tw&"`ȕĴbSƸJӑi岙&b5W WWh'$x6Zdp}z$CzK/[[J>^|zXhZ</#%,.%6k4h$lSC?{ôju}Ɉ_Fgx_>iRO blpz_4$ m &qJ0Yʹk^itn8Fn1O`Cq$i C6la&2*Mua3YjM '#08h2ث_2]0AP`BXk-FPh*7524q_k5̌eeڍ}­ig`R(6wdr{Q񾼿6+מgaǒ!`zg5,sO- }S| HWnܻ뵛uv>v#"I'S3,6o8} Wpږ6J&thv9N\H-ۥ4< Z)X̬ 䴌y8fmzjZm|)URB7 t&qlAa;Vã)Iק3[zR(V[} <@/ZXm:/͚z_-Q.S ڻ+OW-]o˕Mi>qlgsczc<Ǐ;}z7 ~3Ǫ֕;bWr1RhH65g"-;+Uh[`x(̹up=6wT46U#X1m\K9Y;iF2X~hm %p ۀ}}!&K@ѐR9㱓HY4hd]\(Hk#\>MZj~xNB|V7^8N$A`9׮cW Ǹe{ ҝC&IUs׮md 硛?3<+7b|̮eA.*|鹥{#N F.uaIv/<ĸ> #D0Vdڨ~۰^a<&U; oKA6|[Vr Xɳu :l Du7=%$`9|oչ'ٜ*"$! ``1/cc"I l$`Aij6N=ӹrխOQ5=iw;c^?OMwUs@.pz|ZQS|Nf ʧ_-xhU3`%j&>g0W.mִWZ TsGl Ruia{ˤ DMpS#< 6f|Gz>}`x7pl Ýוksœilhڰ}'~G]Rl_3NjZW8!T\g`zP`.m6]nDhv̚Rۻ ^??B0|^5RNlMP[gRO$F0A$\ N¥g0C$Bt,6 tt^1%aDG7u`5ESi\7L4UM>sgru,g>x|7l]ǒK8@d>m,59m_Zwbe"! B5:xzI& ~t6Jw9>GsKR$Z4z-NWsk%F|@feRi;z[vhenvR׫@ M׌]ϿpH(YtlTytưk 訮仭6'# y #$aD1VJ9Ly B0LJ%@6e{O;R>zo~Y퉗ܺks=w΁+{oľNwKcB[7܆)K1~3;GRP%.ǞKن1 CZ|dv*7lR(Յwqk]FæJr߳JK"G$-3}k3=s0 A(r#20V2^9MU|Z防㣅zU} 0`$I xIQ-RN/U/emȎ]s OAB! />~(apH!Q&gKﹴe2=dtkfE1g;[kXuy}|SqJKXˊccظNK٤+spzА^ eG$6 m7W^Ei> (Q"(êrcy|<7^d8Ft},% Q6g'Oa:^{o#>&ihL{Fdv|v[7uL m-Q$sj|c4|VcN/11|!;% \'$iu4B"\1R&2XQp F=u|ntƱ!p~!><"o!~t<-Cgjzqv:6>t 62eXgwRc +OOtFemtsw?JK5ϵ?S4'_:}Ņ]OgD=x 0uj;:8p0՝SPn8jxQjѡ١֯ظ 87qEJHA,q?:7A?d%A ď7LS(ʄGۦchy&; ,y`$]`Bd|g/*S02uaQJ0r7F*k/mݴBFg݈~Y?t;ӅT;6G8eo@x_559fjMs*DHpiUi;>{!ȥ7shnTZn6n0Zm; 7.nvkt=E1ZP^ꏪRSfֱL=xp*x]ew 6az3/*㠐bY)PPKP4FʱͥLDUkeLj#k$Sƣme ʻnNcz6vlz򾡧jJg䲖Ѽ}ilB_Տo>v˥}g5Z[8ģFwL)#kȖm(Rn//u7t_ٱ<{܁=J?Dk7oڮ-Ur2;y>LʅS1@7F]`rPf/WJ&]ᢌ zu`pϦ\T&~I?^ܼЇ~TO_9y5 RW/l'e2w&F50V:?/^jPs LUBP:=جL.uۥzEB\?taJ`1jhIBI5zX~3x FP'$Ņ~3h-D&KͪΣ(-7ivc/ԧF.&$z HDRTX '߿ OX귞 ih<ҩg}D1[X:nW?{uw>٥5uϗ?~ޘ*c?_g.yW_lb~D%_L]~h'JD//V( t5?QDaQ j2r*K7a^&u#[cza LU3b=P| d1BЅyy΅tT; ]Yxr%dj%,]+(2w)|Ŗ{"#3o]gm?My_ɟ,=믿hǷHI~囗xx>_:թ5?@yxz -͗|m7˻TlY7=g/CTyt26jvPõ{ /]0.1F>4Vn8XwdK2=}{;)a/ 4?RDA"^ GV~J#R_˧zGvW+^a(ϐvvzЈj}l(,u;1۹O,\$ػeH=yjN/[<˚ra"N~&~y29˂}M}h!?;sI/uO$k qu#Ù G(1<ljGN;*=ҧ?};˭ o>60.Ƈ>4}~ ?AR~K=UCy3 ZJY^#g-Jdͮۨ?@ 2j12 Mx: "эF.7>:)1>]󚞽硇^?0 G?(~[b x;a*š Mp:Q !g@S~F̲t8si0D@S!$1{F?aش_Mʦ]탧/@6ۧlP~bvϚ[ԛ ۶\6}gɆ_C_C Q|K ^1.F*E> wRشO}mj辽*kOy߉?<3:DŽ{'3K :zߚ$Jd5X4,er^oJΩP?U,S# " Ij"GҎO6 r c%9ǼYT-ީn3Pq֙P:GXyǸs${ Y )R{<0XAbU16.ZGj.[^ọ'^33w|{g _X̞=/ꯪ}՗C'(8_-e烟@IQ밳|Ft 羹jUT!XJ9Q9,4'g[Cm4QzGncO=ORh֡{Rpp=sNB_.)qMw~j|wc9c|-#KBi)W|!XBjDˆzm-H[d$=tV bQi}2ds)r!@-7bAxdPHce3eq.:uܰ/}z*keSMۆڿs}vX^ju{wWүyxjN/|a;{_(XSMh#fy#.wz1D Ae Rna9?9d޲c"cˋ{;\ɢ<6F;&3Kh@ߋ,45q Fr}yѢv/djl}Manr[#e?O?BK^v"t] T+!z'PyMUY:;8gJ٢b/Uؾ@'D#ANn9',]#>7`̲7svOvٟzx+Οc 3_O>וiM_gGzG=h4 ŌݟB:6vC!5Z GC˷u D)/e臉sYlC`U ՛w=ۯ?,vl,dby.gz/'gak"2^)n|@m7/^ J2pHhަt=2y.!h,PՔ2xh#mó`xM܋3_Bgj~/S(x\^fPv"R'38*#,X K{8o㉩[*ٹg:Sï>4V vC?u^ E#۶ c%EsY4b!PBxVf?^z,uJ#29u^)tΝ N7muB@a,qt&Qm;ˑX#@e UU>\Я;0Lѹe֦DAۀg:'^@:J6ԈHٔrӶʣt )1 &.c(#7p _j7JTJ<=rG'^wݲ-S\k~%A+-R9@-3_?sj!X`OmۻÅB5q?Rmzơ=;VmsSkNU҃PB6ʾ~czxc9_J[@FCVBƊ;S# =*ebNuJMLe]_%n c @rBZV/F?}I?k7>9MzwL=|w)מlܷsJ&+p~f)~3x_>p֡*oB'ʷl:jBXwJBrn@麝v0(e5Fx\ 2_XƖ@9;v,4ZlP/m"4B ܎Iqzᶆ( iL?vU1%42$.Bwܔ4ʉØw=jh/MU-CsG.]؈8XY/j={R#|yOr Yl]5wnZl)z}YK%n [xm\m+]c${CO 0aNW!VpÖcg{gG_oZM%{CwZ"tmexGihA,1lϻlOƻmsy_wT5Awz^?^J|S$HuWFpD~^%/LM,tEYHBgMqD)3NwL63NQ'K=?v"5HLD]Ǥc^! m<5K^~777K)cF ܜ5:bK>&:؍-*0\,s^ξrښoMI6=Fǚ(Q1q DNO#bM/Dk[ \Lwޔg5 AǢØ\_Mk| C_zUk'kZjp+{)ڻE%elQm)np2ǀd(e!P:J(y gsvDrB0u XX"MJ*%0H;bwT]<*]i~6^W`z;qiX&1BҢZ9K0Rx)8 |Cv(J=ab-K3˺Qt 2tkHU!Ĝl-+ [. 0sPiZ֗tJf?3ݝ7̺s}xY?5tܽosBe\cWJS `ʀrP4R4bQ֛syLt?xW Pؔ!tiV& Q#>\I(:H;F}haCg#ĭzZԄo\dΆJӏm~3ε&G3'* oBGfMMQ2AL==[-._Kn_UYqrFҖ{#+t1H@c:x%& AKDU۲L:նVM6^9r9q %MOE(IpJskTU[iq^ɛ'j0^ֺ8}$.l[?52w@ٔ-FLp TI<^VTΰJT?Bk,rd[mfޜ^}r:|%yB!ʨ i+߽A颳|f9>{D:j'prln޼`o\q2^ƨK-ɧimn'AGb+[?71v䖞HhDO^+* )( ҔmNRleZ h&7A:y8z|ƺ`qp/fnG`&r0b٘h/>5YK 7Mrq]Y̬>'v-R5/?TxVgFjs.B b}¯~*_?'ޗ恘k˥z͗z%2YFGB?ZWۓlK^t6@% #lÚ)fS'mEW|~:ȼ34\J];P1 &JrnЎ"~С]Sci o)mI)?|\5NSKSR ID43b*% 9+;LƙUq*f^F]`݀"wO"S$fnK_6O={J7 鳯Hw>]Of sXߜ0j?o,7?J@#boՉL:ܐrv<K '欮goBQ.Fu C듴ͣ?}ȾsWĬW%ne#2 8PJ) Ej0LjSsAN2MN57Vr 5DXW'2Q/+Ç}0O+&[DH`@" ."wz\0V2<.KM%q.BB(Av]xϠ+&G˦z!}oX|x!<9I{2ٔ/}x)Xn%3w 4+> irxg ig`U( SoBooVcǎ2PV'E$-5)瑏s~D5TЅFȏhք@$FH)WM]lM6Bz]^Ռ26ޭE9ܼc/|`:5:ְZrIlԷMe+;YIBݿ길}u?Xzkpu} &g-}|| ջ }LrQ/ABD `F !!BBSwv.3%$nzKzݸT: 1-CzMa!}m WJ?8Q%2*Җ R:v) QS6TK_Zr0(2\1cZlk8c㴍9\~/<\m0 Ι{n<>=_mgoc߻j-6H D}#t4s?~V|ʱEYKq!;󯶲NH>dɦX}/D<1!xB ؉}X1p{DBeI2Huá$:&_ s~r&9n[RH~ $ #1^ʲlS-n UXxq`)gɺQ=MZ["w0^A35<1,3&hh,8󈎐ۊ3X{LHM]%5/\Y %1KH4R0y"VYg8n|$ Ĕ&>'l.Ieq)BpK!Lr 5&A~TYՖvƤ|'YShIYQF֏^\ҁ*T$:"aIOʖM2m@Z*\fl5DIBMW0#ߕݹN [P_H:#RWc/`J9E7\iH %Ǟ iLUb^xјN(h?xXJ`رc<{]yAJ*j*H+Qu 3SH R%eB^UpTiJa|#fBB^UeCӬ6mJ.ӷ`A"XnKj"RBC] Q1wLuO~0KGqR& (ۄ&ץEIqi!$s TVξt z%Tu#!%ዶ~It}Oc $JH DSL0F)d rM ]C$aLT yM W?Nu/*f2( M@z]hDQgP-m0!!_ā8gᕍQ`, >o` ]~v(r`pr-jMO0}k?}F_0tP d!Cd__%$K(BO]IƲ-7ػ>ݔJ[j?.pBqr:Q2QDG !a)#\J`ih7;yP:.$:()N=Lp~c_8'P,=s⪤^g1Nu[80tKW );lqYkymnQqhTSp2В1RnN?LpcHz6kߵTY1u࡜ZH+[)gO+[)eq!C80b6[ݵ^ }¥z $(sX/k]BC$L-bb -5Ôpٹfb\QVV{Ub3qeqȫȭvD\bne2<01rycZ &LG"0Fn8P9$UQ.L i})J) Q1BR@H))Q ,0HDM]s B԰nX/dԌlQ_8@eT=NvgG "Q!;7)ZdT1BsDRJRi]#q^JŌ.`<\DRj[MCq SNdd0 P8g=1:ULIF0!DC0qjt!;0f2JBpYz[\Sgx…ŏ"P_ `ŦJ9b13 )2VxMsV(P*XJJY} J?ع KMg{oc##bbH'! c/<@$D)Qp~JCj[p\>GgLs cbB0`RRP ,y?0ڑRJHR5F^Ȝ G7OfSČ+Rf{1\HΩ2`; R*p}* o9﯐GfՕ;1UKa$0̹M5sY&j*: 6ϥH_,maq/{+9&ユ:B:q`4 @ghk'4aW0'l KXAIʩDH"h+[R(4RB %"!T,D*4@Z_#W0o Wu;jyK7-XY)9"IZw--a (d䅜 $$fļ0!}G %8&,KƂ\P1f# h\S'PkRF3XBh@hPcR蕓~$;nbzB`LV7_{ /a׷j^ήBӮw.Lk,X_ A\p$ιCl[tj ݈`$b!P3! !cKt<U*kAkv9\-إ.:L84[l)98r1Vp…1V${j)Ik:aaU cE(R$@ aHJ@rʨWXcI)!AJ.H"2`o>]ǣC9]%A,]%1Ƹhyq`\+1v{rzaBI’bB /7 qb"%e4uP H׍J޺)EuZ]˯|}* ~[_z;X)t<$:=0sl۶2 U9*XaF_H0 b3JT"Eq/(%"v~!e1$~ ![0)o1.]ZWi)B4Q!%ѵA~(\O>y8>Z|.A`z`7a 1}1)PU5&g*DFT4ja S+x۸ut՛7ULI1RJ)0L{ %qlU=1[{~l檟v]uj<є$No9W/+7s Qe<۵coOrF+ ⌢ a!a,h&Jϯ,%[=cmW['HbDBR7|[zk"m $I`Dj%r5+m -'B֙Rcs&ݠ}|~bv^+EwZOk fk4./-D[@PwdžFL(p&`vɇ~&i NqAW4u!BD6Qk-OBG@Ƅ`FL:C[\J!1b)qv)1Z)bLQ!BMTдDQ)(fM. —YWɈ3S&Z@Rh8hul J) \G~厧*w2BLS"$0j@].&\QՖVd|xXlM/[͜YfM/ʄ(NRA*h(RMlm2z!:p}q |cr33s^)_hvBB{xK;x򉗶.VaʍF1! K?`Ur(znʻvtѓK fԭ-̸j2?yĮ,]ZwGkAܹʥ ˀ2,Xꁤ'HM24moڰȩ"bV[8ȇ4Řk8m&m/fJRm&R4 P? ~!aqqE ah(( # !GHN^@=MG0F(  Q:%ef=l nh2R:RʄJ7P]+$Aa04U@BTL$7T^Z4uӈ:ҋU%ft/c;;20PTb7P۾90r6x–,5u.H k64ȤLBʘB/4QxHXlĦ{ |sٯT vmvؙS0W#TsG6-7flLnonrt|;5_74ZaMO)Q9qKam{S>mܽ3:x(=vO.em]nͪ+e:ӶI>˽@-gXt-j**#E˓Q&Jec UipJT 帥ulU)eAJDMJ ~lPjBe`8 Zi:|NwznNn+$~ͤ7,ӔnPYΡ MU%`-4;)X34\Hd5%ɓ8i4XQdp.ٞ)[G)[)MV ɲUҖ+2v?];f~[ =9Lb!dK;R-PG 9Asu]!|XqG. B6˥{,o+~̱\dxuyKsr̄5w,$18+7D%ilYV(NԢ,8Ll%DVNJc(Ԛ-]A;'t8b AWU&TP0>zz;0C$ Y:#p(2@w)?{8MHy\.Lv3A,-B]H@ )N=qx/!{Ī.-Cf[ ǔ fL ֑y{ew}}UQnIMTE5`6{%_W|Ɖe(Rfl846י̼tIGF2[r}o%s 3J0^I{Ԓf05e"肔^kS&{y4>8a[C;#r.A;z ŏ-)ڶ/+ThzD#! "B!RubA^S&~IAH1q=F h((rB( zjH.%!N}8;hR:YsM\?,fO4 dLYZ,N.Z-Oy1_smƊĕkovBAB|^m۽Pui_h9IA*cy=t^@%셶 &m}xᄖ 5 Q"Z!PUP{T)U5!E;7^]n9gBhl?+Y* as Q6؋!fOUGc`sN` ͅz¹7VU7];A⨛ϐf$ἢ@)e0M/ar̴^ PYUC)8J$D$ ^n]ucUs41u>1dRڶHHcC#:()Htvf6bjɖ e?m!5 O.Kmp.( H)$ns kщǧ}|*R!eű|}af1PKYɫޜzq_F51H34'FuTP<ʛa:K^9HMarF <̘pLL(0{dK['g.)8BxnY MQ0\.-4{rI E/r ^z)nXƣg$UR/gM7M+CXD't:cziǶ,M܃1qq(0Sij*?pt:R9:r6sULpG^Bc$ 5Ύu!"ק6& fDR0BHr֖9Sv40C38\T C [6FhqEq嵈8rB Ϥ=`BșТX9n%)f:e{( y :ICH2EEq\&F_j[K^她 dZ#j&drA`ۦThLhTՔ9ÓʺH֋sXjkl\CBHI Xsyɨ(W;F1(Q$S <(2\s/;7\'$BqL [ᜇr \NqǍ=QF\$8V OmGnEs6mC@U*p1ףFT{lTm6c~p!R LZni5d"yMjuJYuS %ĔqQT v" (q(R!%daX,{kZ4/iKYiIBi?HU F{\$ 7s6v\!kj0Z$dITSSDAX54;Q78z"sm=ʳ{4]@-sO$lH yHȞc%uLE N E!>ՎmTBSKpSezz"Dbѱ" sƔ~HXzڝ\u>+l\ۦZQsҧI)ZDы2+Hz]m{6] وh6ֺYRu,@ Jk)DnqduHQTY4ˌ#O!*Fj_ 1l*+BbJ9c祕iI;F J%M!S# nҒIT4{|&0H^N%ѽM4V& )upv՞qS B VU1BdUE*v\\a0ea#D WGjmkr Z#E{WՃazÝב>NT +Ų%-'Z*!}CsN819(DZa 6u*.Js򔌙(ʠqɸ%~w͕v ARCqڌYc*&( RՔ=\ζjmI!"zf%oZ祣M l:00qnPB09&9ㅅWNMdp1qɩə`jkugœ_oĥQ5J< h ԡu9NH̔FWA/?'੿J$A I&Qʔs ܑ7+XN׏?Ԝz_!lFpMqeOį *DZVnn,7u~r!_↫*aDZݛ`O ~I]Uht7ͫDΥnR".xFrb;p"j03l)8-ԙDqKJM"K=̋-+MEeRߋtM@@RR08AaX T8VzRvNo UB$ n?6V5TxB tLT7z$O 7x8WSH"ʱN~/8Q1D\^7^N.BH*=~tW gSP>Ueѫ3(R ] GKuq-g~,58 Vd;J1="gmfQ"K'4&ЙBSE} [U5 $^DnAj"+v3"RP $Шj=Uak,a$8GvNWJz[^"3c1 1b*4O'HJ^uGŽ9]]#1VVҔ)BpƂIDҦ/~dӤ&i4Mkyx6fV3J^xg $2ʩs&R5֣CYXJ'DcCzC?rUt+y>3G%I e9I2<[պ>)jT)^,,F~qh v'TDpbP*%.ŕ[XKI]q2Vqjٶ4q$45ȒPD цkf6Sǖ*BJ2eM 5\%HRǦ{]6BcP{Y0B9'^):?bgjغh!:A `D႗sDU0%ȴ>mFxɟjWoO3ֳ5U+cALzKD:jbX)Ɗ?҉\#sWnZ.#GwÖBrYhUn\K[<ѕD! ĨvzW1ҫS:u.1PhtHwsx,0,^HRi8Ȍ=Θ&~MuM|s”Z*e"K_VOH|jyԏ'u}2Z\h^<їTCR'_~KO7N|v/F ů>珔Of7285$2F_spW W˿:cԱ΍7^8Pۼk:) 3Ac #E1bds[v7;ޝ*'|8Ub!$]7mZ\Wl # um]Ub\Mm yn%UY!/qBF0>钸 ~};$)LȮh^|]ϕfr9ɥB-)+ ' MZ2mCflZH%+@&O-4'Ynu-g훹wg}ѯ}zkW?5P^DSN[M٦CY8\v1ͫĨKj1VOc2Z=3 Sr^>w]hntMH A%486^G4 =aڰuy?7O-eӢ#- "5@tV a͞2RRvLUHRVbq1͘=Uʉփ\ܶ+$ c9Z>؝ۛq(H K #e7ikqw/=72K7ajwھ VNot=MڋopNښQ5{E)c~Fr{ttxlvnE^bf{SPJYcz~YQʥmw׆\ˆʩ_w5HuI\-1=]hY)QLo ӧb 5{).8! %\7Q)nvXk_#ܱ'ͤ7\U=Ԓw2?2;C+L[jB]I"ϷS+[^|ΉX`DH"#^;6]SzW{ɒ{ǶX./2۾F\̇L[% # ;frօD:AaUۉ6gEC!Fz(.?MR`~,7<TJ1NrIezf{oŸ* _C Q1&7nFgl&_)gZbxXPL[# MCK J4 P %óvcnmX2m<\k섃Nh9Ӫ F /wBVEx',6|Cu~߬ZjmmXp2m7~ 'A䒅:_\{!ohj]@TQR̘RV˟zk\WQ% #$%B$Dcb9c!9UjDL&W70dhse8 Mc>EZRJ2o1l Cx]W]OÜ]-%>1PUppA=rz6?`d?]^a9r~Q1FB7_:(?##r$ur e)+n Vblof#a$(M5Q 3YiX,z XGZu:ܶh8VUXj;+H%U冚GErp#.@ -Y!dOZTqɤVs5o*RT2-NDimW }3s5U:5w B \!f@nCz߉mWۿv%ܷ"a)TwNX/ t˰z`J)+ny#Nё̼i>ni{Ǐg~K0Fu7gRUyڄ6z1ݔl,רd;|BH9F%o-qt>ԲwN3e$f7HZ"kIV1I@)-;yKPtᏀ>ۿ W>p/hcdP;5Sv{)kYXFH,WN,lY7_?[WuyW?bp?t7>{ZNLrp>}sVMtח_/+{/=%aҏSq<45l[@ 5j`j(mٚk8:*+`nc,TguSRՔKG 9^v.b*3)jd(XD7IpU bxЇ0BXjp/4rs7~T]ܴ_?w__xdݺ+~7^A^!Cj N HIa$4%!yL5ShY;yL ͋SL(^=+W ծ78 dU Kya&fǃsUktLfe > >{v~wjQyמ ]rB_0)Tu}>.)KH:?WOS_O:?fBѰGN/o*]siB(Jd>]r<ՋL!r`L*Tli$h JǪ(*1џ)W8:m/>Yki %Ggj4CAth[P>3?q5vV鋐:egs-}@ǝv#./`H1Qq}<oz a0Fk(lڴ;?ynY# OA`aAaC X̔gsadlCUE6N糞?f4f*:7~ߞ=CEu,XZ XrT8fG "J&nUf/|)ݽ8l0:*-L_?T_\ !DMo|(caVs?X؛bWy/>>ɰw||*ɳAIQ0FgXV/>/c|Zl.]/v3UH(@Vo|A!i&Vػ}r|gv.M~;&wd)G@B/t\HF7'Ź1YX~詊 /^U)/.cT;lc,od|H*ŬM)&;>6:^a ^IŁ{2-7rW{}1,"/);(6O~kQ]yΛhcƒۮO@3T 6M?hRtjkt@VrVwN]/Wuה`F.mJof=~c?c;,͵ҖR=غF,XP±G+Axb,VO?ɷlBmk080LكK3P7ų wl9<4˯G!9܍g }SV N˧T[cD\U77?tE%&՗޾wbƅi(iG@-7y۟2^.V?<%][lڱ+nh1&Ŵ9B2| QO ƒ޸?86)9ln7=ڳ0!X=Jc85Zq{-I)8pޮnPW0{˒Hl Ls_z@1 ~gl5Oͻ7} İ/ 6_=A^h%N 6Ttd\ktbպoؐ^o~c/7n%'9uA10Ŵڨm`# I PEK0!﹣jFB%I t%ڳ4_?^`H,5etmOKՙxt{}:IĆb=:C I*MvŇzTL.e w 7O1_DYTY9:Ti 23l9[V隂b8)'abN EP5 }SGKNdPq[m?m݁18(6[Iǟ_pw׋7eJ26>n)?:e5ͶBCep>IкLSUx zy9H@y! /K^xgyTH;6p5ɝRZ)VjjNfJxc?/zޔ ޶;y$HAR.RFDQX:H(y,SٹTf$ sx-?4ƫw2dN=[Mv= n7OΈxPj[ }yqW̛羱cuS.s r_>sӧ-{%sf"x`2VISѭ-JJ1)ibQbQOW$/ ʅr3Hb_\nTDI^S)8i']m6)!{O[cK/;09ˆ WmёR8!j@Wˍ)'4fBvm>`7a(~^m,i%L2.26^EjayCG~Sرp #gggA}_Xy[6 „RZBH 5Xa@qk{ Ջf}"MX(O=ojuB )Kxvkkr&Dޣ·@lU86} sŪׯR?k8b46T+'VHM]5uv/.eV6r}[O$(e&,ܼ{u._3Y7߸sض45PL[Mԁ!)#!L*@^@Ə,`xG>TU0d[)i׳! ݴL[[9WXQ 5tY>vO؈'=s}3xjYV %o e.D"yG$ҷG~%qmrGcX .#AIE26P*J]-cd0εnMGEl+].y77pkthd:x1I2p.PdQKfq%|ЁP/ٴb2gKMACZ 0BjjXkG*Q(BMi)KU^η}rZw;c[v &7{SG=5nd2'zSY44TT YEٞ۽+E{?"%ՔK !:c(R̤_nYt܀cUZeXjSzV"J Mn=e?VeߝVqJ-0wl#}G 8FueE+[X ~H3i50!(ȓ"ljjs9U\ )ʐ?jbJ(|NQnM[ CֵZ5¢9{8M3)=ppH7ʴ1W)4Ii֬ 32yi\*@'^HL!cm{4|0s{^#}[s#)HI:ϟ)$T@]me<tّJA<쉓n"ۋ01ڞ%' (ޛ?gمALZ1F@MX 81LuKB<~o̅z14:<0 iB)?7,0;<$H.:ҕi 9`z>f9pr ]:/ 74T(a$ n;S:QUJr!6 j䅓|T~oD w#2NRU!XQXw<@ANX M Cr)$@\+-F%kgHy~K#?|z;1KwO.g0 J܉!#׹VV`,iFTՐ+E( 熅4c|Ѫvi4_:3/`׭O5! 1 W9p:0:7 [P$dp \ɕcPyQ%Ro]Օgp~{sg\c} p:zfʬ6߲cT; Rkm6RTu 9?Pi'_Β- עcg{f ^۠;5C乜S0tBc :3qlz1LcxCinzӹkU(9v=XrKZRB76<Qm)S@޹CAXDث~7o]U" K2u0ZH nh[z&8X9(8J$ ]ee'Ǜs[:  3`FuoE?Q?TO HPA$Hlh:ѡr{trgsުUխ?n^~׻i==#{\8P+J{ո:\XB."쥽1 !\v0geݶs (fb~ lt@iPi!>gBfF@HtC t-EI /z9ܱ^y\~gjWJx,΅ssqI" P(qwb7pa.ͥ\.TUnNM $7㩻FzQ n#  ~!c`B,n{se %p!ZYdpAC U>pޕϑ  5cszy5A{?6]dr4ZUe=7zRbLt ]EX SW\٬Zd qDK%vj՟M[V "^5:BUE,mNсF˛rsus4-jQ## | /x+\Uy5l&㉞]ZPB+`eĺEIpG t@<4 C.bW5O% ["=}zpqzDL;wyGb5rn?YR VB+*{h ۾1 ~d CW?WdBMll@2nH'b#JT[WmO@%JJ̔Y~rrھdt(}`:5=t\r<ȦeU?bv\*?AFMٱJgמW?W2XĄl{[Q"۶jtxZ6[^&dԓͯ~0^Z!0PBj}R%d`h;z~푀_/fީr D!C@S z({# ;@HD0`$7+&a$9k\~bEWo߳2_q: -!I>90o_E0xhx$iubJڎM*[<Ն|S_c8a%t`ήv[F\JYV^ A`pJזB0\oB9^eOOYVEA2tw@%_4r9\[T\q#It\]U|JkvzG^ M 97keb)AUq3l2SnʱqA^4 xl`YX4ֺ~]S NݴHΝ+G,ިi+%l)ӫg" 美v5Qj;K"5l . iqORϾѧǿx3'mv6a$A|1l0Җ )WԿr5J薥G>PИ#]8 ĎFh֙Gpo90Uglgs hx6o[^ ! t#W?WA(R1Rd"fDŽG R,Xof*Nf/ONr.UMBJB*,-VX}1nH5'A Q( H[n+W 4Ԯ</ #AiA'rK2HCQf-_Z e1] bv\" "`)f]QeZ[^6=>|%(d@v€Q}̋WMaR}B`&$7Ȳ_ncG^=7 4J Q[_ccDýfH!S1AB;&B,J q@ A4~ibt Q} 񡡩с]C&X%$sݺe 6۝ʪ3T6ۙd_榖:5=6H ҳO>Awl .IR>(I KJY1)kR HP:n3{gGю Tc@JvO7߰c]ۚO\ZQhum"ly~*&B;@M׋ǍnxXJvJ!Ob]t|1ƺAȻv4EQ@4=/;n0O.Jo!kv>V桏_r~͙DH' TNj8SˍKR1\  qDL^ޛPRmŕ`m%>SOq.TUJe7h5IDATt9#s.Ŭ}[KpCcB1=tϔH.!t[Nta1FݐY<?& +1¸w\PmNKЃu0Ή(2JSp)%xG"eD;=ZRbjg8Hrb9=ZP! zsS=1[!pck7^Vwc]$ qى X@&a6Y@1"H.dmOroFq{QD0>`Aڮ6DQ # h -_?|ϯBeXHy 3k{x%nQzlx,ӸL7'ggQBSt8^aUG ~`TQ-˒=rBJ(Qı! B1KӍ!BQ@b07Ju͈{ ݺSR(zo#nuv".wtZ{CwC0{b[(գ\IBET rMߣa/YUr|Mgh+j $w4i4 M@zZgϮgϞxcyN&{igcH׏ e1Lz3J]U̮޹-25U}!ΙPCq/ԁ8T,b.uC2X(.t-hPJyAKp&44D#Ǐ iD\"@);~c4o@;|豳K;^Ƙ0. Q2if" ;R ضOdwV7w&PB}.Πk(s"SiZ14C: `jȼtw>>-׋*P)O^м孰/ *qBP87jT0 jF3dkW~Wմq+sCQ̒axv/=QoVq}[䐪K_wp;iMGv?f^ۣRUg`Rr~d*[p>yaȮ u[HTG`vQȋUJ# Tnkƀ2H0]aga!?sW/I+ mooWLl$ː0Z_`BmmnSmIsrS.R3 wxK_STŎ)VQRU3x ?tjt<wXcM`FzD]߿Q2ZB^{ }߫sxQTd g VxȜ_:g*|;}=1-{t. 7`o=9e fOu1Xr"~!$܉d@7L"[BPEM]<]bꊀx93XSۚbZs{+x G>Ѓ/+'bla]pA@Q c}@P-%EUD "è&Q&f&&QӃ#oo;/?|)F\[j0}ecLEcO|jw>S XԺavuogƴl9횕"u&G^չsk kٿG8B4;z1@s3\HxCZt@k{W-iZ:#*z[vduf^\g*mkq֗+;-u/*V(NT7u>/U?\FG'9HW#Vj ]{{ f`HO^xa{"?"}r`#$ db"h:2UH.߸W Ơ@%W7]\5Ԫ㏝5Ѯ!Ni&H,mi@#'8(C}x:p2W2?Vъ|`+t2jˍ|OhbZ Xb8S[('fo?߿֐I/Jt]5w5>q9MYMdD0YFN6vU72{pGd"PQJ[aon_=sUUD6nn/~9||)R!,,yr|EVFBP xL_9`m"$'ݙcF[7LX[ڬv|c0gp߬ ]++d1!b@0`O-m#y6/o5v:r=f8 bf7;N.!,Zo̝@-o5EZ}a'/X*1D⺶/'-U:b^xAim8Jj{fC)ݣxv# 4*n#88lcZsIRm]JL 0ics|`jѹBfC37_o~ Rz%&άaA4%I3i4RҢOrI@Q~>;|?Fr_L ]&C4U#cbpt #4n)<~ShO,2*JhH1f# {׽^A]9,/,/d?yǼyHYm'G{f-ǧHPM1C8Ӄȶt]F 7ˡMv ^Bߛ_c`$u5:29 NrݏɧՈ 45VF ՘ g `?C_"xG?tKfSk247kXf0]MY$b/:>+u?`-cvH쐡U%J`@5M^542uib*!(jQJYD6G\0tMw\Gv?}7,H{1mK-nENdƒ`MS#!ՑrvpUiך/3)SLmNq3Y;Bot&P9F|pu(X=wgwpۥ/у"a= H2@p=' 9|-l|=/?;`NJ'PsϾ=Whٞ(h}Η][OM} iUZf"f(fI"nKqNXjm,_UQ'mȧ!<)jŴf-l*U5V)REBcm@F0iw~nvn:7V2|;`ģ_ԟ6m^iN`q^9<3=D@3%&X>ID-{je)CGR[5A5R΃AHJȸ2=ԩ\`)`(ּPwzElJ N-T*6ҟ-/~n BX1T,p|cmk8Ke _s{(l,؂2ޯ;\-W)zhWNʩHٟl6 $84gV-z\gh骊˧7e&tk!!?4ʻ~y.OznH#[Ni:VS#B;оq_`:^5މN+UЫ V:(jPSW t\cZK:Ѷ#qƉ´B  oW׏j guA1Ord~jkLƅijӻ )LS %+qlXAE#C>VkFM8` bhZDFO7uV)3M--L^S~^<\6kоBRY+a*X(~/Y,)[^+bZOTOb;."|شL~bNAXYYcw31}qIj( iA&~4M<ĂT$&c-UB* ]aLá c? xzOۃgWT Mj xT׌,c?7FRJ)N6M0r<kvjfJæCxzjT痫]H!ӚA꫕)+7- 듫[&85A˸զ2&OYٷ'xܪ/-LR-*y6M>Rh@!a*niutf;!PHlR] p(Z뷌D_qۢa X3- J*^d_>;>߬a zX1G6U^`/ޗX@j޿2S!F/j.Tܨ %gq2zL!~sml=65զ&Y*f\:nۮoZBLX!4V|j! Tq7w>[Cd2sq2 EQ5iH);]ox }x J:UkZ[-l(%]4lNxu1B;gѡ>Fp݈ϯxwF#D彸eN88]p*K$`RAxGBaS q218~lv.X)e>W;-]|'x,afMέ!$Y˘Je֚-ۓ]1Gp5cՖ4uxxrqஷ4<>F聾r& p.恩]v?ðv=HZ1# vK!$%t !T'[Ai7Oky4uEERLᚂ@:^½ 5@.Sˀ;Afg8ɕr|ikv.qCll5I zqxD8gםFd_&7(U~#&5@Ĥ+mt`B6:"Hh{jz3Si]""ۊ8(TB]tm(XMbi(T$M 1ʅZ Sfsr_'I$ Q}L̗QCvu$Wg,;"^L@"7`qb(kA(Tz̴5Nvxj`WY?9熑[D,'?F"Pe*LI)7P1̌ōm /z ?9}1#t|#}ZM NTEMaS(e7@B:&4a@໡DžaCtfUzh`$ף0*F*όjMӅDʪa$\QaIiӜ@*ŅS4z"đS@J" C! I0Y-/@RN²L. QQ@R|I$0VKXdj'B<$ӕTA(1K% au8l,~Q+<$AXdKA74ʏwN h8>rkzOREW5#?x_M z%,ԛRr$hP_WI![ݥRCo}w$ϟ~%%H{"8[;KrEH,WGSQh,k_ڝqvm}}l~tS/*v #(S !1鶣3Uvk= ="),+z"z핶BBV! @}.pq2͕ӱlՙiRa)$|!HJ0Hwpz-=oΎ ~Xk[$aY6pA9~oHC&@(`ildP+|$3Z|,3vEce/4L-lBZ_έwC`;l S/>pwVUC%}7d"L@07E K| *9mt_2tvsǾRQۼ^D P͜jWĪ tl_4{ ѕɎU+-s m#$$R]ԘCDҥєbY6BJ:G0rAmH M3UM[jnZ$hA?.ϧO}cDLӞˎ??(:U:Nhc"B2"9-'B󕸙>'?~]>ϕc)%%0LǧA[˅$cS/F|oɕ}k+ 0CwwBR!2dBdx7a2%IvtA d9\i  Mn`}aO;KY Z#S/ ښY%啯y5M$|ČeU}9L~G?Pp;1_Ĥ{f^1]YǗKDZx/Z>яݥo*7LӑrMIf:Hzsk%zjB{ )%۪^&9s-Sۙ4tBkㄣ}9nˆ_w|A(*z0lVݐ@ve/ ?ut۵:]%sk=zƸa$:kH`brp['6(Q?O;|C:lswO7kk_?_BѢ)D7+ !%BkI+x՝w|2ÁD*1p_t%&7}9F&CBK$BRb&!5=c2Ih/g{RUWzɛvmM D y<ΧLp.^~J yͭziTVVsI)0.ZXAK)'LdJp_gفg"}X9a^(S픅{- tnSè AX?Wf7߄_ݻwZPq,D rCj5d` )*D%q 憉bF`jQ\a,TA!j"FQ;_{Mѹnb9Ol.=i:L]{YG=EW3 Z/w}n|ϞO31A Ebp ik,[s̶pJ%IQW(Ykc(JC`{Cbcd􈞇(n)!sS#OKWl=>H`KWrt֢Ta oMgׂ7,#;ǷbBoz#=;sΉ!Ů}}_x;7 mΚv=C&'{ BnǑLX&;N(c2<:#o0'^ʻ݈PDNL/_9ܼG] 8ة fpm'~t~ ?^8p`5J3˜3/=R̵alx/{.IDTO͠3}]KD#͎!v\P)#pZO[ܯl9xjfyn՗{ɟj)Ǐ>@"DÈ~)aZ{ߧowD4ux[~= D(n{^\5\6 F2Psb(ŌK=RU8?9N  9gX6-sX,/?iVqޭpzگ_s2 6 'mg )hxzڒn}Yy#aʯ}d2.->_ʩd %ci@c=5R|i.T _9'xb\y(W)i׼(p¶#t}vb?afJǍа[M Qv`i \ّD"'\;5$ >~o'w Ec :BetF]P|M_TKmbJO'}h6ZT*mU鈖VE$wwW#sI fZnjRD߉OԃJ_ ͯk:,Basj9ї8m6}DZf!%={RM]'>J'x @6b3HV'q`XdbM쨿KP!x~԰A!BZ=Em?p2%*ad+b`+K)&3̩03dmTӓ~y^w~KI?h ֋V2[Zd R]:QE&ބ 5zd6O]RV*~3ニ)yc(Tp656 T :\N0" bz|ȡLxd-mɃ%GBG̈́X\_oo[/Z2DtB>3I6m>ab IKyAy89 *SJ"H)M'\To_ >h8 ܦO VեnZX) Ǹei6ぬL kzW>Vvvr~oswdlk앥Z; h99qQ.KwRqQmNAIq.-cBDc$4U~\O5\=|>*;G&7s1aGʳBd!m6Te4%dj8=!aɩj{[nk8gzT/a-;# r$w 5+4J%rYԖD3`a-K$QvT|$\ÿlw')mJaAWeֻ2ȧ݃fX8Τq)wWw=],M{Y*eHA y_V-5Ș窝]evm'_7:v OX=oIBs%q%dZ,,eL2k骡aUΉiզyL[~ |kxv pډ呈wqU[ (DjB2<)%ESC97(~Dmݱdg _|'حֱ/~PUBR >k~#"MTa 1gjMK!S O3RGBR??tvazO< ?w ZByD;5Fzv OM 8b~ycحֱ/.B!D.uqms|@yl-NHwfIlk5^{ ?IDATxgmiZFbJ]A鈺C8n<nLMp r"( A X]UkUw9|(\govXUo5gOkԿ9@fNy- 5.@VG{3~tٟwmw\ǵ7? ?uFlըtD58&TE HagZ)um?ۻ/{c2_Oƒ.ďƯjB@ՁR="J@w Hq9@FEiC_ڮфXYE[[}g_kke/|W3+%UWEcDP5aCJE,.*3fhIUϙA U$2_͋1nN'ur}YǁzQ&2骎Ebz5L/."ԍrwt|5VIYqa]?v \d -- ~eϽd]js?ǪOgZkI:HPbpȐuX- ޳d3QJfʘfCb:˪$6oǗǍuz}|{40)SwjE aP@R 3m"),QXY%͍ݦ>2UDJt4mm2yes"w82*'/eǰa]F?_,Ui$ 2)N㬸H*A {q~-*'oL*PJ.fa'H"XG~8]%4s ֶmie߳'.O__T=˕8Θ(z6a07,33-Co菗٢kG T VF'F )4|<lctՑDa!Ge2ǁUϾw?@I$ytJ={v]prOƍ~0OZyBA۰A,5-J~wLºжYDsT6yD{QG@ӵG?~Q+#d/χЄ22l T 2T] 5" PC{!]ϔ2RX-0#X ^i ìQB$ t23l~鷦~ˎgmn3}UxW=&2O#f[t[tY )~+_HH"N, D:<؍ =8;?<Qz(_.v7)cѬJt0E[fhppKvqbTul|B?O/;W?z{=Hʓlo$]L}'ޠDJ,$]91}jѲ瓋!o;y]/HIopPjtjF()Vxn3Z,)EnIv4 b"pjBnozڹh*-lwT u+:FuFãNkmk]~[SEW BnmRvY%6:>"j%.s=&z Q(6~A݊5u))Bg j8ERoVz I֮ٚVI.ګ׺L/ӿt>#2ml"ட."UaRn&&ʻ'(/TOh]F厲^u lQ]sqNE=e6VvKbGd$rS\_"ff-/;W5KK*#d{Mq@`= !]N`węnK s@բmi^oz٪̔' Z3srUB'*|ڕ|[I&4Ot BP̞ɿx>~ɭw~ynXP`y0Zmh|0:KH1";/k1!aН3re2Hi1$s%(,BnJ(L O?:bH3io Xk%(`MW Oe'*ޙ^͢>>QQe_̫}̧7dzEtN[i|EtfIb9tnY$̸,kdqeTRM3zw3MC`b-ΦT[f`E%{Yُ<[[{Z%EHxmBO4@$8.s%|@Qd\Z9Dw1>sNJ>x,UY |g<y+绦 z }h|%XQK) "xUqp?uZI/;Wu^~۷c^YY~@Ib쪖B(@Lw7 {4o!2{dܞ+9"+!'neh U8VvNLgv<bFEu];w~H1fY2lȂz`^eJٟ@t~JJ!ͪ,cND*u*[yjfESH PT\$Ί<:W ]RuΌm~ ][W@tX7q+D?'Uժl R7~G S`%X HE,ݺL_i?b3g ],V$ 4tg꾇 @leqV LA̼=q"A&fU&uGpCFG!eþ{*6Pu-ݺL_Q=1T2ĆN)F uK;[w &" wGw9({Py73@I/LUbDY,B3lE)x-2!JdsPEQ(%1%"& o b\vkkR2}E}zʶl;'y!{BH;|nkIDB@ȀF0?(f}sڄ:܁֓" T BBw_ǃ+#1qm:Ju vM!k+f0i})'Z^vkkV2}E%I1LRT܇n# Tha L HJTϝ HF2 NUaZfGi= d*fB6=n1 %*nkJ(>"nuA2`m_.WW/-.VXKR"B@Ϭr9HLR=I4bБ*' L#giԪ JJf%jI :r}ZI@^. nO&/1F/K66_n%MZ8]vkkR2}z7J,7h5]զ@ $@byU0 3&S*AQ^-4 @8m6р񚡪@N&Uv "' "|켣4"vB23-`Dj#f6<_Q?s! iܵ@mQŗ^-'BaO6=l3K'(乓K))BD)| e,Z ۠GZZ)8I6;Qp&I"vј{Fdʬ|cHז7+=ڥY%œQ*M5P*R6ƫf#۪KRE(ĺYVlsu!c.ŦZNuNH4|n[I,P`QbNIlNZ3""eg>x~?fY4\.+fXfۛY/(S[5V+eEo'!_%_g~ק}.ӗ?ofu9S/mPJNk:k!pXTfYqWז] VGi7mepRH;46sg}yZBӶ˪*w}=oݛ>X{OT{c%4^I!VlΩ:mB V1s,ԥsA W"׵MH3@s&p> 8-m:=)@ʭ*LbA"N4!03ĭ#3(1 ~7@atrtyB??У[hڶ^@dmq lg~k`n[Ǝb3QB()P Q/Q RQ?ْih3}D$* n:si.x V]_4`f"|9dD[A1;%E̫zu}eAQ̭ӈ@XfQsYFehl:1ؾ8?b_~^lk4]2Uˉn.˳|2_`>9HbHVIvupTR@p>؈UmuPow^<轾}hG>l`^2}TA hgNN$U9EQuZTR([W7JʪK7|);ب0Lϛ׺Dx0HR@gMw((Eu7ǓE"h;?,w %FDB60(`9/;я˾[n^^Iy:낁u%8Y~[%v%kٹi':/䳇@0, uWh5ղrDk Rv%E)Lu]X3LWK<|ZaWV r}RJbӵ'{5u!=|ŵgpx.i,z_9ڻH@q-&KHy!E7.E+c}BCf 6>dPY`U[5aSlG5޳XwN<VR0 " t">ˎy@{z颟U D@ )T;s흨tQ|KsUwH(""3TO/Oo}9UueegJi(i,/X@]x!,7^?oCiXF;+BRxH;D HvIARDX5)"01@7% O[)ZݳbY@(E %b ;0K&rHŨ1C"v.?>|}篾ް!m!@'RA"өEժ)[LjXIw<[D Y9ftD*Pi%[c~Q=|춋>zYL*eBkgT2XO7vK__eĝA& mjӪ>E3*(:Y6*"m}Nk+Uphh.C`@1bF'>Զi+PK+uO|vo_~q#w'AMd)i:PH(WM . 3X@Vѓ.DhX %u2`/Z) и c\$%iI e Q@{vc/Ζob7.fBR@EKTYV@E׍ 3cե=՝d%NgZ+QdQ3ԉZzy c7FIYH,&K5,*'Bgf0Ԋ|yC>:] "tB"VuBಔ;h2r'>Uw}L\B+>v5)liN]]k(O8 M'MȓnVaª Ful-_ zRB ;/ͳ<" Dγ4H]4(NWu|~C`fkQY~ιeOMuv4n=X⵭Q 1q8#86`Ix3bU=~xy}oClGxAlc[x}ӶgYY),1eSd&g*(xoL'YCvptIRHWΡE/*Z_IBP^iD#@ mȤ@,76LB J!+!Dw>6QKY8R@$⨳$0C `f`Z{q!`+jxVfſ?vqҏ}bF11ye2)BvvnkkA:D]$3eG M6|1nsjBlL#OOzj{i~?s \E༻BQ2eeO'6ѭvg{,fC]{e0yݞJvFDFYg&z*E=BJ!"GD7̝QjՐ 6Zha]jY"O h"@ bb{B`#uR4mhmZOv>>WEgb{'o D6iꬎ{:sX -*$OVj'K͜;Sa.f^*o@Y$KU7<[Q F˦sG'ҹ֘N^VJ\[ec%PuKZQh\u>L?*bY5JeІ*)`" I6>3'Z/ \Q aѸe0+`3Gڇ uLysm 0' 6(f@z(ЖJ#${>AЪs_'»?$n\4cbwSc׷_p>w g2L/)IFMVF|t6Y)LLtjwDU {j^ކsn]QF0/a/GuVUMN(.oEj 3o j-c RȮ+;'E6_ҲU4D?._߲.ӇbxV3YyʁcaNGQ@A% $>~2r\-`R:X!r$efT8d"By,vX "<'mC`DٹViUڷb'{8|bQm-ȹқe=~惭O"VǍ2l9m o YznYUw>6Þpx.N'rC{y>t~66$7׊sKezuwբ((!x˜J] $_5֚e^8^^ۑZFB/OO?.{=2}{B(eC (}.H],4i)b93:2A$ZH 9`Tb$6Bx9v^U2!"C٠)MǍѪV&Os2`T۹askZ> On D'!?½)_.eS"`^?޶@E/i@eOj3+)r9]eU-K"y|#Q±{VO~mdLMW1Q,B󙽱WԭJQ6P5UO'U_tlmei婙/)s:^]{heY>W2mZI$X! cNJFPR4+[zJ#V5)%[dV%Uf@( }@,iYu}Ј,( & fVB#-!`¬s}rW~;6Ҹ{hQ[)ww?ܐ`ڬ~!"Ζ zʈk-(8eݿlgnԴ5}sϿp,7ȜM]}b@HGؕ#<w_8 NM$oxuiY'"4/lm}/u!P"_5]x=ՍJNȓhg`M&=8G0^B/-q(#=*Go8M6㙛Bo #C%|麅RO0%{Oj:B)Ɠ&O">pEm|Ew'GW+`]EbTt_ -n_s.$qd2ҡne#hN&1nuk"pc.0+R՝FD h&Ri*\`uBD6xK|`@! j.4 %6H*9eg:ڿ^.5Ѩl`^^w-bs@^xYG1G2jl%vv](_TaQg@n. $EL%p:igUcɸ[Kf"Oܸ:[̥E#*1&O*hm] BDM[`QI$4>/T(-QumclS#6k^ ~u~~߮ElQ*7$N}D݂QI-V˦Ljg.`b̌7[Vn8Q-*l#em ]$q< uv:WR̖%;ǽL,Kj ۮ鲪__2םٝF:9eyଊLjs'zY;M@m!nZp1}K&Y56 6gc*2gl/F_P GgnYUӋϧMmH>8k,k z(?8Y=ys,WRJ({UlHӍOtmDA)U7t&"$HN/.(ݺL?V\0(Dmm{8٤6QhU5UG׵^Kd:չ .j-U ?H!ec`<6lő!*#vU+~/)HLIdZc^hTo+n-i 8ljAp?ret>i.f %DմW_xpqtumٻLjOR -B,wdM]UqNcVd=o/}k N~GY仿۫y"DjuoeVhJ#bUD6W7өK#:ŶnZnVlQ^٠-)B$bbBc<bf)p^XRۆRőWi^@AJ >pDs{Z,<ݶ>o~_{J6$7w2zks/; #u24Ͼ$u;dvaTۆ|!y;#`TK W169wiPV''KYf)%~l$m ?BL}`-C%4ղj9 #5*6CF}1]-6IKqk&"w?E y)cCoB]pWĹL {ۣn KSIY$TR`F1OZ LB]ld쐝T 8c"39d !H΁L0< JK޿|iL^Z_BFõj!wN Gc5?''뛟 }y"_Xou`j{NWF1#º[8lQOW0Qk-E?wf:_<&x3G"pbK/:Z`{_X/V4A~>BMA?OqtB(# "':L8T1ȓ*%|TtMER^zVJ 9"x0yl#EdגC@-l,Ѻ'z֝h[/Fr2F'?hbO7f=tY5۷ϥTu'D>6mbw`u=lIl87Cu5k>Q"ͪ90+ۤ8ؔ3#Pl@<;!Ćһ~LmDUj$a;Pu ԺՋɹz~onWw(K\(q>^"nD&^(% QY][ >^kӺL?z3l@JKè<2r>#H"MEh1[}\n$,0YT>vr0RN)F@2M,8Ά4B+jYu4H `G$;$DG-HS/mwl.!l6Oqx Tg>X̫T#XH/[]|m|{^x&zdɷo!B k׏d<#x Fe`QTv5!jG$LXwڐU CS^zw6cO;w}&zDq}uw|sc7ųO| gI7Bs(iDL^/c q$;KM|0r=m1kؓi->%QglD|7״h sxBbzK3 ~Ū8M]fmllyl/WmówߘRh}>-6Z@=]W+5jPH֋ ڌtg?tFN]?ظrm ӻ$0*pVko~'_=&S;UD_V\pnոs0oZ=u}~Q{坓4R:# sXrϦaghN'PW037]ypvx|[n0{u &ɕx:GoNמgmlꪶ{;m4TCo1LRc P'|%"Jʺ)Qe~u~޶;pTiYԆ.•-Z5 k4IK<|Ҋ4:Ky찗By sA L?-uK sh/or2#D-̰ه&~b`.xhdU# eZt;π%t6xvG]YWR[ 5mc(Oᄈ}|1ħAnwD6Y^l"HI$n:J٧~Uɐ|6]׸ēa^Y$K`<+{ޙyz/jmx(@|fgq<]^УWY?]m#n=sM7} z{ ^Okݶcv6vǽ^$n+ !MFDj ) $"!HHB\L{m@JUmoIU7w_^{eQjݐdtU6}TZGD@Dez͋$[6xRAJlape Gi!80],IWƞZ"-C٪؏"nFk|G=_/jjӨ*$v6ymBݣǯJ#i՞ 1jyzrbZV~|Tv>r#)y!{qeSzgq֊ͤt~}M;I{4sH%]ɳ|fJ$J(vJJD8 e[l \Ÿ*Rֹ8BkIJJi% *6rY3^kߺL?K\tk}.sPaLGQen` mm:7`Qu( $Ƃ@h:VOt|HQ+$E#1&ru^~㯽sћ8G΍j |腓?y|t>dYYw~uk`%3@l"S-I휵͙rjv n%3ۊ%:>ɼ 3X{qvR 4HױilZ)5lm9 13#1*e0]JiN79gqgt|IJOEB%,)@<왋Y!FϝNK Ntm||4of_Y*ez*\?|zqe]y0|^^?64}F) lf g6 :]~{fqկH=s<~3<`a^MBEMއߙ|뻟Z<@B Jzj10 F7%.ʦHU]ox۹eD#@xx~sT ՃR\2˹i"Gj~[EX8Dl:XG:"8XdUeuBD̬TG23Q !4yl>Zz%zNü[D%݌M:l@` DrYց<BkLmg^OH?ӿ~k{30^YԼ暚駿~}|2>؊[O>{eEe(jB*fsyqlzeYZ@ z+BεZD( t?m}L2*M⋥\2(\qҷ{u!uiMY@&DNX+%Ḭk:GBֲH3CՠR+A@F %u B|יQi4{`PF _/—Md(ҳRJ/H.vwkZjZk9,$Q'wʊֱYQ =}x{c?Q!09)RAއ؈*M^7uөe\ݑ+&^MH3+?c٦e{xhL!?x*SX}G[ D֪:Ȳ׿`/&ǩ2]J8WuS93K*b@!;k: H^}^k/u~~~(4i6l~lXK4 A`A.k ,$hiS$VƉ񋊼DmffUrZf@pC*HEBN4^B8%$BuMA .|?s?'q}un&G[̱gUh%6"JćrwI]5e{>Ο;}(eU^"N4'eQ)Bt]hl0ZD< "m',yI[lt)"7{>xs=8֥YQd_;wr~Z]bBIr>8i$jѻ)m3h#Qh}~}'Y2ckVnX.cR{7}񛗽^.2YF)B*I"`P9DJyP*GUQnb gg%E &_PK D6 ,~um:>Jǯ]5?HO=w?0Z\?;<=7Z1@1FI_x#I_#%Z&+RB boߝ뛾ފ*K4#y^o|Cwg|Pj- %f]]@mmDMkN$"6&&e܈W,fY^=sd{ sۋab{Ew<}jL|4*ti"(7uv~>ןxz'.L*l9w둷lNNǡ 4˥ @k(2eՎToozY`y>y@DnU6u"bց"@̝Z~g^k/u~/ H0jVYI`)m(DƭAO#C0ΡZK$OɌN|pe+)4|7 6 b@k+G`( q/ٿC؆8FBJDG^wdyufGxf6WfY-xFvRr!>(,F@!p;Y⽳ө[6u־4^@iټȈ^ft<#(+Y/>8wNU(1uu yp]'ryO5특#rL(U37HaYޕJ`"/GIG8sXI-{a$zϋee#~^^2p}}ް?^t>GpYUB >ZY=c%9RZb[6(e`4R(DJEjѶ,D`삶4QANHB#u$|p?sRIAN+'g#8:ؚڮ Bh)%"G`eEu'M 7ɋBFY*:@/clox>^Uͮqj]\4i:zj}cJ*uq9y Z睇"My0 ,UAԐ64@l4FfjjElT13{D^!(Z^xYŏYN7[|CF-F:m^ogQ?^DIyɺ)W|oOMS3T$on>wgM#9'p?Z] g(!γu܅Xm7@ם*: 0 DB3p@6MZ`Y `Q7~O}Z釥 $Si@E,gd fDrUq1 Pi<u-D B,e| e0Y"DZJ'uidU՛,*24@9Jj{Os?OΗ.I:KÀ(E.MhhDFf'Kn0mw]D<]L6Y#Oc ;w;@I sCVrLLj!yMk|*wl< DdӉ$8ٸO=8? 0*Ƶ~y^:lې DxOCޚޥ`juV$˽'&)9&;@M=9= 7[ɘ~ȓLPƈ9 8 @dt,WQJޕ2M||e/޵W񁁵Zu;։&yP:mA@$qҎ2y(EˉVNHI B%DPUXK~Ρ]P"4XCuY0uαM94&?#|lx8ko-AMY@"b>Qe]ع>ÝSbz˗sfMYUJЀBAhltn,ڍihCCm̌R37|2 ,nT+WXqq9ژ"JI5)G(8(-3Sk<^zuP=y%,:=!:s:£"wͤhq,wFRk Z"@)NsO\9>[1@ۙZmkW.1+oݽ|fVJ_x I0{ IJ줚H9[I8m81@6;BuyGǏѰnJE:~FAy9ZG6vE8t$Y-$p;\ģN_;#?pFYi[U i׷!8!TV>M(JWuH#;E`,[WA R#۹Xe:;Y[Β5q$;}Y"B@"UCjB`'X5`]bSmo]DEНg8E:CDB=^M0UUM<.ć]J8DRu-6VXV=t́8(mVMGD-W!N46}^f 4߄Dд636w#~yp֝?c,7+Wg隠R*^mMIi3͏/LǷ排]s5|tgS[NwcgTׂ2OD+ig Na6NTD2aomgޞ13#7ȪGs΋iwge;n^N҅JH6#y/X'tiX.o [QE5Mh/iE'y<BHA[_D2 s8$u涧ְ 6UXvJi)R  )e(R&ZW[ey^%u{ȮI1D:n **fzw7"Lo_QZ]l@}Rޟ/Ɨvg#؅T ٪┐ zb|vc}xx{oT-os`8ٚ$w)8DFNRZEiQ:ճޏB ٙNx`zlJ4Yە!UHƃozNao έ wG y1x,Y<a")/#B &gY>$e#Yi8" 5CR vXH{@\ދƈDU$0Ƕ811"ƪ`sm)>^(H  (e)).X EǺSl۳X.nGwxŪ1aJ..r k{sb9rtifĈh.߼>:? 0/2R6RZwG'c^MQ \;d❳f?6$AW Gې~[Ku{YP%5Oi:-vh bw+ߩcY׎s pVICj^mRe SBJ-:)5w~B TI7gn@:#%Wuʒ<@Ro #%IHM EZZHuZĚ4蚣GJňhlO]k</gS4yl:Iԟ6џ"\5#Q&hk0Γ3e %q8P F"7ݍ.եMhOdxp\Q=_U(v|NC<|CUy8*ƾ}oueo2_?88 z}XdZם.llzobY7NUG`籺;/>7oItuP=μJDpܦ1Y j󖒜$[uI %!{ucw<ɣFZYksL(Irx!y%sb4y!|99ǜuTw2x|g<>8.IFكdPM"->4<i$\cWz Bd6;޹>Mֱ1 ~2pZi=B +e흪`7\úz #k0G(<8Y݃Y*D8\Ѳbwokz+z%Ϗ6^/&uf=2s&_ ={Z"$O{KzTJAb^Lx5AŤx%{=ZviVR;.0gIڧZ#eiػHw~ӏ:bo曋&0 y\u[Q1Tb<_qÇI#ٺDH=X'$ޗ00&.oqgng{OT3sq _)OgwZ|Uv,\Y-~/\C*x= ,/.TMb2XӤ>Jc%Ե1)exj{X| t"}- RfD5㕮[ƪr\H{Ĥa^Ju83qn Y<5B'tk:9ӆow,զptM/t;*y΋X2!B1SNAXgQEY=L2&HRFN Aއ3% >@" 0DzDòqor>CJM ;4V|pևq|xV份}w"eQk!uU{6Mo8*6բ7]LV7muUoDݦAԻSDѰi4 1H,n?zy1(Pˮf40up$g#4k~Su]^EJD1RioZI@ybbЙXێA4 BX [;y}tv磯E=IIJDe$a`IF36[4>^U}$|yạ́M_)6|n亲Cݩj+:8{y_X??};-ptNikToh+wš(Tu,8|Pk)a2s>.s7}k{GG|3Zc޺}?KabCOztoHK7^_xj?kR.\z-AKYU wVr*!HlVq ô s%)|Su6ެtio `0ZhBhY6)cq5qUw[WTq$ҘdQG,i{6P!@UqH3souuX^RP~덝 !sE,"ՂA6f@8k{+=3h^Ƣs^r}hƽ=!!iN!<@!ey\b'ٳ]o4 k "Uу[{"×gxb~pgvygP3օ,jydxs4[ qAqR#@>|VY[?$4$q2(A>Gqo+)Tg4.[BA%gpGM`AmIIm@zs&!( Ηe"0ڻ @0(D\I1C |%%3?p?w>`v^LEr-։sH!duoh7*%L"PB OR{G 9V%IZt$wXpF9{GָH.73Lep\HB:&xO I'EN" 3MK'ߺ2ݽPopԯw!|IDAT_7{`We3ߤĺfZxȢ;-.~9RWUo83WB ?H.xR rVA ՛U.a,>+]>|?׾O #=wYV_F߼/­{ٍUj"%it1p්ˈS"w E<+m?"ݷ4B4ouD-ɧ޸sv-UFREӁ)DRP t=QGaXPӕFA`{tB [>R6r0a@0B][)p:8`X㰷*־8+(,vkNKF ܋b(e$eDDBJ DD?| iFtHZ/E(hO7rowO(%g`جWwܽ|]eƱ~pXHONrI5r~Ir03˻y\pѕe9!xLo0T*u.Ly Z% nζ<]`e>Z$ &bٔھ:%=JLe46)9)J3qeCR*yoUU^iZ_ ZfkO?)G9+h?|ItB(VRPrNz?`Mu'#]OIIHw'^$6Sn{n*ʮY ѦM_놎1"$dVӋ+g]|R9ttѬmoW1l 3@[VÙYUYhC㰩Sץ[ +[D8 |]]0yqve֦j _o%Pg"ɋe9ې)}$6U1,^vvww/uw F\ %=!H&fԭ۔$ 9!;z&a7ZaXA6QHD5`o]cz&VE1%`v<&'OڶS=;Lh$Wٕrsrl뙫ݫ7bk2%"xkxw4[Rm7Yt۷}H 9s#x bi`:0-fV-B0.ߚFJoM~ jѥiL'.A&Q'03[ĞY|8qEw?GsΜo(r&:gCk y9%{#m<Eo3};̄kX/"R&X>[E5HHd2I)%]I%e.%wVi&^ :qg'h'Mp݇>49;~n}H6wlۛ<ѫ1wE۾} 7ͿW,<a׻OL[~K{GEO ѯ7wenep.%RI BVCi&>fxUD4<= 2Ʀ MyyDŁ@ ]FmͱOvBԴ#姟l냳~+Um1sي_;cxץbE{&Ti) :Lj@\7U*bVI!Pii jؾγ,(Z ރC1 @J8~pxV$VDhR%D! e( sovoEF `0+k X`S6* `;'d;4ؐS~<]&{^K= '[88cH`}sghooCs+:YdxJЭۤR 眠lǹNydC cd}bm1`S%"@ J$[}粗_cT}f\ۇcug+7|z|GAK_>K٦dgܛ xQi7&1NeyG06H4bHD9:ԧ^_D!DJE!8%#!9Z4U뷪4A$XIb"ngϦ`X|+ۏ?MywF,1/n]u4 -Vܸ_k_79 u|%=1~R떯f1H}g^u A'` tm }Ob's[^{ؿ{l+~9?|yfӸ[w:uDEJp sXnxwhܯy1?'hݽ4137 R ƆRE=gMձ(@ :O΋%D !m}Hu(y"3V RJRR"oFI%8T(%8uwHS-YORiڶFoՄ4^ yVVMۣr}x+ϺpváGѥ[[uhˮ ]ډx_߽ϿK/?w}K,@wo$[} (m^XZ+1(nN rH"[Z!pǬ,Fx]Y 1Mu];W)#*\ko>]悼lQjY-\Vx]7xQ[5x?Cw7b \z¦VF*L۴2ҩ PBpޮ#=u~fDd'jYF [}mrDi,kycB:&35*`K}i, :$!@I 0sRE4QE)d8JPhGW/,Ev4ۺLlM纪nh_ wNK;Ƕ/aUS>= +D@6ܝ\w@:@" \TCӼ+|?H! XL%]1" Y}͌2`i/߹ӎyA^GO\2sc4QOnNܹ߰pr>Gn(!7 V2@N5:RV:/Ӏ"2|`.nsW7(` 8`< ZH&Ax)5""@h"!4m;Jڦ9*J!(i1Hm!DoWQTUlS,r3]Yˍ`em{~z]@|`d.WJ+{]ggZVUE᲼wYe !=]5Ͽ0oO[͗|Y`O|a`Ϧ|<YO>г1lځu}bU-Eq{Gtg LuM 2?.$u睭i /^>O=lvi*Aׁʆ_&LJ&%g! =9S Ja&&mMhMާ?q}/{޽}f>UlWû/ pw['{_('U4 ހ e?MgdoeUO(ѭYUɺ0AuɣNٹ/,_X'ԟA ": B0(A#BdRڶ2JI1gVv l5 S] fXvi lq` Y!ݝlGEQH(I(Nx \GQX0du,?91_J{|sO}e({6'L :/M}_4|| axZGBe_ZUo=|ߘ I` 0cnVd̾<+S"]ܟǃ'vEl&fF4[SyZ̍j4nnD+_u((Žu 9VHQ۴dƓFE44Gs_ G~ğ)PRK냤;[ ٥u! t> gm[-qX4ԺЛ ׽1vr7.cB-A0杹g$6Nh033J98HF-T/YgbIJX0d0Rr1ϖnϼ^جdvLr,A~|pt0Kig̓{UI/~gf"t ̃SD5ȔA/Kȅr<-Aq 5 cf=PRVffŶH>ʴ^y|h+{1CD❻wr17~u} [L篼js\5K8C,"$rB;cD5 bւ #m?4#*^սD'|# mBLHM>v!dYq"=hJ)CRF( D$J A;DE \I|-Kn8J&[n$"q;H"LtY?uUUm4OX3%"ASpp#fn7؟:p.Kg7gѹ 6o?H _,g>1x|-t\pi~l?U3ks_|ޔ#_l;0_ "%["hZ('Ҵ* f  O{'"E,SEB[D b)T(:.s,ZG !t^7p>-&I] 4tJy[|`3mƹ 0qY%kmA 3ĹR7_n-F Xj[57-}敗[m:0Wu{B'8W,Q|-f=qլʮ~j^4_ؽ=ƅȧI"|=cF?n҈.d[eWXXQY6g AxB-Po+;h w=e[ӿxKۿQG9_w?]A &jtee\-2  @di$“yG${/C$D;aAD#A*w G DmoH+Wd&E{!yOXlz*GDY(%3(\HR*I8s>!z׭,}zr2t{Ӌz pzq66gv.h0ڒڅmT;lbxw3@Pxv4L6M\e ldAhX˛H\6#Y{i/^1?vg.}cx\WQ8ESɀw”jx=Mu/Y4udZmSO?}?;/uYL_3?^,*rZfb<#IkYuh#$B @"-%(! YRK6&bK^NyZ( Rtг,GZGcՉO!HQK cFi$O_TZJfZk`R*ZGif+ (9gǃQ9_07Ʋ:"8O(uDsf:z1nIN5o͘xQ:Vk(O>Pɪ x8\> fMUvƏ{wnx4twúw'/g0 Rlޖx:+{yt)#ֽvJ9}_7]\y3~x9޹G>c?&{({hs,:lZX-}Y 0K!RBgmkϡ`f(R1ٲE$@3 JAR"4E:=BHdd!O]Q "a{2$UCXyxInz#:yWL:W޾ GA ȇPu8433b$<>:HHֱ_V =@u4iyl'!ho{ʹ6ϞI^  I&`S^(}0[<ǺH!u@/.Z=L ADDb06y~5|nϔ+ \YRŕn?wby~јn7˷6兾wշngNZU:D(;󲩷~c3EͿ`cH`Z]wpQ|Z 7jq>poY9cp':m pǃd ZRq6$cfꢭɶULXIn;26V<~Ǘ}s|o/|(Qn#-}@3$)/KD$kOW $80u~{ Ya}<ѫ3b?H3c[g*Ѽᾱ.KBm"Ңu! ]QZ)\Hm'4 s6#-8w]yDZ@Yn 1V<%QgN`4s/]yq]5}c[_޿zewr˻׶BhWըtVS~×~wgz_z_i._꺪VMi z_slBļCթݱ{O\0o׻S}=ge[ؽ+ޓO/;oD]'OM0V7.s.}1շ?Ur4ױEN7<$I#`ЊݦItT (p $ [>&~eh}YugF!"uW8T4C9_6Oc> ߸ӗ Yªl=U䶼ӁVUG"÷oGQ$y=YUS (VױV_GZ{m_m.O"=ƶTh1M;:{dtqO44i㥪h)2yQFd# 0/yG,B8 `m΂xmg+3[Aϐz/R Uݪ2;MKZ)"! ljK95?u}'L#V μu,G7bvL <dq)v1Y`O|_}I7oO9ov&`l{&!NVݫWMLGɖ pa.V [^xR:;b;#Y>Ja zY:ExX??<̟;hdSwaDHN YqLM !0|Q+Y*7U`[v(X HEe-:^ =0Eôe@  " DZ L {@|DК{Ѩu+ dH#:[@ !&XqMYM33bU_ރw\NX"Żúy Y;!DQ$ޓA13]zt_Ixbw}߾i.[rgR]o}{;O]'ەۖBQ]O6RIfM&ĠjAjȶg'.<4# /W}\ysJl"$qyV;#Ns~G_U8;*AQ"t5JT(,*>F!sp㒸*ʆ'#J@}&:/6H4]gZ1aV.()XU!4)L'l0Z.\/;ו1 $#-"ұp程 Hޱm "^ݡ?"R)8aV:]mF_qDe-DTLEٍ xzto7.__|.u׍#*Dɪj rvgQt<FY ރoջ0תz/Z,SWQ e [sfh=8֒睵V0缒Bяٟz!?w¯k(Ecro+hY+鼷B<w<@$6ޮ+E]׽| >MS>Y~ǟ|Q'ܹ_#G{q`Nbd\iҝ-[\o8fB$)s!?DQ$RRαB#wԯV1o=e&x]q:f%Mz}_5&N")l(փۋW4s9b^!D 8H1K0<>!u9B D9$XWVZZ%3Ǻ"K"<ՀBIE|c)I$u^kժ]a]u-@8l ɢHK8R"DNcalPHQ Lb̂^{] t{8Kx8zEL)aN? .|{^Nc˳#mݞ^#>֯޼8U2sV*Da,FZt6$ιP5#գNsʜwVI,v ݳa:JUٞwNvD0keRVoz{X"m4@H$+"Lt?)̺IBPob-}݆E0 Jc9. ,6RrkgH1 Bp;pzD8$aXW_TBf 7v<ˮ5>A;"DCe>H"hT׵}zڶ6tW/S{# ģ"Cy*N=ړ.Q,4}t7/~Vb3^J$c>d{3[{!F= &E, yDbM|]JBգ<@@ p`Alͽ%fBg{B^z[6]uc5J WT)!h#)ITmʌAM:'A;bTdu [S9[,t^ME$DB"m uNf]tN9~{&z9{ HGe.7~y-%Y䞽wNAIo,au#ɢٝ #ؠy˿w<;~7n-c-G-쌸@EjY4]_7TB0(DE,uӆBvm/!PgTPg}HRMBc:)OlCo J4`ƅBtw0ﭛR 5lX֤)lY:oRjMFRs7/r;>}UqIN-˺|,{!׶wB)+&7=s䟹zn: ËY}S0٢ Μ-Ǿ~?3:}^L7hY@J!0mc UA>]9 H!AD;Һy!A9:'LYgrm?D @χK>e kg/i:pH4Wm @9~4ȶ}3ɡ˒}:cTO:s#tQ =82UK$$1lzYYBRNTBxOQbFwF|OEL0sQZ *oT|N6a]lzy"ʜ.ֽyi5]Hb۴V|w'bTu޸J~Ns_>{ڮq)qoBM;! a ÙVY92i%b(?lDR{o!d9""")`u SURF=!Ea]xpu"XB)(z+ޭyzcq[w]}R mi%3nmoXw(M1;nܹ_粘~7xW-3ޠ!"B WO\ƃYvtM[$Hn$?^$|Φ̈H \V0ɡ1X-|> D%+{ܼόL$n-E )}t΄Q"Ng1Yob埼2<][Hy.R"J+W5"q$|qR.lgΖMGYN8댗 QAp.Ѥ,I(&th%unXajaƄ~Q:slMxw}OƋMĥ|S{İ3Rʕ%ef栤p9}wLKS!:Ã_۾sZ9?RJ@i|zD&$V{l,~Zg֦1 3# vҨaHִ]sͷ-Գ~Y=wѨG,YV(GJqyn}Hl8}A|(H@$uI,M">Aazl9'"]/QΩ1ȷI=xރSDE$}a{"w쭳euq_zY}uO;ƺQ OU kΈ{*H"gϫaQediK{{i뵒2eƄ"S:#q}clHBv/myte]%Zxo}XGZHrRtM}"AQ$y!$k:|xpj&#쌯дI=!cM%Az p@ *f̞ >pʉ?uӏ:z)m/DŪ\IϠ@@yBVA`-B"i!d#J) A}r'uF0$ÒHc)dt{>,֥6QJKT 2zct+GEhz Vx$ME")lM(yh vrPKI(뎤E%6F]ԥIV%gZ&n{:<=LlUzS[:CB1YI,0,8ʔԀ aͦ᧯;V90G$ I  jS:?GO:9X|V;.M D׎4az4D2fMk pIDXu6}HugՅ]!OR$TVT!X9 xR1Yg0>pXues,kGbTH,R\H  aidf) OBcoIуUEANlpo>3,aN[amUw'bِu]i* d'0ODoZ)t.(n8˒{JAj Zj{h\֭6֧cițS\gDL!@YUmngƣs^}F/[Gji6ndQӹ cM8>^H? mGbwv0%LrB(ܹ,feaeՆ{;o#pA$~y<"\5^]@Z-utl@u}Cz 5u=gD%ؙC HD7.sR[fV $s~~>"V ?̰YVex;H@}Ăj%E5y764 20{M4@tcʹvT<^xŻD[\4>Ue+kdB+ϬG/'/vb\uhV98$w"[KZF[tӗ:Dmh`8F6n zA)Qw,ank"433qVWm뛏oHu8Nr⺅|%I7 pFST*a#bm$Hu>٦Cp( r.dfC&0no Od5"Œl#n^5j4gd@$n3Xq6`"3dl%~pgkVUBT}*є~>D(fFd*&DOy4&WiՋg^x{ Mj|{i}!T<brf?wMj DMqz8{8Mݶ[@1lX4]H@qPbf!,ߝoN͉PHYTmWӦݤ\\>U3c6D+Ů9&0CJ7E ,cbj ,'& 9oПO:kJLONrȞP>gU` JC`Zy3^4!OLQ$ Cʹ}gȎDtHPU^{蛘!2!3% ?ל#/j5z"nFGY3ޅ1Ojˋ67hh@O- h.ƫd(rq{2Ofm6~X8MFb 5xb~؛Ut|Պt X QJpnZ(oHaHVA%""3ͪ]?I5|mU#oB]u3p__j봦F`?wEs vO_g8j03j!mEW]>/hxF>}J5[CDG&,x<˖ܪUlVֈ䱮#Ցe7n'BrDfRO2Gf$uL D<{WDqL-2pE bd"22kS5NR&UBYNmH:f|t>;RRT ]kf4dg 2l:Mi8^MS:;kg*UM興)~Yh:S"Z1?G_B&GU͓FMػrN7["@uUZH #z^&"+*G5EڛVrŃvYfpiW>0>XLWU%*zں~r|4 Q̌r!TUe}+\ n![{v̼sbV\޼q<!:MVˁ3 4a^t(Mì"m񶿚M1SX3w|謹0DhĴMe`iT 'bh;*0!n> 1Em; ޶.ǔJړkyUUu6{\6f4o6~!IZho; 8YAI -ҏjR?,ڍMM#^ D4o_yRSd\q U 9m{2G=к_9)/9b[]Ǣ e1tbM=ɻfzHgZTLԚ\mO_tu\j.6vkw D/h /Bhr*{pLn쟭ޚLЋ)3s޾DyN!XiW&*Ox־sNϨQQx; P I:z;IAN19qtoWTM? V"'YN')̖4^s/7_2oT¡F#DPs/TX7b>{5B{fjL8d̅Da8GVw9OGۇqy1bNu>BrIDh@bU 5w;ܝ7?k>s{9K&f>.:m{Ɣޤi+ՉfAs2ĘRw\Yu@)csB> Y'3 w)q4 yI5׼o=zmY*Yh6 ɋ"yNCQRw^PJϼ2C$D@dd:^^\C_[UZulfȚʮ6c7ܦ1ljܬe dnC@7WtDxͳKya{[*6\oDUj5j)0$:r| ?>>߶cJk0@Us@DJ!X~D4]]rџ zr_UU1?Ø_}y!Ji!j烮[%a̿ữ @_T"lE`~&Jf$R˜2ce:D2]Q=>ưIslE(~cm;bEZuj-y0z/u^,ܼܴGƝ䩮i]\sL9F}|U?mZۣ[rO%8j`WҘYʻc.`u,j]Fdj`sׯ߾yIY)vJ"V @ʪkyLA1Znh9"fJWs+̩I)85TD\ݯɃn\-q̀<b;ԧ.oT "!A<0oE:^9ؑݾy99I_2|} >KyƓ7y_ g?V&A- Uut uR@#\K $3梢v?ky򕋩I|36< zF3,UfvmUvdv&{~N1/mkԔķI|TK\Rz<'nfTT뺾@ j=[̟{b Oynj-S?Ө%vpvuu0^\EoY~Hx2:YhWQɥ8GxP5]w>OL&.%AZ)+өA.6;PQU >p._5Oz QT !'-Ĥ3{?\G i^n=D8&0s`SUGMMʃ:BVY-ܨV[_9#NRVc>5P#]1Q.q) ~S'G* Tу7StTC"E "bNb,2.Ywe7`*j.vzށ1W&"NX!yߘ33UQQ[o{ydfQ3!c.6$3k8 *VRDA,Fh ~}=|?X>UFfp 'X ucf*kGK:2,=M˾#DOu}J88?*7[ďw:@M٬yKWl:a,zpXWaMH4BnNDH1:j\r*d! EO!jC4X&}S7j3C"!*ʴ!pۆEE7kj?i33:Dt&M4e?WJfR&$4]Pr]mzr;lj?&>6|xo-D2L91oI%N}Jgka5OZے'>Z׏lVĴIʫث4˖ڱnni;2*՚`ݮ+xsD!4.] &RIއv9r!x@u5ԏ :>" v=v#QH"O:W3ecf1CuάDh^%3D0f&3p>M+RށTcTEƴ-:\9'R̬s> "ẗ(g1{V )3R@sIr,&k|'Bم)Āfyp+7:\\NU TMav8WT 㺮^<ń_4HpDŊ}?4VM..'A)%Y{'><ѻ~c*~Gx_]v@٥a >T+ dUD?_G_R|q-gaRެ>\0;*:K N<:uR?N qD5xȊ!|MDfT0fR`% 15]s5O"g&W]%);&U03~q|UP-fʄj:)8"Sݦ1|,РVOOc|3fE\u)k uܟժz|߭ڛj9G{f謭r9#qDcRPmE^joz7LfM"lLS8ijcoރ-Y}1D$0r-~L@nEvO)1! ;I S.Mck_}Sа:^ AvVf*?{L]Dy̞/&4 #9NQԠ"ؤq}H<f>aԈ"kl߾R5s3޽;./WU5;:>U] bcַ'>k3^n妽{!L jmUM 1퐈 Xdxp6 "Y  QfjfjxbpSd;c2WH@bW?鈺(_aOJ]-<#`DuSdcRԄ>!3+{oք}r@."L*'ܩYp ;BzlD!Aum%}mo76Bm$ISv`杼M߬Ra>Ogy9^f5  }Ӕ% 3q\~浫_MsG(OR)݉L$S֢"_`:0$E 0$u(ԇw>!4%l{Hr6ĂL@%{IG5׼G tT;82CD̄i *;\4fcJ, d&TSvۭNAM ky2|%Ϳ]sxl@I_y^폼t݌)m0& ( 2a@p*@a7{^6e۞]]]=~9yp﹗J)1NaK6)| SCbC6r .6ىUF:UFTiB}I5׼JĴO&$̘{;@JßgUw3jx%(%v"!`pFSH@Bv: z3qUѧ~OP;H)PtolZaL7Nf,AM|%py]ڎvz={gw4Q q[DkۭIlW/G utQ!0a3Iّ1)+ªR1 ߲1k hV~w: ծk15k="*a2+DlFOݶD%(ӗ1fHD %ϮvM6d=bxwP)V08\6`9ðcN㳔*Rtܟ&m|)'.O<8Wo&%z(#Çd8s\)˺{g_1h|g`_oD]4l}&b,I(KPDǔ#E7 E:DR3&2D" H4??鸺.YBDш4%WtUwXoUఓ{?c= H sL<="VTp 8n91 ^L@lo9g۫VE`xyz1m8 'po α/"{߫oy"«?5٘Eot7]o\}._'"xWDCS"n:LS>ztԓwΏ^%"Q#$Q6m";[Y$_|39I3\r?BS۵c`?hYmkyo\ fju coZ.ٍׅzb1I=sV30wh˝z%s+no\`wG#O Joc[iNj5DtƜ֭CS(΁l{qM㕻\ۼjT|UOmz`W4K1`||0>R54X0CpKA1KpJL$HTJ(ы"}(w{_PSu5rK"=8+DYA@$Νcno/nalLH!"2ѻ5zD^5FЍndubW~/ XmO޹wP/_}rR*iw+ R\V5؍eHQao|y Xd;nWN?M[{뽙k>{F33:"d6kmF'6d'޸Ѥ sug,]2n!?&vY,zc Q1&b@ɤуֱ'Z\v2T q>C$__fr m6AU)Y*wE)$8) 3s{E,)s]ϙUя˒s5 ݘ)u|pz2|g} 7o[e뾉BMǣzP1eӱ2?]|O^ئK i*զ.z7Ξ%L/nUQՔųˬj351ܙIם/{8Zb2X\qL " f*s.O:/-g}?#b$VlD9P6+wWO?:ۓ>;"B8"5ؤ4'9z+,z>n@CTs!VM 2bQ3;o/{EP=D g0VÇ>pڝo yAm5QsPLgҦ>i!PTDJP>[UQ&3>vCJΰDGH`T%E,]7BE,&ØAʘ"[/'`\^vUb@a\ ,rRg~3_қNnήI#2KQߛ=w޼1kN&S=f,':j PxPDTӐo>6|乫Štne7)N*HEEMT3+x ֕1IQӔPEځS){s*:D( sƳ5Oi]1S"%SQ7KYI45Kӳ"Pc/ڨ udrq󙗙3x/l`LĢLkYATb*Ԫ`ӏ|9ܘOM/J.U^T@8zA,uoonQ9MK-6Se3|zgYw澼|Y5p,_x{w|#lc+ļq.y[4/DnL(!R G7I 9 somP+F$fG35DشôEED(ErQDf"Qr1=GkyOKXefUlwӍb/ˏ"a`ڦU"6MW9Bg2K1 jt2`]nTSJȹ3X*B\mx|R#\/j[Bh C sU+j+lrH~%^lrjߩ>^uP>P rm XQR0"%@ vc]~Vnsjj>";=>~3, XEwDhC ":DFכL旉_‡{ODD8s<!nw=S~ի!ǖV`O&ܻ *\϶u\.R>OjEnL PI)q|Xǻ#L˶I3=9t"9qo,ƭDo!{NygloYtI7Cs~xc3u*e3IOXuGrSH؍֍8fq<5E:@lj*]ބ^?Wgɐp7@aQ&H*ה LQ.3}1"σEqif 22i}fGUHcbDsdBU"_1v5 ~'u"DR ?|OϿX1#j٭x2"$bGޱGtѠC7%ĥ @8s@Ey9?~7}>T`~P-4LQm]s#e j԰#iH7bx>wEb ͹y7<+gao{f ׽I!*1\Q*LU?ݶ-nlfhHpjX bQ @I :rL~oyav5_bTHLKIJPҭ#l]/^ Lj0*9y 1"'= !N0fWʙ6qLq\#bbZTUJɰRZ`楧M0U"LhW*rg{7{=~X(osM(M??/%iUgi(a f(f/۹ sU5TO~f5fƄ8f4:R`6c&2MU(le wbt]s>k~7 311qU/ZKY/A0 ) "O6 7AUMKRGpV/vI_1_J3"qv z3az JN՜~yDT0@F..nj""?n > 6xFUUCCâ6f&}[o Y ?]tkRj{Uٕqne>iHZQw80*Z.;*b)Cl=qM Dvk3_~Óku2.lݓY.1C_&7C"0Cv?Ԙ GD(iajzvM?_M{8{YP~92;f"ɢc.X(bf8zpl:3UsQ ͧʹۮ7M`@xߟ;" Pf5;@j"EYTȅcL)ey\n֎aӅ-+Q뱊2S#lǽq5r(?xSS)#Z{DIy#Y$)s`HE3xA|'l\/*gJT<ˎQw'&>ۿ<E #")9"@F"D6ݧeiӔKҶ˛f,ke9]\ޒ0 ڭ}&,qJEQՓ(jz cf hoZm|9{ΚcpY0"DĻ=#!c,.H8}rtֽӂK8&3 3ݘ'TsX;."7sov5_N{~w+";I>ѦMZ u%/ЀdgrNUljx?5ݮukUA4yiy/j}ٷt$diMgjPVߎxOn`U$WAT x"8܊Mbu0`§_D7?4A,1p ,ujWMʩE)QU9(V ERu&¼iq2.h6ۯKwͪ? !(9TLJ)FRXm58XevARQ8˜Q"@t]s_^LOOO~??>8 3113E$:I^ 9TIL $U Ӽ!K_WXVϖs7PUЪXm7=lFU0Ee$f3S=gB&0JpL^n*^DZZt+UC>&>@4mUM 1\v{EHZD2lL8$En~"8J18"ENSoo~vȄh07Ʒ,hH hfS shDHmb*& EcNs^4*-~IG5//պ41{M"n ^Xo!YC#{Ϧ<9ѓ`W̕Ytepϙؿ0.wo=gLj0m۳o[&[fmπ;`,Hw1"8JT<oXDuDsU R%8ϙ ۮ{UëGkT'zf:"r^qnvdz[&nue4P148b`f* RF$\5qLS6ӱO4L.9["TWrH0ǔBe-%Q)!rD !1m:zNBhJ:Nғk_uޮL>0ft$ݴʹ1;"dulWάyDfHU5cn]#)-ad7_sӰ),(H$ҋ:g"D.1p>ԚTOb! ޜ]\uO<+MA0UˣqKEi?i*G@8ԦӚ rUD@hAD&+VyNcUhB Dd3|! FBޥTƤN]IhZHhVf2 <ьE]bu(r!#uWk{U_,~kk||owLfN%""'"SdHMn;QxLz\B8ݞ|vod|mU"h)m׶e6 IE Lr.*1DfVB_#L'"*B]“b<}k+>z;K>7ȜR:{~[@!HG3Y2ajbȮHQ5@("7ސP !8h\[ʺvMSGgA LǛG޺Uϐe DD$׏R+X5@0SXU<1eTCG 0Ԣ۟毻I5˗7Ϟ&Bp1~*Ǹ™j;/<}+pi38RLjH&EyGFD(wfͯS;L`/ m*MYӸrV]wUE^Tc_5A,(Bizal/zUR޼IsHlR!U8XbLr6iFzn@LR\ 4Od7a "n:U1DFjh D4fe23 8cl{D:\M'E$͈L0;Ͼy"6:E @VAQLĻRDʲ6L :U7]m,s"U`~oI5ŗOk-D(" wk5uTI C:B„ȍE'qIHE.oܾ*tZU}1=5!olHr1ya>[poy`fh&*"]ý3fRF}\I&m_b3#y1] V<\#2UwcR@D 3G`+)@>efS`@s0s`W* 3W8m?jm{ޮruݕ:ay.g400# "Uf QӢGz>Uؾ{]6u}vUl6+vl>y%= i[>D L L1>oiʤg+?ێ eۋNW!v]{<ߌ&\%DIf R*1" "9M;n;R35E 3d]8ݍ 0S1\(,1m;,gsiG) U5;cK)(9\7WI1<$ժBČt;dh г]!-%jywwIDATwrːLSVޛGgӺXׯM]^F d[lî;2XT2(@RD#:9h@U LQnMT~i ="kϿy.TM$q5QP- &dBDz;0d%<!C03@DJ4PhbjJ!)ԡtJmQ:ޟ_m\GDS/+DAUEkqF^Dv@bGTaݐE!es˶"LGRlFS?<_}ҁ}5?Hԫ޼Rk x!wLf& FL0Xgբ͛ 7 #ʫ@{R>K?<23sy>90w![7#tx_s/o?P< @ DBgBLpoLba]ǗD7WP ^ac|Lb=]6_e/0H!RCgW| \wI'圥r9RW޾]~?lEՙn:F3>Y]E\.ȘLwŮ!ӬaBTSXR*V1rWTEIUfjO1R&ll9@;"#0Y)*fs7d5 ]DŽ"bPO7WW_tDNLw "cOGK;_<PU̔Qu!o: "2&q5~(bU)Je* {~I5r/~[bau(9K?ME <B]MpM0qG[ёsLcS_O!kDPI0&QCԔ2I)heGQa2U>CJ[7ߺ&bWJ>1矵pijڏ9=,"=PsS@vOS2Ȫ@$aڎU>>9JgIPym`VJtr΍ٚڬBLCEhQs󔇒 N+*p!ˣKŔ*!8r-R ̞^i*6^b$ @7xqvhK-o=u/"1]Q\5S( ع^sʇK$LH4UcºjNsm/"Ιj(͛wn͗ˀwiCV4^:)ELR:ucyx{T-\]607D=a:C}|Qb6F7Rʘ-&aS.X\gҍi0"a*@F;-U3D,}烽:Uʛ7|{l`XbY6:Z9ǰj1&KRa4I@eRmsD_J"B\\G 7dpkV~lpʖ"`O:ڿ/-I]HaDpȩ@;Icm [hTM7=w済(55U:A˟88<~Oic- DcOCHf_2q9>ݍգ:O'ggӃsvѤq鬩0?86Ź䁈s "@JEcp[I66!UtU=}2#noCqxsz~7CUU )=Gē \\8 $tI4CfFTD-jL j8fU9iD^x7D招'o eE h{T"v}vppz&2Ua7cb3~u2 mZTj! ;coUypxE쒾`SFpEl>ՠ*LD'Ū4\m:Ds>O:aɷ_\KWz۴4&n{GfJsE".yȘ a ]+8L0B.l Ev3:b0f4`Fp_k<\1H9->Z!ڞ'5gq̌Hvv֧-"FmS-US {@j}:ǽo';7߾yT0ͬ\z8rJZ0Mlv:ځ4Ɗ.s7OSUL|`TIӋǫ]fӽ1/=Y"3@8i!s9x !Z.|2ouJ\n6Ic` c03x]IBpb@Q\m.=o M|yobۡ4\_'^ KӦSp] Cw27hh;&3@\539_cD\W7ַoy+O?.t^8F/άm_e;ev[QrgagCjr1DwjsjιJ ^ӈ7 e*җ2NIC" vYSdH"eoOs1kQd4/&U@“L -STե @ qbtvM@3ɢ"88k:ҴYp 淃8Pat#)ʥhy XŠ vR!AG%i8ICor?UzDٴ]mWЮ]{Vö7D !bHd;ܮO)w8#I 5_XLя?ofxB䂏#s:eUw4 ]S14YUŗr7SObIL)}Ͼ9v]J ,JnYMvcp.)j>l1DQSMTunf*<>7H7Z %cӸF4®XꖳHKIJy| XKk @w$w[Hfj`o޿u[uTUVK &$甊8X$ѻIX,.]jKqee?CN*L wשׁ ڽMMzxVYrNU'q<Η"9,g&ETQt8^u#j6SbfLVEUUi[?пwW+U7+ 5BPTv_4xٶ#3;g(&c;X*;TDD)0&*ucTv  g 0qI 5zLD9:׏/6D8}7:I.Օ z4 k}9pYعʹĎ@y9wov1#,D'Q|j9SXqRVыo><{Ë71U2vCpnv+?'c8a[?hQvZyRG_mm_@Qv`U]6(nڰ  'qHR<Ģt0}龽cݙd3u௶}< ];, ` u,c"D_g{9&Ѭr" Y]n~9g}~iė|)؄mE0pr&QT*qz30 ޅ:*]bTey64 q%Y z1 ֑sR㘦uB8[SOZR޻b;!8Ź*:C;rSnbc=DQUt1KśN=u|_4}sp~b;o~}tdz")RS`tLFϔJ@(FUj|G 7-8UUzO!*:Π͚|][9ByTU@$".xP˥<>_M@T ًU0\"B?*Pʢ%[QXx00C^΢Xvo/C :ęd3m');faw^`6;x*ciN妞WTv0k6UWy2FqRg_SR5e1D5o헏>֏{30*Ф,__bKPT3B151 V^P JQOjrv7(aՅ: ,'UFDF%,]E!L`IUrD[:i,Q׎ BaҼŔP]I,ں\TUPDo.>śu|ۈ1"U6{n jQWG竂*Vb5)`F ޛeQrƔTJ@ fn=/ ?O?p.2gM #d,ԏgf<Mbj<"xj̨if00q[w~@/h=l|T?񙻷nL<eӷnHf ܬjVc"DT(b6}Vn._nvWchE@q8X̼纙|ԓqOί8WBMͫ \^^!} LZ{'W{S5D4݋aߟO~0&yMm7vC{7}A=$Qܺ&]jfsu&"Z3VmXfY'WÐRS1;3B [~y;N/MH E 096Y{x1KYߒ>?s"{'cB5@n]xݗ" Uo.3!R趣e"IԘث0 ^]ld `@U[1Rb*ʦsu~ ?4poJv۟\Mg\"hZ   c Q,`T%JHsqG{v)Z`Fۂy3W>(O){.1fao.Ӵ@R]g_ ~w^ФKipD?@>=5ɔzIG1lTjorffyL KI@" Ed@\K={z)#/Ro>ȯ7?Tŝ=Q5s; sN۶ͦVezi&nrs]&I͊0mAMj2{ybRaeD3Ղ{6/QD .Wޜo犰'dQ!4rXq|pDӰy .n;\Lggu9?(TuR1DMYam9&JTӴ!Bf(2xÅ6gU"!ic=횁L 20fy}&32@5@Im U<"ϫ*骭EpVwu@y 2}:~ i+EإFwF"!-U[;B"3]L#2"3iS]Y ZݶzpE$+D}HEY^3Q`ٴHvnԎ@u{=iڇoo~͔xVEKػ*=zxc4pUph~~,H]؅Tp5ޑ}& 8!]z)'`VJbR8f*jbBHMo=&MVd0@QOnd"C Mwøm%IWm3i) ]SN"XTj;?D 6F4ɩYm:f,9 "hSGgyY>UD'D `j*֌b jfVs] lެ6R>QxRyw*jb*Q`LӺhW\}n8UY"1Q+7Mo{CmiG mO"[rfW 1Fef&8m489 ѩ GKi=8*`7?/C Wۈ .{XWT"#"Ð\|S;7_oI śZ2!Z+T1y"`d̆si>Q{鶥a}3sgST e!;h r/|k;·_8r8,@&@JF%UAEQt{ﳻV5o7cs|p6 EFF+17I޾ܕ‡SdeS~qv)zJELW]rQ3y0D\8>>6T0![%`?i]pE>Gg03G/a|W{QKuW*p`Wz(wؿxpo;O|(8 =0+"T-=>)a5!D4cv2#(gU#&F1Ws*VX_ƏK̛:%|}jZiėP5z]2謊iAaNrq~F$D$D91s ErY@@Eͳd: ]^OiDZOvz?6NȔdwRv) fd 39X4`(v=AQv,[8,VG%*@%I0TꊇbfAB$jl!Ղ;#맰iu.>VS Ce0լ0bi?q"Gxm`6g΅9 R:eoJuԬU֯Z "*2m_0x)+ـ"3OnWEGMV(+p~xarYZ֍50?߄ٹPJqLe'7e?&gQ" 9=~e_/_qa`: G$r1M'FښcaDmݭ UDʎ_Djwi_|ߞǫWo?c[y8dy8R$]>|]yu;<9oc}~a""2cA*)zeբŭvm@TU6DZa?SvO.wzP)kUI^Djswl9CNVKb 2zNnN\ D*_>lvC{AJaʧLra3q$LX V0T Dͱ\lGޱsD^̎Ӝ@t|ٕ_?8qܘukbT9bLo?n?|f&B1ժH=䫏ͣ'olxwr/| eGiIrQf"Twj*ePP "pxNsC~ެ "g`>y:#J.34$"jyzF !C?C ü0(3bw>ݫ'ySYZi~q;j p305M0hM*"hZqu'ǗDgsd8=Yt3cx>zEMӂZ.Z_-m&jRiʌTH/ c2ϙ Nɋ"^ ˔q02QUͪ:URpպa\HMR:z@^> z})PyT]P3Yt8eD\DKLf:ʹd5>:baY"!o$Z9uC]72%23&hkGuְnׅa^UCFVy= ޾={q#Z$Ŷ~ B☣Kdf*W~_ny6B䉜jED4#B< 3ѴBt&{8nA.33v1:+x{!mW]?^ZU{o@hjJ) EB4љ@O^)>wO׎X!^2;S5H͍C\ArR "qس?~y&ʛw\+盚|m5M0;xrtӼ7p̓ewD@L%0Dbj Yg !.er\b0NqĹs@(>o-ާ ̱hU,U~7AɺbYs-0DžvNlLC9ac)Z)24͹L }?"j<+H;'J囯NM(Ιbx"sD$r>x^wHhS*v^JR\€\Wew"j E IӔ x7Xq0I"Uc#(R3OkˮBqι7P\2RCn7!X N>iU7^\%DUb8=ܿy9O?[4mWU \s"0`]/Pit֙|=t^=̗I/_@3CĜ'"!Sy^l*p<:?_>='Onc jv\7Vx`J'@XD̴allDD=^tpjEw& pJJ([Ǩf5 !_/_~Atm٘v}ꧾr~Z,Rl2iFEd-b{9êThqCyv@vQ"#:3 "$K9hUlFtjs#D e|EZ|>4vޟ<9ê 195K+]="x.I*UXT~ bιTČ] 4xPןC?N2eXuaS-ϒ{@)[+(ǐJ,ɽuwU3?>#$ig3߶zogƹF6̄swoB)yi2RJIJ#2@K%cB7_v6dT17%z0=b񤫜)MklsƯ{.9;.x̠s5UvZz/nW:xj7Փ./5?~9=9"MS~u{d>]!4'p8vmz%0{31fIL|x6pӬ\xQ/jaM#_W8D8= 8Pkp4M_]1X$@Sxf ,9 o?iᇇۮ[{|@di뻱2aLERanM,}&R0`0@hӕYHBj?zOvE^Jh9=q|^/J1&d10@F4UB,Uʩr12uko&MEht !l]O#!qF\R(=>e8vׇIܢ\*OSf}L?MW-YRsEYvH_]ĚLUuCSG8]4;$ʻ]14+{_ͫf?6էNIK%ϑs9D?; lѨei> QDѶ&{OF'k?O8_ vyo&qK:"V̛/2g`Tq@80KnA3wk,u |6i}>: ?_%˻ϥyx*zvլB)3ĪZw5Ŧ}i|rpGO?w퍪vGQP`f<K:f.k^LhquDcuf<;"Rz.nwVݖ o=~+6qMf]) ]Č/}O> (79Y4gb=slLWwpaQ5E4g/wN#" ӑj96u5 14cfj6']0C=J~6񛯎?10 13` Nsd=]퓗-@*\8 R-i67ݼ0ELºs߶oh"JifƜsK+DD׈& z>NьW~cu Y^ugݡ\Q몬Sbs.a*|CO0 9UI91Ü@OH!ʫ.UPr z7ͺi.1*X6MA-)O3mտ_^p#bYwV.61RfDp,D9CSqL@SNٿ\LtLM \i9Ʈ s"^lGUTۏb]]8A.0%QD,fy7_>lSDN)xF5X /P@z$d0@b<aOW;-yO{ y~2'@NFmMSu8q~9u\>I}NRWa`x6;v+?9*2sĄDFs6GljmLUGVS" `Lg!"׏j&uHU,% >N3l pn7v~䝟"8SGU$fp.)!zηa&HuR C[m7 ˬR*DHx+ޱjA"=sgR+)fu{!njhfѻ~ MeM51ڪ&.TTm.:6&603z80* 2P0@Kjf}9jyT|tETmfY+@穀}CYU{9'XDl]ȥ&U?φ5ʔ*Ro9Mũ(% Rv cW~_^"t8ŦT"OmY(.X2 iV9L|e`D1(ÌMHрyAmL~3?:<δs < M?fDl]hfqnY]4h)kR1RtNh+8 VGn:Ъ )8wm⮇?'_v//' !j;'*/ ꈢ88İʦynVɼ{3toXs~_ aٓ'G|zw=߾>ǻۇ͜r0 .zPQT9(3-DŽ9o!@1aԎǀ9~]]͖!JڵM{*X5)ŬૻEJ,2Xb @01cx~4B{} wՃmZc=O2vpUmU[9$䱬" PJÊi>8v'RFBlݔDaLDMZ"Eʹщ.NRt>4DWÜc)鎢h)@)ɹ35ztn}q܏5b9بwv:s40sh>޽Z("^)"avQa4j>9]'ɥ h|{y7֌V}տzE O}O)[pb/zPs"5xJ* jo9mUژLNc2cS霍 EEb5rAeXGHٺwG=!y槗`"s'ğ_}_vΰD-b~cWdDv%6Be K63\PaBx3q)KWb)/7f_3G={|EfOLhͺibW(| /7qLcjavzUᨊ`R;ơ=LUQR)mn7k<K:^cLCFC}?}~}_nw भvcpSuf8^F܂>F n0K> 炎k@^PF,.fn;ܲ5C38J ڮ"oZ/ ϤoES1  3MSME@4,f0b]_sU`t0E$1 @ D*T|37m9T)O/վ6ܝ#s޹*/CDrW'wRB>ڇXDT-T1Ūj5e3Sa\v޾j*yS3p·P:E[3\w~ğ`Ջw_|تژn:80Uוkk0)_BD$D/s i3Ts6\r lW5'FEhXUU<0Qm:8S^g'ug3 !~C~___&.utjT$e,2͙U$ELXij]i!ڪU("0=ߟ]^]GeF5fO.i\o,K/]~޼U0̤$5Co@Q ,8%A+Y8v8OM5B (xwwyէj&% cn*cȹLs,^K;t99&TUTxҮF4T 1XP8ʦsMYwC'r;E=~m(:S1@њsL۽nSG$,(#\s>MHbRD`fjðq<"7g8 ;9i੩~8]CTG'}vJ_<< m5C*lv9xVU{|F}c;"1>9OwU؀Gnt㢃) c^pV˓{.Lsf^^IHyb1ɌNWi߇~b\7Ӕf8On9FDRRET˒Wg'Okh.]lc @hfT ɼRʔJY{yKA)`6p &MEǡS])=O?W~]>"ٱh &*1جœ1pu9rlR9>?=^^]=fƑzWIm1ˇ'o}9N<]wJnCTe j`χ8D }C)/nvmôjݓ g"#"\:F3409"Z>SN[=ISCB?aYCu쏲|·81tbpJE떈l'B|/EL.+̊Ö[;F"򪋸CPUۗ!IĄ%ELLRᚸ;B[x=JJs"[ 8:nW+Hfc+ʦЪڪT/)"BDf ^\.!uzL'`)r\'J UŬPw"""&rDDr>8HNUf}0a8 s.̎FQkM2#32}S@DK1Mk_GS:0V1to o|~gUlj SVf$"o픖 +413  bp4m7I F.4UYgU]k~⃯n6wM}~R9,1cP|}7ejL `Tt^=S[8uC<_4~; w 3`zIyucD9-?cڪ:5~>}]rѶcMyѻHi޹+5ZtD,ꓮvCH*LٝӔxq:9[@H󮭣#&2I0l$(FGUS=%VӾMUݔP5{͌ GD>ιQOj85+11,k(6w/ׇfZVmUcv?T q*!vr'`y+]JsBc׊ hG՜h/VD )/F^#bGv980㓲  MM Ԭ`ɾ7DdZc4%x|掣qՆ\J4qB?4O\qdϊ0;wqΰܔs0ɺLӔ/?? _vg{;竈=z<ֵ@)z? ̦FrOLSvG0#wq,jl&Dc q{^fu:w]p.dmHK߳~"Hs閈gǜRV5l߰զRZ $\~J۸X&rt(ꚨqsqqf2&;h?MsB@7'R)4a]^އLu3g7`EWcibTRDA50`6uvǥy7f.xfTU!|_MⲝE2lE7.́TRt#*:Q" o8'YB魳c33sqUy0Ω`n#Wŗ@ U{_"yLfU솟\fV,Tu?,)gZ.fi|^7M){oKwL$jG[nNC(DCB#0YB^_}ٵ럹_O ѱ#:&:ul±*(VJCᘧyWuS7mn18Mp C~umU!`Lwm8%U¥U])b*)3<#@UQU T\RԳjAläa:TƄUQ ])q6. Mm#nETz[G<>U}CPUUu) EtJ4gLmp}z9ٴWsw<:ojL9"$jZǃA8j`dz~RfY #SncdHƩ)/ڌEr>cU4"թ,XTեZ\s*JɯC5oD͇3<3S<9 T`{Qުhg4"kQ.F*:rj aOib^PNoz{cf*GRrϮlxʗSi!i s7K`(<9˔hL @*#@#I; HE\*̺j1`)/=饻Ո+sѦSZ299A XJ)kMU/^_)*:FTbبwmgZ#<(/9Qt\19g{hΞ|SwW\l9?{D.UU;eSm v^}tg[C3iĦu!P `d&O];REWW^sNǔ71nU "Y@koU ER8(IDo7p躮4EL )v+n0Q昒 ,s3#0 ̚Ÿ1bꏯ=!o~x⾛s!BQ,=f̮HeN\UmpjTmݔCϛU&$$"D5ʼd+!v 00nKF4/^|Y`&EΚۻSud@fa qL/j~;/Y)S\Lq[xQs2kONTzlz@̢^";A*LDK 9c첬ic΅ĕ !RK13xYhSK 0 0imR4}uw.ݞ^ÔҴ=9s9Z펏O?DN DDE",mY{MgBnxqڌSZHGgYv (Tz')dBPDWۓxZg4~&H"#C0cp1/3)eQQ}8]Cg_-8lX|뫀̡~3" 9[tJ0S"foNUhOV":q4g~2ۜJ8dY13;b ̄ݦ]}wQz s4].Ó[9Y!S>[e}KSaQqw賮RfGË[sp:74WK]T58 @ 9$*QxIqۑwAM @Dq(][aemUܵ])@f=TUvǼ>بwђc3*8e|X6* X ё|YU?zg\.Ozckzy'22|~;b6+i>Ms >{DbU]6sWPǙ(ʱ1ɜE0dJa&lXCcfeNe=ūZʊh8ζa8@%DRZK30͊ d:%% OD:_߽=HDI5#*"#nx\4qZ-w^f;fF @>,N*31D p M&V@TڏCxx2FIZDe;M2I{3~"\a:3`5>N6'n#̭Ti9پ1e5Cnl ryQ)) ==W8e]ig mZUvltζia,X4ͥ!R.BmT 13Zk/bjb@!_?;?e״/׾WgddcpmUx}~s_ߗ-x&rלv[dٞZ\S/4r)޹$ժO^k[ws*r{JM޼n}qnM=>م~HTqt0wb9Ɲ$*oQqѓsjo,""☃u!G֓]?>_?w{'!%0 zFIäDPWa GQ*w>}<<7^GgCniݞN(El_mnҧS; .%SORѶY;je!QS{bP, @3Yp?VJu~jǛ}jq}5FnraM|uVBƄSrD]{$d&U"bĹ4eÆFD临ոN|,<1WKʘ,j{}w,DFJ uMT"db9aFva -yj 93y>pXdVp`z&=9]ݞD@λR"pp?r8UEq:x_+i6 3zv, 3,U(xnFsrcbU{zOlwz|v0BIM猛Y Bޡ$"f@/ _G.k_>UYg`v uU[*v|`K7R ,OYSݮVH>L5>' {\"3b]x`nlzw=ިM}| qYe^Ǻ^1d  8KHedr)QŪvǩ Cj缪0MŤvv-?ku~\n.@?LwIJڦ) u$DRFE̶01-L)⧯R?w7uWTy>rkrm[vm]=y/nL&ތQD" BX Un :1]<λlIFUzrn[bC")3-+X0 C7͌8 İxW hxPj3v.݁TOc>\ʜlʾ\ERho. 50\YM٧B 4g!#8g3+'NJh3^8M,BUc6an}e: cO<#UCnG&0WrnYT-9w?/ڋwϜx 31Ѻk,Uf }H;*$z|x^VS baGmcB?=9/;OhAR_5):?} WFapŭWE(, q[VoV[?~|/^3W?Ooৎ]j"ʫ9Wi.NOMFϨ!.{: 1q9"rJ.g˦*/vUEe:""~)z$ N31BU1-Gp-e`x1X"3T>U\@ O@Gw{MWY`YW{q^e w$Om?ZfUnte˺|I# >lWtݨj.:3 DFð:ySRE$TƧWѫI3g s*.6U D_|~Gg5LjVY h30uJE`۹wINYx8ES~?ѻ?zJOn}w$59PRv .xPqH&rqwٱ;֭/9:DtNJ%|:3JWRKܽjiߋ^l(Y䤭J]5jHb]~vNg˗ˍrp~ܪcaafE9UsIn^ӳkȌX ȱbk+ВxodQa((tib2|n]LuԨ#ْqk39y2wίQ9"JsJqtQq,l@c 0xDة ,jt*Fr|y{uJe%/I"VxfBb3$|BM?LzuDŽs[*'"[QL%oZ,\ 0ULy@ƈ)ʍMӹ؀0=+%ۢbcyHo)T=crEL Q$9vGXu]8gz|1mN6~O\رanN8)9縈zqެ)͈.Bh]Ǚ}6~.q?_K/I[w4uEPWUx:g=zH8i$|\~W4o94ǒ)r]WDVMX"8iJ0>9uxx:q%i1QtMSzzvQ˳s qH1UˎO}vIo@#g_ɥ_SJ%Yw:C "GxS&Y}>=>[(k{՗}wUcm]eQ$//@p1N~7~Ͼ"p..>I9d-g\Q\#l*ao y)YU\diSfx~|rȝWyLaiq I`UQD)EyNƗ"r_TL9sXDTTS <nD&z؏NcNԵq΅ )( mڂFuާ"f֭;@5R)lT1pNډ0s.uj@ɪuѷSzsJj\e^@~O/ЏSulD, YI89Eɶ 0I0MI9-,aJ2i.L͟9=k?b} U'BU9UmH`И19GfVZWuWqk߆YaWY9ErDbpWm\>fLJQXr|#d{F\yr}wu0@)Tʜjs}"b`Sh!F27w'$"3uZ=:&z 4h.ޤ7ִ৿6?,amRHVt@1P,f]@ gw5Ք__QU{eͱuzj@^~5iNo]oX$1%3T"9ZEKQc8;w̑șA~ʼnt??;XuLN HIGXÿV"dUa&"~ŸNYrXpn ;G-ٔz08JECU*pd<%G(u4""JHULXJQ/0q."B\;"TA*b} EFU`ȥ,+l̠0qyɫDoӯ[op1?L$d5zOmMCUo4^ }qpuLQ͉ȡȮ~{wgPw+t ,GuU mW>o}o[tUMA:*SݍXIJe5wag 3#4uךه_L?zLpȧͶ͌ ~݈at`WY5L/9<ȶ9(|nug"T3j˳*O?0:Yջ#?cluP%9^VW#lZ^ g,G5{1&(0&;=chvPmxa2jSF0ILqԓ KR=X [suy5U oB.n?1PDRo}8_ P PQ0~",ms w06֏SUϜ|q}>~~OVTyBbD^ߙsHhG8֪@plDa2}ÊڗP3kO؂n*@A5!ĺ) "6M۽Dn *Q ;cpC;.3e݆ͪ"nPڦgf3ZF̀3B[l{5+u6+~&jPN`Jl܈Z21۴)&K080)@}uMy߮Cd]51Z]oLfDŢ|B+ڏ5!ވC"ODlN `F+ݏ "o,-F3ݝֽՐ*A(ʢ:ZAD*R8 $ADqka H9@/n+9k(ű7VΫ~\rOTwñhkblwM3!6)#Ld gvYKh4[?qAcv"LuHKla]fL3s]1gMyDjQ|BĘޢlE8T;F!~O7b11#*ϼy4 rv1ˤbPb?"F$i]x"ĞX[zjbG3j3 !) )0ff̄*9WEuϩ3 PHTռQV$iRoPcYe"e8Qk7JdvHPH@uq&g^L2WfRnHY* afAS Dݘu TdVSw/zF!߸{qϏ'O_alnD Ko}[#"L.I"""hIDAT)D)o1K{杷=B!yQ];l2wsQE]nH%Y[R;kB+Hd31FQșpnuޱ(9l;A`)bDMUa"c 7~xykS{6fŽ&%BUN5W3nLp!gn= ńWUR+X"}R 9&Cx&InW!S;C cM<`>(졳3ġ*K9W1FND,J` >!Cd O b'G3~zGor&tzpm b2Htl?1ca-$)iU$~"NA1D:k8Mi3ʐf N./7~w:oaӿ/rM[ʘ9W8o߮>|͓3iQ7*.wxꆍnИ( rY:_YCsr +c'ϖ3؊vrmDTg3C|E3Fގ= n᱑,9Ii!ݐrapEZCnu9qVn,t4G,͒ Z&a 8m*&6uHCTev 6 WME4;7cYfeۜnCXFkmDd:zTαq bҩK akV9Ft]7p&wкEHD!WPU5LM*x<ĜP";1Ed9+Q%#Ajz'"$eJqonA&"KۍS8iDIE6}b! ƛacDfQMYA`cJ 4or?wDyB.= ! XмL3Jv {kz iߺnݭ)^\ o })6N+ JMi"N;VUA҂:"qP ,n><gվk;S7od7ͼk WAUfBQW(gt|j[L40eqc` oZc͢sqhZ!acaS8Eq*l^oqN<;|bh@-;&աC dُ;\5sG1SUDf6_J~m^ wUQ$Y";ui!18D8ga1N1w2BbBqe ;D͖Ә<}ŗq۟.:Y J9Wouc,pB4(ܚI?Էjzj<L^^ܘV!v)'~ӳjcL=)KްA] h_o,f|=yb1©5Q E$)FaWkK^_lwe[oX*`8c6 *&1҇/jC˴$ J3Xީg˼gGPM$t'["Nƨ,o{CU AE2MnO2 6,5d+:?a#?S/9*=qf~iRzZR1jYPʹBQ*ܴ0.,2͎QU:R S {rrFg0QS~LYY4xS}|ۛ<8 eɉ'%~t V1`b s ,.Jp3>ʷ7~oZo󙳖c4_V$r)īFWR@;Fdc\kTLE2yk$XeLfw+%̩,hh|O/IJHm:urH}:d 8g Go?w^ AG/vrmV]D91[4^%'gIjPE=쩣 m`l`UVeaIJg)_!<lLI'z͢t0Ɍ k'~v(c:y^;IZRn?tUyؿuzz~(22CY~ux|]&D Ea5sHSֻ6[J rLcOs6CbY6;׎2&,!]c) ;OΒaZNtBB2!-D4$:5jkz D;?hcRkgƄI(& iq1єeߦf, R7eW-!J]!캛֎ȵPW0|K_S8<0?_!ƐrU Ϩ`fz95s:ot .c?!1툳㜵4 ;(q&jRpHVSĤ2 t}L 0ۡ{褻}qfeal .#)Պ+z+Zq yy &]ugS?txzg7|~4Tf 9kbQ3wWuLltP]33T%V0oGi3-OϟM[! W׆93fdaNvݘEXڲ0se4Mىd"&R$#,[CLE1&4k O}}d!"r%6,{4Br6\Pyʩa_Q$Ok¼wW7LtwAoLF!Bz^R՘ֆ)TχTUEtsp|t %HWw-#YQ:BYy^ѴAbĀ'UlW?>mםY3x̆!D}۹~a,*I|^S1eEӀd c;݀@U>gXwf1I1*ʬ (Z3`*o 7z4)xŕVb3iS2m75A'L C睈03I')ǐF0?ϛ]pvsi5]8إLMYcU3Yc*1$߼Rjm0?uVb˛ OOz\z]k dc!FԔ(Kra㐼dMʄhO/r`>K_~DO,??4ms֓E؇42{i-D r6NuՋ1f 탹=9|ӛ<7[!k2Lr},TUk\(#@&:BL@̆kvYRmenN=t-Ij9l]mđʰ+ Da Y#"M(1[U6ۍ9&,jTՙy8O9 {/AUQBƾ:s *0aYX$q$&"Xhú,.lb O&UFJqϯڻތšښqt,S)j?vѴ92Gem-wvLJZ¢fBƺ㦜N/y4n=hƦHcH@M(lZN˦*cHS{Jp0w``Er_^Eě1+; (3*ndPcMw'dV×[K0*2Ӧ2HGV͊ ",\;eyMc0/{Lb8: mW{4 YWMRn:iq)rU%~|p,8a0v kwYR {8kh[ 4 @H LK(&?ͤo7?5LG~;Ɲt.'” >sFlaDaZ;IUKoS1Bv1EZJ;ʍlf۪Ұ]LcJ0DRa(-:!ݛ_߯xѳMq_Mo զ# $nV/o  Ƙ@ҭؔGbt,|v<&1-,WIæmws gݰnjeN w$_.(͖ Eeښ t%!mXzXDTR̔B$ga $}XTOoOxܛo>?(I['C$3:K ɤ@T PD ;k+-"Eyͦh*eÛCDA0 g?Ƙej3t"&݀Qܺбt"!:{E2s{Ѷ=[,4tLTpHn 23cPL1{H5lv~7ų:^^ AŤ"*)Yc U1 np(.Vä2H8Fogo<O`g9gIY e]EAg( D#k`VŦ 9!||CthG$Z D !8(2veOK<)"r57eTEb 30;U K#0S?LJ9T l YVUۋW߸{r:t֘=H埬bIe Uer&$wgyvh&w_ԟmv< ^.Y:Ͷٕ Mso;]oNgE5Q&gU4fr:)(o5ejh9M[z͚wlӆ~4pJ1VdǢ}7YzhM~x;ň{o=%J,3SDl'% զbscGfb%VTZ,c哜W=M( ca+oqQXW.m@ OcHm?]7~9cC]4"-6/&\mmLSU!Ks'tIFELBl&gxp ([IN,cG9_Hz[V0|Q~^l&Hc&͌R6۾^wavgO&6Ȫ1)"dmoeFF0L2Ra&fј@AS=V%T>ZB1Q Ϛ4^IE') FnQ]yCˍLdZ1ÙXǻGm, bJkt_?G)S,[rpYZQM_\r1rF,v ƤG/,p~7]Ze CU5Z2V__֭\*vm;:_n)K6D&tB$)U*&D&͢Pz\_w~| /o6C bc+g (#Ӑ*X&^ûl+w||㏵=aw/~{OYVP)@1MtIf `z9}I34C nw;NvmlhI`dSg3Pؼޅ梲/ַۛ|هgm|j:cfT+Dz:CdXEXxd BL$UÃQBDC2ƌmZҶgq Y-hդ]=0ADB4)uc"&,JdRޙ\w/oabO;_bg$IQ8qv0cau5o,c{9qxxVqecf[_eMTUSD`FQ*9GGsWd' (\*nLG߸~I"]ƗMmS]tD^93\m">dSaxzY,2V!e)? 'էs;9.Oژ _YS0gUwK;x㾝4%GI e2RsJ5i(C̦>KRv߹m{k[Yc9si +ёp$k&L #,laPA1&0$G=Ո༳a>m-_K"Sʷ2LD)g"SsfD6qlK1j 7˩Sƛ+E;^~yI·8IL@D*7kՌpP-gfcFqpq=1c?tC _Ǫ4hY43ٜGpn1[kt)h *J˺vC:@*8bfۭ2T;Л{Xv1y(GuU~{v9~ϯ&W_ۍl8 S k1f29$#!jVg( uф\$7cU@bl(/PY3Z C@DE5NJF$mX5 %vc.8VQu%NCW鯨Fh*%f1V<<֬[twp1"$nw :on~=HǪ1mf݆ o zkWBeYՕݺUsy.,"fд 6Lf2waR#ݔ!.Ftz8T.0$*}(M.[||Z EB?/ &EMLYEKGS 4@5Up߬w|.$}]fjG'>Iv/cpyJԭ^\m)g*`S\2c`AfD7iLj_}^dqoڔ]sB\zdw@1j-C?B\L\BBBtH@7)7<52օ!ܶ眚|b9i]lim )CL9dI#6XfPG@c&W{ #m:Uc̱tŤ y22 rR19Gg}ۍдyg瑠4f2KoQۍp)CS.ITЅJ$"g9'* uu1 q@z#t)$[z&ޱ*(ffc b  fe &$ny|8m6ּ !BF7ɤ._nЏ:[uiZ.`t[TUmT1tm |;Y,ÿ_o?`RGfQ][ĬΑt5c*|cuIb1톘`VDsoGOZt,& XΖExL}hsƛkޘBzq-g,//&zZGTȰ*xƕ+t h󎉌1]p뮳$܍ 44u٥,H{=BPx#PR9VU֐6xE@'ӳA Xk0%) E~ lM0:? qWO .߸W7Zs\=e%1M{ `Q!Xψ$HT!fg]#s`D!0>~>ߎZ_jVlR~rkn=ݬϦ7Jt;ʕ1$/弒m7u鎪Y?)jxjefsTC{+sY4gA&q`}V!YrjLX8\FQPIA-V\nD8Ĵ=y3cQ\U$/jyBҔQ0ֽ>z 1f|9J1C_\Ic:@nf'1q ʋTӎM]~dQT*Ua [* 0QVTv@}ۥ,uAQqڣFCrJ壘hZetSg0$uT8C} &~5~OWOpd_QU|j2{GoWC0&Ao_ní.WDdya }"<&؝_}sD4oN!5aK'2_*sll2 ۶vz] U?<%y~=ů&%c !a1 ^ U@ᓝܽVРC\FYCTqO e5QEQ$T`t&vٛ@#dDpƈfZ&k᪰1w<~hn2d{w>3dB@(p[sn4TuAc˜lOGIM9=ϫbw Y߿r*ڜ1犨!š D*GD؉.cJC4ΤBU?\w)бw%#tb",ptƨs'oT͎YD! C59݌GU:CC.3%jlGu&AL2m\ׇk|!Dʢ@f1'B0b3ԥGM6DU͈MoOOO/;|)Ue1݀L8FvAp8W&cZB] _s0f"0#!ff&:N=b*}$I:`8۴aoU,Eaיy=n:C6FK_W.3yp>[=?YH57SUU0Ϟo'9rg!h9JV k < `.+S<5t`0(! Z) aܫp˘Z"q@cļ1^B8:Ma~(O?YoAؔHhs/ƴHCDdCL@0Tn!M]p7˭۴0)3"XK1Iɞ2KL .A)եI{k YM0(aS@ լ 4V~6mas5px~}vӪBF$))d9L`xag12QBܻV13bU]B>XL6:fS|q?5f}nC2iC"/D5[w?Kgk"eNd-:"1ä_Pc0qw islܕ[|읾'VUֈYdRYEӼ<Ɣh W*:WVŤ*iSc_X RAbRx 1Nn*L HdX&GV"Xx'33a>^4;sY9Mcz$eL5E$cd+c6v1&  "ΛIwNϻɶm2a= g-"lM?nr3@Po 91d'A>Mco6y[򤆃e=az莳.FW˜ gn3ԙúX~eq.Vŭʟ40Ɣj2ZoUu ̢{jNYZft;6L(R{l5&*YTq^"cTf%,l*xnw.RxZxڡ}O0P1ԗVEhr*(ָۈEJʔs= G`檾or;b\=0FP,aCsDh"z 1ܷΛbjƀ'6&gXӛsf 1:"˒  1 $& 8z["jML$"3'`}[a`HQ$..e? ]"($Ha!򢰽a̯"QL~PR17(hƔ5ǻrj׮|ӂ"ːI91ψAg (1EfܧDϭ1jPUc8}bg3IÅEʚ2 dU+]m8n6AJ]?Ԯ݌s"8̂Ζc 7'AKOCTKa\z@4M77/AQ5$CiקIY~o'agOv׋iT+#.E\ʙp^oھĆ@@Cd= f5>#{79& vDE* \?~o) ^9-9r^Mj+b'uӍmQvr?Vf6MJ@6P>*Zܬ/ w0IUA(ˑEOzCY<q 77>?/yoDS܋V}W SJ4( {;o]!#0vw:c"\u"f 'mWq׆oiSǧ/}9aRHI픃 B$twdž3!nv+gSvȝ— !u gE&&}[cM[9LTx- κ!Y3UC'`k6`N/E3LAi gmayz>u6lcJD`2EڶeJ7!x"@$"Jt"FU_wwcDy7gղ4]2.~~.09b8> )닳m 'ORHh|rsRewD2Scx[Zː^cs1\#欪*mLyO9?~v~!Du*^/1&ts7je9ޙ_lbH M4ZZFQ9"1 * "{)t?"TS΢k(1GUX'/tH?5?Rg~s~wuYK@X}ͦaFL=y\~D qk&' 6Vu`.$LCYLN\ۖCC/L J?,PIrBr)ψ,e}DKD#a. ?AdaHaRDT[g; @׫횦Qkv[>}W/lζ5bY5ޙd@e},"bD\7&%mp!(rYD@TafcمHO QsW\W{$9j:]L|0K稩.lpQN&^.f-96w9*L'-A)bKQ13$*FVpETqKe5C½w@UMei4&T2poǣ-fQҋ͸[sz"&tH j-\|DK ,HLy s-) չP4i~ ?[w~ȏ,>~LIHWׇUnw;%z Ό)iNbV@պ#Y "TuyuE?**NҠUD=bڔM}l kXkĶoc)`MStlEi󋗫gC%ƄN4*sFxqmSkkJRU0"* Ucnxe~Џ9ƨ0(b?Xm,J2e>Dt7oUš*J&F50ZњRU PyjU~Q hpz~+[b&f"hkUmSznOEbv(,1ːhLS1BFEf$"ghZY4 ('dP?h|]c2*c)v Nag2ՄVt?4ΗCLga>ZHi\4.[ĢB+*DEZ?"~}ntr$*bx nfGL o_U塱qM=Sv4,fjXmqX}?~|vq<ܴpYr˺Mu*'rnx餶c]QYSsZ7'~y @ #!ݿ!k!Mː8cl;v$ ~Dcލp{m * MSќ kY$eޛY;P#`H1e"E)I?Z"7*U3~_ٟ?g|h^Oh Ƹ`~00kqҀ \ PNwCʘRRUq8d="a?XD  SB[4β8K);&5g[ۤkx..ISܿ`/kƠ]]`/KpnN$Ɯ3BtKRuz另H3U11CU/xa(Zk1XXF A<Χl.91h2{NΧ=E΄)gB4).}?g<%wQSD& # SOf:$Y?~c??ᄏ~Ԏ!<,ѻi]/:1Y ~-0#\槫?;n.=)gW~N&\svӅjZt1̧ zԥ,|1)ٶ"kseʓ0 .g5iFl I! )0AڵmU6眜*$f{@֘=90IАM(6oo`RN *:0xˋ|q=s@V- D@z H, 0YXkTQRT %$Uq. "5~(2E]"Y&:X<:8xp}slրt~q^${, Qoow /_՛zmtӮo ))Os7SO_cJiblv:,=Z:uiC.8@b8ҭ!TUJ@Y2dQʢCV)# hLlٍ1gD!5&"O_+aE3Lu#g! U C$o7WL]}񽻪g~crFo5u]D4d?Ksӎcv1G>(|D,Q5v>$'PM*Yn'Ͼ[Yksz{p3hDp+`AghH JJDKw"vZfT#?_&v0z;\Mw?^\o.?Tݤ\njo (ݧ ƸX{hbĸeSvo7 n+DR5S&`޸̺ ̾:C/oeDI f 7pk)əMyR.Lzh4zY,{'u?6BGt MEP6S!o~OCƐܵ[-/wxyO.oM+6sg/;C AXc7$&]4hxhJ*L ۯ-x1gCJ39fLӜ) ;l,Ya7i@1"8œUi՟drDHB68P8JXޞ,[@lLcH!uwg?~Ǥa:k!69OQlrWL|T3qs>-[):rR4޹i׏kR]1˛^"f'Rw=Y < m Dxg&gHl ucC17T+Wӆ>`A%*ADs { 5c8Chx)b0B ]5U K*kjbcʰyYm[k+9 gcUbZ""5"$ЂE4ͪcwOϼdwrt?{X;khKc=#S4ijŜU]k&IΔpEUDH`L K Q9&qT.h1͢GzZB!I<[nwY ;/2(PΚs^m0{t@0<=0%cMr?y:mۯ_^nV8ʙZĨPqDiƨF K¿ K=klt2/bN'Yc>=~|uqzݿW7ϭg7RDqat"wt9;vοr?]jugMYTqΰ zQP7@ ꘔ 9+a+=5{f´YnTIc~Ժec$L!1RHDbb#{ɑX H`LNb9jVTrFֺeȹ^w_?a+}<-DVHH&\x-MUx[1QZs,7oi;lo%=[㭹w7hק]\YtYmw <kfb1*O|~baUY~ϫݣP!D!f]~wO~RDՙcH™|D ߠW-w1iF$wguXoZpܚ[/ "wO)!!VHyVøgcֲlr{wG/n~}{HY.zyҏ7c 3qLݤ4. jV!lq,#Bl:iT%1̖hЏihа^{ CLpn o1x<\,mU9qf-ZCՌ?3 y"Qbz9~l? x,YnZSOdZ_]^r$wwBn0um74ͮ뮬]LPL\SK*;G IٺrsڑH.4AUm 1›w/A64c`:7@RYSn2&Y]y7uDr!9,q3ͨګ@9r#dc}8wAoRh!3 #alJiS C,[ܽtea,sM6m~pBcr1x)xgo 7~`2  Fd89|܄톊XsMyA*3Yq= 3+OcC篻1󫉵NUH'|0mpc=}QD .97ϭ9LsTA1!dCVڜ_u}f9kUĽLH](u7"5q1w{1L+@1IK_ΦMcM?m [ڮ +oEk L|`߷*gSݽm{Z\]L0nFQ1t&2~jw3fWRC,KgRSW=)zxԇw.K~-6.T}>jvxM9>201F$7|ۄRUyolcȽ5u k7)?'rU=slw!"RZTIat9ؔC(*" !MeCd#NQ_VeGʲo,8)4|AXОw"qvqFzLTȪYh:bY<4vr`3\ [Y ![ӳZc@Uz+F@"F$%c|q}G4=dަ^9.U7t,@Lɽ1ڂ)298L0x𵋛1 !-D$ŶI.}YTvUń_żlj01]7ZRV>BB<@<"a>DPa78@4DJ)1WcXUz{қYfZ-pzQ0ӯ]=yƃ\?Q|ʧO?OqMH׫Ջ9o8|<(C 1T i:nshv9Dg qTEOiH3LTBz%Cīws._(jHtmSnc1ې/?|<ֻg5DiP$-懫!@JUKݗo*3,];k˱ˠ89_)w 0͈\ּu]\ښ2k n{IP E H!fCDA{w`M'MJ gv{ 4^]C[WŸtݜD : gb1py}<q?|,>۟wvayѐ;]Uet*㹐%B]ߵWM;b ḑB"goQ+DH!޽]5~hz,ݘUqܓxqc5ݠXeumgoڜ2>mKk(c nT"m6(Pߍ(su)(Qg:P(RrFhT@tHF$y!HF3.?O,'SJr$vcf"H{r')|2$'mrHƘJTa ei!?-|7"3a% 2!iLĖi\lXxnaafD hJW8oE/jVU1n 9ې$HiAcv1(?%*xͽ8:>Ϧs |ٱ[UYl'G7i>wǜ|61|%`/9Konvy0Oݻ>y*b 51G"TբZhett-kBsmqCUa|2|~O1ȒA" c_p8ӪI Y̺AkQ,۝Dpv&EgO.T.ePc1Qy)dQȢ(_lirTP5Zvj^1; ym?f&` #!cQavBb!`N{UѬ6DV~~jus7UMtL0 (vCn!q@X!\?3X/?{~Q4ĕ1 Spݣ?7fY쳱AZ'rBxiTݎ9EmB2lUIg=EUOn8E;kՓ7eQTeg0ܿ{ö,qW)–pbck>ufm -! ]qRuC8TQUwU9Kn0䔬1V7՝rfV`B(={_zj*r圧U\*adQ&4L9mE Yj6nREp(R1q%[gMUC>d` 1 U5#0A(rNYOsV )*|[L.{޻0P>Kl8w{|؜6Mmc4{o㮻%\m; Oŏ"(uYjfӣ;_\\,*c`Ϟ.=Z8kr܆0=3x3c7j 7~RY&q\qH 3!!$} r`E !qUn ۃ9o*c)!21$21@VMY@o|g1 XJ<` PUPP@ޚ8^?" 0>4Hnf:;Yd MTxCY#wXЍuzo*'! ~:D&oPψὐZL dM3+C8[Lw5%8}?ߔΟv^QlXW s"d4JQ5(ƘP A0bLD41.qlEYr !`JūTIۭSUBآ1 NjrE^?^ OACTW<Ļ9_!*!ǜ q\hRjITpY` 5)'$c101*#& "TQB`I5{'L7k;;"L%fi D \хpK5^_'(u7[LsחuW @G_>\Jcv{|=xx GG}rU~C ԥr6@4[e9mAWU{ż\mcWz>ӓ_'o|)EAZG@ArK<C8*9Dyx$6vq9FiBG DƲ1gDf&1g kD˨,"S @cr} Q=" fcJ Č},S"a5DX.FZ9+T)UUoXD49q1) )2Ɏ(~5"f.ޯOygKLTAcVˤJ9w#0m Qj ;kNwI-"" P9 !t!mUW 0qcܡ9d8>hmʠ:Q,Q5 :, A=)a|yv/~y9,HJ" c #~DDV$[Z%[k]JJ|JBvy1TFLj,uXMv]7]!D@5fȂMYׯDXcgTI' U퐺Qw xúA4"SMX !vQOTfRAӫI+ljMDɗ@IUDzeDdxϘ" 1/?::>E?߫˦0d2ƶ۶dK)-f }3e H%] CduKӃ܏/+D* ZW$M11Ha#iM#1(Ŕ0D~򅢠LB ĽG3s{y+1q\!RYUSnH=}-}~?1Ew4FOb"t8LFE bv0{4HxmV!HSV)M9ג}(y&x[J,aj Zck{ΚY-u擥pvC^_b7N:Ym ?;<4È6W/HcUMBdxo{f" M$D>c&M#JRr^=y>=<m"l阬ErC$,P#lEwJ "„!RU&]C!ja1gѐv%Nw0Yg_շ-=8k1L9hh\H@#MmwMIc̅I٠"Y( [3"BD-e"oZԚ2bն̏T1;6fC7lm'@`p4aWmZ惣9` "v<k!TuI`?;D݃f8}a9~!0loβm'{wN Ʈ0:PR.YET) bu+\ 93˘txf>pr>|3ܶK0kQ8uȔ ŒD#|l'e,BQ(iA3UEBZnCU IƔyhlp&bdbJ -@]tL((!7VA9EJ0f>B ?-1+?Ɯ7-Oh eN1r.neYk5jy7V2L@}=ʖCn{ "vfަLX8]bcؤ SK?D@DUg@)3̅j V@T܏=d!GCS}˻;~ѻy?Wj\w?h0lb ڍdwAu+UCUx=jPu޺qÿ4]{-;.}N D67=/<@zktrXK {E2ZFQ];ZJDv)e`oۮc,ތ1%UØilI4hH(θqv7q1lE_O_"|0`]6,̦]U^AEl0W~є0{ 9'] jMveBQ54KfK:lj.|N)o>$I/JBJLnmH741>i= ?w<<;/^1:NS|Nd)F-I9oDRνs<XCvY]xvzg[_'OE݇ÓR7 _z(sHQ%ʻI!eö"bì k@cd˝a,fw`c"v7*LH QSF Vq"ZZ?$(4MS9P &^g 1y]$MK 3cݛ30(nNU)DZ&RETc!nq\Yk^ɬk[[|wgQ7GGc,V{Ԧj@sRq789n.~uJ0,04qrLݻsh}>Y/~c<>z>'~Wa W%3)KF(hs"#:>Dg}Ϋy 7xKte)13cF}` ^]] cBn1f2v;k I}xyrf1~aks>z}qܟ{~lX4j>nWo>/ p8YY[+IeQ3 #QdʆuURVghZsU@&R`D)dtYU#A9Ȥ?V݊ ;V`UCʰ/]຾B!esPR8Ԛ Pn?2fgg#2GD&3MwC]`N,t=z49>>>9~xpv?IZK^J䴁Ѹyc_Uk,ԋơ;ͷ/(,ȸ7Duܮqu2[ΞäAjw*7=:oۛ_&v,m9vSZ;7w?KٕUeZݥ^=;z[n3?)bzg0l2@vvP5+d1%B,XڎPƸc1bm}|p\$#ǜ֋" 3dMa; aPSɰ(y_OKLdwEs)22E,-Jfvo5#U.و)A`Lc ɂD9w|r֘&^یH0 ChIL{mx9*ަ}|$ZjSӣ<0ph&S٫ٙu?ߺ=_LEr> ,r4795#n&{c '>:@|Hpsui(P*sO>wvŋj޻o_.Ȥ #RX31U=c Ch?4eˬW˛po.J9BVUSGDLE"" y6dxmM(꺍Yr VXqMvq krd(mUR~{' ?mSUYmhGiΗq:;)\r6uUY)L&1{ォ!MzO標-ylOe݌~/U݄a̦L)/ӫIu>O'ON|mhjnv?50SZ/nOxyۃc޷!j޼݃d~ciHܟӃq9bV41ԕlL*H- )&# VRFB5޶Y9&˦ J]p7iN1)˴%䲬s 5n}x"1c$oڬ)IU C{+G: c_(&kA2XkeoCOQrU Һt~ArF(W@FHMǘ0+*B?괞vFƂnRDM7dMU 3ھ1}DTY#N(2c L,(NBg:]z?>ٛ9߮äzN5l;D4)Tꆑ_];@D:>,~UsK0lbLlvnnV>=v)K׏|!@11EIS#vZ.q]:TUN L8[4h71D@H/Ngu4Ap8Q- #TNw!8ﺶ~1kDdѼ rVf&Ĕ*-C*=$9cʘj0O^mQy罫Dw!DkD4DWu=)ޒ*annn.7|v>eJL9!zLإc@PW}AҺMLҎƫڜEd"$zj2ݻ~l#29h?oő5_o|UҦ5Wpz<{**.Dڶuyo`ҏ/_o>h匶"ƐR1bVӦQUUDv_!D\ʙRI2&o.rLl W% ǔ0eQĘ)޺woY!`Ʊp(8[ @L8q%ь@d ɣwYkOmfR#(̧uLEtuFP>,LDUL0 % %#y֎e;&hb ޫa3ҳYJkDK"&,ӊH@C#ZN"Ҋ Q$b&䑼H|3" n:[w?p~^%Hu['c}+:Rü7?`߹;C.2sܼIm7oa )Ru477;WzTiZsNScezv:,}an$byX87 BD,1Lk[P՘2602K]_];ܬ,Sg>1K2e.mTМQw *aDpW_nssQ-DuU,RUS6Rn2`Vwöpã{U:MٛLno/q|՗s aRRmq(&kMNDn^u}UQ]+$qθWo|MPy\|~by d9ۿ鏾wM?mpXcbk/>n_6D*r gøUeDR iZƘKKb=>x3F *Qڱַ)*uAv2ܴ¼pO^mNݍ rJ͎G"e#wFFPEd~CVD QA51g)#!QUu7[&-RDU]nVWv z9^LH䬀PuCZHjbjM`ҚH@]Uf=c_^L]\vUYΈ*ݘUIœy$4fE[kL0y5Dbis *W倫EX"8YKu*`|"0ժJ"X\HN>#z[8]dܟ#胐BJS6.ö,uW c)P1.ksJ|AG{ϯ&{lzsud`w_>z?)Z0@'ˡy}ݟ~9<֥۴Xe.Y*W޺CH̜s !"X8l;M(@2!&MϧkUsuNE? jṷ> .f#8Rwt !`cd]Ue$Ó{1/?㱽A(c$I X~y>.jJBK`Fͪ9I?K6[SXSa1ALӦ[9ޢR!N]ll1{Y_5ߎZ!z5xCN҄ck(7pB+ fɝ53kqw-$CDT,# 6e38k :TcM-\D1<UYH6稢"iY]7_;!SUJBDzvS!751om6Κm7(2R Bc8 "Y@/Wnocr1pbڶb7Q4WElqݧ 'Guk 0eֻj%98, }k;Od׵cX/&I@CɀFD!D/'D,@&dfLfʬڱ `{T`IڡͱD;7땈lׯ}¤JPI31e0D⌉vOi޿P dg=fĎ v( #i2(hquRYFStcʶ=+l,,IckP$"vתRfYĺ`$+9㕵 l/ƴ,ZRS$Z攻`rCK0{="t.yͱT5hx/Btg0 S_a B5|J)}yvlٳfG賛j@SvO1a9fQDJYUHʐn:?+&e];aucr|% 1$DT,;k"4Dlu],Ƌ50؁v k9eeB#".%\xi2nR c1 {b9[!RYv> Y=$NI~>{*)spprt4dpV}y|x(iH90NjBŝ,#ԫNWw??O=q:[7ݮIHo,UlsR"9fE1fQ_T ',7yڸucicgpo1DEޚ tU5&l8٤,1EgH%(ެH,'3ՈHQbg`:%O~Y-H5Le:5oƱ Wֆ! eH_tYԦן="0L/bz2=8~?Ac 1rYs2NR#"_}1;=-n?jT@8f5mv%-WД8t[*ʌd d$&&a^&dx0\ # 1 Ir YXQ!ڟv:|֌cXLGl\NiZeDTEKk[&O^], ]0֓B%vyvr>А Ԋh_QAK,v}`6sUU:η M&7"D(]_>gl(w+&6~˯<<ۯ^IBQsJ\Lc[7{w qWD=gWJ9qƝUǾGfIOt:#9el֫0mwM ǀu$&k'"[.0`y}k+7moMEqVj+ԔQ'U6?R WX$(7\U˔Ew>&9`xlGdɤO_l(1Yc&1L(a&cꪢpUͅqDks&ٴ蜉=Wѯ bR, 35q#'ER Q_];M[CYace&h1Ɛu9e{氹% uzK]ffEBb!6&۶0ۡ2ڶ;oo$¾B?WrZt ;kpWź{*\߼LO@@rf6 jCj}1[@Fwy_eHz8R=yޮ7CTCj6e-2xN^O(1%"btRڌ` daE:>ծ)/gw#@n{!$$&];|WI` Oggҍ$JDX8;'Ճ@$(_nMWm1-))DY&%ח'wa 53֎*g=9-RχWoHOHҲ뫆 )*L\T3f_WeʛEwnٗϿ|ӗ?miۺq4 !&_ ȅ7LDRF܈*(3]NCc8CMBXv}^ϔgӹ֚l?x L$C̆4.#jqQ΀wd 5"bL o;IYW-5Pz7'5%[DZD #10>pQjM霪Ԕ8CHD7K)}dޱVMq(8ˆəd ,Y~*_?y`;6L! 3Q.$Rfݱj*LSZ#(h_DgS&7=MQr*v`ߖMnсūaWMU"̄؛5z[6Ѹb^m^dq{{#m;|lw\p;`ˊ(Z" #tzB QSƛM]b9SiִĸPĪj Ȅ1FYbۏua 5TcFDg 3llav$Ҙ= 1&qCXrj^r}u#jbvh]𤮊j~yqkiSMBUQ"Z&֢-:  ՘f۫eg84$*9v"ReSdU]ce~ŀvҵ|: tNBMd/'̈ +57,~IUb] @YtZ!Ieq49;Orr'5dmΡ,[_7?0v>DLR`Ѽ֓SCe?+zA$yaC,T[bDIUUߺSl:`gwcdD%N1sLDc6@΢ik;ODB3)K(g0 4Čs*3gY9L@rYز,ndB5 mOn׫wHT .-"gӲ`"4f ͓z}]u(f>cP(S^߽Z."DO֓҆__Ԅ*ͭp׹\,&zyy5)MmkUb{F˴ۆ[â41;k2L°ܮֻ=~? Ua_%ԋ BNYR6D\xT*5lBTzel{uڛIlS{w8mo!d1)'BN-b}tx0O úcZ3,`ADfq+4brNa 0tHUazL+io+o X%M+,Xz6o_]>lU-őO>ik˔@ onGo[-7¬pvy3=n0j)D4Dw0z?yr)Q݂DM q#D) *"oMo:U,zHM?&kPwȢ 3yײ)$Mʐd2YĔTfӿDS̥ǔac wctci^w@Rz ѫ:0L!"UUĜ GDX;Cc{Y !zèIdD10 xˠѰ:ވ{%HJ PL0:7';شX~ݎi!a|\d !Koݿs%yp͛ Bg[}6?nVOWkBlX acg7];PU$L;"dAV!$F` ԋRZvz>-1sPyFĜ2Nh,;MݙJrluɳ'l*_93'nbu}߉3ރi*;#X9ݠ5ǰv@h-Od Weqt|of& օGyv{^,GD*ӗ9(N9Ϯv_$O^!ﴩeEUjǨ &a{t{#>#")fm>7rQy7kLb +EɆ!!ĔIDCj;04dUaDsbd!"R^HYDTaaՐT1%Hb?b22{͠I@TT8{)-t.+7`ـT(PׇDҶBdBF Hj 2LL9h>' }y{^~jǏ`)+L1 Jߨ$"")"8<$ _c fw~볘:ZbUIl'/_G 8~}l'MaR д( !nZ{iTCz>)"4U&n h_߀3m)DFc0e@ ҨGVN gV\S81$$rSzD fSJ&{PB׷v{o-ޮϟ9 Җ9 Q;ݬ)v8@Hv6IaTU2вX*KM?'I!qii_\mz/t_BYdiG:|(yژg7ԟwGC$×g}fyt731a%.XQ𖇁i#d Jx2ó p(!Zc;!ڶk3ƞ<:M) hAG\M%ROiJjK zޘO?GDV|Ȥ!חD5oZɊdhȋxĈdK)Mlnj(1joL;9zͯIqϪ_ =}φN9/>]ެ.uzGp!"Z&)7Mn"̼st2QJ1W .`7-EXUpyiR5MB AcP1$$L~&J ?=j7FD, , Tu !Ypi MYA1 gvݢPE"jjluFPU&4 PL9J!e&6!X8LipaRw,,0FeUD?ՋuD{SctoOwLUM?xu]?zu.8k wlY ZV^mO_~W8RZ:t2k8Kn&%L{YbUJ0i)W~m?pyp:9ٛ3t,!Dkһyv)ecpV2V!DfN кI|R.f{u5\Lvobg3*oq8n.׭32h1.}Xv15ssLaR9bSr;EU!-&h )7՞jY{~KJso󋳣W7Hf[cIo=tSUUC_1=/ǟKϫ浾tx2Z;'{cwGB5K "ҮlYTE%} ,!BLAuCxv4P{w`}m9;TM0BYU1.rBB&S+d29L>D)/^c;cߛg=>8)PhHPGOƲ~HL,M3=˸r=!38eE1aP@&ZKDL9m/)IbML5雛unxc~RȤ1YT7kHY $ZR( bʪa q>8gnM=,A1U$e۶7' 90aN/TdJ3P^?wwvuVU) vmyz3;E>ELQ ,yS]ZcsDlf֝w( WL&UNqI]Xj%.Xz͜%gn/Ȝ(dULYr(TA&}SmiMu2l m*Ø9D$@B ĬD ʻw{.ͬ'ѽ❻py~t9N޴ny6l:w1k#k ,|Yp>;"DnJ*'{rH^zC d2m \RL"<|}a,_(pf~( |'m-PE$[0 ޽w}P?z$|φq~\Z7;[U%||PIC4D:f;(E$LȈY% UR͈YdAycHY6Ӣr뭊F(l7`6/ |;e5a:;wӏ1cMq]C kWT{)@(`y¶^jW›/Q|ܴYC,˪4" O1D;Wkn> ! 0 "iHޱ1 cL bc&S!m*&U!B%oB(y۴1DH 3QSOf8"j"hJ)ޮ?</a3m(AԮ;QB!5 .?bEk\H9pNg]f{'W߉Mn7O}ZtZ& =yyv7wogqcomDȫrqJJJ׿iˢwtӯ?}vFUPSQr6t 1lKkI2!^\~ƛ۔Z_ӡ?! 6 ۜs ҫ׷?߾^3Ux}8gۛ+XȤ{dz~y_?Njĭ'8kCiYj+UP7GL:BN/moש@QY9k<3 . lk Y52#r4EvVDUIE UtB eQxUTu8&Fo-#H!"[+Y 3s2Đsprsn);,e Ob0ԅaD0L2+֠nsäŖ0bg~Sos hn7|XWbR96.ed6!z!!"9gUUC9tR5TsgW؇eK!܎u ଙ4pAwʹ߽4Ԛ௼k>Mm-!*>od>4C\>^7 zk1wC1ܲ X;Y,7 ڔEbT$ZIU5'8mJ5O w*X@,!B&kn?חmYvN6džq]2(DHcH-F7EB" 9ԃjnhXP>3+u햙-3#^bךs}bƗW@Vr.SÓr#B;;Y%6M[(xC]9͂䈲jf│5 ,庚 Lk6̗όF<ŵ=W!_|ѱ? HGo~8~cf']9zp[\Y[//_g˺z~K8xqZm")qC"e&cDMq}TC$` y\ilU0X,w\v\3v=> ]\}[x&^E!?vXC8{xHc( Go>HqTA L_ӱUuȲi1ocٯo0Z60@Y;BQf:1RDz"1B0 Qb@c @. Y+tջOy)c@ 10219ICVlHDW?' gDÌhNN)l5<9M]7jCrYi }ЋW٬GeOp8" gcY!,ft<[_|ճ$~<)m/v_Z]s}۝Vzh/U VuZttݐYURBF֎ia쫲zu`*'ӔnHލTs] (mdzUƹKkOD͛Gu,")jCl{ƘΟV딆\d8!dotރEƺQ1 YA eg Sn͸2 ա Xkm]KyJ  ~\]?-ow˗~cb cuP]&cBFfэ'hvtr:ωqzk7Ce9>{uU!ӏP!#dD#fPUnED&=q(<"g bc܄W4!e0ϷVD/.oNrƒyYg96?9p 2WNfO>Koe&캴މ3yݲ)=eɳ*Ko.=1Ḳ&x g@%X):笓j@TB\n!ef:N}x EybS )EU5F uޔeg!U%$P,fɪTq>Ct{k^$A NuιwK0%Q   oU?dDL&[ESWEf)'vN,c SBcXيQӆkⴎLzuqx-{tC Τ~oԜx2@g cJEVpx0O)ge7gWϞϝ,w8vF7llg><;:;ngDEn Ckz Řٚ3"Y q\"b4qH:uQ[ "KIbo=9i3-ڦj&LL):=}t+dSI]NO"q3"zT^Ngnȉ(@!ˆ%&m"TQsNmèfV?ꮿ_dzR,Nz24;9{wJB$)+本u|_b/[D3B5@Jԇ} RdZ,J4i8#m&#f׆ZQ0ݯ"~]QE4 b! U)ٰgh uU7&}4zЇnsq*&n:J;=;cg>O9BbRӉ.PV_mv7+Ƥ&~~0Y]I b춭m"(#Y 7cDWeCրj$MRpsws[u=_vU]fW~'Z0@Aq׭ JDU b_~v}>H Pž;~〝e"0:zZ9$yrNgc`4 F 1 /Guٗ.!dgڳl$e9"fGK9 CА6x!F":Yh MYn 1),(C$fVE.}ybUHITC?}ˆE) 9,&$iR] P1 ̤XSBס!+y>:b̫UJS8儘Cwwm,MH[@lڃ>a7Ey:>?z6PWqXVjirN2 uY(m'utzۛ懻jRq.ͯ-n}y}5iDѴ ݵ92weWMsDچj\h3_. 7Z7!"$}xfE %{| t(Hy$(("tSuTV|t8zq}/>_< )eg5(en{"Xkoo) Oc쪝=O6qiƂS4d|8 Y:54Ll. % !cl×n]藟w.Mm|ty=,?l[6Nͫt񋗫3?XޔonWAUvΚ,BBkqkty۲@3e1WSy\=.l>q9wd+5F U`RfTјLYr[.ݴ~@%%b$IllleQm hbR ];}JGÐNcϞmwCv&vTQ̶& x`bn$w=J*4]_za!q& wZxC?Ҩ)l2SEfR-@wv0b͇rݤhDL9  Y3Y~ݿ?(B$1Cdc`]lx6cJlAҧ!P.o.q4Ӄb>v ӫ`:jQӣ&%!!"T`^"*ڣ'G0%7u-%_>_ h 1jT(t4H,?X-wȓ{k"ݮkһM͇LFg7&ֻP1,RA%c,@&.ERHh ƌն8W+7 /o?O6g*nM퐷]&յA h]= ɇz4yU VEּ,q, +q{rr0m;ly߭ڜI Au9jE^lsøʖ_o E2's}g.[ b*H-ݾz^U݋1s懫b~ua{yg۵ v~:nWĄeq܅{UHY$b{di#";v MYv  !F CĞ=R9"aT0dCL.=9{Ǧ)1a-Y^~ `wmrp:;' mNIPc&ù\xSz29{*cE#vn!@aG\dEƻ M"*8#X)6ǣ)!fQgdќ.}LdxQRՔ%_3A/'O?R@$8 XFUHt8]"JoAs1Ƙ~H1iD5 9K]5Ϊ^!MG%"JPpY2ɹ#zS2x~QV!)#lFU'"pC\ joSq9dAu6VKc$9Yk&;oa uA$?<_ץTխRt}@CL F;+.n6;klSU]hU oGlZ<>:zcd|>nf 7b΀a "SxOfLfS`h7?WN$KO1Ɗı>8qEp9\Uv>)~O&sM#"l9sfTf9;$C_'^~E꓃1ψzAU+ ] zm[|_|6s75 fAq ֳZEݺG8f&TհIى1Fcj"ўK"@(1'i6G -ЊBkw9q|g?__5Wn"] $T895Tz*{ 5퍵*L7!k*`e,{*A9*x^N (f:\8'$FK؏P֖f]rքb 1zx)vH }m/XU*9!8RUb֐Ytׇ*29#SQʮ$kx!Xmxu֤b:l_\}NOع:e];Tg06q֢ƹ H0>A"c+Rg ꉁ/!5~IL>xv O TϿk86 c|1*q[6UQBv("YA0# 3>}PFd v}/0li@dNR,#f(9==SҷڴծЌx<7b{j89|'y(D(v7B`҅IL/Ȟ$ս D !FuIQo9ٸH9nuB8o>>J YU}fV})i LS1iHI 7!@dV$o8^\/ώC&$X+ hB2}Cv?ҔPu4ZDY$=<, Z8 Þh8kIJڀ_wiCb`hoe\Z$;k{Yt_9pz@Q!VRmv_ϗ;1jHRԉ3l5li:*cW]" ٺ|Ү+ˢ՜Lw F%ϻss123<;?-]2i1 @MCc wah`f`5,|]c֘}PQIQ(=2QUhCͦٿyTm*CamZڨң)"^^,6"Q]6m|Ѵ>|`dxP:trrh<~w{A9KO~G?ui@l:|xBHj֯vw>D7 =7uZ_x-ti@d1#Z.۟| ҞI~\άVd(cg?Ĺ`oeL!TE1QE26A09Q˦jg Bkک3S.Džxz0}hN5! YjE16\ޔzgs4 4І D !HMU" `~pvZojB? $)b'$g m @.{ka4 TT8O@dPrf7t)#"{*YXS{?Ew8YpD&fBӹ cnbL `z뛮׌MJ҂BJ]k_O1zXvf ֩!D& @L*BlbJư"=en)<#|,MkZlڜnS~;&_.b+CHf2VrEYj K"r= iU@%-Sl3*,u`,~7FB]CHϦLilF[Mf'// kLj70^iZ5f>6%^3 1Ia׉(sYzr0NB$窏iyo?;_ȏO|tC%0f8 L&'!vT~?oW߭fOMX=ޯӐ\]. c m{:|G󋻟!!q7ƈf[sڮs~-\GQTnG+6WYb#r1ADgfhW@r?$\^^ݬ* zeg63ZkPGwCi }f50LMw朆d>9á58\ H7C@CVhڡ. K"aH1-NOi݇Ξ0b̙˗EUwOp4D[/:c0o$j&@bL̼+wu,JJ*5L~{<ڔ0zkVo`RhVyo>-ۋOyyVth5O7Yޮ|,*/X̦^=o情.f$$96ş^vϛ5XZhi[D޼]]m򳗯(҄h;P?;?{9L'YHkː;&_ߵ.&@EұB2 vdZ.ΒSr51g\.Ӷ*"305(PUZHXe "+Bv(@{D#$` Lm‰h]p@Tf)avݰ۶!,)G֐5Ѽv S5wesz#IPDq6!}G~2L 0̧rUDT!eX5.KT(` yG}$UdDr[HSFv23*D !1c` @bn_b7 0dAf#jqPPBYskBݶWBao>jE AsĶmJ)$b#4,}") k}p2yqiɋ?8><ʂ ONOuuc w~t8p9JkͿ۵g/~k˪t> )®n3 *l()d Q)$ݵ )PݦP6g"N^}<R6SBbTϞoG|6F$rvq/ۘvw}5  oݱJD(nu|l2kck$dwpi5B?\N7Q3jnp>~YwM2aFt8)Blv?dmam(\.]ݯcUєJ_uwg鳋W} !v_|!7D؅dLNC WG%',]t6J'QM*G֘~hg6㦹8!R\gT}J b&*Eք]`nAE!DD9fp)e td ncB:@XCխw3lޗY`WMYwFDc֘,|Aщ*Q^Yq?d}ow UK)~MQʙiGPѬ)! YIC¦ec /!(d} 6: Eh0 vbU6r/~kZ:) q,!2S! ;Yv b?QU P: &60s)Lj,]*=m"%Ecm9;8 DDDG3?}pq !]b,X0ڃ캓~-TӦh'!oqvvvO?10ÐXà¨ӑXwzTix~u4I|ڍ]s8ayew kmICm`WbY6-T6M}LWi x *j[lwDEH<*U)^tBX{̏=dԴTbKfSbr2OR#) ;</ݮyVTrY4Ů/^ɟ4aӈu}?!@j:v)l5r}I7CK)"yj窜v՞oVfGۮBeUnVrre뻻7Nea!'0AG.7?JR1k~V)ΜUDg)u4uVXrXĖ!QZ@ǖdPDwxJLPe "xn4mD)%k9%Rޏa2%)|q|r2/31<:G3Γ JFbYnQv)Ǩj& !=iCCDc [cZ U1]B LE+'m/wn[K7$H2ײ&T9HFB{?4f{#xoذ"5bMeAְ3!g=5(,63DxkXs !,T^ib*@.lw,qz̛?C>7ϟs2Wh2m!"pǵO)W8RQ]I8)zk&:kF?oǜ]eq]g vMׇ8.m?r'0y -^UMiݠ5YlFaƃ$B#CŸ~bu7Icۇ@* [6Xژ/Vy;TML1eXnBw6g"jͶ#UHq &DM1lZM)Mk_cכrB i9<}2dZw#QZh7hs~\Q- gMUpkj9h1ƒd֕x4:BWa(` .]xz􍐆aXZ{$YgGuh`R|ryth2q]N ߾YE:?FC(6YBΣP!DČ(DQ }?F{GJ̢ļ7|׮Dըf$wp lX|u{`Ҕǘ5trXTʂ!Ǡ@@Ȓ NEuqn9 ZkjX0PJ?[wH "JCLRhYUʅEЩ棙\ޢ Ę,R95Eֻ>f|/:>dfRX1)%k caDkfz!=|m+8Ӆ,b ;Q<91u; 1 n S浆O]sێ魩GլvQ 5dۿwNn/zaJa;Lh]]ΆhƻA$GuEoCV(X[URK:ȮAۋWmarnr4K}d ƌb6?Uxgf% .8^jݭsU=1{w]&qGcE׺?dv%2\&!'ggq0 )NcwnyY֯߄ێ"™ry[mTyLlʦ dͯj\$ٚظnG5dID7V?*7%'ys<ݬ5"G]ӤdBrFaE m!uQblb_H8K6+D-jXc&Q1aG'ǪjؤGUv!ea_@Q!W w] WΝe D:?_qnU 4BHSpdDms дRLꃎ+3Dh0>0 3eD! _O)"2C-|r+; 30 ~@cK37m!Kν /otՠw2-^1jBQzKv(Ew]P6]$DgI#61@"h-&%Bg4 |~у'o?|R|vĖYM/Ww;`ZAoFTtw?f ]Hݴ]wE_^ǫқg,r3l[״r|8[5`n h;"CbL9dvmb:fq~<. &J|æ=dMgrXf͍E8W ؜qaCCUMJm /.E]IicgG 8:Ly={i_v +4p8Ğڣ  Y3+6 ٪M q,zkqʤvitT{wOTTUQU0?3Bt?{r75!2!VnIYqgmfY(d d9r#wu"2ERH9c MFSg!DP,/?źBͻB 3Mv_BW4鮣No{T2dC L ` C΢V""!ņ!=8>" [))iIAPOW˺ȥ0⋫N1NӃE>xmQMɌkS;F@8rPBd9@Oy=2>Q3n-HPzDh>6Oݬ֜wa\ZRc^d/kKf8 ۻoo]/գpA_8jl^۟}7>_:騹 /h:*:ݎ߹6fޯj]W_ޚ1?;tخ6'!$e<ڡȭ\㺰 )&` x}aw/MNv``6yqb~|J+bﻘv=r?<gID$z]଼'jk1FyHJ7kznjk1֚.}[UEDBA7y!$'R̪}uΐ쓓ErrTa=Xƕ-ϝt|6uF2=<+fu:O ,7ObYV ҟ3OTse6"`ل'uyv4:>(?7,WϬ 3 J-9KWS`3rvMYU!1gqY0I jQ>SS骉("!IJ03v!6ݲ ;e>ONr e0 Ƥn~kXnQ'+DuIEEuâ,UEP&XmTV# )"# y|&_/&3տC2Ք !F#8 CvR{Dg揧Lݐ[\Y5[c )%ռ`eM7EEQ{]hvuἓQe#L_-w۫kL~{{ØBA6|yYھ]:_a==<˃1cq/gs)/o} '/nkfA#fcx>~z~ώgO+_o闗MGEӥp2LJL$)cU 1#Uv.knSj oms.T]]hZY΅/Ő0]cl*z:nY_ˋkkn^Teϗ"!%I[C&U o IؘW~@QMB8gmm9N{æ+s fq0! ckY PXF BJRJ~SpKt\^x?7⭧xrs~rSz[ggyCd6Ī>{tg~i]Uxr Ц'"_A4H$"Px'lgD-`r(dDHI>I*.HE86ea뒽qYYA`5E$,*NsxZYZո,tyYBjX[R)#W…Y/Q@qeFژrJ `߈H!ec8  Ǯk{ׁ~CmU 3!>* eAb_EҒ1@C C ^/zDms!ΊZbM>[45ӯs1[møSIfc3-Nz7.e]<<:+OK玴ߥwRqMZ>KXPBK]'.r+Ee嶕jZ}C]EkI!C;.iXhNAqY HBTN+4Y驪݋v'_wEʲjj:޿uj Jxc}U~.VېV<]us~"8_$"23hV"HzqHb1`oCk!=bfc\h8|vf@ܯaŽ!evK9V@T 9g rI `X>3z ̼m[B(EdM 0c.$ޞ?+]?'8opcw]c Cy<||.Q6\uMAݯQvֱ1){^9Gf޿'-uykWYjrv$$x0kTeVY 1)Q)CL9gD)52bPTLd5y?BgIAUAD3!jFd@0Yȩ! /ӑrP, ߮vLh hʱLl39D@D`ƸZUQ ;爈ι!Ƙ~JA L ipΪ *r(X:jνb9zy]''X}ٛ%/_ܤ1U=;P=Ibgsm&UԂ )jP[d}ASֿ].`e^݄a;%鮋l*VCP圙9l =;@DEXU1e DѰTZD,$"8:C[5^\+)RV˸in%ã;.pBȈHF$"̼[k췦 vcDDUrHHv)Jޤ Fbma@ )#dQèJ30Bu9\/髋˦#jӜ,W>%}R՜c˫{Ѕ7k1Doj<&ᨩ8C'maq\F 5Ѩуwr d2Y7Cʣ,#C#"9"}q!Ώd "B"ݧ;Ad!~[KV9eD2 15^[ Q >(dBVpUfzz2&ڔU$LF%QD@YL,W[VMJCHPU!1!+@KYZbS݂֐=L'/$cP0YFaRQӮ몲6tx0_,]U%ÓۛK+Z" mO5Lasg`K!ΓPIB_, o&!Cpy6R~-WE&ȹ%D&@T"92ui%JU e1HyY -9R:$2zvy+9՗,qhB>tMK-nػ-"ԫ(TfۆV6fl"̾~4M)Z Dh D6¾zTʻ.c n`0SY֘"),#J:s6eY eDcquTeMap7N ~u)g)߭oy #jn_~.`O>V3(^?^ܽq{qs2!? /n^=PUk Y2 I>WWsԜ4FJ%81W˯N-èW[.V>$g3Jٔ([EhEg($ATNȸ2kB2 9˄krcab1+<⠪lFe]o 'CHݸN) tz)QVf9" U*Ó~vF`W8807~/eTZcD%("L4=[F!&!1>Z @Qxu;EeiAPrfdԇOWFaY ]DžMF=}ov\vW?|~3[]^znE>| őfm1@64쮾ϬjܯQM)1~٪ꬌn(-Emw؂wc~peAc|,w0CŸ.^e~"ʈ/sIٔIUl'I¦Ui! i}=؜Ӯu-8 q<nSjg k;ca2YDDʣy~.%0Y v*aPQasYr#DN%$@֖$p3[ƘZ≪dFlvDZzEHRx b]vSco@cDOˬ*LC.KK˛a+K^ԿpqDZ.x<2b\?zՋOAU `˂M.6CO)jL4 GB츸m-A*|]j$·nlhVrמXd*HL{ )InSαH[:o=:_5A]DllS"F"@M'q}uבPn:oH%DU׮6̓:jR^$F&Ԑ:c, iB*0,ɹÌ֘iacy<*H]@4D<|U)wLXxKY5 >N˻arrH~:RW$4527;M"gp&R4u®>{6;Y]lǏ|Яc YYƛ\Os@\\]CnGoa{E z"W햤-uPXkCa )GraBN}Ckx3 wYN ~Qz:C<|*=kxY1{,{oßD,—{RQ"Vi$P#U)js@]{_^(e<@Yb=rM"6Ü~46]VEa\(_TETYU}`avDPHv,"`E@TE@FJGs v젮&O~Ѧt0/JBxuώ8G'Oe>?j`8!h'Ͽz/_7OUS,+îEY#??5ūr:=:In\dT<<1Hm6e@h,!9C!R@8*( :'Fs,Zt'UŘ5e2,ˌ|ZcD-C!JJPzAG1WtڦO/nUd:7MKhB4eZ$0&b?vb@ M}=[Oٟ**|\mY5Qj fB(= ƚ.3+Pu8[gHT X 9K]УWx[0wn3bs4`?}3R8"wSG|,9kw.0 ?{/?W>'< 8W`~z4{] aL/NHw۬X>;%va J/Z7ļσZSFU:(`H o9[nIlSa$,i&kjQTcAĄ0_r7_vuʒR #X7x.o57RaYA!%!k f4g&lBm}rD%_oGf-y40lʺ,^IDAT C!ҨvPk'qm|ZHNI}`ͨu֤L9Q&^v-OCU߶q2FÉeYv%˻v<~д}H~a⾚Mvw}usq}3uy0.'G F&U ֌%gfw["7\Q҇ū'GG~趥g1翆ׁaRXٴBn݇3B2 @0Ad%cfR@tTj2SvVJQ eeYe)`>3;>uiHnbJD9ggM?[_k-O<9AumhRpΒaDD&CU`fx~<|.^,KöQۡӨrTF]DP>%fTxTFTD{<|1 P߶͸Ĕ-|&M1śaW|wvuG0E1?8<|p_攢wsNbzôF%knZs֘MVͷw920nWشn>);;Uʕ< b5[n]*X?ÐI1_ɝniק{r݋X|ꘐdwmH!c "sPDab!5^Ù}I)p<WTҟtaW;1Z-] =[r <a0LhuhƼ* 3!f@vbaK,ٙ1!TIҹG㲨|l<;g8?8v~k=tXh>0$@9۾uOԥ;=|YmwmZ,ZkI^U,ߖEl[\ P-9)NeyY0>wC6FY1\N u (i1*e FŒ mOǥFd`Ƭ *sR Q5{h}CDWr%[)ޒmaHpj, u'o_4rNWMU 9DH f-v-[۠\Px LN(v C'>[1(!bQ L><ѷҾ];;-?=) !ĶJi]i6ż?^FU~kH!Q֊{c}lۜRj/j*>캔wѵ1T ) u9L)~۔ktU YUM)V۞ёuy\7="NG歓ɼ\,,ٮȡ]<,ϯ/>%Yt/vզ֝؟}!G3Hk^JW8 1Gql [cK֚;DT%W!9`LO'w_]nf"jA!?]⭌+S8,"!k. dZkavCg 5(0;m0y2Mey%F!ݼ-}\1<|kV7OsEY (H, @Lb bqJCC9 a_Zv @py7\u zqVAUcPUpé<}_eyTھeQuzWm.dTDHHBo?9A^#^'ض cҘ^{ [`l8cf`rf0,jR C{5d _^n_L>bBD3h /lX[6fJ׍T5;wۧoێ*%cUxQ%iUYإg }r*x]E_ݝϽGkyvL]/Ş=(nF4J@ t+6ƨjLCL&2upՅ;XR5}L>f~+kM"eB0^hQ~[p @%: ,iTAttT"%].sQԳq,du"v.b30 )QA1i.v;ּ=;+0L?7mV˦V@B?*s?h;Ĕ{똔  %XQ0lHUG_?SNlhYLDe1rP$I`1kmIz}\) :<cóab}hd)xj;o'cniXB佷hvhZϦ˛pSJ`?qziH5qM2Y{d|֛w &5*sEsV;onqR`lcLT:duZ0{唅5tϚ0O^-Čީjr8$e"gQrAEsUc޴2$ѥ"`!M;LHlrATBRML{0(uSbPYTd)2 !xgXgǿlwCU㴆3-ε}y_,wn8U!1 o]|f<+ȻoOu " >>&ŋnrŗx᛻mYl*"OMEȉ>x` ZTD՘ :B,'!>xQPu=Nn`Ç<:~8Dzo/L; V. 9<*0UFNGŪcCaR@%]5a?)ø:2nߕ$VɰbѵWaĥ]7x孇ɊOºqUQ4ݒPc"ReGZZ(,ٺ gn>{r0ڻWfXi>`P1[xkm)&,)msLT)3*%_uiC Efs]H~Ko!DQ"rm-!,GX0-!wީx4˺4*D?~7zd "f' ղr AfYWyIOnR]H!BYV}תaJ2 UA"|wT };DS@PHG?ŰMio~!B7]m򒝥f5/ٵ\6DY ĄCH \v1yKue6a*BiIbl꒳Xf 1ˆNATu@m(uuRYD$W.%գ?OS. XoweYt]4LVݺ9_]/ˢfch{`K7`lH:AU}:8Sv޹Qϯ֧ p.=?jۦqOߖkiEDcvm6;xx H61c]Mr\.v grzMi]`vm~3+LAml%S_Hְm.}2 8Vk}7~?1N8ƭ\uka2"nf\*a"DBK$NU!01;W !'#@\hGաwD@LpvUв(ܸ>,97N`4oqeK'=3yHth׻WW~sv~|sov|#bu߲>lι?}5,M(((IM p?yS% dEX%[R($-Ȫbխ۝{3ߥ 76\s~?\!B>Pۗ>xU>M"v=\/˜rR"!":㲫Wh)fHpq&X*j"&@)cˋm,;::We?y^)جoB@\xP)uXn զҮ >̰dƅ>Sjda"vM8Ώ طۖ2Kz_:&F"41 )0&;+!Ȉ@^h2L̑)γ(B1>1*/'=(?~gf%" ER(Ra )+y<_QǓ{ 3KuyPC٪P6Uc^,iE)IѨpYL9P;~+" 0֛k͞_4`hFbzRfdnh1F@C;NzzU}6:0ڶ_ kl{bfmX9ݤĪve0Q$Bӭ׍~H[MfP)Ȍ\'ݐ WϯZ̩""LJ { [ 0JY?ͮȊ @DYdAZm]/w(&`0Dv1 g֔ dQ bEPqXh}ӊH',S%1 s)AZ"RD4}sM JCH1 "`kREӾ p 8tg,чy|o Ui}Uj8.~F)FzdmnO.o b]BC|J #ףON W*N' 1ŴyA !M QXv\*qN!!C IU Qyq~|g7[m8!iwч/*z.&Y~90 $!"=蕊A$t<5"fNEV {E%$N>b gGN l(x1i^'>xo{"(@GӲ1&7 |U=s]fkR_5ڌTfGhrق4Cr}0ݠ`6kۂEv-;wg[ !H ڮr!ȩ*zv~2j-EV}˧ö<{fm괺aںgm oBvwѺ(F{'n'lv[u xs$Q;w?{t=zjvg`ځw[NJ+p&jOeߛZ?@v۶D,Ҁ,%] tVB-)Ču" 3NQ@ǔy,]@) DmuuϔjTUW7T=__}gXpYOb[W~໋ƴq\RSC5" $3Cgh|c]vz4nv׃Cwʥ)Xhsn->3O&D$h1"xB$ rGB>~AfBL iUwbEE DC2j/`) )q7D8A3+CgV2@$&1%3O+C}Zk̕62)ZZQC3bb{G\{7{K2@FJY>,]Cҋ|YT LqSߜz1h;%DRM OU&S"+n\4Wd#_'mwYQQ9;6RU;B̬&n\Ǥ*jWGD f"Qӧ왎@$웫Q~ "sV!:A QClB!ƩKUp_^_U:tJSJ(]RMF.T1c-7!t0Pz:rMF4=ulaRhO$`V_0A^Z.’bf˂Ad,xh/T$kN)-i%jPjVA@"a "07Zi8LB$wX*~dV2ch,; )&øte%"M 0D DtE}R[Ak! "7m9On7Yv*%CdTFVHz ,¶"Tܲ$g4 s)lCa䴭W˼jc}G)er1r#R6&!Rx4ᶧ,tb8AݲVP&LD} Խ5<%N1cնWk{9S5,$Kkiύ:Zg2Ҩ<*+g"'9lϏ4UY9bwxȏgQa~sv|o2͜%TD9K={eh 3kĮTl^]^=wʹW7v>}孍l1X$ @Q|lwSTR@?0\ɸ  КrGVariH)f4wee|w.N|H~쫈![mHa4| >!-J1!N*TJrZ0HH IRK:Dd폦x+ᤕΕyF슑$]c4:M֑~>]m>hq>lQ4]fu/ rğ=gg#™ 8T!x"*DgmH*%QD "hwH"ƃ2C 4 @;" YJ !>Ħ˴ xPFX|Hn3_ HFDIlղle&̢s!!5 b-!bM١T;me)?|OͺKIR4H1! tֶzBI&/6Xgt>!ET89,fD HXv"f?YLbRo?[W7Rt0"p?qW7``qNuϯ۟}|Wхm n^\Z^#BۃRjZ]eZ*@ZĊ{kiEuWYҤQG 27$iv7FJY"gs2Y3Eh23X3\lDI /:CH#oMbALGIcvw ˇ]_Y%a \-\$1 "Qk}gQSV2V|/^_/Nho)AǶ]ZKv~+`:e6;?]$flgms=;yl}4̙Y޹ȋ17h~n[ncL,R8D-׻yk_o˶ uoxy]?-BhZ9KaǕe48K* " k,( oJq0pK  f=D2 O #zY`>4$NJ)m.ͨHN'cD+ hFbMSd(%_IQ{ V>$CSgd2B}Ј Ms0F9vV3n08jL,HkACbf4>Y|Hk|L!& vX;m}1Wu=|` `BBHZ+$`j$%# WBmvcև'ROowzɦol^eM4>rf)1qD,3eY# pM4(lWx\C;%-&:v뵤b׭&0;Ox}{;߶~*E{\ou "LPZeŋn3Mɸtt & N5ULW}} ȇ98>p!sQnڃ0 H:sV+H JaqDpq[#!Z])X mofcLJt"f~qMJFŠUSLo~I1ws901*U0!$ksN)$Q$jᓙYni5_d0+ (b$PUU}]NP!-76gCJ&˺[$B[%BJQJPpGR_00)$NJx :Ƅu [5*7=dtQW72+cg| M 4TݫCR@tu )xfNffWwyGw2/ll\uSzXqa"VS3ToYdCH;̌RΝx>XBR ՙR]HR4dR"MNXDb IRE'>uI#cH$#YyM '\Qf*NjzT];GGn[mQY?滏;g4J1Ke , dP(&D&q7A,/.n:2,99=ƥk6˓و*FnF#YwM?7m&HŜ} ujdU*QiqV'|d'!R&\+mL(&@Z̊}=j>on.WmoVv,)@+z!Dn" YYkL5If#,D@Hqf3o$RGIE̒|"5Q2 bRC]8$mg?ֿb:{}zLJnEhd, `Lb5]CYoǥFنiA$(V_oOOc{4zc3!l3WX;.hTtc~OƳq?Dh>WYݭ=Ew/fd~~¹{2\k)5}'1fT6QQtrĩ^IgcjͿ;Qnnn(n ӳgOgխ.swjNN" |cm|!YCD@C!&8 h(=YP$"jc]t'雦Ѹ|}{}hi"Z*s:h|s[&6B:$)5nQ6̉DRzP($P$1Hb=hzD@LMLh$fB ֝f7xTğCLG]}sa(VgFVo8s$k ՞zkͶNeĴU8}"3>IgQ7\$WwbD$ Z9"feY~={ZN+jcL)w]$?d2k.%z}b5M{3x$|+,'Go=+콻ݫ0jc܉pJһN/z膶OG͛]<++cfJI07W8!b/ !B7DS?DN~iE9H8k@)- DHȇnQ7JbgucЊ{U.HJd6u9}0Dtw^]Xdp`A-Yf*1`IDE}@΂݅ ȭ=FL?gq@Q|{޳̈EFf&TEI10 ZF9k;(\i T_. L \'tH2VIg/_ΚyVîCq:l&nER4F1"N1(ˬ>VC^aC݄{8A7/GouZv~W^}3QR_o YdVQ>$Du⨪}3ܹs׸Zg< h4qMU6}UMLLxuw}Bд1MLEfErD*s@HI(EQZiFYlWU|2P||ORVR̊<3֌vHB)Fi#h*23ה(rv)Jm,Ƶm|v: =Ɔ0nL?WÔ6mWwݲ,߾]Mrkg&z6= 1}8%i:1s|8a#ġ{]}=t{k3 zE`9vvu==pG]1v}Vʹ샷._<|xAj./nϡ i|\uqN)Ȝ!I$äR }9.:A@Ik )!r@Adcd$@&dpk5aj]9D$@1Z՝ϝD$jY*@HL1%|qc,"Pw, i9$CP1˟s'1o l4B;-jZRbr8&13"L*;0@J!pc x<ݿY׷náXDjpFjZ|w?~vq0rg'QCȇ0 jja`NQ~@$o(OJcg53v4DՆ!ӫMy"ӓaxE !,CYwB݈Qײ?hBO|ޛ,W1IBkuq2]}ҊӼ}PUY*2&ir7$fkBVv=g#J@!嵶6S$)00* {@+iL!`Y_~yW*N&ըF])YmPDDDH8حwqjaS5n_ΧW8,&O&~|,&-oWmB\Z߷z.0*MJhXy<Q5iE1< `}g"]#Ej\m{=|ղyqzp<ԫg6uW7_,fY c!|ErfoVNV\Pf` pVMLLh<[ɇ"Čj"|[$;3lh-JCf- ".ǔaZv^S2 2@:PvIcEȭw{bN`qm AjJ aRBR2Dg }_kK?)Z+,tϮp߂5j>Vq/{ۓKaIhXT]qH)]K }Q1sRiu yzZ]) ox|3:&>V޻?7r.[d_ә~:7ƬvtX1{S$-0ˡtqB‰R YF*&o4]ֈ|(VFjB^Q  b^Ed )v|6[C̒gz\ RjGgHT;ٽ 齇Ydw [ﶫ̧Gj2|ŝ_xο*~/QRBEG!k,; mwώSU颪̳g"JSaO7MMP~c{˕o|'Mq "lY1>;И_.ƀt!Ѓ:FPPAD3 'DHTB0Z߬Uy/>!($cz~;d^(ZD0+t*G4 ^5IS2]$m{]UL)- " e]Sc5 /(IbnV4 ӉݷĔbC@cھrf$io O'cP1KCCaeP`4F{B(BZ)Y2&xVhFd5ir\ P}Yn6up쒔 YMd"(܏Dd5 }gn.h}l p'ϲUúծȜ:buxuEbwwy gp q"3Bd#01Gh.D$^= Lp!9w=WWVY[eMB/ OLHFc5fK+ŢFeC *鐄@]ɸ&r|YP"TL7+I`VBgsPzWckT7"D k}Ym}Ow/.on,sfLʶ]Hv<16/uH~0ٱVѼ?`#H)H2;zpѝ{/=WOFIǀaBWdvc rDPޭwcN4;*d[eGhoq[՛mn6ߍ)Bm_tB ЦʼD`DHQ[W(f{gp˛v:R,<;HA,X >އ2D:$fBXdz&*/2≠̀t|rP%ᦏW+^C*LGhd.$D˒ȉb>Xc6%C |.L/'1x1au\2 0`<<|z?xiDud2},q^b2)q emewe(C"blZVs}Yxu(!*geUkM̩qp:m#7MfoaI_wNf_RD}Ƿ 2!}̠Vms dѴof1 :BIjMUZ--:6){TL7>L6A~Vɒm7LGٙ7k!fNkClAQh=AGѷ^mCu| #BcsD}H^FSھ|1{)MڢUL6ˢ^ad!,3`}s`@1^']ń,]ݺ޳Rl^rơێr" Ya1>n=4<4jh,]h(1hŅHYov_zHfɍjf|vfQN?.bJ1"XP*&aoVp}?:29A>IvIe Y An~QV"rP]!{/ I8);Dщ%w1u}7~]&A}_b""+H6ZD֝b[7>e#( Ekx1a~ z\)E۴@&2[Z |OO[Y0,oL7`F$eᚶ'RF+Y !H2.J$MMͺ!-#3GAS5rl,ҧoͦGR"0t\GWZC4p23)p=*Ʃn1F/֯ͦF50~߈I)a$ hwSEY Co=z^7?Yo= mvhH$fP &C[(MvFj۟lImKOwy2*ڮH<;>5r?,Ɣ^anO,4~Q2vˢtVdf|I5 ̍"tF'߾|\J-Ѥo׳E< X,"$FD+ y~ƴuUVpxğh],<2BL/(8Ӹ. mLP>tO- HopVV$ jC~DAĘhPFdO \&S"KNt3 u2 %F.\S!}0&Ӳ7ލJqqh4_(w|[}Ǚ}xxp4c@RȂӪKCwAg~_SrtOޤ^es:) +;aןyKqf_LtTN{UݙǛk6( ~Feep8}rLA: !Z1J,oVC>3P,ܮQ rHb&}*;N4 Fr8sZوqfE5UZ]{7;=hon "I~p'_߮ΖMQ=)Q!X(B"1#B)|v2:9Z!Rw>aeN{A˫=DJFnGz姷z绦qcקg7͎hybfi't@d:]~Bn '!V]ivv>ŷ?./3B8Ā"G@ԑH@.Swn !xχDr gΌ(nCH (dY(O;)%I u|bBD UI_a&"ܹտ[C̢3;ԚG(QB!#ͫѼ@JsB}WOդ ̴қFܤdRS YaiMD08dG Ph<TZ᏾N كyDiJ^m^߮Wi/}gA)֍r=|#wg&GjbQ׭;l C?DwyZQ:vO_h=s|ɫAYL?8W{TJe@"Rb*]1Z!JۃR+Ҋھ>JYDP ىvᶰժAUq̈́cWΕe2mmU)0'EΝ{yN&9g ic(V]ǫM4Hew'Wom6Yfe|Q{w3'oΦı]]o;]}}DJVmߺ'w&gEal͘RL'ɰ sdF9 YD+JbW?S9}-/XS<YUĮC "M]Sb4kB"E "!3 #؄)/~/Mfb"~3 BnoB8sD ĨRӵ* Q2Kt ! V?߾Ӛ}zȲ.ݭ 7.䦣|Մ*!qQ Q 10 _v# J^vA2 xى>%I,I & Q~O^h:_-E<)4RDʲD"&lk`\ƇiW,3*"ZPn]1c.DgT. [Z:FZӣIZ]!Kyx\ӗM7'>Ѥ Qr՝<0">_lNWcj,lӧ0MS$ X崯{(!H!q23nAᨲ;?;ոLE5 Lܾ2wP"dVJ)P*ɭ(":tU&Z ! eVNcF=*qeki\ͮ)3 lL.M&+RJ tjt1?OƯ_?ώu[N^Vi5m/&}ҔnͲt|6&"B$%倠]\=.\춞SEmh_J)|0DRYw<ɫe x"k˼(`tSca" 1Bvrv5towZ@ 7BGe'Mvfզ٬Y` .v[#Cө(L]\g'0vVeI5 S BRN-0pLb OΤ<3" ]@LB $(uPd,@->}1LFF+up;v9#E*n{:;462=Ѩ*CȜbUfR}4bL*K-oe1F8Y`;B4"$Ak"O.8ut,@WuZr>yV7iI8">H7VLF>:L;^vD\outql7yGvBb!g@@8*=&Y2Qc[:p2Gg4?3e6V"M -:R"wY611#ZyYxm ez<)J"AFBh_j1O#5EX4(}D֤V¬ΜLYsǻa"TM4Fj\ S٘1SPІsmDa 1'c G9khb3)8< XǤ">|j#|PO̺[!ϒ%Ȭ*+k(Zln^Ǧ~Nx4/{mnwbt3$#\M!.v}YE[?/Kq Cv/‘rXɫ*vH>$@21/?^ZfCe *F+D8U< HC)`3tQ>yqu$w~Ɍco<@*"ȜM)HUyJ,/:ھQΠD|L)gwqqUI h2{u7uYvme߽bzќ_}g?H13H[[lm5$]臽 x0Fhq9]Y9Glj)ʢQ| QyB@f^^] ^-ݻ阪}?8eU)m2Yv$uZmp7a63;F+g`>BfoݗZ=}sg H>'QWXPA+rk!>(pX OZ)fZ@:Jc{^o ff|2 D EF>,A?L7>@Ǻ"N@`CPDXAɕJFKP8Q!#*bX | F!R)^l|d033cadZ1j8DJQ3~goD8E(Otָq%" W5^kwEztYi4hUun:׭]`ﭱFah$$/ad24q6~=?=DׯSRtqTfU8ZBevZDQ[3!>lJ&j &Dmx C+OY ݡFeI+\ސ4"IcХ) YxM|p Vzٜt4*c]bVV::)b"".&+0.Q||;. δ7]Ј2/ڍ zS eЈJ΃lx:;x[|s輪j]V@HHE^Q$TL%qtSO`K:gxi`wԒ'JP mZYE g1 F+i(f"@Ӕyɫ&3_k].iJfA @X91E(PBBT!Unw]j: -Q~6HZq0xSr4  6 ASv1HHQQ$Y€C4mA9i@LdUZ`u#VhH@!qu^{h:%4i7!.et2 (kŇ?ɯeXtbÍs.Ɓs${oiVCYf^t_W9s`g_/wEC_%ր8-€Bˍ{ϛ$A8n'PH{ E&1#H)2QYQ&YzgvZ%‚M  {u|+e%̪~wȢX(FvYh5{! O>$&sX9a` ѪۭT80/fOެjnݺ,l֦now1"RB8DKXL^"1_s=soNmCQdr:{-_޷5woyy{Y "֎n-d[P+DBI]'jf͘L~{=l)\6G麦r?|=wȠU-?{_N?n"J`.͛G2lBYU6{, R/,C(ުCe"(|2?0;w!:+cJATghcBP$ :`!K?d@r(U hΣx:F$HXb<'L@̘82D@|wK6s1-Vd+D I E"Z~*;@$hpH19ENz~`D1MP>P^ؽ%jY_nd/M !>"(1"H@UeRfp9)W}9R_\t^U6DW#k !C,R~OׯnUe)bNsmYi8>a҈~TMvm@m@J6">!QVJh{w|8#SE ߮尯zoaE@x"3Z@(`&WQH%ClehV,6's}4=JB'#kGm|7}Ӆw!D@כ!m0W7_Q~I B)%Bs7ƺ4"/m\>}?t׷!Ƞ5<.҇\ĘS^~v|yzyU;iaJ<RiW@͏-'eC6FkMwN˲Ȏ;hT?V,Ɗ1%&lo_>pB\g [fYPޫ"^BWQ!3MKH?=G[ycO?q`\4xgU)23cRpFk$*eb{BTJ9kECɫk s ?}ɝL#Ivٻgǿu(YE ޗǧCDf!ED-u=1cr5\sYiT,}v꺡}du^}kv}yq:Ibl'DB>8%mSO^_;`^4d|ѫ7/BV>yq4 f52I.$wj~Ep6vWJa6޷1<8u;}#4))DC#"csޭ@QHek۫R|krݯAoepbB[yLV߾vlJ)OPchz!r uTt6OEFybd@ h$BL&l|B>Km72Ľ"!"!Tx}dVaRVއ_1?S%&, ӑ QEFE XlbDfκVȉ@v{1o V7Q"CL;3F{/eaCBd"Ku˂9@:D,ќ6l܌r46'q8U^  '}+eBJY> `8!Xcv"~r8''7h:Ӌ%@.w'/"^}(H\VhMp (+[DP 6V bۍ"˷P86[_V)=*ʋ> ]ѴɋW?8D$%~'"H5m8$Ԃ!"uH|^iHY""@ﶳE"XH3u//ģzkT#-hKMdOgof*{C靷2Δa9`Q-;Kw $sBz'Ň>ܼuqbsn=.CFNdϡfy)`Hׯd:3FܷhM?¯ڞ*a60tfy\eZ0L> #b$FƘB/f*䦞Ir("gRxoڦO`6ʁvr>xt1EFǥ8nפկoDd, ~QaJQ4,b^YmR⮇i,Nj mNWZ}Óhջ?}ﭗw˲P?n/?Adtft}`ABϜ-AP@*"^+rI ד QUV'ÇOZv6;P~ &nUfR1?>KU#d/oKu>`NI7QUC:q~m/)$%yyi2Z&!%AnJ)\b}΋{t[&(Q@EAJ%$s$&zJtBL BtHQ 4'vp~W[koM+;9Fn`arGnB@$LHkT(B]]P!B}]NQ5ɮ =y/װSiðԸz7kO$hgU*n%-z#>iء/y.8K_*̈:$篟OOz\2ڶOۆGMr&D_,7A'W'/>;M>z\֧WׁH]BTŔ#@9" <OdJ `؈yQiKp-ɶM-h\od?>E1s@DF9RpL>&wYB" qeUhxj#.oCIÐv5Q՛˛ŵ}9SnF+gDpRԑi[!JEQ.2SlaBG#J}S!l7ĒZDǏ /}lz}xv}gcfx6~15YCl 7ۡ>M6Yk<;?5;Uf$8{>Y@bkq!T򘼰#[`ph{V"77{a*DluV'TE#[K;c DΪĀϮ׻P4ۋEFJw ®v9ڵ<Ĕb]8MD1E}!K6ZR8Za+`(DJ4ALh]wJ^!OK3?s?W4p"}o93}&DbuދRjFPE!Ё"@!*C hw7+ɋbU9rDHmCLH0)m,u}0Kiw 7xxu>ݻ]}c#BQƦˢ4hnU_uYαslw.|B\1||G~_C?pK~IepSOeyfBd̜S(2>ƲcZd:qѽiHҶDD$ݣEY"͛ DʝR$Dh5-, D\[[RlE$fԣU<ZMIlfooh6yphy,ݽL8z|sh19}<#́WW*Bjn[L- \Fjj'7!w3'Gx|,":ll㳉Q+ڴ"DprrZVӳ JPiC,2@ 2,bۓj yƃGTwjרQUtOxe/vh=Wۦ'(UژY1FF wXX)Ms$C=!}CQBFRXd5:#BD΀Vp ӑB*@cig 1*Қ kmztڪ6e@H)Fae=s7UbL?'{K M񻭟EUF ܊f\= Q]+E+ !,$nWS?x]kTEqb$nEwJU]HI+c2û/=£/k`2B*Gi\o_/އ˛?q,&z1,7W.>G^! Ub=.|Ib"t4Cj|Roq8"k;>~݇>ݾn&xm*p)Z+G0Z 3-DL)Μ8㮕{ =-"2xWR\K՗ZF8CSVn(gfI@܎JC H,99# R7@|GT9"!ڦ v'!'X܋iC} ǹ3Q(ͭ 6_}6;KRZ;w^(In`[`ʭPgNS #ۺ^/xp 12x ;\ skgFKJhu7DjB,}|uYG ߢZ8pD90R8EaziC00"֐ w@Řlf")GH"z?9v5ĪdT0&1CՍ_LH b13ޫs'Fh#W?/7FĄiqHJ+ (+νZ#H4D)$:ZmsҾݶ,*"]2@cEw[.2"pd~$"nZ::*ѕ[ɱ]+eV?d7;lg1Q@-C dlz2j]}z+?4V5p]=>Ӟuj:Uvdf0DQN i)$J(ri0X۔嚫g?=^Z[t%a{}ۣ}?zl =wΩ֮$@<|~z*:v$/th\-bB b [SJGTb$fIu>U$Urw.zc b1ʴ ˷/G]/ߦv;qsȪrV.U!$C REϜҚպ=ZdlFԌX!FRYWSt,YLŽ>yQO0y«̸?Pp/Qfhb&Yhpҏ[W-,ϣJHiZ )04\0^UU2 ^^\koq;~c_nf}U>DBFUDUl{nL+$LuIV u =t|[ٌS@h$=K$(0xf׻'DAM]lC!@RkT=o?I(e6"8$4(%ADnՍDAC̬'gphrs9 <`MR$lTF@ҝc|`n4 溱ٛƃ|lF#B`@HT$,Ӻ/w9ڴoWlIJfs~g1ЧWMVfjO[9SXLkZP~󓨨XmϋOo#IUc7d g."%TIGI:bTWُŽ_}盟zmY&%o[GY,#!DFn ÓV׷ol/7U]pAEUlr:L rfe\|Ԙ4F%L@UH@)|I69IUnzb~2C<9ۭح0#c" &E<4^7v1!hqvٿG<-2wz16{W>imC(Tt~t|dGC]Ubc_/T ={@yӮV j!vyTS-!*DLIUTDڌ>"; fgΠ{˘JP=Z @{zmNfMBM㺄)ݨȰ :`ߴptqEz<߄NAElzGt4QxM*`"O 0*P?ʷMS_W/y&?IM|RP0c3(shɭ7u]נ^`}p ܦ)(*$.v0jH޳B;?N lgaVaeXƺ͸01!0# 4ƹ 5p&iٞ2=OF^v"z0(2 ,ΛW a]@R:;lPf<BlU@DhEUTQ(uջG-FQggW"նunM?4y6w1d* CC,w|<" \q;dA$ta>-6FM H㸵B:.T#"Ob|HyVBgt@ Q(IQnY]#xֶ׾IjN]e1?0颢D&gOvAA Y<9Z^obHb~tvv:C1*\'f !!P׈L;L4'Dٲ5fw{6j90>\>|?]5΁z"냷D0)F Q UMΪfF6.&,2Q%U)s+$!P=cBp,9 R=YD|H[ghxt(&T5Fc(B1`Ȃ p3yyw.]qKtӏbR^ۓŶ.&ϷH6D?Uհnp03Z?+ cLGo#&9%QcRUTo";Ӵ$"')>|Qb&'3+hSUs$I CR;)ƻ q(/ 8F#os<%Pef0Uuk.V 0]3kDPR bTUG%TXܸb0ӪH)`Ȝ¦K+-J!!58I)bf#bR=_ͮBTow}u 9czEdTG2M&kCUp468) $&fcm,1'.F}r>/5*IDbw~fT tXuV4sTI 2CnB:% 9_j>ɋ 6źɪJ]h.q8aԏj̿Ds2Lu5Īn۟~̒`O![D,2$. : s,V!){"+u.i]1DdV2(D$Kͪ=3e4fk ( #5C'B?1휆&˲*F_5" * ;FדFلim6п~xМ2.ݸȴ* Z=;fylqz3:뇌\>_ؙP6@00AJ̋>_*T_Itfshֶ,>x26ڔ9;;yz؛ФLdC_~t}`^ ͽ[♦(XW+IUٔ;öUt^uTTTL̬"m*Dve|Bbv6Aga@fVH)(Pi]MJ眨Tb<@bND." mW/ '?푣ﳿO|/ DL>jU)M'+,02*1s0ƸaJɰ!؛Έ~2@P@[纘n_@sW;k `ʽ@=Zz?3o13,aL Bf9jD$zUH=..)楗/M,Id뤷0n|oOͭs e"jJZkj='#Ie\HH" DXc9fREwýc>/^{͇G^DIU"/BPaDAIpRxz3v_eM޷JF` HJR.$\oONڶ+J ON99J)k]U7lqܿTy, nr&7l {|<* i211bWn0&/O/q+ {cӧM}`x`aIDo;<5&TCOO VkΚ#߁eOffGe8ec1 wCtQ_HHf S&>Qx~VrG_Ւ 31z-,z2zٽ/d|i DǧCK;K Fkt^B-nGD $I ZE PI~=$*uъ*k{KQUd JjN!!bd}fӣoa\B]06NibgjT֌>FҐDb}:cVۮ* $IY4& I!/rTqRwugGm14ny>H~V ۼ3l H\'I%JY0¦ɯ6P̸S +Tmd1NY[Lr#&ИfZ.zκ̍R,3!%k( :k㗢_%ɒp"pkݛٲAb& 1^Yf :JLZWef!4b>sRi3F4 HI,Ha{f{ڜLdpק0?Uaј7:+},=$<[=y&` #c{~I  7>/YnvG3U=MӴMon̦θVMIDATjoa蓤MtN72W o&vw 1į??^y<*U:Gs<ޗK֘eYHLTRM Pcgw}qZ㤢II("M*A&VPE"'&$DUA20D0La\QT{`bcEƠ!TcXD#6Ԫzo[NZ/kn{Xm}?nEFTX^L;n<>:]NW4E//HT9Ĺ,Q~vND]΄a a0I3 @ 2g5vDADT˽);W-Oщ$Ji:rg)eE~''60@T(:Ah KP݇_7l]ڗnUiaD1w,mF[.zC"dR܅8ZXQ}DrƞlM]|溩nn2 - 1`Uf[f B*~QNU/.h"v4ZBQ ID43 :8J`,I *(JLBHueaNooL/ĠHH$&cFBBT"c2KD QU0%5FL"$|87Xk0J,9<0Kb,96گ6t{,ϟũ.ݼOK$$ö/PUy'gӼLI +w9< 01jۮy'uݏfoTSf "=-6&w@ju}ppD6w\o&"0DAw B$e8ۿ1k8هά/ 2?w:_|Q{8/1P]8Q1L!RL0q,nݺ۶#AUp dl#H!eV M׃~,W{ 9<>#wMh?{eYeEt+_y`b~v όI9+ƫ˯hۮr0{WuU\6Wov/[7,>;"80G aEUH"|:?4 l6!XœslRK73ђ2Fm7>I]}.*(ӧE= Qv4y^i )r.o{t&7>уuXb)*F0_M;In:jڌDzM/|>E٨W'?)R,@b[Q_{'(厷x((=:'_' ۫: owOjbb I`bJq[պ,| sXDe` aRe}N>(b?E^&IJHad{RB8f&QEUI $&pҺr5gMʱ>5"!h93۶۾g{ztGlK[x@^B{gh5&afg9,Mk(ʛI4&n~ eփXչ-ag]3D@0 _|`J )3坡(gN PKq y[sC\7];_{I!0*vv͸Ym7dL7$lK`ܟT(QU (Q BܤuxY3ln ȋa}Ɨ+%k[_ Mʔ_:un˫G{!3b(ԍKcwJEяlvdP܍4_\1YG5cBtGal}׾M̳K^6 >g)LۼɴU=Kj󂀷S lIQsYZ_8"O> "Lꊈ11DUcB *zuc yJq<?)>?߿w{Oow|$Wd.4*`I @]m7. A)IegͮYH( 6]{LuYDEB2t~`:fY\54P^#ZUlz13&ZmkW/'IBj,{cK%P(dZFm7)`ۦ -n1Q@=P3Cw˂준GB}~Ҹc"ѧ~i}THڇ|t8.VȆgvO$C _\glX7.'^Z.\WחO;/?dW- # l{ {釃WIGr{bUK)yl  !پ;'3}tECڞ1WVp6](;Bama]܍>M]jy遈Uj#3!JWo>=-@L z?21>ܻw^&]ϲ˫g' 648tØ &qL?\,k5ú1Qû'DpNsy^ Zp|Q*Hvk7m\<5F']} H$<-0 xp*c—In  2$ {G*#D4^7_b܆-GnyVvEvDyXcf2Y°mSkr.RV|@ήi_㉵25eGݺxf8<4זa06=u>׿)<'}=?P?|qcw$G7FoeyǶv67EBןiKJS+Ii.7/?ȲF3JhuVUAFSt.cQSb0! aeauR*FIܩ36i͓$Z,{&ebJ:;vʲ]ӢQ C51hɚppFٌQ__}{?v/B2"}c v=n#̴2s:+[cvEϬj<|gL1S> -a;óŬJ*V9Sh{zx>[/,jF |Jxcc%)!X̉IH r׸Lj`62 IEm^ìG#?xOMh41eC&7!Nt<_4݈ĖA!s&"%+cyZmꚐpO%ͧNvWkwQ_yRW[=ޟ"̦BfʹnD;L gG\`5;ZԏƤLPXq40a 2x QrgTXC Pm:&7ʨ|',GW8},X0ݖ ":_])%p|z?ldkO/Ej[ĢYwuƮ( 6L*cчWq|)\lڸ/}60qy9Y/4ϋsIDo>l.LӃ(@JGgaw@Hu1ƺ޳0%I-$BJt\nтU5)jֹaVvbOr07Ȥ>v6$@VˁT'1vr D #.*H cO~ߴ:SG/%DV 6̌`B63 @IkQ4 au҂T4cbL'78c\MfhB!5כq> YlZ}|;:^17ek(Jfd̤ĪfTuCUrӋ6˫> X=\=@3JLKJ*)[ʋ2U0 OU^e"4F.3l3 7Ƹ]ouɳiAW.’E5FY7D-BڥeinU{̒FHͧ?M&zVG^n@&"aGd(1gfŬd"LL,3ᤄy{F0ϯƻ'Խ!#I10xCxq s]*I2""(!7[Į[$яQ4luY-?xj]UD8_>{M^ϰȷS6ͅXMV*e&Ίaw>㘔(sU76ܺ\aC927F>o~꿩'!WzoDC[,]xvՔ9h \KcjCFEm@.4j((ʒ f6gSz|a hYDWiGWMQM6arݼt3n53dQdl9ܫ.xLϒt,@-7{7 ѝ{"8ojOWwMӥ,/ݸ۹ #$.$m ;0Ma.ƋmLϮwOp(GP"*LeVӼt{ጏ3cTq7 ϥLQO\May\)# _ٓO0"q\ a~|쯟>;,ԹVge9po1E&$&G!}'*{@Td`Ζio=M тq5iz46M_>9*IR0 9+PQX"kGd"AD$eTчNTD$ܙ/u ^ў~S<*!D evX){LUZR(,$cd GC|4'M 7]?; .O?w߿޺LUOOh^3)1,?] ˯G1?O=թmg*Dԧ*g12%E2J^>ɘ3eʈ%Ŕͭ4 f͝8$9vg6? Ek6ee9gcuG}|.~ثywtEy%u(@hm^ d޻[}KnCKY| lgk;zq6=<$&]ƘTM?fI1b}5hYna/ 9Dn5\7ӱw%x1DPY eUxj˕wO9YG=k{˃zlA`sp }`1$\5ik0?V󽣏Ӥ gz*|#dYAաHu]Cur/6@grP1uٸ|?L I!ODlhunpՖQW'I'{^nX@ VgӼ̍eS&.\QANaTnnb:$"y@@@!v$$TTv]8#2#$"@Z #&Mu|P@Dgj<1Yc":P<&J)$*c,!jEP>gI˫lKT%??#_]U~}]kO[KkI}S1܃N(*)&MA $a]wAMg6Q^SIx#0 )2٫3͹M !%4~/=vIjžL5`*}tl"~<[e/Deƨp\YLd ^7`dת6GQۺ\r#)>@Q|qEGDP`Ք[ ʜJ?ܴzh꽧M^#[=-q܅vĪ~Ĉ"`-gnUDDT"fș]{p<[sܡMc:" M hGld[?̡b[s73lf!)L}(5 pD nuW䣣oӽc4Nf"(Ӕ"]suT{_(,< YՄrCd]\'n M]HxQrӊdZRܟ. h B܁cY]jy%OJ^dC"w#麕fFFR֏Y"$ABjI C3Rk;Uao>vQ5Rܶ"!h3¼[ē9bFC˭12gb (TW"CC÷Qh)>Zv+4C2w/?K'~*zZL~mG]> a Ĭr !t$!"#EdJhD םDPWeeL@%hPIJ;` A1Z,T.w0N+F1[hhnOwo/@?=Ų}>{>WƧOC&*mL/Ŀ/wօ{bih(sb^MYʌbmqY ngev۬>|6ui'IDAD""yXL]iivZVثpsaj8H(ܴ$ڏԕ%M˜UE3kRip:;0AX`i|V\p2 ?vaC3 H{`R$*3nL=-M?8:+r}d;\> :h뇑r6OU>z~J$˧18JQ'eY{X{zO[~؎9FaNɃ&"$ZNaЌƸ`mqZY 'z hʯ>eWv c̜UvGƮo&Tkf|[.wPdw0(0!Ĕy|./7n⶧n/F "(qk>]ܥM Y2kmo2"*JRDVgΚI)!"*YYPQdD jgg$A&yRw?z]z_dm2H!QGhZc}Tժ02[t6U9Z>Wc]B}LʋMJ,+fgCln@R9P8)9&)I٤>W7Xܽf^_~k}77{bP6YhI'S ݧgww.f9,# ^ cT&}?&f&s.ӺSǤ-IJQYYU"ZTLd{>ĦSJ"\^\t cJ)j({PHaJz|{faRusdt)OXP{)kX(e;z/ڮX* A~ܜ],xC!$ճW3g'7>\[_>뾹F@g(m^d͞);cCj_9KpؤYY7]B4"Qfb7`;k(&Pf+"QR{h>ڔru&r% Ķ,$Q0iU0hB2rH$.B Ii^\Ea)]qtzQNT "c $v"35FD̹(~Hm@`%ڽAU j{OWo^NrL\ZV޶4a3 ݤ~nxiCd`tFYrl4`m$Xk DSj]dY;/O&7fv.lqL 7y+G僳Ap̮M\>/1M.R2ueV̈z2g]v q]V;2:mw{غ,+j2Ɗ.5 } a5j uEOrא9}n&je4wv& ׈H)A{Xe5B>Z2K.sdAsf6Y[d d4YuFo6m,2aP`1YS]5io?>< k{0(]%bJc(b29XZ s8gy\on:V,`ɵkV#XR'1DR4Z&]ۊyϺ̺ ޼C.'"F  jQ/./2g $X< ,L>}1' >B!!@HPnYI<]rmh>Qͧ׫1nC6sie im8>9=zD`{4ƤpmƤ T5D jY# <մ;Ox>"+ߚ2 $a iݦYu_jSS]rI*2aYܶm7퐖A˞""$h ǤhD0R7IU;g!$Z*@EtU2 c UGh6:6}j4T)+'#ixOOQ:~CL%5_+i0)Q5Z4UEQnsΊ23cQ8٧^sG>ZދPˍU 8Q)Esgq $hE9k̜,bsDbg?Ubʇ*۸0Hpe0y}ˍ͍I_͙<~/"Z= t_6{L=;Ͳd4waJ6qu i EY*O&դ_z1~mJG>E"{614EvR,/wg|c썛7B҃CƀjM'g}v+ЬVܟjIovtɊƮU5VW)i- ޽dNlr䥚'{|U1no>eVA)388خ>@zc C3ҽY5<{ⷝ<|=1ɹVY}D[*O/1'a" I RS"0Uyvy *!jR@),$Ö/W2Pd ;l6#LĨ$\wl>&C6d*ыE rDž[e(RR3!$wndt>bH&7I c@go=Gw~gq,@z})iۨsʩ1ue)ԏcGD=XūcĠNJ Zf\:,TY! ifL1FkB E1!pU$D&r/PIU**Wo}d?r-- q>anq<UrǷ9 Y黀DG{lLяʄ!U&8wY?%1褲;so!!Ф"k2^I}Lĺ,SD,]f&"a~r/Ny%Qk h@ć0/N*vhU۳rSl? BlP53/i[C${0"./DfHs!#{?*$62.k&\?=_ϝ, XE |8~_?t?jn4I~Sw6g# pFHc^@ 2p1k 1Ƌ(12}Ll!mb'{W~˵7B wpoh0@״ݤr/wK J ?=31)lsTM0aՄefB8BUwн6=.RPd8)MIDIha Kdfb2ָ0uabԋƣm?ĘaH* )"4ʜuUAU 3-S7lZ_d"jbJe"! [I`6u]-E}nl~o??/6L?!I< A6 g֎aި5u#!)U!C~`bL`J6!kURAeJISc7F˚R"BP!"Փv |vCYjQTwHcs+@gw2՗n-&S#`Y^N%nZI1 VqP̉2 Z&k"9^oy!LL* lXCb"bUΉݛ`]L'3Uh7gxMjլ.W},F?n,DC "CfaBIH\>iu s<<6=ؿi$lS?؜gEt10 92&Ƹ"Kǔ41bL 0&Pyd7k;[#b/W0wt?C8hz\ΐ 6%pײe_w![/ ,gQa а5Yl Cm/G{XL9DEڅB wC4 wI)!b6dl_+eV}'gyEeᐰݤ)ePYXd2(=Ɍ!ʤb*"N&eH̲ 2P|xB3??Bbߡo'N.V_(Dߛ4V"*7X ňBr7* #5nƝ0/;mJTcٳMmO`%-rc-m(2Sz!lPCs;7Z7՝{`mw=@PТ'>;w%%'z䗯|e0^7) Q<민v/W[a I?!̙.exx*'v%H|~hӧ mո/~y|/{} "f^Pg_*+{۽TtӪ[o❻{%2 Y׍~}ߍzv{*]w.?u Y7Yf``y6( ((2>|:^Z2 aK=^૷5"jORNOΈXNEr'eG#uvO*,2:i3+Q!2cL7pM#u嬡#=""nM}$ҮODl rуXP:o?ߜcnјtMzGIUQT]0ٚA FEr- Yf SJf-2I,QG'蛁3ϗ<c>|XFV/>>k_>>^˧nWA"׫ܦ30cj{u6Yc% rJJI,s(2Ӎ 6::))sC,`I@ďۦp‹ee ݶq 1E!l]7,n>+i²*}w8a>;+nxk&I`׊ɲ"p51׫6$̊vP/ŴMo''Uaky+;xuA-7-~y<_~v]͞ߡɉS{#}|߱#jH~\J~~KM2<ۭ<~o|Ax|^ xNgyp ѱ)@x ICL0x2+RS]<WO"d&,Yf8w@dبjsgX&^^eGK&I$srk-y'De$퀪>Gr ?h 0!9Hd#/?N~kӏ/Op>RYI7:dCZnКܚD(q쉲 UG΢@e,>P1+!.z;f^AWw9QO~NR1&@$38!a^2H򑯚jx&:7fЊ٭Pމ%J/.}n 퐐d܈<{| 33&eK9c(ɋBF@X&grk@zfXւ3"rwdǓ}OM[UR 6ɓeo8Dl?YvqBkw=a^&"&I1tYL ^eʟ>['x;2!hmRFPz0|}Who4Br9f7kv(;\Ηm/=]7*<|$%e{'Bz;/uӗRU*\mp*G"%R LQI̜} ͜)"cd$c2DUt9p{`|/\:5lW+Br}ȬkD5֍>l;´ؔ fƖH/9)NsՂmeHa5cQLۇfmca?C?Cb?O~W>8"ٹYDW"RnZMLd"s[A UsY]හ8T[gWM'eUtcoXб̢D0Y!)Ӎ j('w%`?(wZz0̐9RATDdeD0("OJ<_5Xf$̗@ɜ-9aR R7A.#YT~SQ\=H.ˆ~h=χYD{)ŒoG3C~Bo*ggDaݥ# ޔ6MNpx'G Q+K~Ip~)8LG}l6MW /}_>՚7xr3^[)ych^b4xpt6Z BaӅk~oV덢޿{nΧ4)W/WRrIQDP524C홂RV.'@T$"mZGQ'c;,`M?\WI{7oNϻڍ_l0$D2 {k6=U&j`ŭUA٢(EDI$,K y ˔2k&wc\LCvGo鿉1AT. hgv)XtiD!1TERFV"։Z?jfQ2YC ?vZ&fb?BAkR^`[LO}JfUzͧy ?h?0[(3$m h ; L2 cf 1@u^oK V羡4 L0x"SvC)2&mGjEvKӉ뇘9/8)Jx$Yߎ%}i,2,A R9,᱅pofO'xݕ]^x627/.@`kyպ-Uks5naQ_ĘC*?/7!1!,gB|]nh6_:#1ޜۣ754P6tEۮTE5h|غ ?\Go,S5t?}MӃ7מg\Cu7Ƙ`(Q9HHDD I$Q,bclw{hWTթ3{{aD@>Xz{yiU|vGx:0K .9QLrEMMT&0_!ψu ֒;&jDhZQ!eD:=$DgO[*y*׀Ăuuiȸva$yU*EH Cb81@9%3-@$*9D!&D|Ύ3 ܯܺ]<|-rZ! CbhW[m R4"6}H>Jg4FN/Z$!X*Gn2n7{7dy`_f~KhoZv1V@i{FRg¨WiڳDen!DsƸ2W1vkj V7M36u36:X!(y|WyϽt#""Z27ua" aꚥ]=Zjo|Yρ=^<=>'[7[' m㣇<.Ruŧ2XX̜&j4?Eu&>5ӭ}~ay1# 2vSX̏V2~4qRKn;c񣷻_GtVp J mJ+OTz+!lZf@|{"H^Hx&HrӃbhÓU(.NҸMK>8RKE&ҺCULRG1i˿T^^!maM۶xr6-7]~{ۙtu5EشٸfH(WxDh:n`fzrZ,Zf B ,r>;oN1YaW?N7E“˽[:A'& ( QVM’;C3{sV"7IGoġLLB!R@/N(&O,<,Nyg퍹x}=4aӦU7D' QLוdzm~;VD@V`4! ?]Ð*\"ʍ][>ZYrg*?}+0.^8 ܾnwot_/˷+Ee"͋Gvgj CY%|ޝ=-dSjL)431v]-CF*̣x6nƲ+}X]Qń&ceQHD[9b9GbIb!BB~XOk?xN>~ҷw?[ bf.əǿB^S<$ N֛xQ)19tZ6M0']+#ӟ>_::;Z ""eˤV]b=YBJ%NdJ٘n)kd\;n.W >Nې+]Vv͘*R"^Ł~zI˳uͯ`W+ghӆu"elr㷝WDP*"giTDPfPYUtu<Qnh\H{XbP 2x g!"czڮGE~zܴ! 3IV@Cf0x؊D"&浘}-_^Z]M9aɦ$ǢCNCVKGl>A)3H[x}INz.4<ٟqZ>creznyc8I+4b@!I7jl6].E_xh@%O{u@ڣI%/+7c‚=0oa1&򷿛޽Oyq6iӯ};;0+^yJMoQ>)Of~E`@|뵠)s0!R&R:%@YSU3jJ\gR:CElԅ0bR?dO_O&gPfT)wV:1("EYy7MϣB+2ħXf#R cJK)"lz~땷$˦;?@ݿ޾x1XpFv5tN2>S:2nʫtƝ1$D *xlblSBFq #&bzٗݗ* od%* r`E Jëw&=#ԥ\;YX@3ֲئ~zj ȌF%-joEz;D6HGDv8wC2O~5sx"jԶ7jX,22cY$!"|*]J{m oøҶ%C)w|T^יm?|?KK_K$t4lbP!06fROic\#Tm;˱O޵Qpz>ž1hDFd็1EDU*fF0˟+Sǖj\(mǤ ʫEARf.ff 6лg!5*RbVX)knX^5/ݬ},C"e"TOr4uw߻saju W}G;Ը6B\]oV(\[mQ"OcK"u3!bfЊ" X6/*e iĴ⡝Hٺx/.[߹j Fʳ8$:8* ,)Wm$0lZ1d$ |BL*N~zvÏwݣtsֆHOj%1>ܻ./;o7^OB@p]]>FgiCtC'EV+]eZ2Fg]š{^!ع2f 4Hʤ[53Du0$bmi]I:krb[_ke,$c]Y6 @vF!dM3WABZm:JǻxHg9K(Dć'1Ը,¸#A٨1Edi4Z%Ny hYN=>^2[j\.ӰHμm'C׬ʉAzya/|n;bY㟶K\;1EǼuo:'ғ /JWף6jzTSPd:#$onRe!FgX&ARp3m*35 E "W;:B=fY8w5(Da֤6cvZ$6FZ)QE+QAq?Ns] QAkROlȪO?zP:7b){$I{JXl۷y!-vŬ袓HM3Ās6|s/M?Byx8_|:ɢg|D8]J$u}so_Wկ(#趃Kk7pX"uvJ$̢ f!J<%l ̡j PPz4)!ES1q"%~b_g#.تO6eY#W b eoZbvF0%!ve]rLbORfMV>%!DAĔF 콿׷_nBogjvʝAΚmb4]d@)\7e*w;xnV4ݹ޻Kf8+k<:#}Onu6貀ۓkSяÃ'y|wpzAY32'kNsB?(kPQA/كn|>ſ.3bNփ:1LG͛ Ef\vTj5HOoE}  ?A.F 4MG03цΞ}8Y?ëKb~|8kAdRһ\✗[t4y?v>z? U|p,0nR`^ת?p4pg͉! "ke0@M" n:qC;)Mgh]o&&nid`w>STպ+u@qp j P+"PzFt}N yZǰ$~>?z8 W񃀉mVbCpNb h?U -G-y#wO^97~'hX vM_nR ̶UDTT`DJIbj]!!Hbq:M)\[!vj#-k!ɲi:@2 1ZyC(]l7~޻?. w镛No{*sȐz)610"/Rr˵J e.D "SBmJŢTdYb!D8@}}]]5ǣVREn# ANv=QN"gGl2YAâ̋ĐYҺt >y|jnI x;!&T{ew~L;u)Jt=afQME.\PbZo6ĝ( X8)F @2?,ಕ|=NяEA|8,ᗾ;9J mw]/C@ڴ^;kE"sVXDIcAXzۥOyn+YX^޿uxLJmb0 RM|=^z8 1 Z2$DQqf$#oB(`"" !jSifU?^5>ۃ_ݝCbwt\V ;^=a:]Es~H7 VM/ElЍ|,=i'\rd(NTA>zO?6TLwl޶yYW>T\>a}OӥEmn fj1:i ,vmGnZЄI("4|kw]VUq,O7oZx;jgbb^v>'"׉QmUG;N26hu=5ӂ.aNN sPդ!23tӋCHOדo6LF)X'""Eέ54}_^I8s 5v9ٸ0)S?pU"AHC,-MZ2w]Ӭ>"Jd!d iLJi`@{ٛ3b!PF9$yMmHډUJ<gSfѨ4rEՏ>|?x|H="*P"mը_q7o̪єkf%Y;| 3v) جg6Ne"ff  ͳ"I)]茏z(x ǓQEZ#)m igg3STH&$edpH&B6Qiڦ*DݭWH9"cӯ)jdC):oOTah}mލ ϢGX5z γu5"yb;Dĉ+o"\kA\H b⋯8$‘I Wݩ aF^-[ϖ۔9+T")@lAe><ݝ$<#~nA,юÔxUcg:1hmúܯm3gJ,DQHQoFi1G$@IDZObΐiRIQWW%A!Y3e+Lt_<<DBa8 K %^>2rӨm~.' 9rfNS=mH&&{<(9_4 C[pFQ֞ 1-.N#/mzB2@´oۨ5m;>*o ~;Q:WXS1W?>'gK[}(n nFyށXއ:E>=2OOX>b;^F7E^f(Ŀeh='B]@zug f&,pxj: 4iNAAaF$ī\!Jzx:Yd@l;FnM#FQoV5Ŷ'7儤Ck Ň#ۈZh~!a.o*-6<U"g#0r֙7v .pyѤuҧQ㺟kOO5pkW)zCom4?=亓߹Nu)Fg̱$~[U>FDDh0*C,E]bZgh'\nx4%|\_,U?t,~Pb5g?QM+HPtZU95W8x鬆Զw`uU˵GA kfD3 H#ztv7ZF5PMwr'hh4(QI+oPk)$ެ~tr1ZAHJ=.ESw!DuE k"<îD>i(s $@Ȝ\2 ޭ瑴\ w `$LPZkQ gcw@WaXwݷ>ޞu/OO~rIny$K<__+_xoJ!UWWHϮ81ĬBP;Ze&BԡBǙgBӤ2+ɘ*a%|;ۘsM(ڡ24ĔXPǎCD-$gfHl*Ӌ6.C}f9Nr&Rb>>: @ڳ`щF iõ:z~ryfpZ.ҤRQ]\V@yf&Cz#{/>wjpRӒBG=޼+U8ٛDywV/j}^ r؆i-+b93fѳO 2.DlouRhTӕ(,pyMM/Ū(؟5Ǖ\6%ͨ*mBRgdƟ3MhRև#ץ!"E)HcuaR%DT?96AȂƤh@9h,gyi|'syfY3w;5D'xqk󅗋)aq0 0>;YD :FxG @L8unR?Ϭ-ZR"L;קּ{Snaf##+1 )%DP!ZD$:sgb|s/䟞n?1MMv4 {;fJY)LkoFxvW'.Oq vg#<ó Z#[ޜI\:uQ7Zo{o~wШհYM՝GDܩu[TΘ`۬~hS3''y@>xof1}8{_7^ȥ< lF,{TݒfD`H@? ZaL|lmm/Vbyύk_:N)?ז/13!S&Y*9,gI. 6޹uXnƭEX.@zwRQqTwVfN9ڟ_NQIk(~mܤRf\91 AFn۞$EvYC50+i"6}We^h1YCLFSrg"7Rf8>Fz3>9[ tg_qO,fL_U1j9(phs4Z>83r0*ݨZ/@%̘9:BB\7̼Ols]Tj=Y$; M.MG3uJgM f%!bJ8`|k!e ΋ Ͻ2X_y6 Cs@͙ZW瀎\f9DWx؟'dgs=_9I{faI46&7< =s螙=v՗ULE]얯1"mlaBae{ _W 4R\em3?b1woQi!WGBGT=lo2cػYH)[! 8zO$l^jcd9 'I v(] BL)^_ߌpk~QSk57vrjb?ͣ/hH :h BDV誽!R'`#iqzG=bYF~h3Rڶ=!lc0 II?;_ſ'oVx4sveRnsuJ2 1[ V(ΈBf٘^x^-ȔXrV\6W"EZ 2AOIfpg}rSтpbV$|CL|NZȰ?xlQ/N`sMjtMGcP@J鋍5$ I+haَIg7""kEpn3ǹ-*B5dkݻ%$Bϒ`he&:1_}䕒$PvmͳR)'u(z 3{jg`R7YAywhIz=PzѾh7qAI tk9a{ADo:8M>~*ƍvôLO^̗.?sS70"',֑un̩WV:OAjxVĝ[i7N@?,ZUTFD |zP$ÔY{]fѓ1\i m7M3ܐA~raTokrw=_8e1ѹ9y'F0zZPMfuu&\.uu_:׾5Qy +-9mZdѧۦ'DR*cY!Н-b{e)&l6IdD:X}5Xlټ3$114M+ZtS@!AetQ nN*"i@'Wu]K$SbT =|vVeY TlM}vdusգC9{&.0Dj3f*+ %, >,y)>":D4 sNm5u^9;Z>1I{-YCŇ蛟'U/;΋ -I>(wS+㗾T@OsA{N896)^Kh<)#O Hڎ ³ǫXx1or͆{j&etN~;VY"\,UQS~c$0ҸT C1DJ u0 ةSz < 7MO *Ţ^P?|!"v;~:2DHH@B* :|i{7Rq"=Q;ǧю|Y+ke17BV[īG(QN3$h؈rH}TboWdj;DRȬ.r5yi5\qIcKc1 &T9xT/tTaRU*C9$kTLZ$ 57w?m>֊3IPtN_ytq)qF#3~|}@$u|vۜ#4!',,s}YO @O{k-$I BH&DA]"?xkل:ǝiRܷo֋ef.\LhfA4HR#+cxr&G.Q $h9u '()QO4^ ET@g1F,;N7vL,/Dg:A6ͭ}YBRUԇ3?!Δ29AJPd | .6gn?G?yX"""ԅY P)%bmO4XGi&)Pn"(GUxhĕ$%ERrFeTG [λo-fE urRcl\3Ǻȏ潢#ȃgݼytR.od"*bE=<c RIj(mCdzgwv@'ðbhiexRaH71HI$DA$ b3GEZ }%pbc0¹ixԼW2ٛ/֛7"!HC=LNq>[Փ;uuspg.&yvLlŹP`LD"")n_>$03#h{D 5h4&FfIVsH>? [E,Ũ/ |;˘R3@5ʮVۭ5d5 "bZ`,٨46whZ.+mVm̀U9 R,xL51ނ)zYTPX@HNc|&sj*F`E*P1,(.35*CLa$f4*Wȱ2;ܝjoʄc@"BlPFD|2텝j7'.si;f^qY{* ӔDP$aD,t"R b$% ~SWRZv,\7RRzfd/[Nړ KR8 sD!RtC1g1`T8#n=G.6f&Şb c)%vD[].׫ C9")U= yh >J'g|U!cC xVug7,1)px%YߣkDs:"!LJk@_z%X.pQ"^/7 ׷nk?S[EWO԰ћ#fSŽs|7bޏI!W>}tIZz ¸O5QElHqӠ1a iHw]ltL0CL7`3DDi6o}۞ƥfQ6g8 PUbbЯasÉq& AV!0 #z.z@_4TJ)IBz=ppO_܆EVX X85xmFnV 2bsZ@A+1:Wt}g!4I{I)4ʤ8Lg7Y %t(nX&Yqۇw)"gƒ)uZ9;R~~8vlFJ8X^M!sq;٣ӹ:^B^/-@a.@tt >MnXn~569sٙ`DPjFO*y| M#mnelIOPHEv|c?yVy>,sJiӸ΢>E{/i&uXvĔEDDIZȝՐ9D"[ #'G2i'?+/Liz)jtrwx|y|CVU^JmޤFJ"y09Q#P%(`U o??3*KJU'4B6C^iAȊgiMO H}m/c]l0Z5I]?W{aӱS Eؒ!9v ۍ*Tr[r\ɧXN@3\lF&3_{'E/@ DF$Akb"iby6 RrCYVm !&m&=ϥ I҂3 *3Ӥ(jy=7+_x}wcۙE=X,eO$nNi5'> Q?}9 VE@+ap`"lB=$GT 9& 'L NPhh,{Ge&  @b)Lmoe1>_xcV(~tG똢"zCLJ!i1ZeON@B5t[_%JgMjcy^R*ݻY !"H@;L8)htT4ɝ̍2na%&bɁ)~oO55tB`N>!*˔'{(R^_(E6+N?w)$%%a@%qI1EeIyI5 id{xn?-?EY8]d-X[kp?u[^()/LfJAI i U])wp鼳0xLn Du~r?FⴾuuP+*34TGýWy&|ձ3rSX= hU߹^~XQJwz.ggTBZn:Q7@ldagiV$%晛|-ƨ?=<*VSb֊BSDV[ yA ̊ VluU߳3J)$2e҄2 ck^-6I ٬!kt2i~x2 )$etƬ1ngvTf7MrʴVa ixdq|)6{/͓Xm$?a#$5^с.o%k $]/d6W~09ޱnM$ߛݑQUE'ϻ@7-1;6ZϏvꢂpomOGz-YR9B-[E iӤU3A{h< $1!:GH1FGJ!33M"OVldAg'gtտ@Y铥b}"u[M"ЪѪk'!uJ(7v$봿gSJM !&󋓧e}uд[u^)\` @VyմRZЏ)fE"b]=:Z!v޷Q4;~[?#VOw?E&.~i 1xV\^ƏL&վΛ܁‘|2 wFYk27&l&o_7vuW/ P#JY#VU_,AFt;ۥ"cܿڳ䕱V!ӤՂΖ(||z@uC^o;ubI"@:gIh\cEgkTfYHjDR:ܩR2~r^X p{_m:묱-Xk0 aCL0Te؄Gm ~y},/ 6!iϼ쭛b6וˑ& z4jBĦms+F3!L 3*ވx MA;>FS{d~ϯR@M+e G4ă7яS$a|hvCio]$E7PLwnOr;)"enj94wfPAy7Fnk &v'in+GT;?hŒIse3RS3AS R" 3\娮6icYl]eY*'cY"_=hv'vRd4J'Nhtoy9LJ;՗f{{Ym2$9;?_۷~v}t}4mib>\4-ֈRFκ$*Db`NH("sbSJ2x0mo<\mXHVo!|?@3g JLu7>WZm;2$6p%\.6, j-X*VĂest!6֨[B`<DXeg +q "~,/|WKEzUܬ'81Dț3,Sr3O#mGN בf,2 a̕ۮP'Wx[/[=lӑR:ƨ"X0wuۺ4Υی+KȄYaJP8P,X8h "Y7MG4s*2@ʶ] Cei{?.2 hm>K)LEU[@:_,*o P""5@A!mz "R^-6OxIH(,yC @ZRYW| KM#韶j*$Zm:lI Pf̏v˻gu,}BKTZyQXW.2cRoΣg>9ѧ{KJM#Tߤhn^.6풞?fhrycTCjnv)0W7ސۯ:|Qi)w*tmYɶM4ːpΣ5 3U实ޮ wnk~ vZz\IHBLvD83EDo(*bؙ϶Y9$nfE\-:wpV`Ӵ狋QU%m3$D̜.,45(e6ĉV1qIZ_p7![(|F/zADvvӪVXvfFI<geB$I˭RP-X"̬eqeG,mdHT"B$"XUAr*i\AD‴H5Ʈ\ᅲIG׳JBũwG:RE^{e2F/6A+DѨrhZk y]WSCMg,֛bp(#;'xT1"uN.W;;rҨ@ I%V3*!`IDb"+/ܹwM1SAFE1IHZuicݛU\VXAyJ=r.F "E^>Փ^ΟS;w;oǕn(/$$jsn7_ɖWyOY~U]Hg_3@/*7 1]Yu/Ee73`wL3Q4V`A_G @2. dovmCPUVx6u)eLJKTdF/sL[]ꗾ/Ư~*[`Z^u!ʌQ!8-gY7[ǿ}as؝S%HjRDUJ*8 [4C$$"J)YEb5Q_56mz̏%C 3Tb{oko|Q H՛_o@?{t1/0{Ȋ,::EvMA棬YJIlRv&}}q} cC>U5ph`}ɟ(F_rBI"i&QAe֕NU KaxͪC xHp~G}0ZiE9N5V+Mdlc2zfdzow6n՗gΞꧯ8y' MB)C{v@fmX8IWY(iȩpr5͵R"f$az;(Hz\7]a1>#fi+)9ZWB::cX+%z{p1x7>=t V$Z59 ȵѓX;5>Rb%NOBD bXSD73ݸa: ?q񷾛nܠh*=\(.O/;Q5s4&{](DAD @hT1zvX$.H^1!j6ێ?| GJ cQn7bak"syl~{|,"V+"j}xJd[]+[ۍGepxPx=q|Z?mϻųQk úʥtF)C攤)t6JFBڝ=PD>DPeICcTRSbu"x8켽|@jev$TU [cYbgs Sz(ghXմa.n+֧}X>p|Kt!y@g?79<:<ŧz!`ݩz BD*D,l0Bt:FkG^L! \Ƙa[ftz:OEpVlBncnE6#k̄(>xJAЅgWaTGcl!(rZ]>r]u[a -O.ƹ}Ooggڲq?F ;'{<Ιu+N?zEKhދǒY\./ޟZf]Zigyꪞnn;JlB $J"9Jd" I(& @$,16yza|8[tst߾TϮ_y2ݴ-}HYu{44I(^\h"ԺxsGDxvs ][c(#5"(g8V||nV /7| Ǩ6]i]ͬ/VA]fFeC9v#A@14/R$"1) ],yr*"$.ޟ\G<,!4fO'I,Y60n+Ϯ.;0o}# 썖ĘJ)ADdfJ-`Vj4 #srmjCED͢{|T=;9ڱ]s1,ZNqs|2wv DZ #t`?yK'VjhMDiQ_M#κG2;m1xcgΤ:"clp=gNo~3RrPӸ`r?@] WB_JBJ1`5Ugw르u,JZ&y7Ofuwth.ef$7o&tq4FՙMo"ǕR4TĴ^I`PI>έSi\9NKwtkފ  3lۏ ]L%Kv&ٙ#Sݫ/FVʦ'3c/^ӟz7/JrU1wM۷(>WsJ O3i\Hw%2[Aߋ-,;:ӧY(߯`{ݬH쟝6Zs~,6NHZfkx[CBDH)!"(:AD4p3[^mU\'#oگ~{_hF+k#z!sRt{S"_ 94Ӯ8)2,HB H(x{=!:#-e,1I("">l C ռYGqëp~plo_O=%zI<{a ~Y}ߴ(}Y8H$Hi[Xn&U{z]]uW`x+cΚ9iºbXgK`'ˆUA Yku cDs0ign]e9/E6Pj٪bXIfFG&FF3$fi{Nqc,Na(b.! x:-B5cydR}a\*-PV 23ۃw3vZͯ*j0i5DY`!cĀim*Gش2Hu/ Mz$BWiw djz[O[,T,{ZM5")&Ϣ=_]>ģxJ 7o67/^on&KU@T3hW6\\fL_wN&[7ϛr Q/m$GS[f'MW;Cf@|O?;ߞ_Qn}T샾^ ej{I"(" RI) }/Iz3&! R+"D#"_}Cyj|TcB@vR\'{gm[<:X_^ڀ6]k4hWfPX@M [=eE}Cܞ^wYdObdb="D?IەY+i-@u}Ef[թ^_&&kj,2KQEPkZlBTsd6Z*&Yvᶴ}2拞t]԰ikkgz2 5!(],%,,8@bJRV-7ˮkY>]̌ h PqoF .Zf{?kTk7I*Β=JW7u s+N ("b$ oNfZj*sWv);ஞɠ3(Ψޏ+`R_P ų/U %V)A)B|s˧_rwa̭ 6bH: :+@5!ʳʨ(wq>J"YWxX$QafQ 6)"5LL]nM8 팡 ӧ+oius?ǷŹSw3phx4ڮll,r!^.ۧ*M%FDP1EaJMućfuۦrՍ*TRֵ,7ɨWFa.$,2+ӵOYS@U;&O(7 (A2M[eF 3uwJ|umo=[척@H7_~X=W9y ܵƒ"Mj*BշEs)̔uX!CRoT W, @v""sFݰFlQYL~4ߝ={*B=ӮAW꧿^0=(4|`0.r@6luz:f]Hzg3>umC&Q1)!}n_\x8\ JtxU9(C릕qADa*ikrVbpj?6nX\g6DO1yDĘ1b@J^oȏ`/8iDɋZ;' f{[O_a|Ӄ/YhP汏VJ)/`0)1uVy12:W,Q"[?BLnպ1 `v iD,d4A bژԦD=BHoM }Z)7JCoܱ'ў٥PژI$;ڥN@^i!6 %F%M+1r/wU魑VK]dr}E*!!;,0r݂Ym}yegAJ_ƳǓkh;E [3YmRL@[C;;HÁmHaV}3ͷZT:[5>/F >6 YH޼8gJ3ڼ篯UP)uQD=P)o_ᎄP8\GIz{{J+xF EJr>^N=u!ݢg~PDk fKqP*PfA 1-Qʲǃp}_,~"$!2$첮h y`UtAߣ= /ks ?2}4J53ȝ3pg;^QS@=}I;j dV tu)LQ2PD;0%찠YbnidS2U 5"5M𶇐YJ }UnM'X(}U{p-AliX8G!r^,K=׊5ýyȹsQ@ML\i:m2D9r$l;ٲý/^/@vYsoiK!ƙpw,R`M&AH)ܜ-7~jlO!we'9؂ȁҬi'#S2 ^ '8KÔl*8=xw .Jiid: b;_zBmM<+\YA{gWw{;= {ؙLh~^<'YմmW;C:<:'BīH9ᓹ+wa{j~.٨R$ }w(i{ZY_K^}]F_gpSp7-01!$}#乳eai>~-;ZQY0X 4'Ǒ] E$AbJOV|97kFtrvڄQ^t)8^]PCb cG:2Q$|OTˋf06>eVanHJc뗘jl.Eh2sl{I1]ݲU|; ŶOZ n9E ?r9ٳ% 5{ER[qlKJcѾ[f_,6A y[w=Hk_6>%'^ŪE>IenU׉_$cfX70S5+%ݥVAҬ",~5|-|vƽT3)7ۿ2ıǸV<,‹iLp˅3x "p" ֍AD|q?uXmbD@DnZAQ+!L+lQVZJ}9 7q?OFr=47B jMd0*7!sAi}"Z @t>)UV2G0A$$GGzDyYG-A#N)xipvPz?oݼwqk`92Zן7: "ug&^HpFʝZyj30<ΈEDfqgg$=1e>?g[ή>Jw(2<-kL~(8Vm @3Ry.>(D4[e@uҶmqa )IɨĐhkik-&~=*~&w7!*ERJEk}e'&kLs5TL]~w.7ڌn.j>>U&/ mA\HKbۜ $q=MٿϾw*A!X8Duv̺df淿,C~SÈl|C V󽊏W]vl:\㭟Xk-M隶X1r'e1$1&,)S2!0)6uO(Z (B@4RW5􁌆#zz^5]R:?F)r4ww?{ʙng/{OLڶ#Rr֍ʶ,$5W&b)wiUoY,/ u;Ф_*1IL}>}TEQ8o{\m݇ъE($2}#2GPyъZ q޼9>٪nFym9֙MVɧ۸b$H̡t}*sv e.n(H2ZŘ:VE%Pݷjl:|{.>vU*0oNOmT50j*9oEdqsv2chDh0] E)R;_[i (-?/3D8cb45!@ʒdKgOd >-ίC)n9c,)$!zMV54m<.w?<7޸&YњD>1̮GO s\ pt\fd\]+&:+9;fMͿwJpR#M"(S|]=|yD$,,̌mڞAw*eLsiHG7bG0 >,  RϲW)}̗5VZuRMHn{QΌ1zٶmL`4NZ!"R‚BmڠtTx6@Ef+ &$:0A HDFH2WIbEkk4հb4ȗOΗd_>q{uve]3'swoa룳 7HI)5R/WbB@.ICɜe"SV6؎J7YI81pw\}DVp >\ףE75}哏?]pA^"phGv֧,L']bHRY*)ejޝbZk@ };9^T>ZQ+PʼZNp5uZorS~rW/^6|qx0Y $O">MpKM7PwamM?fg*~4.ʵx !݋Q~|쐰fvDmĝ}]?~su<ܘP};._n8+H ecusnϷwg/-" hcP]=Q.,]׋ko .fK֫y|95^-&OVJ,{j4ɥQL@cL IiXԠЙ[=6wvf]Su~. 逈[$LD V6b -sJ쌭uJC~;a`A,"y"N@k,xP:X4ׯns:H $"c "nA`NR,2:%A0*/ȏ` @$E^(kϲx,<[Cl8-"(r*E@Jk킚*Dffb HjhJU7,>P}cIխVFzIDH)P &BxЊܤ|xtb'ſ<,I%>~SO^MnٟO~RYۭ?8F#PL`B9">EaZ9g`Ykgz~U&/M!Zs:A.!""s7 U# NMW WzPGBLVg8,B9"Fhܛnѷ+ ¦Cj7R:s,'ѡR" o>LpW:"6 ޺ cN1LtK=GyMrv%I2oٕJ$hW]'_;w9[Q0(mN(EACulO{C)" >)<[7\A5qljN- n6m)E!ܖRb(!x8ٓ)p[E ./ei^F%4ONbetz>/GL :=%R*[nVef  UB7(FNGU,RAJ߽F*ƾ{)fvBºg3zxhpt: ܊!Q%e*`FAHaDT !kcM}ݟIsUx6W&U+7o$HI|jGԈABuXC>wBԂ Dh8rlxKyCc %|AP9G{J0 6mӗ/l"RҶao(o__\&}lVM[:ַ6BP$,hAF3ga[eӏWa`@mrJoߕmToDCRJYzܑNXЪӋ"*B QFTJtdzY *H9,BLymuap=ڄ"*~ev\\__wͺ~h 0z*+]\Ŕ`]/Zq^|#,hľ"'קi-YT?"!&aOM0#Ư_cQvX(O֑H)faT JuL0JnVADCi2p(;FxP"U"%(umu)GLkWNf($rgcEɮw]"}|:{bqhztt_~̗f>o{ DDBC$"YD2&ϲm`ybJQ QW41ϰ*"˳,aw"ӑ  )Ut0(]P ȸ&^)~yNjή(B(2ae#+ z:9 ҉&ā1~9N] 1ggvZtw__.#{7?zY9ћ)S wWÛjؚ/mƷ?KͲVdOpl'qE˥%QPnèsZ}+?A;r@SzPBbªn0%=(1%X/1\|6 U\/fxeͽZ1(G@QN ɭ'"B m\BH%]d2ԫV7+f\4Sm ,4R@H֎c g/7>>9g_-^JH'><|<rcT7t瑬7S|^kfۥ bJqNE늭~yۯVoLbD`Sw)L-ɋKZ7Us(|>G7!ɏ` ~UV6d2 R"Bt&j=*C;jVF+B얫p[QVDQc!}?:D4Wlj[ͰtO)hMF&gMT*R8H؟no)UV |o8%!)_|lͺ)av#uh9 Aw@$1hmtg1!A9,uk- @n_S1IkUAFBJ!Hu#NJR523YNT#jww0rHr>fDD<IDBE^eq.Iڮ A)Wn؝FL ;EkLY*xzr~.v"?ڍ!UnhbDD8]Γ\_F(A R9]vppf ,K;ݠ-3δή8xOB}4HQjg"KSR&e%Էpx$l>9w 3"@H"1qL"00y]@]fM53 PgUDzٿ.ΐe\#0M(*D@Q" Av|3-|'qeY>zB"ov÷` d.9Df̨>HZ7Yo4ZM1զ]J)*%, C̒>?Iӿ[h8PSc "4*jøSD%"Z+k-")RMB#1r›:C^׳ϴ9ao1KJ][׷fkTde4( !h B"̗O>{t?9?:xuݣ79>=ݜ_xg}*\/|ĝfgxXoN>^\rrUfI+n{aD[qckE]VØnV5o".8b\ֺM9ȕJ"@uZaA}ZEPΚ$n}юGz@ONǤUTah)mswQ@t  ֦ȰjU˨ʝ\_jM(K;TJY*bfSb}4T.%ŞH'1tR@)+ktF%gťI%ݼe[ͯdY/Q&@.>9:/̤h{/]̩2#EH$;#탼 GǺ7V̭5\EAiIM#bVƨ&[j$&$3H"<|մ=l5)o;] ,@ 9o]L p"Rs"MvO}^" `!D9?1jݤAP."AQ2 3(ZS@jDѵmt6(Mo&طV?~s0"Hik|ԉ5Hdo Jk s{`Wٹ#)w?LérfJL FօK"m9qV RՠFwJ$iy^ z΃yQD`<,/|&1T,` w'p9D. 7~busy9VJnY$v!Rra#{j]rEp!tR8!rfkhR&vݨ'|BlѾ8O(T3Q4)"B5da6(yY˃QM//^˰"=Pã!oWGꎥ'v2#}XNGpc=Pَ յzuaCT~EbQ]5"1˪q^\ٳʓ僇h|~S!߹k}w7O/!h`rKJF9 l_-:{ljQ)Vae5FQ|JD\7ozn|НgBYpp?h$$7|4MDD-jmS}hL@LQTtZכCG@O " ѧ%+8͌ƔBw_~"cBg\_G;FحpXI qӛ-^->VV~*t i5bE*Ι7iP3/jIyr^nUݧݣ+ rub^O/O~xL?CMl'I^Λ!hmHf2ܽYYHvhno&|Zk5uq0Tbpʻ'FqgíufdWǥsE8&EݕV)fh4,'G,rh~Ϟ\^ڮ3lPmGc1":yt??kV rsg+M9 *dH0c%RNN-bTeWk;.cVaiE=\XF۔⢆VΪȨ$Dre40zTU"ru(&1a> |ܙźc!H+e*ɖoWpv!$YV\5Z$SF@rt:K85k`ؾ~JΛO8FMN[v<:%ɩi=H^]}hTY TFu9gNrw\;C?i~;P|E8wgٰ("OnR"yuIjjui}@D27Zi 3Jv@L @$6bANv tYƣb`g8(q?zZ|Qv4\_9kjUE94e(e$N֛9'_>zO٥kp+5iV5 rڝc4V S\{"K,E^6Kk,  r׳QU4ӪTo jA[vzf?gVC ?'C*r2Bp6ЃTZ{Gӡv*/e:1LB`-="ӗd2'0* mê[VGLtv!;@"!D۵,6"@Чԃjzʲb]wJ 'O=[i;e, j*ImǨT{Qn^gxOy>:8H}eq`{q%<.S#}vi^s)y$ L*2&J)N^>$%02 RLnd4^jv-C ӿηwuUV{_Z[jBghXMRLvuH)4*2.JkZ4MVc;T)d(99]3ZscDC\Jkm[HCs 9)>/Q&RnOF8|7_7A\]Euԫ@dY>˪1,Bh.^Rȉs?߽_~/3w9w>; [#iznH!}ffFvMo䚼7֢3n9<^Z&ra S< H|l1!"(\VD>t;2jQ+ATp(ZwݬkI]߯)Mt.G7U>ƹϮ")!\-&{cc :#ط ubE)$Jjm*LIn}hB>p|BM]ҷ+E8PȧL)04i:~"\ln skBa%pVpeV6"rC'N5"]sflP.V̀M;Ӫn ""&a)'~X֋S4vy[xp3a盶~̲#-7ڨϞ%\σ QkE ʲíO_vDl3Ms 4syLU $T1`^9Sow"+g"*ke28kA`XxEzXҠt g&!h,#ڴ"XTUIsϰp}yb\>:C4gͦc ~I V*1-øYDQd<c|pv *Y<]Wyd a\ŝ-I7"= C?qisR#2E\^fLiZ?{f!p0FkIA"zXFefJ)E­9]-"K Z 9Р1Z#< V!d6EA `7J5UaA-iX%q|z606:&t~i/F%;c3[ܩez-g^T' yTBҸ̪aBDh&>J,dZ:-zBH,>Yܼ[#Lҿ/(jKUpXx:DXc9~o:_~dP]ge(Dz~Walm}ow7lUҭϮμ_w!bb+R*B'FQEͻ>=TDΘ2[p}qh[cDTzz~4~kʇOqN:kK"\IDY|Zr~zC}خ{W.$s[ļ}Vۘ":$"@gY V[gwכeALюHi hҫFDdi$!Yf!mu(1hCPw5"YCݫui1//erg ueF,m|H_o>k\VjG@m$O_41tV֨AQcQbzn)e""m/J`WWoO^uU <3~t1Y%A^kgCDQφ)Sy,Z 3O=P9VxӴVk Q26?#DxU3*۵~p}H!ĉHvu;Q;bM/N7Gɓw_yVnZZHOwFIJ#3 20hK!QTz6=I}^3szڿշOi冥owRH%Zz-JfW ">$E "F^zzTX\l6u@fyQy*h03.NUobkrOeuU"SFeA&RxɄH_lYkeuNcٴ<[:}QoT*e}HX6!"|9W`Tc$77yxw-6C/P8,>*g M\)N(w(1ߐ,ǽpV6I-KO,Q>$:qCवN,leu+aB4BY6NS=6zY_tCbdYc쬱w˖:8*uOb$rɰ. olbN.: `XVyJ^m$Df@[mגBLjĢh]wExXI*TR:|t5=\~|t_]_ } ?o|Ug=xt0"n:g#R)%۟x6LF7~h Kf߅ Q9ThpBa}SY!DV 0m;5sEd^Ȅ`{Xƹ,w9R2iQDckL".f6%G1R6 Fm"Ew}(CL {ךp黃tbL"/O^?1JCl(hV[K@ 4E8wuj,U9Ah(Rni(AF ) }n J5䤍zzڌ. E޺+8s7;G8>"|A1%DHEVvY 3w%&N# @@$}@Tf0(to "EE)BHSuKG;Bz(` gNY11*v*Mgm.(jP6Wa(Jݽn^dYAb!*e=("4]c0DaRJіtF_\[y5K]_EDV9Nե[WRz?w~?'qdܭt3g2]­ZֈhUȇ+OIg6tZ㪬b ćا'Ue;X9CQ)$e#3+"QV֌16 ̭ǫ"WOFDtv㌱Q=ɟ}_ze٩*3lQ8tݐ"p,Rƃ,Xd6"%Y`)tt}H lSJ|y(:2`BTJS,H@H=#%uGw/y<(sfu"),s'fT2MdcJFa(&QBQJF@OG}uzP6յuJ)!Vl{Q&e`0MYP?3U}29̗Zj{<ؒq)t~biӖl5SvM#RLX"Dd!NaR>:DըQw6*Eh4aTM+yIe?;Wbr< ą#rv& JUxJ3 !JYk3BbFۯɪ*9F$!7jP"q.SJgVm<}4_RĬ*>fG!zZiTUI 󆈕3TyÇVAPJ+DzVO!̔F&e%AN:sr>]}yMcUkt-)F ?tם~f;J(ڀ1"t"B[7-U|{gp5製>lDZ1Vpyq02w?DTחeww*)FANYߨ(خz<ڥp9YmhBD Bcv̋W7}8Cr,ҙY_:o//b^UŖR=}t\|v3#"$ﶿTYl]MDC1rsW?~8,jY#j`'j3/2Oh"{q˛u[Ϯ^d:JDRLyf"޴ȍjR,,Veo@Nj|HɺV):Y#+~0<EÒnIx4)&_}"|n807%3T(Mw5ܱ77G"+e12>{m 4E;^ @6RLQSd[ez᫋x&t^(Bf£uȬ֞WG%6Ll dP>,MgRe9B0HL6T< >* êS^ KH4WAarg [I7~k xs h^_?(%icb4JBo7FE MbB~g7iP"T7)qHLY_^/ѝɛCgM0QJҤl*qi# U,g6m]pjsl=D=8rexZ_dE "ߢݭOev$3q<"&YK[cm(|u10OX7iwgn戔\+Ŝz%5>ƞ0vky}= HY5 l⦕F)*P Db.rEen,ڙL`0=[#)}37ɬ.2 _M_8ՇXdicLPe$Ф`xuN&jQ ,sSlY@;_jӐp>_mҰX8JQL^ F?\ןή Dv e lf;DN F !ډ|!̪*^.ta ۈ/.S שtM<=LJІȭrEt;#Sӫz\\ R11nj;9鸯t=Ab5ΤɀJc hwHqݓ+,˪-&,zTrIEWK@D b(RJU{o|_M&)ؤc(&پS]=\<]vEAL)1 &1"zMrU 5I!3(]u/N?/;% C?,Dz< ڙUGl"<{}NYF>aY6ed-"jDq-4@pվ%ByF0F3Gkn-vS7vw޸n>rV*];*UXNKu;:)Ȃ0S&t5jwG MOVknQ![.Mzl#r` ЇbMH"ʚݪ)>r㌺\dMׁhb{TN2K@?_m MQL5HRRG V7> *HYb'M|㮻|20ٓ'aȃд pry3Jfl37` F `舌M-WLDMR uǒg_~u8 UjXvsn,t8_mx~9yl za( Ls0a!8tZ;ɟ02wEս=>Et;)&%,ƲJֆH!bby؀"RJdo2l̉uH0)d"lT: 1x{BI`@ u7LP_^ t0Κ˧O/ʲU.J@)`ۯrխZ3#$x6zuek7kK~`/~l/ѨĒI) ݺ*dYGvH1@ mpЄm4jg'G/l_{ReVܨxOMv-D;\%w"ZƔY4@ir9X4Yc;ReIDATOdnoq4зu%(7k!$Dt'ZJj%{mUUSq۵p$ACic݆"ӑq@db )閠j'L\hє9Z3N&s|IfPXD ]Tw\?csv@w|:uJ>wF`=%,m*U &q9D֚(׳,_84Ҵd9z)ݻkF`+E (` - l?Iu, Ӣa43)|zJ<:dگ=6] 3PӊbJMbdX%n%Td^NKL3oEhh 8?7xٞcqy{&VQt1ٍHgfkrXM*"8!!q" rg/ *JPJV͇4fȬ/2{v*]؝VۀJHY6z 3!"˫ݽ8ɇE0^^l3/|w3ZW`'Z`uźlc'֧˺y;ܐ1>B^`0}qwv0m];+A(m KRR"QD@{6DZƸaY]$҄zT@0mtF+guf9&r?5K;<1͛ceͣJ%ɢ$2vF`L Xm F-ZR *RfeefU޼3wcr/w/܍mDUY+"~< Bk ˩ 4 w4@B;wl^QcQZKF+)qoD"+tQTyUX&^EF)ֈh,"zV,,pĜe|[~n9˙22 X$Y!(gaeۢfEuF"{CǦ"Igxw0y_uG d4OV:RT6+KWK+0<.GaƵ/&`$JcbdIfp/^^W\xYӑAޞl;Wmv$AR"ɝC%g& _Y^YR6|sA)zj'@X<+=Sw ֆ; 8sޔBr=M"4Ƨ1+j,qNs`PyQBH%w[Th[dLVQP&#K-N,Y M>idQ1R!/3rvT[;A JZKi'D%GT#Q?`*<ԞƈuXDG ="$ !P(s{趩wx}T8}i$ݭ\%[xjk&/w$p 2Ɛk='kV64VwyiY,wG"+hdIX)hPg]RI֌oy_ҁGGeA;MZe`H;kN 3)R ε8H"݈OI@YS)Kxɢp F'K͜tiÜ 7tAg98B+yږ5??32_x)39@8I^۪̈́"H0`41č$L:u{x钩y7q-1'w9vWDdYZ L?BeV'BZ&(3GLJf=O҆' 8;1mD1JiVhbYo%xx*8 :'vюV#ggF}ͷ~vB΃_N]ctڤL)ֿ+bicC2Jo?TDTT,cB_{/j6E(t6.no/bQ^z'꽇7_ʧC&QSOoޥS~o'?xewz~t5CL!d6((R*S`q,gfʹqqScਸ਼Z{|x &QXc΀޵9JA:-Plzbu֪jgv??%nSA wxf1yV$Hv[!*mzP%8˂JĢ"9m,4"Ic>٤ISi] qUq /Φ*sJRqџd%0^ 1yD¼X'$ !(s 7N_2x4K6ys'ޓ˝l~[qJaxX6Is*=ĝ4硫~څ(Ax]F[ UnOH D2;VXky@ƙL8+1<‹ RBsPLhԎ%+p4BS+};~ dUaL~NGWVsNLu!TBN":tM!%9otֆ@p$XF)K) %XV%'~G~&[g?(0/} 9"c{O ieJ8G[)W<)4ڱx<'Zͦ6l ⵸9|sHVA>x|w#&az;i&y^p.{.6z|ݥKhycVJp$hn|@yH3?Órqe?>8idӚЀRFqueEkw[MBֶP96\pm҅ @^_WIF.r$" 9o. 3c 1#8[B<y3a(i^jX\$i^*}U'nkC B)c"'tl&@\ht)c{PP>(_*t7>#!΁0NLV&,q8]i洁R,aH9Zcp&%{JTU  = )j֞':N fEa91B@0ktrFp:-Ge6/ FsdNيkD6*ieqM)lLՕ Xp5!T S8)ZYW+۲?מ~7G52IJIQ"|E-cuX6b;!Ӑ0 k F|gkݚf_I)cR[/&|َlcwE:9y~7}k.*Qy>OzkGOKVר|Ӈ~yV7n?מ\=':I)f:j6R=RMI#@8%mrJ_Ҳ6.gIȒ@E2;m^. <66V !C#S%#y ж5FO`A9C_XD<ÙWDJYagYJ(+BA)˚ǁ'JB%8yQo BV~|׶Qr E|Z.AG {60NwڔpDP ϫ5 D$`,$P훣EAjX$:CV.0L[3[`58FuUΣ+e`Y@ijT_BYNB( %\Z~R`TveSU{YsZq#:ƻQlP+ RA^c?g?o}~嗿t6JGI$Q*(F,a@p$)"Hq^y{4 CN$#V|REϏKK#JO|3b0M-=@#֗Bՙ1n<9riAs>{nn]׶^Vx~mX#$q`|JLV=> qF;)1n4U@'I%xX[˕yG)Bxo ̈́}wBpJ^+&"Bzֆ /-We~a mɢ@)bښL=x߾UI=&nJxqfȉH+U˙KP!-u:뜳SϦFrb_};<;k g`E)!EDBxg#p*"Rj)) 8ﵰ֬`Q)9D1wlaw֭lJ%T)PH@j%68]oܼY?ȇ~U/ӟͲ9!I;Bd6fE= G``lM@1ƥ:khuhcUYJˮ=o~uX:INgȏqjt0Lf^otm5C~_>8>j;_\oj Wֳ--m ڰТPZ] @(%!Q BhfH={ʺb#HR)YF]_u[ZA3 Nř^dCSbiK '4*ʻR+=¤Ev:x!*v4F&TRfJB^42^Xhki'Ǔig="PP灠洛 %g, SW* H:$4@ ^{c5ϭZrBh™as+s@@7;IYA" 21*Ƭ/>8<[?u^t#5Z]t'Z4,Ve&; xJ0͵{o4d2RlzC)|w%Ny1JV_ ()2Hp!|r.LW4b Vqe"cON3f-zͰN5"2h\(g|VRQ[gj#`k~W֗O.uټH-"C .*LBΉ @;WM*2{a3iP)IJ٤(uJ뵭Ut43. M):K~7?O0W6e{A-;fKi=,7+N? K,N'F$ D.u=դn*0piUPkic B$;穠> DPnK4"F؈yiEYYA@*D8h0&( #mK.R7):#suɨCx)i^)EJ&˭8ݵ$$iHU=^nIPp>[OcL_~jh O3*9>> |PyC1rF,{5h nQ$[Hh+6;R+2Nڈ)c4Rzs4q.l$ϾG~V9;,#w=)R[rDD*W @J9Sc<U]))U{O'2L 6s!j NH;ǻksEJKɽ DYVԁH`jeuU4oԔ4-Ũnj[i=2t~5&\s{ɼ b9(ZUXw奫*\T5?|O?[6_dZLC) m(V`<﷉uVS*dcSM9|:nF5!ћ.|Z7_g$8 OǒvOO VuQ#.ޝHxjr+FݽP7^R5ergcl2]-9s+{иGgAN/aZ$?(]!p$ U팵8]@:)Wj҅B'fYW eg1i csS(|ָ0jsfډfk678,L)mxKCbAy91 Az$sdV''B|̪[xmN~g`JX}ꍪO('YYWR/Bj0i@#ZJ vVQ ֔qq<<B+8#ĒEYF! :k<]Y$H ;y`ÆらW3 j1S@yx!`/:]T”ɣb*D_7dXx)ng5>_FK2Mu2Lm Qo+sgUTt'w)LaPJ."Rc\ ZRO>9Z,u( PEHR3΢P zȳf.fgqw$88Ӎ=ӟeZRy|t8@fե;P5 זg_Nd^kags?YoD4J*()o,X ,DkfaJQU&]YSJa[ЃC@JKvluK>8gqwsh,V6:208glyyh8]ʆ1l,Rra( d^}vf  &d"'JA9燤QZa 3e$Oe8BY|2*J4n&Z Rb7u_'fPb3BRNfsv(u}9O]!JZ Ͳ)ۄnz:mΚ˻g[CDiuKo坝6>\]kgJUK[IK^%XQFem=@{1D'${gje7SvtO@0w4KMkI TK^ƎcRR"zo񥲃<p"fdqK2ߴw` |^XpV5y<\$wVFkmVRUJY&OO)6zv4/n> y6ʊ 8qdҍGκZYe  ~C fӃm?1[_;,jBX"4qZD:_{grm$־VkE5R5TītһY_xzcm5BD\7ziky-uoe~ Ӄ_}Ki%D^;֝ADγ8i0z-\RBځuF)W:ZRTSeU9׌ vy{y6w; :Lku_|qtQ8j6eFi.Sb-Թ6MgBVcWd/ AL.Joav`2:|͍JYR Fs 0J[i&|tQ up yM9IDyE@x@FDDyP{@6JRɺ JLy+t;$Aaƒ#O[i݇{v|.L2W u6"I7ƍkϬ_Ni,uPG҈rut\Dq ZI^A} FYYW{48gyS #V%A# E}"osNN'r;;s`)-R%3Dwŝ'vR7`PbʒV#OgVj95HtM2R3J{q8V &g?zSO÷Wx8i]Z ., q j+DƱ6yydы(A)ND1TOv{+Ato}4٥dM\2ۭu[}Υ'''w҇>x>^m擽->Ow{)JJ~gEE F"2l$˺.z9cQ(IƶSإl3&@0JNuΓ8ZO氽]kq{WOc d0o3/\1W4q:z,'WyfY.'7~ETUNq{i$t6:<~gei/=n\{/پݧ]+r$^IQ@ڭ|Xjr8_֞w)_J 9t"PzBڽK˓>"Z|^(BB;xz3\GwN/򯜮09Όqas9?it67.~yUn֊ fC8;ރRcw X E6o$ Z\*j)bBoޛ\ސ5re)ym;Pi_~NZJ97E6B'٩Zp>}bB<@{+9,W1VOf@8 BiƲ0jVun Xsgjm9],-3JunFs500(2:FKonx!`VIۺeJJ1&A*9a$G‹:8/'Q^2o۝JKIuNJ&jk4B : @@FBH}QTi9"9EۛƠQP\vZQ:]\Y +s۵mVo`&uFcm85k`8iBI0Vz4{Kth?l4W6֍4RFIsa@8CJhV!rmaF97gni$n #.۔vßOvO˗߸ʗ4^*[N/?QB|;o㥏|x:<ӳ(n b1F;[/!bUV\p(Z<;{߽P68j{~ݐ(XpnyQH(dd6v1:oVퟴҦ<:h4i^=>mnm1ѣ;"°'@ )eXU(%cTy x(fd&!Yq27Ӥ2r67EMnw[ lSkd ĕgV7wM$QTZOCz : O4q@*g$8>MEQF2|,wo$BDGh.YdE R!" ywWyKY3@2A%LQɼwXSU%D Sbi΁24J9뜶lTU_C廾_.2OƗD'4քkAJA*{(;Mu shE˲.Myuo^yW^~NnkΩl>o౵UꭍTۿ zȀ?euQHxz hg HI%SdQ{OF smq)L (ghSb o6)^;KZ)e6 )O}e5ݯls&w>WIrx'?yvY]C).-wTMGn] jtUY~^67e18~xs:?t8Y41"uh;K]F^l]|D]+_?ozMHJ@iR~ÝMU]뉝+I}\yrm\K<|(}AG!!wn^>ag "֖V]ʺVW/pEQzq{iyyWX_x2箬'2W~3evwx ܉- uzF[ R- 7O;Zy)zl!#4)Fv4>V&Z&TR2:0ٜ]WYe(-+T NnJBit})IB(rB3 S;Սi 7wv7W$Iw㣛v1NU'i%q,@ptU88^HV]Lg HORQMHԿsmm{?ՓzPQ6/#U%˽˔[泳bM){uћoJ:oj{Ȋ&YQw޵VKλo5Kuiot٤Sث\u <k_{gs(Zih\0JJ$i,PFXVm4vH#%FHPpfgc˓ %)k(:1+k)#c 1u]e=.H]Xk+8V.`4_oZ=wAH N'C׌:!`ZW:9J(,!`=+g+FVVxNbZV DIF_~cONFJeE~п|}|o/'|9;~ź\h;qo J`(+-զNYW6uS aŌ.\FI2͈-lѴsεxsu \*3z l0p" g #{''R[+e EUZ˚I@)ee 9BEBH(2Sl4 7=2Fƕջ+K٨۠Ι8mMl<-:[apib|m[U@)nt.V3%~''tysb}no<i&"} =opw#(eK;Ãvgc^`I8prYPjĨ B·J$c]i9ijM7M{"e*,AMNWBFh4$Ef ks>a<.SƈRY%Ft@oJBi՝"qPgZj; :69R@%!n/\q;. +8Y6g;7^X A|GNҌ 5c8V;˘WuA &Vq4g΁|~k1O{ۢiܘ-i$:t6"?W߹F=QJR0mͻQsʨO+\M` x`:ֹnc|2M; өR2D|'ȦeɩiN-8gp (4'!8d^%"( i~'{6B Եm "MU]P q)R5z# + P2|֝C(;G999e}On?^lS. _hۏNO]n מzR5y==ҍh<Ҧd8sYut:}#}[_Zw'@@F*7vҍՍ?bn,i+I_5oƼuծdn"qOFwW;uLj] 'p6z)#/ajUPzv:+{q%/YYg9%R_8P`Yٜ4w{3=yP!RNR`aX +]:{KFip֣d_1b4rx@O:)3SD0QجRp}7]Tӹ)k) _ѿ^? ?7k__H;V~28+~%RS2+^H|ݽsE^̋b>A s8ΗūW*el1qVJم>>vGCH&(PqXE4Z&q0(!xK'TY0~'ĄCMeI":r4 ~$-],Y 7ـ.xó7⍄ y~}rK&:w~x7svµ~oo؍cЕѫ-致sjj:LRT3Jt{pVNgm4){YVTN>{bw,<ːB8!Ql7B rkmmxqyz 5MG_xjbH f; 2?sAkZ]?{ó^=Mz \CƛF[zf+'?%> ഌZb|bu^.iR{B:OSkRO>S0,rRVP^R(ZJs87C@O; 0NyPWy8hk'/\Th&ޑA3%YL'$b҂57.4^9|b](fɷvL'uׄf2F$Q(kfi^ZbW/0A?WZ.9~]1Ã:$?9:;Aw_U(j#̼;,x_UU$t!PJaVr)VV TNs kcU1O?/3#>w羹X6$թi%Y-@3^R`N?D3?7n ^o% <܊YVҮ;?do߱q_~l\X@E@w_< Km=Y=pH%@;ѴX~8͟(ۍ(?ͯ-U:@B`׮YkNOz(^Kx,(y aM=<ᦊx}TY8K{\t2.Fq?w^c'~_4B|>Zu,7!i$քtnVмcHJyN볙AУ)a$eD_@07yVyUQX^VRNMzURGO2ʿG?o$QU)J)$ (dL`H.y37]XzEJй.,)_G:,-׍fJQF^h$Jtrq/ed䅏VV?>#rʃ /Ν_`}hY{F=x§n7}WϏރؚv#]oJqtV\.ub0NwkK@[Ϟ'g.vGވRvyw<Ѫ>lGF˰P3 Wff7^I2 ;zy߳O/o IrN|anޜYD~_}Evl Kd'e#*X[Y"3B$m.VyG~:z]}'?_?w2t)I"?E :w 9Cp[愲 Dg,P*#b+6LOV} "ZJ@Hlۭh61IÜ{@Pm|]tw0޳w}Oq?\[^n+w%+3W/>u5_<%@zj;᫷.?뽃Q̵Pi`/gR*wwPo0)<pvzp>J4<@C8ƳEedS/lQl ֣;˽޳7ɒꍷ9;q)c\ ޻YtIUEiHF)j,PZ[g ap;`hF,UNXG I(bs2-'?ݟw?:絞jZGb>3@8s95emB" U GTZYVMh 2q癕\3,IeGR|'+'ƝGo }Y^7=<xz?~G 7Ώ0 ;++F3}'ƭ6Ţ rJʵ> \tZr:sՏǍKLVw[F<8kehI*~8Ȁs6)(>9;\#`Q.n\,W]mӍ@ \q 9E9q4\buY47.t{ߺO4u2⑾yk֑=tQ%B8k[|,ʈGB1sUɊ9WPkM387Hw;"=zjV}~goQXO-FHY׭eifVյb|a}PBfs>_V8b0,tf0J?q?wq&s[GvM~c _O҆\rYzYο~sۗwnCf\뫻y5:[Yb~ȳDXK˖Xlm5b+k[`o86JFeZ(֚r6:Z[<8% Hy}(3( 5w[v6y5zl}yVƠMZ0i氹043+p0)?նbsc zai%[!CO+c^=|Q+K*ǚ <㣤ws/&GRll%E%:j"2z"y>"quBhiPQHƘ< lq 66|NA0@L[~D+۝'scqBiQ͕ bX2R x} 륷o2HMrJSGw89|" ׾1;"}wo`ylI(!_|%̳+*,U(y6l`X!㩱`^燄l? 8lr'f}cs6FEUm.5ΆI_{އ">9Kkh62ͳ</ɦ,$j|_{sQ p<-\݈T('jwY9i~o{y_jo?_H2``LVVpPV:*Ew9Vj'6">BJӹ]dNWqd-q?\DS5htQoS*8|<-Fظ);^qyu}lc e>7/ " ^@Pjeɰx]4m|knllz1e"]}cRVPu4ե;{k=cunDqk2T $t8)2dz8o6Vv/`|Lwnẉ0n5$JDYenPv m?v˯r'Y5Q@h]9 ]*;~q?^/Lv|c& oZ|r?37cj4z) H/-Y,`2fܬ1-IGGCGKۼ^ l ^;bIUͭmT˓yhLӥ||gCKIEV7•Z$`ħD2hi<:f#FֵA8z})9GpB|jrΙN&+ցwvW9 u h >9>Zޓ$iK$'|e֗Zg`g.RvXX5UmJq.9f5#B)L, ?~~{盼3V{>/u2xt[[GXl2JVEUᩜèGǢBtzyh,.%@nڍIVcJF{rk/2dVW.xNZÛfy`4ZW#.C"eG#œvO0 _ o޽NPJ[+7fa? bnurWuU˛ 8+ꭵ!Rkh ?xXt;@óq0hVpjeB# Ig-N@+OB)6񞌦%8s0bW^YO'j8"oT0RNDNfZ+'(5>}\Pop[:ZЕn\p1^$2}`B SW/l1IXWy_GƉy$YQ-A3 $rz8qct,D,{[~ fGYFYiUj󲺺QtnRHly[=˗m>v\fOS 8Pںi]l6ޢ4t ;gR{ǣn4euSUe;ѣIv<ACfgzQ-KXN| CSw!!Lf4ʍz5?޿?<՗>{?DV)Xָ0v@LJSGūh4uK-ʘ${5S˜obR8ܳy=f՞1v0QȄAOj K|u5F9 A1-28⍾u?ZO[y{Yחۄڤfdxk64Y`4 ?6[L+U[}kh-7_z2'XNqxk[шfʲ5GϾS_zxܕMkn`,n`^:BR.轻ϥpt7/k)+Y^SJOjQFNAL/Y Q,1O0/*kSӬb=> o=>{ʆ3;+qIGp< G5>U[WwFdR̵s~Sfk{^O2}U|Kj0hn~⦮|sWEk^私𰹶u/HFh"4u6ƵbWn+ك:q3a*Q{/'8u^L,K`NWi0jYJi=NFy0^TQ /ږa4~wNCEY=_yFrLrkE?ruP(۬LJ_=/9i >>0JY>b:(Q;C E>.J64j:(a r#bIAP08N>>uW% #include #include #include #include #include #include #include #include #include namespace Dune { template< int dim, int dimworld > class AlbertaGrid; } template< int dim, int dimworld > struct EnableLevelIntersectionIteratorCheck< Dune::AlbertaGrid< dim, dimworld > > { static const bool v = false; }; template< class GridView > void display ( const std::string &name, const GridView &view, std::vector< double > &elDat, int nofElParams, std::vector< double > &vtxDat, int nofVtxParams ) { Dune::VTKWriter vtkWriter(view); // SubsamplingVTKWriter vtkWriter(view,6); if( nofElParams + nofVtxParams > 0 ) { vtkWriter.addCellData( elDat, "el. Parameters", nofElParams ); vtkWriter.addVertexData( vtxDat, "vtx. Parameters", nofVtxParams ); } auto pos = name.find_last_of("\\/") + 1; vtkWriter.write( name.substr(pos, name.size() - pos) ); } template< class Grid > void test ( Grid &grid ) { gridcheck( grid ); // check the method geometryInFather() std::cout << " CHECKING: geometry in father" << std::endl; checkGeometryInFather( grid ); // check the intersection iterator and the geometries it returns std::cout << " CHECKING: intersections" << std::endl; bool skip = ! EnableLevelIntersectionIteratorCheck< Grid >::v; checkIntersectionIterator( grid, skip ); } template void runDGFTest(int argc, char ** argv) { using namespace Dune; // this method calls MPI_Init, if MPI is enabled MPIHelper & mpiHelper = MPIHelper::instance(argc,argv); std::string filename; if (argc>=2) { filename = argv[1]; } else { std::stringstream namestr; #ifdef DGFTEST_USE_GMSH namestr << "hybrid-testgrid-" << GridType::dimension << "d.msh"; filename = std::string( DUNE_GRID_EXAMPLE_GRIDS_PATH ) + "gmsh/" + namestr.str(); #else namestr << "test" << GridType::dimension << "d.dgf"; filename = std::string( DUNE_GRID_EXAMPLE_GRIDS_PATH ) + "dgf/" + namestr.str(); #endif } std::cout << "tester: start grid reading; file " << filename << std::endl; typedef typename GridType::LeafGridView GridView; typedef typename GridView::IndexSet IndexSetType; // create Grid from DGF parser GridType *grid; size_t nofElParams( 0 ), nofVtxParams( 0 ); std::vector< double > eldat( 0 ), vtxdat( 0 ); { GridPtr< GridType > gridPtr( filename, mpiHelper.getCommunicator() ); gridPtr.loadBalance(); GridView gridView = gridPtr->leafGridView(); const IndexSetType &indexSet = gridView.indexSet(); nofElParams = gridPtr.nofParameters( 0 ); if( nofElParams > 0 ) { std::cout << "Reading Element Parameters:" << std::endl; eldat.resize( indexSet.size(0) * nofElParams ); const PartitionIteratorType partType = All_Partition; typedef typename GridView::template Codim< 0 >::template Partition< partType >::Iterator Iterator; const Iterator enditer = gridView.template end< 0, partType >(); for( Iterator iter = gridView.template begin< 0, partType >(); iter != enditer; ++iter ) { const std::vector< double > ¶m = gridPtr.parameters( *iter ); assert( param.size() == nofElParams ); for( size_t i = 0; i < nofElParams; ++i ) { //std::cout << param[i] << " "; eldat[ indexSet.index(*iter) * nofElParams + i ] = param[ i ]; } //std::cout << std::endl; } } nofVtxParams = gridPtr.nofParameters( (int) GridType::dimension ); if( nofVtxParams > 0 ) { std::cout << "Reading Vertex Parameters:" << std::endl; vtxdat.resize( indexSet.size( GridType::dimension ) * nofVtxParams ); for(const auto & e : elements(gridView /*, Partitions::All */)) { const std::vector< double > ¶m = gridPtr.parameters( e ); assert( param.size() == nofVtxParams ); for( size_t i = 0; i < nofVtxParams; ++i ) { vtxdat[ indexSet.index(e) * nofVtxParams + i ] = param[ i ]; } } } #ifndef ModelP // parallel UGGrid can only have one grid at a time. defined ModelP => parallel UG // does a second construction of the grid work? GridPtr< GridType > gridPtr1( filename.c_str(), mpiHelper.getCommunicator() ); #endif grid = gridPtr.release(); } GridView gridView = grid->leafGridView(); std::cout << "Grid size: " << grid->size(0) << std::endl; // display display( filename , gridView, eldat, nofElParams, vtxdat, nofVtxParams ); // refine #if CHECK std::cout << "tester: refine grid" << std::endl; grid->globalRefine(Dune::DGFGridInfo::refineStepsForHalf()); std::cout << "Grid size: " << grid->size(0) << std::endl; test(*grid); #endif delete grid; } #endif // #ifndef DUNE_GRID_TEST_CHECKDGF_HH dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/example-projection.png000066400000000000000000000130461511655130300261320ustar00rootroot00000000000000PNG  IHDR&lIDATx8QV'4[(SA)Pgoߗ.8ȻW> ]Q鋋K4-R,n9f )r`}|[Vr'\.5|A9p9r)F2@uQN1pPc4N 4:^y2F~@E1v|[6:pO;LQ(֧}F@9 Y;B3R%DxY8"y1ȏrW%xE"LHYE={?-Hң(7:saFcS(kqR(ԩ<(<_w=$!\9𚣎 O}"a;k ( 6A@ P@T^,OHb5:3Хjxd# ( /"?sz iZgK1$j󳥘:( ʐY)$Oi2] $SҌ%M1<4:4'P$Ep-ӈP\z4N!uP.iwp9 Bc)D?IP?9.`?2;:Lqo8=mP'cjE.o^s[=wA9>Dwq|[bjT03trL T"2L0 1R*CZ`"O[*y8P6}t+ E Sd"897Kr $DZu%^uʁx*֑-v=h@0rK4Ai\TbKf۴)[C&߼ GTA^A84:@"=#B}'zuràvot>/(>B:fd`fc߈];ˆ ;r@|灪(QQ2Ef%C߸P7COf=md/s< #pfO$!f Ù8~P7TNDp vPHo.\:: DgP6p'o Ne2jDM:q`CKr|q,hqoGr辱:{b#!o\uN9VXOA9rhcoq ^YU8 @9`M߸eThUrQ:9oB߿ ;X̬㲤_t #rF 3XbكM `O2^Ϥ7\Dk?ߟ^?!͌of{8フ?y%wI?%t90L{R3c2gf6t90 |cO_Y3 y]Lx15'mMMO%CMaR(Ɠ7bQU{l3$I曠Γx~ N< }73F90|Y'oLYߖ6# G iλu&(vniC9ydjn _84i۝_???|pM>@b~{oȔd: }pȔB'x'$y1I_ [qP1&XNW&Em(|B&9[*˙͟(|ˤ'{z3f*4*(|cO% ڝ4 nmZFr7RD_g }zDtl1'k QF⎇N c~r7OSawAZG9(?|j,DsgQ)F[X[KChj !&oCO%h#ge ~okM9EM:ʱ~!XoҠ/jEu6թ1MLC_;GM:f9r7-m66zYc/9l (|p6@)b@xouN_fdBRw IgP:cs"+졜{ԝ0o í3c4e ʹ3gutaF3GϒɦrZ7`ό-m*o Rʦr7ȨvgauH+KP5&7RP5-o z[Iʹ߀}SxbK6O@95 D_8:/~7qWmN˅or:.XaKtXf:eh'QAu*ɛMk%6I I67 `T@+@)ƭ TV57MճV87/T퐷T(l$o;cGP9Fd y`Ly6娞RH$oGfG9&^Lzsy;2)$7Z=[ o6dPD)?0z^9l/f?hz^B^alhF7c+߀1TO*߀ ¥nīgAH!o u [=7/)߀/:e½nUOvM$o@2!R7 jճy;,H7YЩț;ao@ !X7 Փ}1o@![7  |PA7ԕo@n'y`?G7͇6P,XUp]BYpyDT91:^JSTpL됷:-r @!A,[)|q[͂Y$o:LH93ÜnO =r @!e,ܟ oH(@օu0z|`!o-(fsW(,R7 Cb|Y[+EK)@n? "vo6/²um򶉹Xˊx,tTO5MMK7#*o}@o%{דHjl._]Ivu`_K鳨N^TZ煢 [ t#^0TOL>򟚓j6۲jy:ϼL)Azk.#^ G 5 CYo_/ ;v^c>н?.> ltO(?hsFMyv&hG[[N8=KPjgZ&'sAZ"L $45*e\D^]PIA(T]1 Z !~^OC~?ܿ'ۗ_dy0>/Nya/}>_bue MXfqcwgw| J)tnn.=zi+sf?0u+u̙qfMNNNNN]w_4=~x.횛;|pt=z4NNN9s̙3MrnnN<}Î?g~m=z֢l? GVj?'wSJ}?k,/1iw5f[#o6 {+(gY-q08~?=U~NLLLLL\ 05>|0|] L#1cRV]*EgDZF3"^b`?+wĎA (gݒ{ߵmx{=o퀼3=}ثZ6K{{-Hb4%O I!}KwM||{1 XbyAr^ q}SN1}NY^Tw0 <,`'_S{} i!08l-u7*lF}N~*< I,4Z(Ak:G{ /?ԋt)F/:t1 {#u 8==}ر-Mff<^;ƨX@}7.WW&''O<ɬ'OF6???==}8FM8~Hf=>zBqPn"Zk6gO""O71i`AÀx+8@C*Ir͔n.=IBy٤$obQ(~ՃݒrWލX`濏S+)\ʎ"w\DFluCOy&FGG|7߳tǖ{~~ajj*ZFV[Nђc? /i{_|KqaQ"bZFBjwCg^&ĥ*QR,"u!ymg+C#Adc'X_\$"p<3-3ϒԆϩrMzHʅ7ho'8 bOr'$~xcK=6~o^ou\.bV^KR>Ug#qAżBB_Dܵ.50J42$⬇QNHR{6y071 ^ᥜbb(h OQf E.iq&fHHմ'}o|czd2~ˏ'-s' ^Kߪ~ȯ}ʆ_xz(f0I7q䪳K$Xig^&IBaP@R{8B~K  @`Q@ԭCLx ٥0=d'"a# ?vs{uȤفsSLOO"Gɳ?~kH&ߎUN ^ /&ceD Jq 6Me&!SX@hk&d"6l1 D1Ѽ&E/Ʒ֔E[W]u ʴ?Y_f!! -Rו-}Ex~k{҃g!O?gWn A W=S|`D A`J4h ".&Ġ4]P WdP@JC8JBa Q\gYS< ܄HF5hfFXVhYOyבsO# ûꗬF,,4 Izr37XsT.2Z#$ ׋Yx5bZ[Ĕq3[ ] }uI`9[P1#bRPC_+kR֧'GiȩI\ƾ/#}$@$ĵZ2~|QZK@6 ~`#<3.Zkl#cܲxxE:,Vf==tJ4"+"],4Md ɭ-څ@H %xК2Э@)v)pkTHxǿ=<7W[,;#ꖕbS)Kո˚fјncs'/iy,ڏZlƆIJM@:fn鉳KHQL2@)J$S!P#Z$Xkڹ݊nla@(ΥD)zؙoZ# <9`vn*e&iZ##A؃d'[FWb&4/cmgyr@CO!.P,ЃУRNgrD!'dhzo#gtTO|y'o7VUZV-ufjb|t*몆:X\j6!kgˏuV~~~ԩS/PiOzד &1%JBm`_dẀT&IC! 01賜2 R1 QHXLSg7 hb($мL>$ܖ:KWo6Y.ѹ?S>+aEC հ0V"dfOĬZ47ܾJe ~/L^OǷȒKٸ7զ{!= +[vSI\H:u*[~j Bд9 ,B`",ȁ^Iϥ D < l(NRxE9 >U*8k\$Y( %u d W'~s'wmBD*u ɦhW,qvx3%,{ud _OgyN؟˯xN-1ǘ8>)DXC) B,Isv))Y^Mv.bx?IKO@BoR^I0`^pvvvR`&SG]\_6]~ m@^>IrԄ^m77tC4[R)C)eN> /;7>mCWC"~!R#Ƕv>PRX@)rk DBdbd {6Nן7wGi-uJ_NQ6,_,PA#eD#o`6RrC86E:T_}3Ȑ~o@J'Q|[A> z;@PQm@B H1R($oʢwh| }#D "8vpN%y|ۗЗ?]/Fe(رM\lPjhVu/})S 'rTUl[q3?Տ|מ݃nNYf(/Y"&=9wDێAmqYG<"rȼBB4iW6f )iB֍J*[\ĭSe@t<̃!{ri l-1#ZW <_=Cp]3P(si/G , VWh؜J_'aPRJJ}e.?Ir4nfʲ8//r&g:^ĈcW.āУrSb[Vbhr"傸 ;cEcA}#L qQ89Rֱ]"4ݪ=&W}c4W@e‹b+fQ``YH9IsA`SNⶑ0쫝,o sWr~e䣯YX܎c2BTuT*aLd`"=A'Шtf%"%lQugY"+,+eY)IR s^ҕCϳϋF9e3V^ǻA U`{Idl"F śFƫB5WJy̪&v|"t!p tL e$\c04 Sc/+@oNoH.{ږBm"#סRLΊ 4YP*k{c%K(6 Aʱ0{6z~㧦|r+ïhrɭnMeme!mbCGmv7f(qɓDe0v-v7;{U}[NQB.~k4VV>2a1G h!yWqAZJc&#$eA ^P;mB*lj'U^\t^?~##֭q,}uC^Gxa㏧v*(XExVW=u rS7(N07)fzJ@dn7Gسg 7<9ʋn~K\a~qʎl/:Lp׷]{LYF6ⲙF=y?!={ ʑ#G>mb ?ɉ?z4?iS6F:Ztcǖ4Nk$o" |i\As+VX.}#t)% 앐S$1uGYPr )qΝ˿O Rsl e*1~;9*FЖ IMMYijrd:8y̜>} |Sn!wӧɹ#ҡ}:c=əD# on}EFh^i;kS (BA^/A0'Pzof  IBX7QN@#r+ajB_˜oL Z"0a|`^]|]"t 9Ze48<@ZKh8EuPάJk짥hLUZ[ȡ*Ձn(qd MLL=z}=&?<|Ai{O~&s'#IŌx?Esu*A>⬇AuCc*Y(<h|EmiAZ Sd0@`aR{IE"+^carbfϞ:\K:C?;^n87Vöe!'GШ)!`ZdhEKDw/ȐT=UxAvK_N׽mΫX@ Xʁ'GX|S yY|NaHSR'! I_$񞹛MZKDLa"Ѷs|{/'0mJb E+rj(![mO(ʦK)s0`Gg^y ȕoea!He6AMg'Ǝ i2uħimTXB74(YBMVm{&sR酴mX xQ嵯}>1J=ӧOϝT6>c'GV) .[|B %m' ԭ1Xvw* x%ѩILu$tb@݁pE2>^Ç IDAT /?-y^jS/*~#u?eRU`̐Z3͖f[E;k)ˆI>/#ԫ߃U_OY/s?,Ho1#Τ7MWcYǝSOƻ˱xYfBƜ/$WQK7sAжW L t/_d+oljٲ0_o4CJim*_U IǕDfv%}_+j[$S( =ע,V7?q^ЧW$%?w{MoWPtQ* Єc\jn*p4J V¸mKyX,$Da m 54ΒDbȚHyF@6OT*2tr9P]u0Man.pk]k%s&@@PoǙ8ţsV }dyaqߗYM %D-[b-3]e"K! !Z#րm8=Eg^˭*-Q{xN׍}s1O$T04dY}pk'oi;8BQŇMC}XE,>FN!|\|$!F>.IewEW,.ٶ =:dþ\˕Y:~ӧ{Ս?J%@H~g|ĉny>VM-/G~Rmb#Lr >qW 9b"4W <gkX z. @'H2XDΓ6¥p ^۹~^]Be|"tk\|]옎^[4SuK[D" r'?>>^Zy>o pl7ZyRm* *t50:\\:t !{$"N{Q% u%,BA:Ҳf=1KK/Dرc0%%BRj Zs7TS ̔SfM I4w1l.sy6TrUZwܾ8L'ePRT R9ZmLlBm!%4LB cru9J$nbqIA8ޭZL;*#8211199y3 ԇo}K޵E(:??3)VH6̦)s[eIҌ%uu&.q3f22k>KtY"fc$4_X Ǧ:vVmB`\AФ|sj /V휃˺"(.^ 6d2OrZ }PsK\7Zk#dSv0JMs7(`m =*;ك|z2FH╸:,Ч4(䓣>OoMU9u ϒhneİG }akk*!x~> ##e/qo]sVľc $7*W :Jm>S6eZ+F/ڒi}97LM̹t=zFhW0a(wO?[b*4͢wK*աa]^_ L PBS8,A>0sQg!<}",X,oQHԘ%RuZK[Ta$%dj# Gju*la!k^Hh(V5TIpev6ɸVX]M䲮P,:o}WeAH!Qr,;F:mr:4@vYd%aW02lG@&SvTџɤI0x!'N1?>|xffE^-e駥wqqٽ{| *PJީ2ܕoœ_f[c'n3R0T"^uՇ(n>#*EX_GaObz# ˡ1NTFGpc, =Or RqI W񆷇}0$Z,6a Bg|o[4޶)$ҵe8':u\ծk f[E?gԒm$aYI͕'O=| 7=qDy3<zcB:3w>gnD⁷AC8@I)yPcoX\֖]":Rs QwevJO^Us)qt:zl9% ]Pk[+%BX ~#K%5[ .a*+\D/@-(~jG疫4S׳ ݍFi;2PUI13|F=l/C+0.6c# 3Ug`.٧`.N.{V8Ov`)8A鎝V.MTH +Ę' gC}zX;Wh;^I(jYKBd;3bs`:s%@Lz ɘ' GUsM_j]ldA<.&TTBn \6}[dz)wɬnY CGz؎?~陙{wc7홹oyV}? πo-і`/A M.|ȓi);゙ټ j^.0O==XH_ִ1OCb^![d4y5"`Gkq#N%ii-Ex̛ E $b8cswY)}^44y<!yf۹[6S2=ᢖF5`D(5=>R,7~?i9NQOQ%]lEd #gmtz}o4Fe\F=r7+/ye7U܎W|TB WiQNxF>WNXs^y>PcV*^P]ǁ})PClJs<NBCrlkNR[$&u I~ uVQf|KXJ]RͮLm "i )A _:yz#(R;$ zGm*t YVSLP*`\UUHH :[?-NFCHKK&t]Zzkw/7%fvTgH7>N!Sp X\e "}L|J?GizTYb !vWTƭrRq\q$Js׿#RC8O ! j'Ď5QhN7TK۷jj,X\2|g˹'G:"AWݗla%XJ*\@up*Kж-o6\4ayH.z˦E+Z LH0 ZtzhK~ﻁ^/.]/{m'Δ id2rc/;@ƾ T_(5/QDT_CGTYzT.W겤) "1KB\Q+-oA*\`V}e.hzv,hx}M󶼝|rYa6 /N{;;aŢ^~Oۺ; A|Opm_.;@F,7&:dfKol]/4R}_kn׫}Z_4:ʫ4ϴڟFrKFs 9Xqd{Gt0V]P6wHblViB_|RHj\JPZ -/%kI? i (|X !0DB0+͂Q;XK*H* :ן wu4>2G +€O8aV-f}S0V<wsL c@C*"f߶ VjbRR}@e%]EV8ꞠVtz`_)N7'WH`a,Nka!|UT#qM+`-)S.EE:踏|C 4H`u5whҥ(RI`l ̿^;| %1+$TnIyGjXp@ W$Ry!A0eוUl$B:<] 71!Uhi#+7fqSSS=W`$7ϯs wxY- ٔ[;ӂbD #>m{>3?~_%齄\B9-G1[Vbĥa$5%Gm.yJ>Șo3/Hr%4`h̀=4; fwj]gwB…u`+>0E-? clZ6`̛IS[V36Jk<T*u5ְㆱ}u>l \w (riivƀ YKQʵ޷GgoCf=:==+y~.WO<]^z^h(w*v>7 /Г`B"ɻ uPJRZhȷAă8$v'+ܐ'$^|쑙yX=^sBnxd\"J3T%@A.\bBޕLDxJYl-[{T\LS>| 9m6"eH4-7Bm1A%( mO]oBW,[_O Zw@"6H;{;Q ShFC6 %X T +xD-yi DE=h $,k[6{^fE@*u9\8BHa(rˮY5V6"$yTi0 ]xDMuA4QŎO9Hn ~?%tCJAr [K^ BJNjp".8kL7KS>'J9\/Z=O4Pǡ)!R>"eBk>o̅Sg$1zHkk Ums`yY+T]}k4FCzU[YVWr"7 f:9AsWy[AC7H ͍YJeȢ𲉋(eJ%j"CCqApFVL3He2(fQQkq}̒.p8tIJ$RyyWlxco|4NLL\paffU)Ϛ~ =B7?[ayTLj-KDٮTd0$(2辇?u.y%T @CۥЭ ɈS t)dVm'KJc =G=9%bɋp6N^I&\Xl^2 ̙Ckqǟ$~0$@ZgꯞdD<|eGǀ)s0aӴEr]R: ˭f8a*uU׷;Ve9 Cs,^IUU1ϯ)uvq R* B<*^u6{$(ˋP $_V(@ g9Nr1 yRQ6oqVQp_&sJ@6PmfgyFV,W:6|soo 2~oOkdii)XRbBBF &akA:P`ˡ0ZT_xI9B=R1itJ1KapBv`: r %>LU䔩7|Og4~ JCkn"Dƚ7"!\*Z:/MS`u Ҭ%VpO?u^OT*# t ۪CАN{kkɝ;륒vϏR.g-Mq!L @)(JH~.Hҁfs򮛕d@6TjcUEp(T!D6͡f}%"n&lg$!Z.2:Zٱ?*2tgv|@AMqP1<6X(B} q.g_8$]׵VꪚNoH4!\__s}]x˗Ţ5; ~lt x5H#B&|$m1EUf3$Y0Ŵ<~)Yu "d.rm9 B`Y33#7Uezz}mZ> q^_x-֯y)ET]UKvBHSLF:UڗZ 9oG? aUi\ʀmn,kJi胶wȫRVV- ,! 9Y6_^QM<4)QQ2]w!KqTmC %VV35?kE%O~7K3552޼[})%J^Į]2~ih.;"ǃۂ!̢m9P,æU}RCTY FAB^O_ШPb{(N~o_c{keVV$٥1p,l4}}fhۜ[`%<{[6^ۨƆ}7|…ʝ_Q37 [!Yqq=oqPQ3cI@1LQ?s11FQ+'ܖX |x7ngNKRCWE!XbC#6:f?@I~|ϲ~qYg ;kZoĝ+8\ĈI8)[ɾ1;2H4-4r-/,fg{cBɓ-*\ZX]̈́!Ki<]*yݮiadS?}BX1wjz;H0} "j4iN kI"43 A 2t:sv!5jBv0mNO7LsV썃̋/~^7'/Kzҥg _ΝHG@[(,` P "D N?@$jH2 IϾ"9ӐIBCs2SiPT(GbwoAR)Q'pyuUX}-˱B?Jl\XX(,.~g+W QLVV2_T Ph%>^isnM\l4N+BIիFC ѐig;O8ރ4-HqY\aƲx.ve!^Q6i0z; (@ l{:LfZ.e#;x9s&?c/c]WFԘ'A͛89ߢu{O>?w][[[ϟ}.Ojk0 t:  AVV,81 H*((Hi*ٹZ-썷?,#챜2 Y&ȣ,3<6,\SMI BFDNEWc@Xȑ"6YYgy0<1F)GT5Q۶A-0D‚1;ǭ8I^OtTeuX -R ȑV>P}ٶB׾?}?J„ )]8I*J8VTu]BX.-!Vs&2b|c)_u]CX C4+,;N% aVQ_Ҙ~Jĉ'N8!/]tG?[^^{SNS(.[<}۞T(N'jxE6BH%zӝǘVRJkr5pO<34#ǐ8dftC 4%H3fe 2JḆ D? ԰WYNeW3G4Ij4dQa&Ѵ<0$)+-~ _YɶZaxqMadMk}v~*x& ylObG+ZMm6eAsa :9y99i05f,KXYPhv:53մpq>w}m/Gw)KAw1 bFplytFFaGkUMk h)%0mOHR+g7Sgvg/ݗggg}:ٳgGᩝkzh֏AB3+BO j< 8qc`hP; !T'W2uf0Gq1_ fXJWyڡ$({IK սJ@ JhS,$,?0EuI;33&Z-et=MnY05eU>,:m`zڤ=m^}?( ((Ax}= V*;/k;qVe|Ǐ''m^-,.uI¡HNgEZ.|ރӑMu ÿs?B;2H e`k`RjK]( C ; C=z,e7mjvE9:ygӧOΞ?{Ħt*Nl& h 䈻-f%Nص*@(Dn?,ZV&U48=)ڍ%4%!:ەMƍMc|w{[Rmɲ\m[V,Q܅$oTVz=VV2ݮyrA'{;>nSwUxӛ.U7@qinO*!aII0qM Bdci&-Vr=oOM{nj,ov:G`gli-Y6reM/'IruT*|Nz!և- [cVu{ųgϞ:u駟KSOJMDʨӅ쀬7a"O(@eF*-!@=Id h\@6@naMS_mm'Iȅ0'Q zн yAKXٹlI66?7mf緭UdL\ώ_\onV\W鉉U8|x}0{ddM9!Z$hZP,IGZFX*9iDLeMS:y@HRt[vƒ҅\$5Dd%I&(+KQCy04.ݙ-FL0IT!z7K1ͱ>h.4G>Öu'g_QG[ּ<-ޮ>óO>]}qXVYc(G %"@=:n@`qmNJʓv>B@ m Z7;ogWcaxIE;>u|IM,Š62{&CK%Li 4HL4Zkt]j8^,6\FR譭e￿6ύí~9\XjSS=^X@qӲY,Ї!HK pXԾ]cVk mOη($aMR;#02}$ 5'(_{J}衇.\|Wϼ /ϱ&ĉ`[- _.^7'\'e:w՛C 0OMO)B52JVv I) De;5&ao@9>XvO?4`gU'0d[E5U`\:n@)X\m6KE|7AlEHjEi GQDj@GKm'Y$vCxgY@, {½\>~U2anMLW*=9[~ \i9rMQn:em[*H=M4K B`Y>}ɓWW mpG7F(KC+-t&JqV(V,ώ^/؍ mDZULs^`cd;3ϼڝO:u黷3eas%{٬Wd ^ l=ڝQd4RC5F L㨎 @ɎI+'PݔkZ{{!ۥ{k::Ug!3&08/iYc NO/ħt|ss];D5wֶZMOKKYI lG\W.LtD{a>^l$|np9 TG_R?X=V()"M˦q9LfZ䋢# 8]f ~ԽVwcmV~ollS}?wC6DZr$!UC{0Y{C@&"I*'.*'"tcĶH16֕PItX _[դ'EM'I_ z>!(+ V@NpZ.[e[ȲPEo75At Mtɭ˪!AЍ7˭(^/`GG]pu{ڥgۢKg@.!S5y੩Z$4mcYZ8b78C ìaܤ0\8h}ylvnwc'亻g|[瞑;uU߽/@;nO&6_O}(7 jb< &,s^E6 } .H8ZR0'CIm˼ݎ; 10cYBQDG:1)ϰ)yIm`#]1lk%E.,˞㨅B jY@զ ]8j 0 0Rdd.|>(M-yuС^n\M tBQĹ3 ?MR\[nfO;0B$0}Ay$L.HsBD1R(9.U7h 3yYHR?巾u^޳_Rýȯga[_Ƌu`@HxHNGp9H(fgQ#D mAL8Ռ1400tA+C'L ҩς " oWH28jeXeo^l}}bbb]쭭JZZu\{2lnV*MBhj+' vil LO/lܠO4u5EPmە3@Ϧi;Fc4 >>Cض<;۞ 389G>r>rǁ0IBLȽF\(f3j鷺Nrn ;[ƃ@!EZrf?OOG2;;{ܹ/EeJrfve2ȑ%1#ka#'~,!{87ZAu*3Q+2'x (@M;; K(@Jg'Q:Ev)sZ^mwGLDRJ,K7VRP訪:]Y[%kJfuktif6M\Y9*^Yuqуy~l4bZMmȑ֖lԔ5:ꎎN>ea_qDqǗJ'ss"U56M!u% jU_[bmo˧N]]W߼-8RL8H`Y`ZhCP:NcQlvS@M͠a,8Nc1[8W:;*md2 CP Bn7>c?+xSO'>QT^xgo(ʁů_g#C2EYXH%DOD8$^+mb"iZ&tPƴH3=AC.%ԓ! ;Y_wW\f~7F|_V' Q$y>F\GU9yY|y IDAT~7W*5-Kؘ;Cekkq2:hrj#NraQ"j5kC/ 8),榦,M 25-Z\4 #?jcc訛͆W٬_W!҇n, $XԴ0E7EƢ)rP FnrZf9f$ Hqam`lƝ/^RѺc7 jMBoƍ/pAґ!cPD:)16y&Q6% q{ńQPf{xK(zuG=h0ƕzuvdL˽^!n7$'mm0tdYZc^U͊[{yMwS77+NŶRB{!qOQ|HUM9}i2 P A5:DɲBHUr C~l̺j>W.WB04XִZfioόE(D 8NŲa <ϻ SEEӚV-Edz1WL"Kx]󇟭}6LsW]x'qT3APLqb쬓Y*i.}`v k5pV̙Xq@@h㰌AL>$& 6H8U0v9Έz;vZVWPT6Tծ+fYhsg'&K_?*$ŵZQLvs33+􉛛oDQU&uZ߾!6E1bH8,e<=x6İT׵?mBett_?"~fWPQ 7yaTZt젓 ]B~}PK|.IR]z y䑗}o}+CN#P@ U@@A@kK i$&HdeS1Qc 5KLGkaR?$1ry0"B=oy? ž^(511CH F33+>91Q][/*jpD^,rPT,qTϓ&I9O{ڪUgf,M `y97;m Zt=N0QXRJX)wٟ?*NS f? D`0b;rk/z^y?Ƽi06۽̢_u߃{*0_d$" D(ة#X33 8-{?4DkagjvOGM`כe3z^80AF~p%#u]?I UԴv7+fl^vCr aȎmf׮;v#5eZujuw zAjrc}H} ,';M*AM#?eMH:JIUm,HHHH;,+ZV!wN>kxa~HPCvJA 9 W [d&>LZG]w8Ÿb Y#; (j8ah\ k:;J~CApuuzzz7>]YKaddm;I[[cc鏖22m:ÐleNs\8j r0/:C {WO@I]`qјo[uttϟVf--bM4 @(JH|ٱ_\y;Y"@Pm'o@KS-Pn}xFG4sg… |3{$Url9 2oA%K2cVq8*xM3}XHZ8`3<2#'#:BB%3s$qF$$LA CoMfg5Fc\^7ޱG F juzrru^Uu0f'S.70LS+Pa 5s`\_on?h6bjŚRkh3觬pm-;5;uk;n.~-mFc>u-mc0+ÊRkSE!-<GK.]x% ɳ݌"4#u\v6<Țv"fp>&f4%|iz։v46H^bcb[4hAK4y (;4Q2?/ZFWmo8N'R԰mMmnV"4~h.gl3??n˶5Mm[ץكvkˢ|R<( R槦4nWz?PQOE-m?+.f>b.tGͮq@]#R6o F3o ?BX凛 #!H)^Mm105Ry@ E1F ތ0ax>EJHX0 HAЖqz[4GHq0H<{ʌٚf۶fډWyұkvůahmk$v{ԎM MO[Fu @QQZrښ.I:Yx_~_ ı)I&G[bM C:K==GZA GaoiP9}[~{?;cz?O}{ӫ~bcDYX& 뉉+AȉBz-,T@fdeX`8Ǫp\!<87qXV0N[h8$`,`ܓ$[W:0v'puu.p\f%1ɱF.Z4B*fR>H#blo4j6Iضq05|$!V-rI&h7JB>2 i#oCň!!IR(I BL} _x/-ǥIb1pߛX%V.UtQ4٭z( cLS9n q~衯~׮kz o˛8Ɲ0l7z 脄,E#'B9D(FF,ٟԏpص42ivI;>vZشmڵc'˳% ų n||C׭9HM)hŤ^p=D(O,ƴ(Cζj5eaa8ueoИ߉v练C2bvae%OK33Y۸0,vtaOQƼ(ƺl. @E{e7KmJrն'{/}yWY49s!B01b4W;w!? ~g# ԋc4mM_gCYI1Ȳ(AeEpWI*ar؏4PU5IQЩ$ TU;L9Ӕ_i_tX|G^ w:me{L.2 Is27dYz>QίͥM&t8ԭJP..imu66#G•cY D..4-Lǫw<# Zۥ\nQQjzeMA^כEΚ֒$\^K\-*Y@o4Kr䩧^{)}:r94#''LE"-qN={hAh 5p^aǕ$*0r3,+rMMxe8'CiǕ(wc<fBBBD #). Cc@!e3]gQXO80"$Zj!_?]:8`M251͝Zm]~>,kǚb ۵bڑ#l(J{rhhriɓۦ)\2 7n%v@./g/]][^Z! $bll!qD1$Zmˊ7\6wo-0L.װm-͌Զ,Bl',Y{=ٶE%Jm-j5am\:qn|;9Jcq+q<ATZm45m{Y0d2M,e q[%"@3ϝ;w…%:udsѩzpZ>󋋳 (!)qB8Y!I↡'J,3kcGUG0(dDn) ]!e 3 !0AХ3IO>PK+WW&~C st9=(nj߾=>21qs²PlpZEKQ!Ŷ5@Uj՘l\WW3##6U oKcN} +W P.~[q)˝Va\|Vպ t AumzB_zv{ϟ>}'CC~Ʋ!$s\a$z DH0<@E!˲AB)TiZ|YT Crq ð7>E,!$HHອ%-B-Q`8`gNQʮ[Wn<,{ѨABb7o:R:Y*5Rdҏ{ 憍aR4FN3C HeĄy H,K9~<=`&О9fJ軨W`/F< 78mgd6Lsr(8>zŮeMIXDM^"Nx.S&{377GI) |AH7W˝Ng(ԥ3ަZ1U-I@DB"l^(r8Nuo*J9IpDah pq pi",Ȣ,$i $qX6$>!!4Ow~J́@Uys/b0DD4HeI[:ez(v]cnFVn|ժfYyUi'N`Yjnd,3v !c$}OܠHR !yŔmockllcqNܹsfSQ:?LӧO?:ǩS~Νk0^<9KPp,K0YC! !,FQdr\(rhJuE1qR-{^]0Qd(ףJsy{D8|P.EQPsOl{oTG P1bG)Kѣ׫I]\W>8رk7o$=xQĴaı1DbWoVW p1{UC#J.X̥A*eɿ_Q߿Lo۵N>M s=0sⷛ ܿΜ9sܹ~G]^^Eҕ|cxb.\& x6etDgy=:Èa@$`ʏM`28fRaTBp^-ovR|32=젦!޼q\w$Z!7:ts^*m1nvGuݻzubj閖2\ Ǐs7nY6)~B%?79}jq,0Dǩr|&EU,>$|n%  'IT(l%9.gNUI+Mj}ȶ'1Vz"!QoE#4|a{6L+6M?c=677KKKw5'Foe0fYVĘgY!I0lj,Ʊ18c (/(ٷ#߱mn]F҇zh0d^ьt-ם}% BA`2 f!;,ϫq)YxB"MY!YV#$#-I(l/ )/$&e9jIG=/.SRW'.k%-n64 C\nV(<'kksd[I"V*׾iÒh2n-,cnHT'&셅Ą}K,-eG8i>8<@H#e)|jI\47yr*m  㝔B YeYcAN°5:iAh&01{0ɲNt+9qGv|jS::1\E G{;#zȇ2A@J"++_~c}'OFfU7PU'"3ߢ9qvyN4<?OkBnP{h4AMOu{8ු/8no Ma9%r>I|]/D#D$%w"+J!,JuT(qh4Ry$x" ,) 9%IeS`ltHRMX,n#0KR1OOz^o=; `ƥK'Xm]wuܜ.++˺+JBkF]V8teNc{{fnn"wWYd tyZ33j'S# .^,lԔBla|Z^ Q i&Io[,ݮ8muc#yX(6 c[0>㛷2׽}{׾{{z]_?uɟS78dmz|e ,BA(( |JmJRRɘ 70 :!B*!!X+ +1,R%( ) TEAI" b o!8w1ܜ+f',g*'}?75HZ;;]reֲSW5 c[76}_'vHIxʴSSv>>ݟ* cqzߧqԙ3zxt_lS1)GzR4qw׼бa(i'°ܲ.d,S"CU]Y児0vm{:@Ȍcy'XtFR9o۷D*2Fc3c뮻G~ǟsݹ7%n*|h*ljj114=B b$;M'XD`sc]$%.,8(c R<@NQ$5]B (q(r4C!eMHc-UrѩSOaȉ,5s]caa3R?dVijEF"5}fn W.gi\MrWUj._.͹%Q4MkffX7yr,` 1Pl[M/}Pdϟ8|2д%IY8NM=2L4JU܌2q. *yض@Z)JBIb S_r~>I\`Ap7jD$u%2&q-ι-8njR:kpxOErtQ5ŴƘ8hT`YIR$%3q-c؀.^B,i"G&9o}G: kκX'Fzm,t 0x^azzSם!q땪նł9f].CI8@^O8afcJFZ$(ue112‚ADv,DUF:ܦq2)(m{X$ 0`,#ƱIU$I R Xf.SϿ/rF {oEn;v#˗ap1,(bhZ=X(rȑ`QQzHI]\I"J1169&dB 0HM?G_ H |akD^xIAxp mE"rƅ cL涚:s8lN*Xǎx>IiJ8m ) q8ss{(D^<hce}=daax/ ZJ(tn1fz+VJ%zc ն)% IEӹt˗Ҷ,㩩 SnF/D?7zɓQqtU$CBqW0xBcC a f㬪$ Y̤6(jKRP$0 T) ՒS˂~3C@19GbQA9։^/?5ض1!2!]|CkQ7&Woiss~~~s3>kil nnZ]f!y|vE\Pg:H$şsg(v/68mJ(d" <H !8^oIp=J۹\oO;owݧ5}Kc5/弇 I*H-M+`,EQ1CHÞ8D)P+*!yusxvs0HʹΊRAH Ecر-81-v߯_kTƕ}-,~Cnժ x;ml]Cs %ct6(E/V?sù(>^(l'Id wt`S.vKBJi[Q/r{Rj"nii](n>~o3zJ9Y8g 2"O3`,yrD>+IBx<;\KVZX}28 %*. Rv/.Og0D{ѳ~Ca"Bi"ō~ Nc+JbYNmb?I$IiJ`%s9#'LpXVjYr-+L.^>5!#t=!j573;f8Kի1'׽MU 078@X 'd.r`h0wrlfTR X֎,G΢e20F)%gsMr=k!EyW }l:+x)'E9L'0E)$I̘'I&,Tf$Iāa$C]=A*Ūa˜7>җz3$D:qLWsWE MVwhmy~aii#'knlO8e(_P&2ܫ P5-Y\?~TX|cC1hc ިr(ab,v5bpYփ[[=I ͪz\ĀK91e\_ԏ"1eyy m߯| ++_obz/~sC"2k=$i I(Mĕ2؀PA$VМ/gȔ"*BUYDQ4X8'$ ʂZ ^qKi7eH8Vۥ]=73%]w2A, 2 9|(\fskb` zW_vլbӌk5yg s{.~xs$ߥ^.ߥg(rwt͗a;^\S<߯?~=97Cw>O]7qҋ~g?-ZeXSID+3aKע0ȠE#-b)  hZ(iu\U JIґƆ,'L}c`s0U%BoD/8Šb#l~<}R׸jppd"\m߬a@9'jWJW{wReˊLL2 x7@@1rc Iq,e O<)mK2=R%0W,~ `-וuiێ_s|)U$̸<$[I[늬I+:)@FIҊ.{C4=(1mUGH Á tх*0v"PASJox} Z^ʿffuYYYV(M`,/q҉nlbpk.M`_Y>X^R{?_i6uQ66 eB$}Lg8T76#m>u> 4S۶`>,<}}|HLsWQNgRXye╕w2NLMsRy1y7eX(R+*\+ ܸr~t| R2~Kuzh|CoO<|("rR3g^zpO?s%If̗,s$)&c.b״ B4IlƨeUV FH˜pN9$̘?XLXXav(2BI[⹌d2qN90E.,s}'3A"V=O@۳Jvl.Z(R[z3imkeF)\QI3<(R(E#EIt=ُejPw:,sSesaBB$ʹ-2\MsR$ɀI8 ?߼EpXW^hWH5+]G,--rb&ViffP@933sjU[^^ F޶';cw>h*fdU{`7f.g]gG_џٛ>SMM7E(DNXZT`08a$ HJ|yGx^qJW7]XV[iɈ=s;;w _g;氿w۳r'RT{[zw?oxr2Xhv EQa,$ y$LߣIEc!K3ds$e\^Bi1D&@$fqjJяٳ΁^]/;{G5^Myzp㔒kOa荍+ `iZbR@ᇫ-Khw<mu}P.aH$iY?x0 @n.xSUs\U7`-oˑϷ@XvEIxN,|\pz]]-9"8]}M ffZ͓XhkkV7UYk4^F㵢wӯL;3ah"Sj W<ءW<6> ;;o(]*% KW>#xߴï~=_EyB(j8zwO{0?ߒ$ Mcc$@=BFC <#af0k)"Tkz1t5;fU 9eVPv0P#g:b?5K#O!X[[:~|u"}&Iww)%\RqmIO&zzd۶VgfCO~0+N9QMە,+tWփ&D/ |b1Um em3P,^$$c3U5r-߯ SiV9}%9"K,LC{B]2gWn^7iwq<pc1 c!5%niV;Ga e ۩!==8+~7 3eX~QRヴ_0VʉL|Y2gfvtp'n՜u 50f Sh_om-ͭf>'l;_7i,aP`Uu+&JosP(B|j{m|ؠ/. ?gc?_ye2׵.o٫DQ( XFUcRQ>߷2ƕˏc w1dTӚ6m<￿T*(1> {c7ozwHUUEHMoDZ8kB(=,Wut9XF_|H^33BN(b0P7?? [exPF*ZV|> TqYzV##D,fJH7!]pPy޴M ۶=#Z1ք#y9t)eF#APxkxF͐}p#<1Ut( Ks=s}wa8_FB1\4䜨T6"Iғ j$uBq 喜T渭QIĕ2Dd'"}dJI; ˪(€K˲nyv Ӂ㘳B#jJgDi5rdhhaΎt[0$RTj BhTjVss;gвm+;;}tw?(R:B_՗'  =<ኇ TqCa/!5Ips+XJW47v$tȘ/+buubbǩ;=d]=-wĥ^Wi,:R1vT1,Ic璢 pB(;|”Id-0nG"HR5-alȲ:EE0승$iRBc  TPB!ޏ=;4TޞDL63=1]5cH=kd_ y"ts[kksJ+[T8Zqqq} O }>ȃm@.@}M[.jZkp1a²0%I">+WO^ |qd9pKQe$ +f#l q]?0{9cP2nHR FBhsNve/2"{ⴓKE0rE}1(8IBI* .ʃrOLp@1lv{'n׷: Cþn*j/:!ĭ\nb?~Vn"0R;.1EG)w:Ż~Zr f}uuiuu);[S=#F-9<7K33P7O$z2)ٙa EJ{B}L2;Y^Tnk}a>_i ꍾn+M7y n04;3[U"0[wvNS&ݨǡ@B2EuΣx^uۿZ1fm 5)JPj2OIx^3rž_K\ב0$DI(ZQU@U ԴRNIiʬ#%`yKϞeEa:ocכYv4ͫTY'BnO+ImXy幹Jo1(UF6: u0F}Gx:Zw@%* 㪟kSL$$rA04T47 M{O3\/$V(bO8 MfqRtHf/Ra*yJ(jh-Gu㓟[ZVd!!c. hZI0aLh_ ҇q![3ʐ$d*Pa,$EE@7 *s$Iҥt( SbWΝ{XζUXXX:=ħZm>>njp65(tq̙5qRP4D>}G5|0}#uT偆ȸ9z&jt|zߚZI_]3Z}[_B*ȶYvl{1Emf B@ڄj{:}y[[#F`|+zz|^;+t*ll*+zJ@gl;/˱av+8ng? 6af Mq|1#N9Vpʬe O~ /Ǿ-CCF!w*n!၊0}4"[~Q!ߪc(I@Ͻa|x0CO}rJ;kCl{q|$ҬzXLbbq '$\si!/~(޴\W<.yc))C1&H"1U LdBE(M nFIe# 83xO)2NTA9%Ie s)8s/?>} /1mz#cJhe33ێc"wvA/ub(X8mӴ̴l2`]nׇCs㷫 TwK-&\, SƶXJ[4m|b_:+#ʺm/z^=lYᰖ)vRgiU}?h8mO?7}?R ;Qz?I0F1V HRe @7BJ2!!$2:E)ńy:)@ik{q4~nqNsk0P^ʡ?ɓOűl++˝!{&vZ63{J>o,g/io6+a t{{qeeYh[[39We|ۧ[wG'g6̱lRq?=ddZ sAB.\+U}zY*GA߉Vf+/,˛Z'qU5Y/|/sǻ&*;)nP~g?va zA!(u)IR~b7C${iVTP\ BcA/d̾ߑ_ cnvc$PÉ~Ν{~Xg^r + G~Ѵ$v%akZvZ+в tf}_EN4VYPX! /"nQޣ~:T(ۨD)⡄ h"?J $i2)>(ή:e߯cp_tidyf{4;eJI.׌z)i0 04nwXiowO}n`7:o8^7p^k<<_AaK)XeŸNiSʜ'B)͘CAǗ'I$R4M  GH[%IÁa\(4&cǎ8^T;.Dnss[Q_15nz# sl[/!A;BD1E?*=/TMw.ظ?ϊcfC U ,2q! x&4j=ܜjjO,8<_Ie|1RY0,wj(EPD*IQ4[?̞q~oKAV»2]Gc|DU;[%IU+bjoVx ˥8,p >8vѷtXoh PCHE"<'I3+Pʣh=vpl{?!`lm-ͭb>dm|%n 1''0monw:l0}TKĻjWWmiۓ} 2> ۭvUQmy}ap@sLkS.Ƒm/ `*kAP芨9CšvǟiW=q1WGw3Oo}Xn zPXp u$)̥+}%IpRJX"Z9 +IYQf={'dY’~}R:17wҥj-%ۃcP)wEy05ZqT{ NFA$ = $:N54(2@ - &D4ÅnA'a{~TE;+q#CV‡$3?gO}&.|į&w>Pmμ5Fkz( :Ic]M ;!V 1VũR BG`+BDQ,dg[pI b#T0uYOK~1+T=8%J2T':YvOdQ'AHZ G}(4lٺ}K1B@Ky텥@OSst@ce^A0ߪ&`h5OCl&3?3jr@) 6`L^6vKM΃Bo>WH`y*=IIaP TRUu;@HGH-Ip1X8FBI*1*K$E w6cEў ؽ ;gdVVޏ,`o,Oe׳SޞcYp{tz)ړ7 އ;Kt d_Zꈜ:gy>UE5 Zȇ&{P)Pȶx9m2uj@-MuMPUC:Q'zOz9£r̻ ΝFŏۿ%)JӬA ,嶒T✉dٌcG1 u5_fزf+كQS8I[7$ IS:$ @L`l(7 ,0ns~ϲZ1_N| yz(f3$&[JJÑIZElOUrTv[rՖLI(,^ MA3W[pOlwg'V T׵%Ppyys4'P/x<H H!ѩ -[aPDgUX$?B+txf @}B$]>x(!%Tr(&gS<`(~=o6<¸!#(h >Nܕ4SBZ2x"Ω#;.xw~)JSUK$ eQ]Wmf0(i˜#MSA6BJ$YBBq Qx' Q }{f|C?+^X .$XmV` lC.3ؾuTsj q~8Ed=EkOb& G Php} M *ִh~lj#W+H'N(K𭬴Ȩ'"7N7pxc F]㡇ޭ+ET)J41V)U()0\cb%I(ӾNtb0vN k?_I!IC HRy\/Wϝ~2?ȿmnF߂U;DҸ4nC ة6oб L@>;+PF!aW^'l_ ͍x;/AYTCby. 3X @q=!R IB&Z=߷zJO}-}c}|ž~߂!,+})HP"/Kvf$)e Rj.g ;FAZF$<I*<D>pe/{Q/'Si ٹdn%' a'Q+2=ӆd>g5 IDAT Fҧwn[EwSTvxS:uN]ઃ8Re(RP;[Uɨ2?S@At.r<1 rQʌcDHVS=3+>.in%:TvBWXqC5A[I!s(4d ͳ|#>`$9(=IN F2=-BThUGaک+!(J~4ĝ#ѷ}?6>7'ٟ(Ac"R|>w3?G\] >IҲ)#BEDQG*D)A; k)i$}I*ac05s#bc\Ax0U)(E(uRM5c.B1& :cM(,b8J^cLI4W[I@oM-;+n)~=|X̢8PټX`(+nYE 0|>ȃ#%Dǚ0d2>/}$\: ('+~-[:zF?==NLv\dr_K1 *$| *>pGMw%zw>Ptu0V$Nj% ;$VCz:(I\E!fp4ve2֧VR =@B*(]Q|so>/+XGP 1S!x I¡brP$$Mk l>*,9#vey`(&c `JJg$I!u=:f)YAID#4'/dKq"k h" ,$W:"¸‰ANySA5( Tdr G'śi?j}!x p-ECΓ$rsĆR/m_(1!8EW ԕzA= gA9lQDQ'RB 3{ \ Ձo=I _G^75f4ƬJY =õ!+mVRÙneTlkQ\キ$Rzk$& aWC6ఋol$eِlLruLpBpИg֨Q%T*i 'k_3j.=~pK5خJx9 X)i "d+:j'˩:jLTcs/it128q S)SƖ%M3X##NEt#1mw}PW5Y嘻GZ x%BZE0cEa/ qA \NE,u(Qtu 뢸#&FQP X 4x{rQ-]^h"z]b 䧓kQ: 9sLG!̷pCu !,@\E1L}s>+dO,3O_حyх(և;urnă bFZ)* lA(okA60i>$gבW}1Ge[dT;̑āΈ8L9IȳuQVD0 qΚf0f?|_38weYV F]Dy(&Pmjoٓ F=)iwx5SeG j !F鰍 A $e 7=Y%`MelP8=Mr A5X'Zj͛Uh UҴ A|UMlUʎ)m@T$oQ:3){c(*[fI%U@Q:+MW\ljf|rFnA)=Ga&XYTrH0WyΥ)lۋsqg:YU~?'gΪW4]p[)r*F 5H|*lC` D1&H8!I7G4IH4CZa!+QBFYiaZAp"UR^S 4/do(& 4"Dp: ^;.ME)&"򊢲k^yl~/[gI^;.-wFۧ %td†/阺75GHo*މVꍗGW&m^( |aC2<.[j/Di4ɫ*}VUep5~XYdáղ T8B "dz&_X+ !4OelW=9b7 JB菎oi`/T[OF:ֹʽH$(KAڔZ";q_L5:5p#f= U d_D^Qށv,I|6>vHe?A ^;´wSФuPR hiR XdR KP生_rm]Ř tλZPEsk'tc- 88Fr`F$i5J8дaKA )!dXV!uLri9|ay%kЭNHI^y[j;i1bCg,!{h%LEa=cQ"qT&h\w ;kV+N5>̉d4WξegQ̜r,XIPhȰ+Dۣ>} 6jǤ +q"nP_jBc # ny?˄XU\lX0(dlOy!ir%$6E^B9^3AkRrB*ʔRrmX,ɯ1XLy8E( z2D r;rpN=Hs5&&ZJi(MdzOjR '[-n(4t[+T Ds0nqb  `zu.zˣ0~7#t44$41(eL3exq/ '$Zrd Xld6@/˚Q)1\nv8ljۣ0TbDԖKu0)9 s*WY5zmO{IC"`Q)kǥ9@-QFjt\`ZEݚY+*[Si4G瓝5mIeDwꮤ{ZkӐV/lz.^4]_KWWU| j:cl=YB s@c-MYŏsc8܍sr5A\\-)# YFW6%=B9,NfǸN@)Z :hWfRV0L4ϔ&/LZaUriVAM ܯ 9yӿEDy[E:J9ėS^hβ73&<xՇG3*= ] - 2\ۿ}e59w3BuU9*c=خ ! Za(/ن̵'[OfƋg7݃դuk̓ 9FꮒnF (&QRH,Ld$A~#Pu"#|7xѻ{m4j{[E!67 M`m/GXqn7ȹ Y#U}X~Dʩj%\eh(Jgxط}Ѓǂ+_$ƙ9ÿkf@_rY"~Okɹ49t[0(otjJ(#e-n-ܩЅ쭴KX {mitŒ J~n9<3P ;&D{coVÈ׎k7;tD,/  Ro<9 ѺaF)BD~!14__o~doح%= T 6vkxZ/„_%?X|և5C1@v/n2Bf,Z '4ͅ.FPA-SmST/%JOU#qT@e3򠦕t` alp!|5~COpTQ UpBt劊|?`kjWM:rkAnG:U)$^\@ mpShi`vxP9&K#뉆Ӡ8դ#OZy< tT&"Nō ?ƿ^a T[FVzwK<@^I=% ׸4(O}hW fNPh QS%/+}o׾o~nle_|[7K!!sp",(14w0t# H:0r5%w/WQJ0GHoZivrrzr9u7g] by%=tVDƩ#A`!,7uΠ^]ػ圉7f~տsX[&q;ԇfn7h;?7\~w<^exq>7|M XT%|>ﺻɩ^StWfW RU3EyR@-k@r̵ĝLC`&-YP Щ)BBT Ľ}byP԰[J3xvk+w@ܗ<="D̍ Aw'AqRȣyA$aIb4{^$nVkn!Wki!ߨ}-]}QvzƢB!a5 i慦>pg꼶%-wҦq|r#5CZ$gדs#ͣcKĖ43xŊ´YC^t~C, 4WׄLtPDf2BĽ}|8 `_rƎ[f`&\ZĞZIz)RPY c,^{,[w BEaLaczIk\‹ S9xP!e;BPqގRi'e`w֩U M+͢Jox9/a9-lTUov *xQ̞D-p6,FA'&asu(1eZ:scbSү)KÉSu$!HI/7uv& cUWx޴exp/>tZtb9 Q4z^;FSY]4N5ra >!%mb$UQ<'GY A-ȡbwބAH*$UZؘ -bQ̺_Z]@]N gTTNhxEcn MfNOt2 Z|aECߖ|X7 //}Ε>fIDATW\яf O0ֿG2 g6e=oGbDhPeUiT 8zaE "ZkK!.[+S?Q\ڣ7?WV%}f_{ڟyB O.!%,](sN)uMm<1yJÊ^>_co,k^ .WOpOX#UYh)Լ ss#cqr~]D:]q$'&0frP܉;j\W *RKj3XՀ,K|dV|;b~׃#/>?ȻNheK_Tœ)%$}R>vözYK P74)!Nŝ:+rc&I m;1IoXIDdP=PΝ)6yObZ) L>׍+/&sRꬦ@ |Z1,D^9Χ^;ğ?~E~T*K^V=ԂQ`jݥzat:F# aSڋ{BXRr:&Y愊 R%<-WG{xi7[L*yԚ2`WV0c jhJq 5[BIW]iJiY8.cO{Rlhdbc7pRkc34 j򎵀 @mŸcdL4ɞ`: n{~ϯ|o %V> BhPÝeicles#oAѢ4\\ 5_ 0Ԋ| +-!XױUHS%3 ˃گ򶟽ǟ 7g&|d_Kq\F0 bqvT/VPkZERF"߻&&զ 5XǾķ?rxN/\H!i/iBJa()Dn\1Be4WInH$]W4&)oV~yu[fI{:iJSӬHl;\&uBt+6Sd!HvZkjrT+-J)Hl @K]z6 IsRSgί{s$&uuVw% rkInM͔qntރYí>MMӱ2b-,~{V"Ějy^zqE=۩LVudf'{bPki"(smEi\;="-b݇2LП7JoƠN po׎n[PVu2{5C`F"][+s{o\|~󝇟|OfIe|yoLȶn¥Hc=e XsQ 60-JfO k0(!3nlG[FWZFUD| Cae/MX@/"ST-(ʖܨhk %ÓO>-MJ+K+&T D3:&iޒcTq|o $vZ Lhp&6 tGfnBg9@{jkI!=ͦkDA_T>zԗяgܗE2wnGP%ap)"d0Y)=Z9K2 4 Jm; )ۤ sRҡxWRr{+[eo}g(2ݠ_O7~嗿xw+,p|ڟ4甃 B&VG0.Hz B>cdw:ƸwAԾ ;ktDyKu׎c /k%& 9 x:)2 )8Bo$P?l_Si.cL.}N7_+O 2_vnדWIJeJRejY3.|?mjՒƒWbP8 WEa:ff:C`yM.muYN%7y%DtΩ%ШB2QAn"t?o}-n,pR|7!eR Rx*NV争G25i+7ڠGe(Ȥx3oJGʻ (D~+bhۏ5*|[n߁<@S:z(߉A=nCjW~#weOF.m><ϼWZhM=Ϗ2~,lV8W 2 YQpṈ |hXVQm.e)qiHӝtY]mЉ4۪7 GFom! *?Z. 瞫 5CBv@#qH!`<3Wu:\S7ٓ!)Riz-}UjTJߟβ41{Ty4?#͕w@u97 gx!1w忼.~e_]wSTKpA0W Zv[@Z qұYYNm6yawI{ϏMB6s[`B!";xBdp;Kt|OkPŸa_g4ny? B^R>M!\BPƄ`+O\VWKZ-6Fwbu"\q_*Ramy%cdYnjg}Is^ex7~G? Y#BKDg'$# K `Βxan eYoxkZ~>(Bn/_VKZPx{3?t%\~ ^/ Py˿җ ;jmÚ+(z ppQ1A L jxLz!qz~tiTfF/N*QOp_8췟_g:e7+'198IO4|͎T *C^V7ș#\wX.msEs=@tFnޟi~amt'Zk7u?g 9Ekv_U,kv>aYp8Hn@״n˿N@-3jc4 fWȈtDSMR jLΆr|vOrK_qF2\v]*ֿiZ ǖ`0r/vB@;&&{-HVw3ə#z mP{5z M3n>_kF2|_xvt!VbJI+ܮM]|qAl7d+En͟k;G7ƣ<M95Kg_~YC"DVpQӟ╾V)Lyh L^Bs;L}?ɫ bsv`b [D?/*[G|k<3ː_Ç|1G~jqx\s诳k|P{ Jg}zk~W_2ː `O|Ⅿy͗ÖMBlAqBFyl$|Qc䕧8or*$sõL-nMd2XF_eV>n)xF]t)BLfUv]_9#ġzG:nNx0Օf/|0QCmYCDp@m qB?Mwcz۽ My~X Dg_Mhd_ Onyiy҅5"ͱ[CN]̞y8n7dmByv r'sYC#2dxjwG>Gy .%cev[n-~Rj%i1Hu(.M!y;uGϢ 2yO AM=)<Is5,l0]Lr /rnBDzwy|ߞd!Ł}7_IΕT0c{`aeL|;#3{Az _er=9/C<o׿~F5=2L>](9?d 2dC⊏?@x p[swp_L_ ׬i >ԇh]koՙV9 .A|G{=u1}KSo&_ 2*Ʀ!7~Uh=o! O׾(6aX,WoX/C ٞ O\w=,N t+ Ȧ>2<}~7?3򦷼zK^r7~> ex;뮻C*ʱcDz/CfxUz{exd O{Ȑ_g yoӛޔ}73ewߍ;O&$I[-\IENDB`dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid10.png.license000066400000000000000000000002501511655130300264010ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid10a.png000066400000000000000000000223411511655130300251260ustar00rootroot00000000000000PNG  IHDRE" bKGD pHYs  tIME ;,Q5, IDATx}l_W}`*V2hgj GnGN|-LBE*hJg$?L!U[|&G KT BġkNG,Tʘ+能?}>9JR?~{9VVV!2% 󡙉3#[ԇ',:*w"V`=!Ncهf&ʿ=$4ٱp'srZ u^X$"ʽz?%x*DlD.{2X/0 u~7.C<փ; PJc*_ c=@do{=MO[Mm|jxwGZǧez9:>|܉+k҃ߴ𩱾vʌO-WXDJ3_{PrZ iz!.8N7܉%[N*wW5yXĽb.2Op'5dXc}gtONLo¶^*>5փ;S_*x77>_c=l[5bz|/[=4c܉9`6K${aiHo=Ǟ8qf}m) wd?Q[[vaL%|`փ{%Wewd0A:uƷ2ǧ]*O7ٖ]E0փ{ix)=F[z s<#;mwӪ+܉hRP)T}P\#-NDNTvf> ݻ=J) `Ow}<{v.{R!C!{=V[] jڿ,yzKhgȘtӇJx$rhYnN|s#  uOKdd,j!+2N.Mv5:#:xTM/mu5*@u}ި_m=@t/5b}o;Od m@LG)NL_6|^l /g|zϲ^)lRo~(NϝۗQ9ٱ!-B$#cɎ?IgJr>O] /'GU \3ƧTƧT&.i_ e޵?Ry:iħ{ә);>5׊CD]lK6ٷ5Ƨ-C*ڶFejw֛&p'bsa jɎ Ez!;k}uwٿ7p'dwpf^ߛ}rNIM^!nz-k;A0-ٲWX欯bRݧNթ\iec]5x ;ңɕor]2\iߖ܉DYY[MCTp7cN=JN.^]xC۲;';e{m|Zuw3ַUewB콚7}w+҃nd5rƧT5>w}緔R30YJi])-+=fJ)C-Dڶp"{#։Г cёdzBdf15evttO4-ͷG;#s}{N3'}?+@[q(=}ٝުy[IpqSn6 R۽]Th˸&{e3_^~d@O6헼ݗ::> ܑ,ozYO[vm\"}ݍ(FڮɠoStc\tv#j\mN4nӒP̦皛{0)0]j%CT]/wd[dWKwK#{SлAu~| Ϳn/Xhe! VKzJ M7= m 7ne8+Ukgyֹ^AoN T )/)4P0 OK^uti*鹛 x"-;C JfK.C_G;3V؀ԣ#]מ-} Q{-ͧ{غm"{S Wi|. Q.H[; rd>>*1}utЖѓ0ݾTTk*;H90;GZO,ySvs[;>r1>-dR\ ]^r[.i$HQvSF {|N=nL{BwdGv*-{Dd t.ig}3_{0H/]n__^ӋD'O7; Swrt]΢Ӿ+SW Ƨ!j_Ab8:`[^QJ]t"iP|xZqX;}po>>]+(Rw _Nlo"Mg@*3]Ƨl/m0> rr!*R9ȏowljp%{/ۖݗ?|州^~/׿州GU>\v䥅ltEd_cl7NUo]]T7f塹W7[b~6nvॅg4wؓw잾 i]/9z)ƧrҺd'ɮ.0dOGH~ obb3^ݾ]vQwse'ux'7{Ͻ_~@Ko*gqwnܾN^>QvQCԪS+ET>ƥ/7ߖSv!-Sw{{ϜA7pwZ1 yjX\m^ZvL\#mɎJN.ȟ量{Z72E_]۲ɸUTKo.d&2piS oӣȎSr|*'8iO %4d=$O%^P"ܖ= ?o5&{ ,ۃŝ1z=^ɮޡevƧFD{kX^wܓ./dsTͪ3%%" w;8d-xTC#jq[N2m۲{yJ3>橘ۗ O!4=>[O6nϞ>m^rO9/Mv.&eO/ٝO]U>dөi*wdl{uUz5/NYi]Fu(;Mvߑ\&VTOFeN G)!;);n>7\(jǸ#4ڙ>y5Q&;[w$WJ0 1Megm|fg|Q~8{|GrKJfi]ZO?ܑWӢl;zaz^ߖ^n-\`O'ٖk-DvZ1Mp8{<7=Fٕ}ŝ&1-{od'^{lޯOv%i'HpGvӞfeZ[]ƼHd=}H?\+e&f>h[4{z2ޕ!B/Sv;SZ}]v$^&?xb+w3>5TЩBd`fzϖnCBqins|Q^,j,ǧ+sGvsvOcM[w"zyٵO;+wWLVNqrNy$/ܓ;ӢlGHX/Rik˾e~R2N[Ĕ9ڡ&0 dC-ߓqR?&vZWIh;aGOԓ{minT֝nTW}>(iǽjΩ֞t0,;Mv˦kaJ$y~_U>1dWnsR2ٕn'Am-9xj:.ʝZ[먵mٻ<)c[NP+ƧY2A>sAѭʨ%SӲsed7zYԄ)>}>k/'^QJeOPȋ~yp1>]}Q1?De|jAo[1ٓ47sSNk@5[zR*jSzXoroҖq8>]n1&;۲e݄d/z2qO6l*/zוک}v3>՛eSÎ˥SɆM%|XǺ+OW_LQ]ombRKvMz=p/XOGߕ.6Xo%ݧdɮuU⠌`dWdrً.7尾-{K!*2g4-{+dޥ);֩dg|Y;헶Ojz['\-Wuׯ7l?`Wm;_c.4ٛ:Ԧe/rպcߠɖq-ӧ~ѨK ߖ˫!*.?X.Ջٖ=Ԉ[n];u@ټtT?[vM{ÞL[]nDh}ۗOW/%^|Q[Ƨqo $wӧBIo&vV#qu{{?jaX?lg|J/jJ7߽EL]6>}ޙ=J we *ǧl>4vQX[ft;>IiVTk;7)]ɮs%>Hp[v A^t*ۿxxCPܘN]}v*Xlє[V-+Mg ĝiMv9~8yƓQO>!}(E]rRʜηe!*)%GIKs}*;JJ~ w-{IvƧEQP[1=mmb}`~l-.8DɮmbyݻRMP>dwU^<!j̲F<=պd.Pq/wdsK!%GIѰ>OdFǓtZ<)hd6O#D%^OSGǓ+g>gwWjxeK#Tkdoى—*='䁤S efߑ\߂F5Dž1jy)MerWq,\|-5?>mazNՓ<>wBI7i\3)-; ^A %mC]A^;ޱN;#][9>-&T93>doiڠ5X/FuO{JC}ܥ(u]ɺCԐƧawro+;U{s5dٖ=d{Cc2+]JxJּzjve//OJ{=>-;k %Uq[S ǧI2~&;- {R=N֕۲ɞWo ;7Peq|AeӱdX> f_MuĞjѱdR*<ٕ}KT2+R53ܽTlm`o-K=_jLuԷf bdǰK4>mc=xrr#{뤔MZ1߭筘eU|WmzPT/[_|Wu2ei z|l/m#6ًjSޖu+++>} &{4>-ozTVJPJS_$\5٣=(C㋢/Ӫ#;[oΤy|9պ|W޶Q-o΢FnYcn;ns|/iRq BCT;sP)T=M,-nė},T7'i^7yա.>ucS(wWPdn^%hHu8:}νIi٥O4>MvqOةDcQkUvCMv)5۲b>s|z|)nBДdnGvQMv+Ƨ"};;'R֫>]8$ad!&;&Xm>{4I==^o2egRj3BƧzKudrwu;k!ًI)]u;ob=m#Žmn6ٛ7[/v"a|juZquXoo[;MdgRPvZZ^zјmd[v5:I\^&{=PYÊBtSo_Τy\m>lKީ٩܃/<~dgwcABd[Z7÷tRddczh{,%(K/by[v udwo{1D-9> [ۖ2&;Gk}uQ#ˉ}֑ܱBbGvK:;,k,-;}`)w _Qh]t]wcIOM5ٝt`ʝT߿KQdg_d74>5g@_ܱؖǽNkMvnb{EX_$GgS?+&ewXGvp'Wox):.\(94qɮw|KjguGB=dǷsY+uq~DZ;V)gF֟\_By۲8}2JuHzXz_-)*|y!&zkFQ|tةϾoF)uur L/@Mvp'UlVJeNohDzQ2>:;zu8hI{^Mmm 6=;v*oij ;Iik.SvƧ@Uzrs+WsoKт XoBMv;!;s+>wuv=]lc5468ObZ1Xo-5e ;=jM. 7IzP;H |z-{ĺ^o@jw Si[vXGvpR[#;dq5 5{A)+)3>udp74 ۢMvYGvpwR; k^&;M%}Ƨ^n@w%EƧrNke0qw8 4@&;i|/ֵS[߶-ud:bIDATl[\v %žƭ`Jdr/["KR{k [[eudʙ^TCT^ω-3 Rҙ\/)<vؖܽ1=;vRk'>B`>'^7ltk%|>*Q ;rWNnLP2dw3 mKm 7i;u ~) 2)!dj2 +EΥ@vB޽N_ŝދ3et^(5΀43eEvb-{yaWtf,ʓf3u82 ww";Ө-/}VJ)5vSa[vpwƔRk|Wm&;K k}3^$ ܱ>&B= ևJ";ww-a|JTxc}+ B;;AvX|Ű-;w23>%mYU߭Oνd$/X琝P{_׳POhpducy9?wpk.;-QֿwqՖa|Jm$үpNC]E -c;6- %-eh*wXJx4N! "N;S;pzBIe'XV BIaX lc^-ĹBICK!;P[PkpCQߵN;zىs4W'卋zVƧʝPK]WN;zAk  %N;zU|ܑ;zNoؗމ ֋]5ש4ىS|; ;"T~Ts5wѢ);MvBɒ#;wBDX_KSw d} g.|a)$ $&\^(IPA]߫EӵrGvhD][4-;wBΙV/1Ampg|J/4#;wB>=ǝ&;wB±^){ BQUer IENDB`dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid10a.png.license000066400000000000000000000002501511655130300265420ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid10b.png000066400000000000000000000767321511655130300251440ustar00rootroot00000000000000PNG  IHDRCS bKGD pHYs  tIME  H IDATx}{\e}sfDY"4-'لd6fNEֶ ⊡Z-(zAȻRDZ]+_ժ-mMIvs&3pqU ̙=g}ev6̹e<\U- >ʛ\e}j@KK|7~SLrا~A8^^B,+Ya</P\zoq"\ /j66YV5Tmĭ7Y |/lۑ弐FG,O%xj` 9bq |^oc$N+/YOw`^NԻv(ۛZWoznQ=.m`;7 ;pTw>C{rVq |e.ޮXMaw;8mk/-z^7Wžgg݊62 Xa+ͽ~-.5qJt[ tpp6!4XCXK*LsMtx5A΋"7;G?*]쫯3? w&YCinoNzbI:UthؗtxX@Հ c4~:z VC>v/+"#8GY訋}" EG"떘k>^-w=mGHxoZs}j!rmkez{pxw\G%A̅VnJJb4w3M|l]q0}ͪ۳IzlbCڋ Q I|r Ve\Gfq:c .;F.q  }fYD޴ |nUb.(%E94:-(ݘV2O`AX0] |/extޯ-&3+b#-/(ېyZGH7^.WZ0;[6ce BQ5::f~]6n.[s6q$Q(oا+)b{,&rgCNTԻ Z=숹"Z͈X>|sp]PU&1PM&}+T } ^ wՆ6ރb߬lե=98&+E2x$_yVľ^ߺ |snܕtc, DМD[$K]ךD=п'E|%As l}R4%@nhCZ^0vo"D~(GNJ 1P`I+e-(_#=e>EăKHR 7DƒAhJ:-ln}!Ɔ5ѭE`˛-hKH |4sW:oQPSl}ͤ؉Bm.45&] 5Y=\jjt}R /&.e+4f:/"Amy`TߐutӳO F {D;7^P& GWb sYDOFZ.ٴ=bg^K 8I+!mQ#&>(*2TgtUn65g?p^M\ \;l/>uްljX~->lP4(^P[Iꎪ>r3Q?gnxܳqu_-5II& {,|hW1Dk̾mk)V8Cqo.q7Iv0B!Q Gc_E#bM/Xcu}dlG)Wr|u|?r353OgFߧ+EvZ^D2*O;s _I?Muzfq1Gb&}U c1k}Rį&95QxuKN@zk8͙D\>Yq<^Ӆ"]οTy?bzd +<:i- gj0).|Aj=Bof `AY.ĕl_џM~lBz ;MWg6%zd?V쌰2L. ŶT8w^bqQϿ!*$uo;>I}>8> }_'l!Ɖ%z EP V/`o)(շnr.#zH&_7H͡HkZLrrJ,&)`(K$$?`sQE$ }JMyӻ4ޙɉ}xP#1}a^C:TW%z\Ͷ1.E 0E/T" '&9S3-w6EᯩbXN$ 6#-^+Çw~NST*؈PA=ᔔ," RܦrBԦ!PV,f ?OtfQKbs*+ /&)b7)DƄ(oI>tWu(Ev@7c Y5IWc QO碊>-Q`9{ˈԅj.E#AbQBx bb1p2|gW{U90EPڱ$yi3z,8P# )牦.SyeKeJ>gnt=-S]7D+C QFr̭?"gw"Qo+3k蓏ߢ*xo6))EžY)vb_ :A:1\ nVw b՝CVF8Y@^Lg"&|w=਱`秺ǥ_DeY3!#}T9@G\a@ <׎N;|4M dʈk־. OEmSCeab +o@d[璯mhl嵜R3*'BXzheDAWvOepQ/ݳH<v4$H@i`1/}],GfIJS9sA䶸t=ŤNY2blPHrV!IQ؂n¿ӹۆ>z˗BSmd96Yۛg @y{i!>bI$'qKs@yVo9c:Mҹ/A0UiҒR DSA }hԐFu3{鱣Q$"5ϵnAKOPD4 1A X'"X:7mcl)1ۂciX\2|)S+"KI3-)^}j>{me; !׼͆ h8ĺHm"(:;VM :B:Rԫ2MtvA{w?Δ>U~&o\V"Ԣ%me_e 4(SZb>[^=^R&ˍ!*Yb+8sC}ȵ>K\MW֪z'!e"O@f5Ǐʰ3~q BN- :K_4sD>JsAsyeDɋ}u[s41ĶpUOEi:)1Z))y4B[ NylJqr/y鳻]di/5Ǐ_e~Y@3ݽ, O=pǃmAyQO}uϊWl?+)HCW3h&de-6 t Rbo!meAV!xKVD.bKzGG٤Kɔ?Yl*rWCb7."pT!vBBbԉ,fnng1m%q b_+#SfeζIYz)]LRs&b?I9O{A'0Lm t*ܬ;B>D-ѡЉ;|6|Lrʗ,  VD[K(3GnU>Fڎ~<7F<3"V`ryP<|q*3"6%f?\NwJҽ6X\8!b6 \<cъPBB,pi}/4s-g3"&KzlF t3- V|4D8 mCBV&nh5a)ێ(Wh5xʐ^"?? `$UЊFEIyC @""$xŻ|5#'ėaYt]tNWsi~O⹺_k-byZK{9]$EvOR?w(?{J.*,Myn .&*B5z E9O]? /ֹDjZM $ļ-$݃@iH!ޜ"l$mr'@+~t&D1'z/$N;ˇz"tWP+-^%)k )K+\oĝA4cMhPx.yX+ j;u'DK]ѡkf4z 52kT*ԭ5z)`eV@j$aeVF=K /c՝A=*)Ų0x {l X ƒ2N|z4{ehV!1+#%[u^""'Le*mRj2ҷN] ̹W.i_`D"kѢX.bIڦH͆+ECu:1Qow9 u 4>^˃'> ZЉO BJ ^768O jP}VNY[|mb3tz"C_I= |rFIGGgw}Vs92aq( h95+$ #%EEneʐ4}YE `m/n M٨1 Vi3rV e[:ƿIӋ c 'vPO "}G죹˚/vIE)VW+iCܹB+Bԝ')ZzzG2jnBPJ?:)+_Umdr{h|6%+)vk IDAT1 X$z PW/=q}ѡ!'Skx.(4Zw!mur2IS@E,@OERA SɸV2$J o |#lWYu$POEf8a`Ea(: t%SthN|Jyp9w:Zh(2 M"ͮhքTBVFUwT2ěbnr6>[L=U4Q^E<-ϋQtbv> 1 h3"+yyn8Tyؕˬ)&=+/^qP~.6%^Bz)24G( ,䕸4(61 +Ks]#t\#&ƹq~p~ygVą>QZW! AY~Xtx%7-<sM )(ŒR&k^DP+C*XiR 4~A,uZwGǎњo]1L A|+RUUiH5h xY=&٫FZ%k ԟiQO5*HtvdlVx.x$^z~fnxqu?߁T4"vQBR&I vQŦCo TQ<[I+m䯄湩<."Y(`bheԢ$be8^r&ϕΚrR3:_-#lG9,%'Y@-`r՝pN^w!/WU`!^ ,xo1&3WyxP9܄ x.2|GvJϭJx-׺҅z" ;y5~k +%JƢn$H/Ux{rИbDPKj?y :VWOOlZyx L+#̄ +Ïz8Qs^Fv],Gv>6^^9I5vz]D/8S(tv$(lHǤ% jبJ*"s*4q4sC3_TBfH#> |żP!J<s-Lf eY-z9D̀+!O+SL+P!ұļcuU9]%VyYUW_i^5ӆ} ӻtB_Lw ,/"Z5P/Esz*pKuO`fGv(XĽ]o%@bf"Gd`=A*ϥٛ$6ʧG~߱ ㏈C\>t–mx0xH*# AIlgJ4ynՔ|,S]|SVQM$-X};L7C Dq>hzQKWHny/Ӻ"ž,oغӑ_X&濼VLeSgULWw~iw(%4\Q:4=bJ~AIU2 RsƯ*w+iKF{p0 ×^^cG͋4¶QL/  g6D#a0. !d,̩\qs吇^U;1pSZ\~.?ÅqYr[& q]hS,qs##lUU",ѡbb l%Ԝ 99Q!*~gws!2Gi>164{4?S䘄>S># LSy!2?c C yU'4)iX'QK>YӜa>-)0(74LU+-,?OJyhXaoߤdd|3A@#V/YjKc'CԸ%G4sb +^T+⹿vP/FamЉV:b}EWK3TbF#ǧkQjO*RP0|d[soRRTpxn ,׌e^<<ئ{#viF⣷q\rj#s vjBrCs[hsq-Ո믥Vϝ}ʍ͎0V؆<jBL"1^){Y|Ɏlbea@POR C ?/1u/l梃 -qp0*i<[S頡,/&iǬX3Pfjyr257Q%ofYٟьž&GJ%ZNz s0p[ElM=0x tQۊM[A5RVBb5l>kP` Lf*<[LcVH h-ثg%oK}xejxGcƤ#)Alnwlx@V ZlE=代T9*3Mҿb!28n(ͳcf+O9ǘ,[5>o7Iׯd?-,Ϻ)sCg+s_ 0=;6{}M`i^9zEµ &sYvave\9OiU&όKb5+<ܖsKe%lCYirbՊR]+t֊i4m5٘+- ~0enoIz^S?::8lNgYž.%azg<v 3D VQا##k -AkWoҩsM<ڰ]ֶL3a%t (zIƏՠ+jhfOS\a[*t[! pTbbKu/߻z8F<s4X s T:7`onN3r'Wb1#~{&w U1ϭ/x.=!zdx>9q~ 3dm?IESl^X!ۮQp2,'Dq_Y1^AщB[a<@ IDAT ,T~~a!S1ޞ.ƫ\,\r6/ xtj2!sRfc8A<Fd"%&-z aG¦xv ݗ8^ f^QUT{X\۳oIvӸiI^?HX6\q1\! ]#ii\TaE|">Hncϟ‡9C>=dMs`ce6VnIq]+?jع~g=!{+UVoT8 KEdwMI+LCRYɅ]b 2#/}VaI 3 K?ͬ"2!UW`1Y!3arȫCW!L'zt_HzZU.uִI0![\toWIF"ܫrXkeU,8GuU \69׽O'D I$*<m+m" y)F>V%;z2oOpP/b}> 9+x`Ct|.9{TyUaPݪԯnZK2 ԭ =ԓb&ҟ!f`Op0؇H;q #P䃚Z1:q#Txmrtg8<.>A;|WJlKZq*vAaNm6ꥤ8JEriržZo%<ŠŨ 7KҞ8yn$WMW6Ṥ{)+s+'c:a-*Ţ\j!;@Ͼ2xLle]k,~O%VJ~zd03S!C6ү5V2aeb8B $Xq_CFk еcWбp$0P/Xmϐ$Fn"/(:tm5DceH~!oǖ6q H*[NVHGyΏ77;McE#6VYrSf ?4x6YR,ϵu%'[9E9?.N9k :dMd7YAtNu+c)_/U_^I1dj*EFoXIɛs ^ R= .`28 ;PyqtQP;VU 9SE\q{V^NF 1tf˵Э96ڥ^ځQ̄ \6H6D=u sx[u\ׁ镑P1 ie j[=6Qrihע5ʈ<׈~ Z:~Nq(1)@$ lI>=ت4nNBJxW `M6pfnU}+ ڒY!A&AVz?deqG_h7%%@*Hs I׈b4Vf- ^*/ɡ H@G"!]$&a`S&FԬP|js %8dABƵL}#ԛIgiꄠ H.Ͱje\#υz.CK_xLK][D s,1Ryx)f,"B!=k.%)\a}4OR&๹A=B+s޹ee)_@υ^Vګ6>>vCՄ܌*6sױ!9/xIC]U&ϕTcV?i[Wܽyķt <4KxBQ{>EJ :a`dKxϭBu[vVq$T>Ehì6faRDKbk v|;O%wyntꪼszɍĉz^k A6w /Zm2(=?ާ;&}xntL`#Pt$D\[5Go4E>ݧ+LrVSysO| 狼޹!vٰ31 Acde]I}c= @.IC-.'WNwrS,q7;w+18] ZѱF 1%j>E繍@{*箺~CzAKgVF AlWŞ >臢I[VA=9neB(bwB [`-V3<(zHClA@uZSܻmynu}}܀>%b;x%!(gP }d^ߙpL%x Z%dյ/e Ee{*/p0q+C57YH eKb=SFOF + CcQ;xgx!(1'lU Wd^}JXf",r,2)(!\Ѡ=툏_kn(7 ⳩Q:'OsWe)GCQD7RVN~:iI}vV b_,7D}. sY(o AS{X h3Qknmё1 dؾJ\b2$իP⹬tP*'r]쓌X1IJ:` ܌bGBgH^! W-ZJsSj< ^yЩX.[4NV ;Xa>$bN*Bl~U&9==.QψZ<!yn$05ɦ3?_}6`ò,9"Ffd%A+If?3l=ۺw,]o_Gm__JI(Ֆ=}`*\ ; ;^T:VV۟ӆb{K}u:vx׋J˳89zܷU/&Iյ4D=XB'Zʈ+԰ VF4],rk~5civ=-ͮ ?l{dq*1XIDTKM^i hc/SOs +M4L v)vb_}]R+ B\CV>ϩ3;S$t/ݑGK.&"QO2y874km YV2yu+6 3*]^Q/A^I%g +W0 -U,@6Zc$ӔZxLpQ乆>ϵ!oaGŃ8O/j]s/Z&Z*xʊW ѱ ?L幤Gֆ҅SC,V \KT 1NBU$4~hINi^P<UN=ʦa3܁A<LW]-#)͚d13J ȗ4??`T|UQ1"b b_k vQQOSD&+CIx.sU?@q=\{"^:(B74 פּޕ)0xg6BgZ79$3=X}{Яv <)@t4 {3 q dž~Dn!Hnoy>YQ=pW\4l3)nt3^e/z=r@͋%W}dj%k%2dU~z8+l҄zM;dCج Qtgs=:ejH{u:cgITnd:,0fU+c.(C3ά ylDU*t u6 u{Kt{Hn89t k2l{ D `gH~ngVFkObUv6ܔU5=,V*rYeOԋWt Z u/]D#}kMBȧ'T C& I 8Ah+/&9zΰq~OvV`~1WlgmS"hMdl(*LHw q9m3 +ub, vԟ5ɋ2Ԅ*C1.*sI 8[ݑ=/r0=ۻ_@Vf }U E+C#gmF>c$%x3s^NFi&* %L!X(N]ich-L"4lYPH7sM*%M~(׵|_׷F[teI RwY!}1z]M 6!HPC?dahs Wxo0<+#8&d"+<S|eô$rPز! Oa-Ctq:|8(IMR@;D]n5yn|⹇z^C Au_җ!2+c/ S+!s ej_N<ۃOXU P;!BVx]k@9zPlu!zwW1x!]/"lE=Ț< 51dy,ЯѷЯ@R p\aTyܫՆrsy  V8!LȠD&Eb:>rKkँ ^MRYsH0}}0tr(d2ؾ _`O­o_VrV\.g;JE)NYtZ\P V8hu-֙#P/%j?g XMxu Ṩzs_BܘLQ,Ы72O-{BO/˼]-LcgbT^7 x6 )bu*}IRUb Jy*!t:s!a'PV՗k Ue%)5Ɋ=!F=қ!@Pʐ:AF=wW´:ƙ3Lʫ1}TnB`C-Lqf*AK0i#~c-k2\b:*\EOpvyǢXs`/9[U޿;PsjG2F.`V4BH8%K$*OJZ ڔX9 +U)ا[$'/!zt:υ2ϽJa" Nxnz!Y '4>:54`^rEtCIDATB4@S-gz4(T`aUTTBE;Y*??bXNVʹ"5ѿ'sg:xKSQH#sޗljtrQzӷ2cHzƢNR.Q[CTl#ӧ~])#e-PƂ 4ASB$dƛ _MR@*^9C\, H'PDMYRR+CĚ<;+6; ?$@AmTgt9?Jy }GOV,x?<^ ;c&1}*bR_1 2HJDr,&+Fs5$ϵ8<7wcD=lN ]tx`\1?ۍ*yV(`|mDiz領N9>]nx,W m1Efwܭ jnœw+"2"FɩJB'pbߒnb;PoC7DAA{NdVwES߂kќ6p 1Cz54?ڠ^W54GX eoAw`Eh̆bVBgqbӉ޹qUw߳D%zz-_Jϫ!6f*-!񻏛 WP=FX}'kRufi~JR̾8fйë/}!-ՀM**Gg}gy6J,B؝I߉_FVf?G& z+3'bv .Kn6yoWձ<֊Vo'Ⱦ2-.9*=`Ś363tܶVt=xq\od?wf:mbHԗْ}EGoT§lcFj[ nHl߲ts"eV,ۮ[ .8`Q]l_*l~r/q ², 쑆SI입i2}˜O7˺Z}᏷xwDlˋzH7 p9= x<3i`gK&F(A6,G/ @triZy&e'|Ve^s /mߴc3\)}bfBgP.ǧ&0"X0X xW+-pH-jxnܫD^a(Bυv^Qr]Zϣ2[N4'V44lZsdž~@籣 D}{ءO3!aZguxa%_ Vx(\$ċǺZs`XK`2w3l{ v ܶy2f+uM+ɾ)"ɾsW^'PK~(~lD_`0Gy P7k ][ԋ!\Ak_pyfj— rЋ¯[ϑF4ɾ4(Ӟi3~.bS5رi`GtDt뱛CLcz`X]Q | Xun)}zv-WA /.QFlRO8 l[B>%V XS|;ld'۲>geDJi}Vc`U3ƶԺO!b(gl+&԰sЮꂶm;V/i*U8 {Eb>v@/aiHO6HO{.7*vICQFD)v(%Z¼_Xew)EV\7OI7+&nZ4Ҕy:4L2 {p2 89[v|k|3| !/ܩ.2A"n<~nL]hm̛zne@`e i`:W6cg2z1I[6Vw qp<{$ee1;O[  yaD`mEƗp/}oͼ@Q/|;&Oަhݲ؅:VRpsg:N\}@ ֫/ND#45'i2c< b$]C"^"vNFSzf+ A Yfte~aOY=zD(^[8 eH ~>a2c pYC<:79g}*|&$&E^B#) ESZ.5:4pݮ"WTy=s'*ٗld+ńx1cp %(:Bwd^VF 3te՛hzf#Y-3#i9\:pwKVG[fTsCoj(Ro9 lVFi"^*4 Ε*5兩*LW9#y>tE%hA+3֋D&(^:z7:]VE鐕.[iz.+3O$TysU䦿>X f\|mun/ANNQ/5&(P!U?zӾ* P)7pgTykeʾtQ'n/kn]g/C1D"QAp>zY7>4 zc<ꥆPTЕNc ɠe -;'Fd~!L4y|!}CMJd6 zǺE|٨++iA鲄}22:^7kL'7BL:8:pdh$F.;>}h4q-8Ao+2-5:;LZ97nqddMw9I;N4f\>}۾;:#5sJߟOeʶ2<ر57 7~XtYVeʫ3]0Uvy]-"G{j3{kCP7:z9VL[kMo=4xV*+#Mcet=2Azfed!5- ƃc\KSC#Aeȶm#wR>T?c*'%⛸{I;' R7W[gmɐꭕAU%nepy^:+#=<* ƃNc#-p- yI\Sԓ߱h58Vꑎ?]]QV2%*=a'%ua+_ȝc.ٯFw.ÏVRͧ;JҊܒ*CmKQڟ z2dJSrX"qG6H;"]Iς~s>d#:2Čm|V\?5 )I fQIBr|2Mxf;<,]T^۞/;O ]ʬs%Z!q.|"ypYywH8]u.s|tnd[z۠C۠OX&cB`Uwɳ2R^ǝ3b:H1o:Ws7l7+|blDm^O^'yB2PȄ UY"Ϫw:"~ J|mGm ^tȓ`6 WedOZG3kmEyn>%R&%pz} ƹВ`-^Z˥=pV^*H6rJLZF#J'1.aǟSvAJD"SL$SX@PG@(ъйȡs?78ۨ{)<:`L*Մ^9٫2<iE@-tn8GRQo vOlO^|"E˅SzpiV^ǝ$M ']1UEj1ڲA0E^lϪ^7~NZxw  Ao sq4+||R4\~( FmԽF_{`m=o?+Cj9닱2Dʈ !e-qa` F_VZi9mVF@jъ"w\V^$ROpI2ĵvjQVn$WdͼX%||g@>hu2xBP^O0jO)Ty5ȋע=gu&}^%/:9 ﶼ.{N?.+CJE[=z;'E\/tR_'=~^&2$;=E9s*⨗3O+Ԁ^>7AUV_'"Yy[Zl,a&/)VA+Ce"MYZ1Ұ m? 5[nWsж{ae@r[=\AChw Wʻk2"* ȼݏܶD[Z!^%cE3+z*UG}Z4 A !Hj~pYb4Z7 sfnVV@VW_ڍlt5!H.}`_\Vpɞע%G5E=%u|>bʐyTrSY鿶 ;`etHkɼ:wg/ڍmstBeeWerMVFH9aCpz |K64q Arw2AZ4{ledxm3ؿ+)-> @Mk0' "!>!+Dohd~.yBjV%oZ̿jZPTsY4VF ` w23oWհ8X/P4spJlYȶ2s Eyy ύ?18;z |˃3sae VĝXB5jap/v 晸`UROu~Йn>Rd`K'IFj?wЂ~n`CQOO 9x_?AOz+ 4|]7sah jKHeRFV_G 1,5)s6\ VwKLדy[6ppGܡ6f.5+#[/ʛX]$3 /wB:=e*Va|-zr&EONf[ܹc[WU[KmgkYy-|pyX^WʗqQa7֖TZo inTVkP|鿰E+CT_0r|s#QX%Z<٘= +za廅;AIA۱Yo`w+)T8x1{ҟV.K/JД!LV ܙq|)t5sT%RYb1>OFa23[d5>ORSZ*|1$R[X`mܙJp>A IVWSSK>ј=,nBP\pըr#ܗ+;z |j%KoPONUU>J/27:!`BQOOO|1j~_wph׫Q&_\f+y$>֘}5!gUFb6E+ꩥV|1LUp_pd[`3Ub-@} HcaJ_'ܔ'1n~~)jOƃ7fPK1A_R+Ķ/뙵\->Sc9sj<<{$Ф :b piOZ |j phx7Q r|f~fZ |j-F;G|y6=._ pS?=Z6{9w,L1jS?(Z7ݼO+u?jH|3IENDB`dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid10b.png.license000066400000000000000000000002501511655130300265430ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid10c.png000066400000000000000000000332701511655130300251330ustar00rootroot00000000000000PNG  IHDRn9 pHYsHHFk>6"IDATxiYߟw[-zvO,1LlCR$)` 88DD  "AXQ$,bAL޵tݺuw='ު۷w9zOan}=9Rԑ_m|٧~9#p)G'o5@Sdӳ]ٳ\Y8Ynzoȴa=]seᰅKI_+w-tz#,p)~3鈋, _:WN\Ԅ__}+oPJajDse,KI9>˿[w4nPӎ}pexRRm|MX(.%Kگ&:N8$hp/\JO/%0YcBؖx|.WJ7Ycޑ W¥2|/^{鈋$ " ƹ ,KI5ofhBSA^•p)~3E h5i&Җ\YJ3ځ,¥zF<X,\YrKIIy/MX4Tj\?\YKI ),_~w\k b/ȩZO}0<|e.%l:l|3΅*}λ:֪oz&[(??EW%BMum\hj㱰Cw뛸$ MU(gee\t!-fGO~S Of,KRRFdIm !Ҕ߂,M#B4fs Դ9?Lwp}RRRDQeI}*2Rh5eq&0"|R/e7;Moxj`uo|+cp))5ZF'ߨ2őňxu_Bdz( 2}Ջ̓T?;sCQй HxsKIrb,ڦoxe^ QހȢ03K@Hcȕ =iedʢRKŴiC!s,7ض5UW?_ZܼR$%e[8 F9 yHy.7X.%85Yc´FIJ|fx mtԍ\g8J,%Moȥ$9Gާ~7{S=%׵]=d:lhɷɋotLYtGn:(Ko@ <ްP5YD gBN@Hhi҄gKOE)iQb:7<D$ɺP|[~{p5pHS}H˩Xev&0([(Dv624m/9GI],F{&1A7GqS\J21dx͊0Bk<= #4nKI'?.E,KI-㹋w(uBFW7 (44|< A#Sd]@m.%̺fY֌HY,(sKq+H\J|pMtfmnxFkD93'*L`ܐ#ENY_f.B8V]S)YgcD^@Dk\J4veeuNEd; ucNeb lk3'.%2Y.%l.ݧ[gc7R3%g@iؙ@7vdiDK//qΩS@FV+%xuaF1YҰKIp.Z-LvHx+pe=ˇ-ag nK Gob&Sx\WY0һѐ K8cU7{w}*da.g v[8XRBF6ųP;|8n\u)_2jս$:^jJIl4QzW7GEָ,=E)SXvv ՒLyT\}xPa&K50,[{D)HWHJe;ANyur*nQX)I휆U;R$륫|`gj(lsR*HIlTtx2B` `JDm-?j.%lcGbYU;WGZg& "V7Po)d]@jJ-ؾG9Xz+Ű$.%Yr#0S+XV7|窄Ust팅ɏ^rZg4UDnRQH\Zse;@QوMFDnfRRɺ@C1jܾ8,)RVtSqZTGJg;A,Ys(V~tW9EZO'Vu,`4qi(9F83#ͤՍiфj)F,"Dj;!v$.˅8aRfjЩAUYhfr{(gpŽO+ŗd~ AiV7EDԴh!ːB^+dQ*-%f;@,蒳[JhJMnQK@̰ILUvNQ|PrZCnמ9IZP8$ݣ\"!:rߋOo=Xz30VM">{wϽbڴ7 X6jiYgު&<"&5}#ܭVv;ۇ6'rmT)ʜXhwbROsɲjJ|jdvw8!,BR7w:wN6jtRiq'?f#n I䓋aoܾ*ҡ6jtn\!%9g;ҽXE,v4тP@c]q92b/Ojl"Aƥ}#q)+nE-3Z4iSÄvCJepk~os DyXw7$Bʳ51YxHuRs*z#Թng.X6P#( p<"k-)y{~mWUSŴUM{oXcRRHsxOo1,Lyn[{@Knu;pBEQ;1cZ٨RlTJ vNE*6/މA45fr'!֍oyu(w7-CwybSE '}8QHRY #>Ҙ.[ADl3DM@Q4۶BQfJKOЉc#UW7m[u%aV9I 7Ys#qj 3֕R86E,cDQe)n-M8U]YBuc;;#7̪7sg;׀j\9Y2fGExw ڭ-gδ4Xk:b5Ʋ8,m"q/5P~_u!aw8yRRl窓xG<%#K!|Mwď0b lBc]2uJzQ7FYoo:|fn\2 e;W&KVosߌ7o6nZP/}`UF6P[(l ٽ3?Z:x8+)&k>$$njHL/? 'CEum<GoWeU7A .2je;WALMYj{8םceP[o5Ĝ• 01Y78~.ؿmv" jX/a,o4!ʔ"|Ұoxåw>SE+%75Vw`׾vƭ,4T|s¯㛞ek>fo ɇAf_>_die޷) c뻍;Fy'ɚLVgE;'ki恔IYū D'i,On/tD2A #7Ys qs ۓ2";dcXWnYy,zFky UּS^"g;@/Cid|d+̂2Y,72%KVUAo;DvYJ,cI cg)9͑ldu-IfId5,ƽ7Y3X62Z>.I \JɚLjMMASހg )ep Ab^҆|vpUpcĕY.l4dMFKCt4n>!19(vS-ː$e^ %̳`h]*\,(hX[7AVkc5mGp؃$)cSS$&/ v.6tjXJ 7c¾TQ4peH&iV"Ȓp<"aozCV$V|7+fB%0\Y|a`$yyslvn҉Oś rVҿ}/DQe)ƕv&ʳ3!CtrL&0Ff<YR-D+,Ŏx*<9#|$wc1B(Vp,” 7]?q$ضm4[Yr3Y]^G|MV휞NsL& XvLJ@!wIXvŚ"diZvrno_z_n2A fgz4:C̷,I pU?.LVl爫*;e;O%(!S%+0X7EW2vhB/;jƎD\UlTY%a;ĊY[.DT9j!TB,`H M7c?ɤEe202,E4Se49غWU<9ULgAbYr6Y][;#V*9A7fueQr}}O8ȒY1Sn#V_5ju7hbP,`_R<֓Wkza/%´ WVNܐK&N$v81cbG"JzB8iT7i+W?BVRbBI՗'RRjƎpuF!VDLorV^5Yd(%p*>&:qbƊd;=& ɲBB#Mmywg&d5çKHвIcl|"˪MVk8M%)S9_b;8>Zl3xHxDV7m`IJ\Zh8!,"_jv; &kx(juYn,˯7k|UJ@0Nuܓ"H+Ig;79VBpBۍ'nt敏(&ĥD)mk|mrB\ƎD s;EdjIނWnֵDp&65L:kF; !꒏պBJ"Hނb2n⚬^D0":e({1e;s$`D=">OJBHb)pJA ҧDSEE:mV0B)jSYM[K^Zm"N(TIJUw#Hn&YMBÒʶ>JIbե5b3C*&%.k-dqNlQejA,Yvƺ:c@lbե5r3C*)% p'[bC֠l&k5plZYZf AbvfHUekM 1ӋT$W:YmYtƺ25 ' ILN[ţ i5J< f;ZhUBŴťe^h5X'd,Ò|$UvV%O%bzC&&q3Cj"%Tig*NT$W+cG1D &(O5M3CD8s 6eL(Ic~$oHz9g;7UòiXH;%vf0޸q7f))bԶ ?ƾcd;iʢ-N$#&C 4Y еZK-><wǎx,Kˇ&*&>ʩ,^,BõZe;릌zp3)nD.UՒ$lgQze04eYkN%qq"kS}Vk-⚬+;ĊAdk̐dWY.mK1N 'eq.O0"#A&i5+ycX29Lur&I;GEwLp@F؏]YZh4%XvGv6, qͦsT+Ďxtw|bGSv)GZŃIkw/݁Ȣ=*'ʎL.,LV8+&TdR%)Y 7eބNxk4ckissEllgevfH}݌e}G &i U6>³gCLJd;.d;3>Rse1Y7 vta#~d;3DJ`&+euƺJV5lN.LVÒБz^ND2W:)˕s{НN2`dCY*91(a3Cj[b`DxWĎ_Cǎء`oݚrf;3_>+i5 e;Ϧss?5 f;jHFHb35Ԡ"h.MCr8WҚU6YTCJQCe201/MUhʫ,ƎxkHbJ-%!tب"K-O|i7vʒ򳈛NJLNuqymT&`,☭bDY2v"ZlgEJmTU&œV1%;ٲe49VkRTFeV1CrPvϓj]ؑĜH湋vumԦ;fZEVb0WMVV+7Yr"%jq"`]7ݮё%2k3dAYFSz#Eh<]/^tٗ\Y@>*UB)R~mV\YJNKCE*^o5<6j??c\GNV+ ?UdÀ;mbcIDATxw$]HSwuWj3=cvv͎+ʬ2'>"$'9qp}x9āa0ZdVfhwL{[U]ޥxYt}z2E<(0/|}^Έt$O|x .;#ag#Y*#Now8?O~ ,&ı(%qi$+#f#Cs\?R2*Jj-yYM('PI9vdeDCtdxIRL]v,HT*o<PO,"V3X̐ڛdeD #>8Be:q&W٩HVFtdb֮ JeYmyv @ٯhO21e&irtgfv>{HG¡-ސI?E@@rłdBqv9/r8Jvۇ29:0\'̞zv+Sm'.{)LLQN24rde#HxO{2"d,wnkBYf~ݍb{HcPڧeesהFVq8))Zх-*zbH?nJ<{Q dPzHG| dy.݁fW7nc>!J& d'wchv xbG4iޏݔ9(jLȴ{NG>'oHqwˌN:e"IS(NIVF:ҏ|W?77+{nI*Y%EsɊFdT 쾬I]r4ʗO]sUe-]IQ|2\VF:ҏlBJ[Ȉe5 o`ΟNFoES0&+,'2L:PTȊۍE^.f6zЗq.+chS|o1X2ґ~nzrw/x->21 } S,%%?bUZ΁pz{.~U x% t*TRX\VF:ҏTHFqt rY+nUUA*|8o*l {M ^ޙJdm-d1;Wқ&2yvm~#kK9mh~KҲ7c7B)jmǴڞˊ͆fmLOIgUW(s;SyPCx&yd HGp`r\{{~ײ`1EEqPzt]mRrv;݋h櫶uYIdkTV q{L׶ۋ#~us7h=HGwϾ}uߕ{K_T|m'9Iϯ(+NF]^BFfk#*@NH9wI%l,m'f 2ґ(h5K'~rfNIe+'v1!*+$~n3%<0.JN6،D}]8%-[Kd,;=ˑ鄬tDjcaEeb<O׹Vb 2ᡗ=kJɔ]<ah!xe?M9wT=C"+#1؟~C0!11. R`tوNcJ7dYcˊ6 J`\Ն`J%(s[>'4Мt|ЛF}>y^W1²zY9l1A:p[eMZl X$i@O\ՆԀ4ɉ0e ee#g/\m?g2R :' ` ;AFYqxJIݼ:pµ}:=&67ٯx\_'_*vosTkJ& a0!PJUUQw;Auq,}0f1ئA'+g-U 6Lf" W>{yWti՛& -n3&uI/{_H;Ag~$ڇGPJ(%PXSPBKTUB|e`pVnHx5)7\|YVX֞RyK:oLV >xNsN+Ϙ>>HG}m$>/Ie|aگ\[i(ڏ\P Vҙ}E,8JդdD$L{bӞd^CIWV4xޅ(K$+ⴶa_[xk.|C?PX4`#7~Zϟ>=O|xQ[|c$V{Fdu) `̔ Jq!J)B[vHɸo= %9 fy O孱dEF\2n,R2ۃqkE?|.y/<7_?7/.tu=Je^~yFfjvZkNʄxf+Je%Dc1ٸN 'L>RJRi9-ÞJ:Ǥs5!lZ;1ٯ6/;X(>ǯHK?α#i瞹'⺙G+8jq!狂zY q(~HaV2 E)񺦵md9+I9E IrI岒| ɛYthKfYC[^Gn9Ri<o#瞻;T^};#i瞹O|Q+ He`4f+Ot z KVJDD\JlvW6s4ЋlwEj ٘= Έ.ȊpOfYd?Ur;R^?w^u{-Z`ż+-AtI>WWJAKE0HVWwy%R2{ "HӲBhd%6@&-|j0 ,waiBV +#dO)vH}L}% O^sg oG: 폿r\ |~M$oEPpLV)QYl7 "J`4&%!Nh3mF)񊯎}KqReHG#[2*ʧ#V6Y"Ѽ_"(}BYy@H(Ԣ s37~DMdqk6OUQU&R5:#i+]UE(rLh~j:A<!"+6SHUy6ǥ >mܚ~FX4?NQdAV;oT+"(F:b*DUkTUG~^ MJ7)iE:TYQT1E>fA#eQs_bz`3d#̧?ǖZ9Uaz mkrY[dIupl+Qc? 0Z 秷"xuR2oҧ{!6S'YEdުv8 $3Kd,䴊&R 6Hɉ( pS0Yrs?u'l:*"tC~4)QUgE#pK3 @c%q?Coy'v1?|?I6I*~p|*Π\>F2Pf]V933cW>SN%KqaʧEK+Rru$WF)%#Lc;8LNOEP, {*VɈb̗="+)LNy42]6,31B#s`EKlA ;LЊ8iZ%ͬLǿ1qٙ}UA6;3V@H8Rx^ [^ţ ġ ,ͱQtL=Ԣ, H vNq>=6zWUQYJ6YJ YMJw՜{}>$S"t:MeC+ 6)˄kl#0}V)T!鈑pV 'z}:E5dè,#ǭsi.M)J{|(Ơ{ ;tmVVnyn5+ƈEYT̑c!Ӎ/z"t`8s04 53C6=Ocn<6-9j5  4 VOn)_M%/ մʎ=-w)bjPA9rHpV(Lx<6DŤHNmE犛9wRX-נ97o>5e8k0K&xori%F!0c,+)'h1",dbE\[#hyd[j44A"+ۂ070{@!L^:V;'6:QWi 8E=˛ѻlbŅVt8nuv,3+ Re8EmX QVv6:+iߴEDP KH] 8E=4m̙]DD,f}JN&rEq֬^A= TeI1N[Mk0fHS5ʥY~Hs̭V9 N.Mcf"RNܪބge^zoZWaҰECZB3C1?gt]1" X(aO /ƈ(*}oT˲Ȳ\E2HM'|ig *隫ZBaWE慠edxA:%uRڡa ܍XӾ餏:훶HV2ƥdxt%..[\T0Yu+Z8&%[cTUH8N|ӥYSpeߴEJ$UQmH-(hqPIGdjb83r{>;;f2%ϙ%^|l=I+ߴkeD1-xPÙ[0= Q,gIF頞b2fTDʼ/B5DR +8!V3?~ l.p9vm|ӶS|z}kU-H`P+5EWUV8 ϔ%鉛,Ӱ*e`EMBcj2~\ fre2-JMO)?($/ 10 TS$`YjpfZ[)Kj͢TwC)]݃P^^%hyecF%RrNa ˙(ۚ!=oN4)qs7D ;,hdWGKAcD{ kÙRޗh[( ˗G) Y6s-2ۻ*>;jFYFAV fe3~{h} X㦅ύSlT7:pV@Tn12W3D4ުÜ2VP`1"b5Q[^G_tU9N߱'??.T̢W^m6Lж8cs!jO <i{8s+UpJ `8HuҼVUcqh\g[GSg;ON^ 4WurR} PI)sT&¡pt=4?ƇZݤ*ʶq96-X{itDCCDdfT(R gd:*'v VV+"+e\fm^ZDTx³&I1ժHjy;3@)" Ț]{T˜Z'Gmr"o77ߙ^V>ġـ%8a>[AdS;?3\8s+M`\A_D̒b!"Y,ȸs"ud#D6Bjca>y8 Lnr.'7mޟ~R2:H:.gJ^c2gk݉ͤG፦Դw(dŪMnUULR85M'+kHlK-}/i]G#H!r+jiHW|̒l"i8U(0oׂQ1>#eQD侳ۧnRΌs'\>[7^z/sYG ,+I GÙ+λ+sj5TUIie/J$ RLFW.6SeUp2x0Bhaz-@Hw™[vhy{ctغpfxQE],ǭNy.HكżTn4yS9Wuelͳ2f]9Aq|CQ {ozL?HbDcq,1cDE6D4VDVŠmƏVwYE<&BpLV5'B]6 OF͓Ɛ?r o]#qn})l9CzoaNv[-''yT7vU%tHvTD>'Ɋd{-yt]0MZjPКb8CD㸷*Ws[,@>C"9S5b)KiO,,+p?9w;?[+_@Ù[ӈGÙ"eJUPTfy۳ezYiMa85SRVxTG81Y. [7om^x>ё~i]ߤi1" nv[eU [6*eX1!DQ0 sPuño?d-37D4[VxEic.N>֟jcMYͦN9x9ri-N@%d`$+5kA}+>VGz Gq=oÙ%oHDުv[-Ĉ p;D*Xt˦ G3ͤ|ǝєYh(A.9 j xdEi,Mc)z 52%+u'pOqZ3S-3(0 (衎6E AJɡňhKU[mt[Շ3#*w6;4 x Ü 2nfe]Cg;BCq A<^t(+p &%nc]U>*Q0V%%0X<6Y)9Udè n@Z孮u[Շ3ώӇZp.g8Lj"+طɹ :,Msd2V)gnH3:> [ gΉ&$@/"S--ѹCՅ3{;;8ֆe2ӾS7Mɍ-S}PcmN(*sm+X⪞I{[:5H3OTJb8 ̓bhp݃qIzhL%y͝tEʪ+;ДNy+:weLlԘ3˰=3OUNJEW\n*֕tj gnm =uU׈DA͌i[lзѹC-3cu-I(ڪ1|i)M;mFŵS#f1݊&}D< `]3Ǧ̿FCqLtGV|Ns"aY,@{#׋/zn5D_3 P逝p|/nj4jײ괷Z gvXw$mͺdp?x1o3yR{oь3e+ rMTxyaE>'deoocNUM+J:Dt7 MʭChҋƽe8>u:=&:;QfdLLZ,:5oؖV> gncXJ )}+Z8s#DhjaUEeV&c[jml ttI }4B(s7>JsyZT.+^'rH:LUvq(+E!II$Ѥ^.ęxaH Z7-$#5)x/23W:kYpV@xvXS g O);jV,L G)T 61w)E32EI}Z>RAhJh:w;6  @(>Wk>',N&+ Ȱn2b)9g0CI'(Ƿw^JʼR檞N9j|֩!::#" =n\#+Wkpf+*g26exsyG |fʂ Ly*Eҷ^V2wgi6LVE8Һ|,סJ*~̼)c,&ˉGHLfnk}(嘸}v$ JHC DM"Hwaz DY4xgeo?F*vjq[`ET,MVqXUḷϲh;b$1n)Y8b~)(OWtU} Lݔq9+#?-N.L™k/VjpfU?SSsm=|ga2^ݳ8X뵧]V$xrmWUON ]G?JMֲ8N,M]V7X^8ʲӋb4176>J `0<)Eh^LzYWaSՑgnD)S\F gSlvA:fEDF0QJj3ݧ3Zi}FgnvcV;S ws:䀷wNE1FQRq)vHGr:rS*u*w-zr$IOXj DٴY,>lgeQ+K|}f<S0j,rZ(SC Ls:QAAZ̄jIsU DK[ _8kS ^{U}8s5WLjԦݠ\Ռ|e6z%N[ȫ)cnbP~j@U"6!pVH,3G)2>*2D4:]UAȪUZc.rRpU#T'㢲CB&0qRY)\[9P2SIiUj#APWNM&# FSlZGfqq22಻鄷Z g&DlTL^2oF4a@UDP&2JKW&}"; F:5P_3K޵cS$Ln(VWZVZ3FҸ;QFl`ݙ0F@&$)@)p,DGn^&EuaR4 -T4*LANF-p)ا/41MsUhhTV[1"U I1"ѻ3ha0Pc#6h#"Z{T,az^NFepV0=z`jtzDc˴]D]UQrΗqWXueR-jp\mIMAH"CF9;5PQG/*#8ņ# &g6^CDު.bZ>*7tA!Q$Lܬr6l1R6/+ʬmosN P3abL{h|<'/M,^CDj,㼽;Q7F$­E&Vf*TndEPJUuRsF$bAWRЭm~}?3a6O5ީ9 1"i#0-ꈡhvxz*di!V +*cbeAD%y*ᓉj,cA] : ?-o<;c86HU )c$ >IOoVզÙ+wUc BhC)CCK=#{F\^Lo7FK Uy,M:,YcXJvj슅 HHB=\^Rz '%h7?9RmwU5JՠoÙ)qU1fG-\W+Aȱewypy6c\;;~Zg֣|;4?LcU[n!:{$cu|H *&vUmsl<mV5#4^8鉒y@lWg7zӖp"EWNFU 9,dz@hF+oYlrGn.TRY=Z}qE^;zc&\ -+UfP}Z͸+}h3\誶ά1̍sAivBZ(* Ԋ9=vYdE~(bmXi9Z跄z 0-1S7Mɍ-Q;dR()ƠJfvlg-qEe7s-zm g8!YzvV(]B9FJ Ԋ-ɝڮ\Xu`H&@81[˰=Rx9r:?@Ҡ Jey]bӫ.T%m g OYJI?Lj+S'bn& ԊzG]U=*uS6ԩvԅ?e]3/P\f~''+LvRRb=`rnfi%JV g.iS=:uUr6(MvK$̱ucw ꎫN Ԙ0i񻥧oQ$G#T}.++8E b@˚رy\rZV(檉Ȍ_8?W?qd3/)2;^`E2 "I~Coi&:5jIǝfWoP\>S|m~#󠛞p̌plGꖼ|f&;?J3;lP:=%\}[@ϑhנNɹNaLc*Fz.+V]S7~S~mD'+$X(+ ]bDo`8_8=+"\|@F T -C " dmWUN#?xZd j7p9eW)v`!o`dtA g6Bʳ+u4AbD$f/ޒliUoѩԪ—p/3;S%g˸j0|QWuhk h+jaU ROr|UXT`r.}gK{*TFUvaPV00bQb{=ުp&?^3wF Ԓ v˧'9}((ZGS3U3}j9lS+\IU8:Unee3ت5.NfުÜh0iS/JZLu *[ѩxC1]ӨZ!.&v\UEhaAVѫ}7s?r|~mЧnvdUۅ&+*:rBrSQҼȻ 3Ox󳩺<|@)5@OixWT6B]S**(;їf*Ҟу&{cKyUoSi$D^39Ѷ) Vx]Uއ F ԊtU fs9NMzX/y^?TO~U-4g3Gqxj4StuHG#R(V3ߵ:7Um@5!.\JI(LgSş>UEN5?iC;?? ^첚ptUSS(o'6FUNz~.U4S%yY0 NF2E™5՜)M\WPpV.Ԩw|Їv/ЇeFVNVMK XHP;#j{u丷*V 3򝧒#b4CUpkMWu?ȿ>!Nd@\r:fp֩QwD]Wx^^Bc *qT:'8Em՛ʼ:  gVWxfn2Ew™_y_WM/dy> PS #?[F\r:~Z~:fF‰ҪpԀ*[S`Aefmo`8qWu™giw L gn/Z~7>7>?i ,15YW  K?eU-sMƖoF#RƮb"w 8MQFmi<|zS*Р37!hw@pE3j g.RSx?JP֛pX~B )U '[3;;H1o 6ʷpj g361JO>:q~&Xc+03ZtU跪HSeId`\=v?Fo3EÙh;Ԩ ⴫Sr (CS7p3daR)0MpA&]Ua58fv*|X2=OÙk}<Bdjµ루 Boti~[CwNɁ/Gƀ)e)X]܆C-ުAWu>?3S;}H\F3e nmU~|w{<^_uDbUX[ZjuYЈb"7pFC(C-=Q[p3n ] gn#sT ?qM)Y/^@Pa"I4QqEAqSj37!ϕTp`6Ot- 8=?xfA +*9  (#*%Ś:R[pgEz#RB? 5` +@?kUWvou*uX#]yjު>FA? wԂ|Oom2 "&mYT9A@mz%OWV?h0P\ƺ7+_sW+ŇW|_׉>t*S:=rd XV}+p梫ڮ!j6rfjjߚ 53;^\r¤9ÊPVJ{)qThJ!5nhƭmS~g)0MIϽ-/JLH$/mnF" wz¥~>aG wk֞~^,}'+nl[5ZzyeHŧDz emc揩p*\ Xk 35S ꭫7A4xL&I҄:Ws5]G1Zpa!0?^[[ "Z B L? KQ:%g;BF8EBp8=bX&,AMi b ɜKÙvU{vNtqWlj]sP~vl|.i8]5]G16(sy?7W_ܑRB)!pC[{,B!aة1W-WR֖;DN= @S rA8xXYQٵHPQ$)j8s4ڍM*:7XS`x!2Ύw4#8pUx6,Cb3sK?@]y> ,WSJTeXa6^ɊV* 7|4O!$vぬ˲J)mnPQZ g΋~җȍASj1C7_!r~fe몫Ͱm7jWR)NtTՑO᧟~n0d, '56PF.0 sXyVH(hJ(9IڤC3e $)(LjҦݨ9 377 |bW]Xڴ3l&SZ]~_Γ!Ju$>ҵlm^ɊRa>0V),B;&  mGxEصW"C)VW ۇj9G:r{yOn܎MeYi*,@DH3+rm1dGG#QdYTʛ5™eFQ 1+ymy Dd =yny '̛aVA ]\yѣ -,,U8,lܾ'_LJ2T uЇeJZPch]Z( {&-NPYIn%wԗ^ͫDV08V\DZ90kWs r}Wu3fz)^H\t 5Oȍ9sc#?骖@6>;͟ HK,I;*=p;$+ժ«{Ҫ0"p1Wa I =IZpT%5$0bxTR'FdpF:]qU  s)ӾRDOG<, hU'.طy|aN'% D BcUJQEuK~G m_ULtsZ-Fn! @/-/o8CEVp$akŠ?ckF`9+6s}UgoHk{;8*7!YJP谚 s(L~W,Zά fϔPe{BzT8qD_ǭJW{㛻}Zs?t@e^-,5R _~ZzXhNR "p C+#p,&r+j,ͦrL( &ޯϻ˚0ۑpf&HS?^WA·Hf*|swdbbۭYі; $Tւ̠lZAIsyJ&"pڣV͞W2ڡ8/)(#x  K50uU=&xe?W]v"JH(M0ge3 U +-G\{!jjQj)08PQ2Cff ]!4u3Y_Yp\K6AK_jN]|fpiLN|] ! !ae0](*K;zzǼ\4PKT#/ %EAU33b!ѓװ4L^dwݨ|0U-K71lYVa0p@?ksʫդ.o;k|D&أʄ[6TVl*9ŲÒsd 9AҤdV.Re>նpXIk N:'mQ {sk1\*+yes_JeՃ{Щ\mA0f.D:{)>,):)_]3P I&ViOr]XQn-O^dиU>erzY*Ü8ߞ#&ȄW M= 1?ΟPWT-셅#HB}3xV(jJ Vk7:1qv0j`#2abr 1ZZV0{XKdmA WՈ 2t'(OສNH~ TP[^-/2Lz);s{gxm4$88r"T:DȜ?|0X97ۊZ>AL^1:RBd43Wknjnh"YDeR-ƈTPB1ְT pMCPHTe@lOCY1c{à?1ϛyC* HFIb=.bÉ^AiWՠ ls&Ai CaMJř<+Y"f^ c2r[^+ ל@5 !<l8;&sU~MC*kE/& Fbye3`TP:-Mh.`a+hp6rr.\겲s i f9ߊӛ 0)<9`~ % \HӜ,)acqYH"UaLmm!X JdE2pyfNx8 ŅT!WZJ҅@~-p x7IԑdFKaiebVdsmHEklsi:=Ù 0)T5lwU9A:(+;ʶIԟc$TyLtimV@^$2j^%0fb3]"5l gnKa+ P8s~ maeGHev=o`v# A8sk$b}ӆp'niez]Pmd69DNUA~TIfԜH9Y)7eJ™;k"'U-uD+t7m)/P{<+`/.>$G[4W[}scJ1XFvhFHGMiȃ}?yˤgսRW zܹ PJiZH^dwN.,^G4t;,q:huYجyMeWg"+J*wt_Zzy - ee3$sDi<-'[іoJ07bd_^ww!ְNBHLGno P%8n ,mM+±ό>iD~Rf "NϑK8osY8xJַV"^{,+3m:ҟiC&l6KfyCVT %O^#[~t 5\V4v:Cp6 sߴ!._yu;An/!nvQUʎ$JI2$3_\K5lh9vCF 7MyM[ v0gWꋌǮ3,PSU6RQV8&+)ɀ;Ž; gn#Uu$cmxy{\jTu.N.;3FX`*HX 74%hNRĆ3RI d7q~6ą;.8 EcsxfL~&$d3$F#] 1#W-tξF;G?3n(=o{m!c'A8p,լ*j\vQБN_G_yƜ Z= apz^9X[TQF*le™M-5/|,:Jߴ! N(ZU/L(}XFm~O'o(x#]ffV ˱gIV`FAt.؏Ua o0$+[ZQ8s#}Z\[^ok³'KV0ckqٷZ}6ͯѠUƳgŇ'MV ^RT2 ü33&? T5!QLPc`{j™;M3kNԘ93X1jUaMvZxyA wQ8shCnPʊytf.uwZUxuO~vYk0K83A(F;?Wq8dqM%+B5NMr.屗PVmjЭ0 щ ™FYkȊԏ>KhbzH<$v5nez>wVv (*BDIUDdMD\{孵L*޷7.c?zzԐFwNt6 QpcQ8s:Xxᮣo}(+qx~g~ׇ Wop!DS$TG1"=CY18=OQ3xO=tsmC}y0yqh!&] {h2rU{EH =( M==[0Lxe"(4LP(N|U^(}Y;=aVQlopgOOe|NwdyRTx& %`h£2H:RBdGc]\W9D?9Ȉf'XU|%zvFk™Q{S:`U/AI6yM-1_Ź16쏌\Ձ`#]ǟ$b wY) k[ᄐ4(yH/d%NP)e7yɉTcƆtd5.-46%Ǹ(ȇF1"HG)56>WؠDF:20VVD> $K7nёQ82ґA'rm]% $HrWGHGJ)9 u;Hf_ň :#N:-+ժ^:%g?Lg*UF:r"脬EsixxKpE19= g|F:riH zqEY/}bU\GF1"CHGF*+T<^|8>LtdD)MȊp,a##QrmC]*lD:+3#EYArj*M9X~slF4wtIDATxyl[ZSFf|3|^իRDW/ʆnn%Zp [mZ] Em,lie!HC)U {;9"c>޻ؑ'N9"#"#Ow!91s 7`i˿w-^}{vyohq\zs㪂Wە91,q>S;Y^*vieꇞϗ9fsKon{ Za#sDbN'ڏM4~̉˿vM2_.|^)/W~p#Oq =0OZl)+Q(ICӆ9q\*|7՟{cJRUچh5J.Kvo|p#s;H@)u):[' @qME cf]^MFe_L0l.c!Ԛ-x$JyD) 4H[6  G'})1 1]5G9q\$Jڨࢎp`I&fYT$P$3.mO\^39G.C"cʐeSUA!vF}<2F̉ ZY<\M]zl0'TJ3!I@)g} ~ 4`N#B#j\@ٷgm/HIzPO@1s]WL5I -)cGaEjgM?39u>:#r0q.~?W~Ѷ]8G'XPr]ǰc K#hvG#>6xj>iYkHnT>X>nx/#,U6hLVԭjg?<2'[_AmۦXmu)ަ5u\TБ&UAW{X%\]Ua$\5LS t49ͼo)Z^命*Ӥ4?Op R[B̡zxXY]Ap !,I"ckwoo)AE*6F" YShk 2x^X.0TD)g 0BV- >YkH+#s!xՊZ. k%3f{eY#@^ ҭg?x&\0s^k#|EHedBYyx1[0&tM Մ er<,u9q__ʕփoƞ&ڃi#{>o9  ǶSNN\S쎥o,o.GnIۦD8D`oy5!H7k{z 8p{Sl"\Nˀz?GY,B(y,BV^"$nzb˿(_W@[)IkK- Ĵ@\zo,8fB6m2/H)P^CKEQ=OC1)H,L)u)z px8DBi*%"/&PïTd(u$!$2ulSkݿK+Kb%#c#%7+xҿM~ܘQY,a:{=C5ۺVpu7W#&38T^sg R#B1*0e9q8ᣚs/<5ɲk3E❌0[ 6#<2TW Im'\G_[6T%0g:"*H>Ror+J#vZdݜ8xZ qa?vm -@n2ު* \!踼mp[; @e p}w6WR2<#[6;RӁG4;NG"v߫1y{2 {jϑe9qd#yCEQ["#SEـg8(# OZs_ ^˛[Ւ>mj4Hn#"6<] yD0l.E\{f٦82TVc(٨J$P8~F¢W?EYc;m`,b\IDy4] Wn F8bđ*ۋ8cxdF".*dI ">Ih&`j<" B sH( 'w.~^mZUG‹O_׽5~b=^ LGD)Tg#w)Ή#30aG &|P0'L:QLGj`.N4׍p(ڬ\84N)lkT6蝒rɐG^I7xt0R_=' .p呛WxNEtL=@0I` (gKE^Q;3xrd\o|{;KP8#9kD"G]ct]IKch@H&PvE̉zYcm 9>kOc4ÜڴRCGˊKLJ.%~F"zl+'dF{WOZAgc y#G1AA)  J1&Bl(y:I7!mrS&DeE'Qfk95z1Ŵ-Y/pȧ!d?< ƹj@ @nLj$VPh #5pc,.%~H(imJylQ LLE_&?e[, 1]>h;x8 0-.$z{q) H@ Z`y$Na8J$xxeԊ}\H[ _ILַ۫kNVYB9\0UFMwX._*e:,GV{v^cI=GOzq &0"Z.GGLH@CJ(ebT2-&+ iJn]veX9?TLQI|g6{EѲ+zڮS}i9eHb=*ˌ Жiswwoخvtt_]w\I (d)oq4Qo3 ttn|6⣽cq evA0CQRFł]Ƣo8`jMO1&(K)> "`~Z[T~m92k>\qII^чaqWOP,V.tjZk 6 0l9>7sR  cq/dZ6tjMV!EBJ6?@L*% mu4|_5 2*#1X*aÕۏRcEXt^Bqȭ* =yR:LpŘXVmR mb[1r@[P,%rfKD+4l ˪zJTR͂zL" Э2) l-ɟ@x5aQ➮@1DJi0F'&H"!8}v0vYՕcc~Ͻ:QLG sPO~$% NvD.z<ԥDbYmL2# Ċn]kMǺlnOx$m49 tYiX#;8^͜lK9p[,EYxRxݣw(vyQtx$U% mBa\^zX>isoYQW쮥5k&>>1s#8ݣc\^0xc\ ,ZvMߏ[}X##V!] '~cR.T|c/[}vH8+,- 4m] z޿8.S)tr k)PTW*RB+k ?{;2tSxwQxO$`Խd!~ץwGEz fn@to_o~]s̥r1*oM -@^xFWn,]ǩ-$e\()2\l Dq*gƕ=ᅕ0FR"#"yg|[#,é(Ê Cl旕sk6Fm19:aFضߍ9*'+k眆_r\ES ;B[JJ]6t*v(pp>![s;Vd dJDؕ<\f O8Tp7$^՚G aUB{;'$+;uLvuŖ(#1}垽ur&=gVo@ȿd#yDFd3"á_ww H"oE5aZmjo$xFJu4%VGvLBTbHX3Y#'J@XaxmѼy@ sH`,Է9rOL]G f8+1[awfG&GNC6D*^B܆k9B*B@_/g8FPN䑞R :7+xӧ]~Qx$RaISCzlW'ˀiPd GD\ L3s /TJr 7/yk\(,{u?@AqKy+pxH{"B*w&c, < :'BHzPNUBŃM>\|`⌏J$N'}N0e'*s,=<\y*-T(McbNL[~ON*#WIq3dЋ>@G|eKIxεxP7 ~ϟ8&$*he1>#qB *~خ+usF* 枮4s(%xۮȀϓ'̶1Fkr_ BQ!+e" 7|U`MƓ/8<=2OT2m頱j~JZ,fmEΙ80>2ΗG<#UBC|<k( .ov(#uM/䲆궋c٦|rxv cP@ϾƌHgJ h; VR'R%s;![Q&l {{Gb}8v&9.BBwp]de#zj9cdʾ̥Z5ҭk 8g0<;<* .[rYB9=']MiÙHPFi\N(zdQPQF i Rz|m$u%c\<2Rھ"%GZ)T9zZ)AkHEVq 0bFa@RB?:%WCH(X j~Q4M;iV+3#x1O2:\akYq7T8"K)>.%RGū\#,zHvmåPE`0 qPju3M0N#2@PxpԺ,~3?Y#da4I>\v j k*z(r($) mw_f7j}eʘ0&$Jާ~W}gfKK6΢oi_\2FO@x'BzzfƟ*g:/sH˰ᦙw]b@\`KV'] (ΑGMdA@=ҭ>n"?jl.N?/u ua KoO vRn##`*77KՅB97F˷7FۘTJ @6+ 7Swc[]zx Słc_񛋙 JL8Nvgu e|8ͧQ^)᧼I퀐ДEˆB>GczcHK΀8/+ʊf֮Ћ HXv,I cQi# A"ޏQu@@9|uU~9p)mu6='d(OqEe T z6^͍%%h@RF(_^-l^ofAꖳDߓFҗ%^Zk&PqȻ*nt.7r La9VR0eIY,9?J(Mk tL^UG+'0P7QeONeJF>~ dhmikIZˮwa=ƸJfnSqmxeitR!2p]*9°"kV 8Z6_{vG& k5N%Tt;nj2<sZz25tv\2^˄1.A|<V37oLK@;՚Y\y~<%aJ]2 X6yR"Fj `"8!π$_2TB m0,bٚF;Ga)pH?j9KxMUj>elF7[=خ$g(^y><ϾeTBqGHOIز YViUmV7q)y$0,Hވd8!O(f%R%TI4VZ<т|l*qF\ZA7,n%q ǏS"IZSZǍˏG^u oa}mDMn^k_=ScMP= ӀĄęh_|x`ʍchFP)P> aPmk͓2Zo,&EW`ѕ_$fOZSWi\MU9B$|z;qC.:!\ss[Y^}y۷HCj1UFZZpA?ՀdH_2.4D* GH(ޖQJ` :^>Z.5K-'F\Q|k6:] Xv#V.$6°QL݃aT_߼s, Öw RsRYC0(,mS{t4c0qLAaG*0#<0QBXrzS<Ň ]Ꭿ̕=9.eԳMdPQJycbνUL(x& _J efnC?yȸ}"a9|#!G&z%( G Rą)&&I)ޞ,mDHu38UUZ;-Ppww,>DQ)5;ħ(KD/s<+HOu|srg'N+4N´%7gsdF &&EBjKMџei$d #|Rxx50 o; #1!2!22G5Hĥ䑀^AUzMM.ԗKCϬxd'pa,>JlWw-vQ$v (LL9 =_uAI(1Z-$( bB!Rסc%IEH@Nt~F[=46u۟gjBHaxyd}ɸ$,H;*sMF㮥;0 @Li]Flfk yxʎXw2TbM[1Q16iHcbH^ArN*2.4;LWBS#KG{Zȗ#Vm[$DžV>wXg]H9 Gn B]ֈ,<`n[E9e4Pe-?>G!.hGbe5Z6:/'g{UyWw\nKwm;!m"[&˧0%!k,)tjk\X:"2<>)w0l9|k3B))$V\Jrj1ŵ&? c +!UGlyL%B 9 Bk48(p&S&Oc=u:VH}B"RC'r)g\axj8IZwpG6/]Mv$D46pU/ V_'VdDUB"t=S(<94j~ Kvu|g'==hKuХЉb aHnXt/RR#[oەf Y`sB~q-$EH6OK.lH\)CBNX237zB*.)b6s _RhFsE$(P8PˁWn\g$z/( ٝC0RHA4%JcqocraJM:QXon.&"E4za8"Lz/7".=]wF/O&Evԧ]=~ 9S߷]1@_!WAR Ehv6j답4nzspnQG r\jmcf aّ#|^&'L:bk Re|[]׋1V!yG>,u-v哶w<>ZzȬXT OEYu1)z'9dɀ:XB{CҵH>Mg.ɻ;tnv d6,,?ا}bUJcw's[z`s['˥ o(9i"UQYUdJB~n[a5nk4\.2I 7@hyURK8 ۛW &o:z+~E0Rc6;ĥ5hu{:d$\7x|Dg\[@B-\++u;G OS#fH`FialJ9;J";>Ut\™,05RDx#lќU/a,,%Yr^lH; @PʒJPFs :#uw'jVzp3~rrNRR,^RVF_9|5,mpYʔrI,LPGSRX/y<VNV U_bvK01rd5Í 7&(=(R"[6mx SWJIHY 6 !Jyf!dx+Wk t+O/px|C.I}'>u׌u, +d:E.D y&<п "Ϩ*#&vIgT `)'`ѯn\#)8u $)/e'PI%0.9.ly]FH|kPs"]TϢg+~|rtXUVep wf\8TT C@"Rӓ>OPdYt3#&Y&"2e矹~]IYVqlM!y)= JJD88nł/Fz6 J1r!9%?Cs}#hL"HSF _{A(wMR~?:fGo$ r/>s \IM[yŪ\kMVd}[#gFzmqa:aΥ ]+O;ܨS4Gd59c.<yk[ɚՁIh?1aLI>{r]? XpD9 "Ojy*nǏ?g8֗*kbJ@(zd,e77?k) tTk qH*\㑽* sAgX%4R.i0X2 qIPEö+yߒ|?&Nzj9cz'Y>'Z6yǰ+`f+@^Hǘ}*5#ߒ uJ(^?v斠0lA;#<*J9>HXȳr, q)q "L77;lؔC@X5Y17!o,Fo…zTVLmW[ރqS(#"WHVn,?0]IP-',)WEVd9`M)>-/B`A6SeRFl<%uMNdվCfWO(P1$pAmcڎpy^8~U.SN*fDNzP/?<\k|Kz v,etfX0mn:dP 8ȴ qC7*eT5)N%4z3N=2)2qxSx|6aU.Z 6új%BȒ|!zVۇb AK1 MA /}*rdA >{^_<^[HQL ilEBpp)!}YdRnwϧ8 mm^ @JrP,|a18ceOjvӃ=0E)`B<"$K(@D_aKaV'cΑGtGo@!z h}HUX*++v9A6خi6rkwzf"5)30Ca;DSRȍ5`nXz.8]U,p{e5F}o;\x DG Rx /Wj!5mI@ڮ3Evf K\0lTpQG@IhIV rG^>[Q$IXIJv|ߗ+4 $_Ml=>UH5`<"r'j!R"NaX9B* <GH.,/bâcp%Cś#+KqpJP^ȫ yS}r+kOpx/_׏qHP)ٸ }uɒbNv,s3#cBHA8!Oj4g%HPQAeIEJ 0ܝP.`1 Z|{t\vl ͓ҵGJf O5Lkˠ\F.1gGе%nnY$rs*j;Aգ]~e|sR|{-g*gl W(`7{m"}/#.گj 2F.ԇ='Y0GLk*C)4˷+BBkXA[MhdiLppNC e`qć<`~B_0T'Ÿ0dqL]dm,\R +d-߷G}Ꭵ]a8G\]s,wkT-b-QNG[#d9Vdr B0{qpk6}Kպ Rh$1 EIE+BØU#Wo8XfQUS$I2`.;O65 @![g_6cxd!("&rxɷ@D2t@*B *GNER֣mfSΨz3JaLNe9"l2l+ #C2Bi1[7ޖ`6T)t(I.!x<6! a0l d9.d>㑽*6v!Q*Iپr5mRB-T+2S2Y'/'q͡i푔|]7<$W,.Bl8x4;2 .Pr*(l-$ yBo5 Ēj7/H d犁oq5]~LjamBO8 *S.=jZ^)<%pl팰^s,!M]G' H$JfC|U,Nk0&dΌdaIVhT,cX"'q!UO8&YUM%H㕅jJyJrB0SddX` rMe:y$9* PkI[0YfI?sH i-_!,ſzɣg^|yZuhH}s7v;HNKЛMEJ@)=-tڞˑ4xY|⭭޿gqQH,ʳNU~^?i˴KO{qgi䜾˷+0*)% 6) V[9JyDK.sI CM۫]]8ynƓ3eAa DJc?2'_+?`'GV,Lz7Pw æxvK̀co[.$,!bQ10F.DYAG-8h6UдqB*b7F ۮtu4SNHS =_#G?S?Сp2F)B  Կp5vUBrj a{o]@ dFN81xPlW;ሴMmZ"KDJC?qmXc".pzC;icx|8 1SGDftuWd0,Kܲ׵^*X#Pp]q*ڒp HT2/IdrңFyU^mRdmsk5kgjN:M1bR-6o9'׈Ŵi3+x+ {)d# [Zl "ϣӡv:k*Lp9 q>1Wp|0.8```]+C'SV#, %Y}GvaQ?YϨ"@ީ^Pݺ8@%瀛l:8}[;:\d+HP SdN0P|a9td5FFlW8Ίi<@RC4 ɗ0(* VQ!$~]`y7E'- ĄxmInUdxkF$*80HdzWOݜz~Ex@E 068-PhB-_4FԚL"$4:WdMR9LqLjL"ǎK̎#Cis PwY<$j.~c../PX ul䵬t[#~ <6qG*0QR񮸜|Lj!R"s ($1틷YYf3*n`0D,O߸R}Pp<"Q9zgO9gQ 8w1GQf%])C̡MٷTUAUד!"(olFRv?ا0#|!u'r@"!ME+ \ᗉQYTB.t)4ӈCٜ(46}I}!(*[ ߸*@`.ouWs1 uֳ:?<x.]^б r0sR2x3 3+12@?9iHi+.Y QŃ@½sp N PUZ]!ByxxcF8^Bh5!8иBĶ}W$ԜT"3?^RhO˧}mjĪJBNziLjqTn- xw:R cDI#iB..d*Yt,8!aUBYE9"'䤗Iax9Mi2t<-E#hLH-q ("I;xyzjQH AGkކF5fGhT#W'&+ SAzmlW 8cʍ>  6P_= lM4j(y`D}vtry IH2F* {*Yʮq4j^B,+B>s}d(\L>k8vEkM^mHn$Y0W #|KHi9-+JcU/~Ⱦ"Y' fxyjOGS8!OI)2rii#*K/iVE,+CYpYC+LmC\#ؾ=!Q&wXL^fMGr &( KD3M%< Yc UB{ cP2ԡv}nB!w ;2v{YE"om.D yJlGm X% B#)U%/7l_ݸ cӱBt]#YJ?B6tҩc!7hĂ1:(F%;[*' ñ*1P|9:FW$FC;I驌0ĂQ#VXgB9㠩ʒ8 >q OQ#Ϊ19)HpȦ#g!',Έsi#BGL yB Ce[2[#)o>1SJh$ÊO1!ΡMGo^O@KL>89CM_uoo&YR łµFc)Q.˟Rg\Yx&fT$K l- USʤTHvs矙OxDpޓ5#4_+pm*tT̡>Y/I"$#UB{;TY@e&p!P&}[o: ?qdC(EJN<}Qa/sLm|пt9Gy)㞋Hh? &ڰJ_@Q>xeI(ޱsቢO.C>g)`ۮ d}XZyQ't0ELpm;R QK9+0z$zg4ȶO'F&>N 3'0W4OY;vEX7gD<.LƘ +]o7 lQM)[F˛]`ZR UJh} (2XOj6mngiw684 Yc0< ?>#<2c2QS+)蕭w߃KރeHy ׷MUHFYFnTO/リi>w$x޹ZӬ JqnsY 88_91qđ>/p !,IrIR**H"#i"IJmpEw|<Yiy&+ {> Y#5 хow<">F1 5Ζ4eF#}dk{# yT2%/IJ)OVNP e,@(G1ʹ"!0i0T^p]RDO#y2ʩȥD2>S_ *a׵Jhscl˱n)@˨KU%IJ]:Rϑ}]-)hm 8.$Hؾ PlZ:"R`R}ᑱ #',xF:]%#xcJ6=9g }akKXSq!\"I}.^t vK' ãzB Sj(-0k4NW#oV0@Gi^uA+#pZ"}F'%Mzh*+ +Χst<2^?@1Kt0.:nгH+%dZ\Hy/|N, ;x6bzn CJƝWw4/|:kl@r"qȒF+vFC읦# s[;T4-o?m޿{9Gq: i|s*;2~W"_.c0|A1'sqn׀Z¦ӎ1.?q4;&hP+ _d̉oѡ>a-6i v C@FDN+[1WA=:M˷- !GX%T`0|1'Y[ufcUo)mф kaP<&ISKs`qjD-% KxG҆\s˅9qIDATxydY~o-̈ȬʬRP!U -5= 48g8}03:L L @0RRj-"#36{annnfnnnD1773w.?/}|TB;M tI1Ԫ˟ۍcv|FNKƹxqI1/>;?w~v 0cGKƹĸpI1/8_!QFq\zֵW_s.)E?k=16 Œ>?H_2%%ż+zlGÐށdK %żU/l@SqeBh' YˆӮ(rOȤXL[XdK%ż~j9㉎,M .AxZ>J5'BoݘeYvEO`h( gXW A s 9pJ6ӅKb^t`46n|*mRjJFrjKObYDq@2,L.(|PL.%ż ޽Zxɣ Jǩ.9 Kk3NW[rI q>>H")|vbp8/.)GZw׷(}h*R+^RoESj&-$CM8%$ 9xOڲx&/Gy]2 KydI9蕻ãqDl7D0N39'Ģ!K5ViqG\Rsw[l.tqfrd{c \!OP~§PeMq \R[[݊%(s~udB?Np]fMkPs8?~AbTbL+Sx6[ӲZGA)q;q(H$ /s~Rn;GSj B^@4q@rvԳIt *4 Kƹ jo^*)X"$"NpsrP@ӕr==^kq={|8B8H T7#>8Å%.)yBɣ4iKD+]Wx>E"tx/|,DI\q*qtk Qe @cT͢'Qჱɴe3?$U'R%6.),tұ zkH]9c eZC) ?$HB dy  u԰x>%XP&rSo~b_wBۗq2c] ʸaOy)f,3F䒄2X*!|/9 %<;omGhW' !yuw8^ڹ~?{蓃K83ۗc£u1Qv#CELg]μԷgH BR׏>ES=/.)B鿴Yܛ@N`6\6oZe3X2>`<+|y&>8scfzR̻}kc?7D&|ڵ[\X?5y>s A@aq c(JJ6 -[)ת-qLt-Na|^i2Jq#dIYBs*6\Io "P$ݵѳ *|N@d%t3īMڒ*-E]I1d'q.)baHqW*#~ȧ38R1?s  5SiIS:ËӀs]4ޭMuּq@Fu'tױ,B@A6xF_vrZKD1ctO\REA'(;:"14n1 8 tq,|p;"<'{2N2ܞq!i`Q$|릃yҢ!a_~O%'^Tƹ w_9 - АyFgQ\(| zSL qgdcl1z}~XYSd^0xk2H"db0M7-6@/^ƹm_R1\aFە8/WtD1Oq^?R3uBjYDc,brtIZC|^ 8s>8ي~蜊:ŝԚ990I1pS]Uְx:t%'Iid"1e(&HMY:̀ڕ]d4qHsI1S3 [$ 03%bkRtI͔-WvYHB~[lS)vǨ"JYRu\Ɇ=8s8cO#o*H `2Xi oi/ciܮy#S{/א$xPF=M槮Um4=~i(cajP)nF./yd29܉K9S G }h0u$:'3rTuz`^D4ީ+<4J3;'gNt>{116\Rݓȩ hQ)!wg'4[(ddyS 0AYT%Fcx8s-e3cK9]\4qSQGRL8>B~Q 䓼XG5+~,q7T b*H6J~8]a7l8Kic\ )XMgz2%Ŝ"}1`*Ӆ6&]S3jK,7p׻&Zדm1U=ޞM ;>8r`lU?O?u 4bN }5uB,L8mIdRӨ[ɦ#1vM1k!W1{=7_OE^R̩=/kאsPQeN| @=.APi-Fνqjj9__x sMۀSº4ǺO=9.Rwk~3L?7g.)f hbS.\t}nۧnq-64Z }Wiq߷}PZ8|p {}zm t:ߦDyCxdm2cP:%ϣ|ήX ++̲X1C++ vM3h23->;_~ S[A8_W{2SMJ!%^sI$(|^$t-HA ׾,TFkX.|R1< {sZjrU)Xop{TUQUAe4EuB )d\> }+wvq%2ZJ C=<Ջ5zJΠ@gs!qBPesZX~e(uAW~0oWeځm~jd,fyVvRhǒB. y\,2nokuJ`AZ~ @!˯G(ݻncn>~ gcNW'xR*rd( u%H`a>f,LHR.ԅKi(Z)bвR a9Si؏9ٴ*b25PI !\،(R)\e&ٔ**.gRX׹𹜝5J.H)p`"1Q31s`b]s{81xfwxŌ hټesXۅiPqL#Y奩Tfo\ K /@-qyA (HI&x~X_?%uv}>FWƐXwg擐OWvKZL B!1BbѯLdb< k z IڅO>E)r`JW(6Ҩ0޸^Hi HB*f[ ]E bh"ni{U( ,Љ" ~(ޅc\-;;'?vOn;XQ <J3~@ ˅xɼ/Mtׄtk8as5NKm#IZW!#O :m_Ʋr7yuJd"B.)NqJY+-兔0lJ;iH!(eH3*aP+Ԕyݻ Ut DDP9n  0]C=@%zOٽ&厾Oqp};>/cړ1 >}C v<^rS|D3<2]04]$^R̰8/Oﶈ[RS5)s³~Kis?oզQh?qn2b?==K nmHA3958Io˨$aBX؍FL(T|3b8* NDz ٣ cv)ѭd:q7X\Y}'r.B 30C߫#1(*GXBb3qyz!:Ww( ICE*O`Z˝ZUN 1=) ɘD9SCgT\Rx%5;%%I‚@[ͪk ",Tr<1NKCНBA)En9۬PhZ@y4Ls$Νqr 6!ctG_!sI1bxzwS)z ~qZn\JL' '2eއ2I(ahve Lb.C2Mh8cƉl_:u FwP e;g!sI1=pqSBSm"!Cփq6M&%U+WPi5keN 8eh.RQ];^Ge2:=<.d>z?zpI1zzFLv9di߾_UUYAUKZвʤRQomZ-d)l3], 4 Kxe6J|̾F͜Ls$di 0ڍd%}g/ٙ?]v &cF՛)Y(7bիړNtf u%Ga!3TVf &wk E~k~9{H3=xL DHB(0VDžVl0~mlߎ) _yP!` ` ,V^3c :CNV>d}@6!d4%rHI 7C?vݐN)-hm`1SuilLT<}8CIHصgBc]LF6M)F-2qT2E3 y/hW~/,.+W|whӅ.,cPw/-彬E8/ߤt :&܉Fsᔖ 6]-cƤzv: US?j*n?siI࣏vɲQ*2MnTt߻7fDX\Ėt"|b6'_>Lj:*c!(gfv9?KMx|cI#YXi?_l*t:*?篾 *Jr)?}_{w7{kmE'^]ew\ʻ5kbCS#D&ֺ[.4xVY7z~  Jl,fQN6Kƞ|m]97_!sQ!EV%"^oO|)w?7@Z}R>3MIU'>QIX7Mբ֋9V T-߾֌ ;9/= 0pf5Sr<+m?^<AuOe ed %te~ȃuVitm]5$zňUDL&&+MM7'ؓO|׿.wغti21_ Y7m#| KW_ѣwղMjۗMZܽi 4m<%DȈ'X]7i: M5i ~U2 k޴(p1d(8i+փ ,dj|[H [Ӧ+J\-wWi1Czz' QLG)]Pl^H0,+V*¤$T-˲M9'q:-'pJɮﵺērEVPGUWv'at6w*"?Kb VɝZMa:x~"ɔ,ApP2vntPWYFӱ\*[㤗F>nSPs+}K韀ON3wdvߺ &QL i*mgnN@HKUaV=%If3IM3=ryE8xvPO_:NdCby*Pj\Y.DHgzFA1G+2[13suNbN]mj2Lg(k:lenAᆨh=r$IfdlY  #=~]Q G(6R;qXE>XPլf9a*H;wlyIig"Y xjfA^-Ȗ+\HdX!A\;Y̓zȶǂBOtk(H% N1c4Xc)8(nUJݜTsv M#"1`\n_n_kfUݲcolX 0AAmoYNJ6+ ]%@`"m=QT8ź|B&)i)i4?6Ļg!*`!YؾVm*Q_d9ۗ>C SKq*Y%0r}, f{Iaʤ'ԾDmzN_y4lőLFNݧ/PzOgEQ4(1Q[ vOY-k=IQ&b*J'tf̌փM$B{B)9ӕ1~~kI 4݇q\ Olc:k"*:>9FӐ필?f)0=_fYC9c $Q&V[c1ۊ1:ŕN%8II5]E! dor;qX?=Ϻk, *y_G$9 ol:g n#i('Uë)o~kh~OjA:ʁgJɹ0΍Ytc=>LOhIH遛AT8 ¾K&0j(d^4Ȟg"߼=?u/,IEo\ZM" HA#$"tΌJRޫWwVߡpQR{Xa.t8Ǜq I>wYDKBſV[zʊxbCwɈb (=p0PȼP|پc^EEDz } ʲRBgGSHWf̮m2[`l>G%R+GWla8 y@ 5 c=ΓI1t_RžJBšӻo߉hqjnk+\jK@`8>ƙ›εZL(G]«C}3DޑːnAFuQzAWxab3f]|!"%0rK-Gh} b^z]=OhM7I8NOov.̌e'҃>e+{zpgHɣ홆Aq`tpa8ig"Z CMMe!ny76X!sQ9zGW -NMhлڭۏѸڟK9tX&|F.spF6:ZjH4s x0<||0}Y|뺠ef9tz:W$ ,볘Cj Du5O@HwBH$\ҩƨ r0xQ AӅA7-ݯA#Pi?Qs$61T$ =}ߨ}OYETzpI'j%X 39i&'8f.nٞ|ZDBcJt]]n4g&Ae%`=G; zW^ jW)P( T2fyqzھxφ o2_/V:|3(ﱈ~@14H m 6Sx*fχjڞz |~> 9#{4>(*d:3%T_A!AfH%Z3$\06qj+dg":}Fzԩ8 1N zqʚl`0^B&Bm;<+d8XX6jFʹdw($GwPeq 3qĩI1kvX FTH G4ݍCWU1sYQa*ɡ@(F<>JuJ`[m? WYBW&+I˯G L|'T;8sm1gKODxɥ򅚍{µ*s|﫟O?v>ٿY[{b c1!^Ec|KWM.!=!7jԹ ȉFݴna/mVWU2k^0 bCqlao#sݚ8H\{ZR*y뗌s4z  FoSX,ԑMk2宛m:yyKJbBA(tXfw*<oLlI$=ld&Ϥ:<?zNqaeABL'LV[н13g/v0>w D'u7R f9ݲ$*I/VQzg4!l KpL-%Enœz:85-td?#pl2M Mj1˕i8XwvmfL<XفmVn'Щ8Fjf=eA1^mGD0Na#PN67iCW\}.fݲATC ;ɕP96i^+5SaWUob2OŒ\:,o]6L`zQyؽ^շ J1پ/x* YD"gUCͮ悀yزIi}jR0dYrR(zfl =ED<ڞ<۱Ni O;%fI'-Vw)a6> K,C  uH~`=d;Ǎx\֚ﶝ.Ōk oa}8B&nN1LXZn:NއN:' gĈ Ec( R'ӕ T-i Xn&kUEXT+˭=^nZydLg(:ڡc2L-+v^9=O>#f-bRͻ:ArXy a(* 5Φ{4 6l]_s(#?l_2YsČlQpXG2zRM AZNo2iu/#4On/әpD Q׊0CE%Z2_Ӄ:O?t;\x~JS9zwJbӻH8mƙ\j ˋ'xkk ĕ L& D$W`4C~lvYgI#^5=!A4)IHHugHCܡw.aڶ/RѬټZ.`\ Gt^kR3 |u!/vY$tBPh2˧Z4ܦ @m3w˹<\  ,fa?扬lݽe{i4C*2z:◞m3\@O#_'-jLP<"0])@$ Rm`xCa*ypPb ADZ>9 K]muc\c wח`hg8ME9O( +޻fa_>[>9^B&X`\(Kf>^sR5gjz,unzzbDqU$Ifleq!#?[F3 W?\SF,^:lXX5+V>Mq!L( ݗqN9mK6K~h1O`(%_Yt2]4 L)} m*鴜J vvx !c+08(E]O \J6[qb ~fjp7sg(ri?^<kC"Kb ;W >;qvNLlN  #|4 HBpouQ}vvK`{ʃsic-]Nqt$o~Dw{I&cу9vk{,3s6€B(01L^~ZPK5rwZk;MPu]4az |Q08Xb uʊstwu!ʜUT_Zn%UXї sjCڌSiL*>XfXNJN B|8 F{'IB,(wO}G+o}|ZiBq5s9DZ(&\O=QVt2xtF ;ytk;f+NI=Ul޲)0sN|*Ut[уU[#s}ma^#[o^?F2(EyG!sSV_BË(*'L4v1Zkm'0&'om}ߍ H,apl1 Fؓ MC/0yQ:=%تwj{8 !KhiR(O!m=#qMOEKʺ-Kͦݣ9Ey˹Wd}47To;$,('bݍJ:NmF2DЃGNTfhPi*U+"Dа DzeW\[l8 U6=[\e@&ex4]5ݴNq&R?#X.|-< 6$w>)MZV+iڿ>2 _ɃӅ郆KKw3y@D`&lB}&^a*[͆J(ǒD^0,ݏjDIND h:8`i6i͜05=}4\R^g~(.= xoZcg(p;V஘ddsm9,'52G2g}J\qMJ%iii?<Q҅g FQNB[(o_t><ДAS~H-\lzB@j ;iӆ+*$lj9Gj<9h :C&ٔ*Bwٞhg"q1NBCKZ =ܠڭRMfx%ÕB%;.Ӆ\"<\knųo / c,ˠi12Rjܹ BQW_736ʵW7 H86-)7|k]t]R0-w]Qd u.zL^{LOvgpdŕ݉脎U^0q,'=c[9}q4-3aKnfWRξY7_?gOU&Ub^V3_ʏ~+?k_|\kp{\=@T=z0Ft{ ?,ToSi~ܨ5CIx4-7tU5Mr<3l*=.ONOa>vDM'($yui~(RH,M~b߻gmL0 T Sm}mUQz)͌X~A18^MM<ikoH~LQ(<ی!ԊtFJ#*z )$9 ϙqF>2+w\V)8KP*F.7S0MnΉLg( teN )tL-V jN *6~'^e ^i~C4]Md;ΜZz=1KKzǨʯ5d̡s/][yҒDA%7ADQfL8y ΊwxtI33`rFݲZ 3*{4r 7`d^gRNW4`pCDo(*!")%q֋8Gdtb4H(T<4 qHPϋ=,خPQ ӂJ (E e8fqyzF{|\ #Ā>f Ҧ0Cq_L3@VpG; rcT}1I'p4U'? 6=pqYI8f DT@l/t$ q]L:^3 {O9Kzz`|# m]8!G8NHX)os臘2 0N9 Oo8!>6 TЦɌsmh6o*-t IP FCSKq*SDNH abY34QSP*d;1vć)d(3nLjp,AA6an[)'c$'(z>xt9j<"e Je$`:),%;M| !e1p<̊~8ڟ1@+ c M12>ӑ0K vhUJHSx)jߑf߳肋an &j,!r"gn x1Psq`溾R޲3Ĥa0_ 1z@Ę}1p 9ҿ^}ӊ/1lYAl S;fQc8w@cX [ Rp( zAv sYfh $(gzȴ1xZӓUZI39 Jo4l]l.ÆOɪ$DUZM& 6ٌH F@ڣ DR0=s5!j¾*Ffjuyϯ=~0q흒K$)ىqs{#㜨S=Nxx{p,AЫq]S00,.Ғϣ`/{@cf!FZ5 ÝYѝ>׆i 3d(:#ܬ,Ս׿Ӕe) #>eSb8ma, <.P.)ܼ~>(Ӻӛ $*0X:>8e{dS c]g!d:cCp ejr˃ 8"g_=~B^mv<.I&3N282:ic DDZ|DBfU%1]]xq)הcd̳&8 'n.J76dR[n^&IR4=tTtdx\MLF<[i3W`ܺu%?!kfgS1ml{v7@~Lrs_VnqKį|GH>w^\x)r"D6gQM?QnQ (m62QG1F K"\ usA&n zr4$b ʜ<5مg+.)=!1qJv0tfT* Ju2('w*bx۹⁦ ŽܬtE>: P!#oaǯ[+ftdin>w;ŢS._2sVT-u @r!M懖ݍf ,O0bIYXt7>jM8b,!D3;\io6,\_h嗶&ь$_`X)۫+(9/F f3 ' >Ҥ5ޥ4 2ql5Ue(PdKl$I[}ϯ=ݮVis`VK n$Sم}gmmT+8Q_%COa>x/ $³6(W7l1EIUIĤQ>~xvόMrVg q1E7gXڬNDG~(PJaxyJeYRU=9QB70s1Zie^XDGK0Ҵ2+0-Cmw2mȄ.]Ľ.ups'}97mh8RD0&Re溗'[*{PxW yg 0yPWP )ܻg F,}J) x`Hx&1ֳ1Ea @{#T ]b  QS3ݟ,°bH` gsJV9h7F`rSзݰ[VPkX]%JfXnTDž: T,{ǛWv.ۗt!,d\Zս2Yoǫ462hBT{5:AhK[Jr4Ǧ&)IMU Za$2Nd;΀NΏiϢHO/-Nݭ,K*eqGgk9Do\\\uàfZ>4wv|]W&&Ԙ1xja8敧c }dW@䧮硽FZ߰ )S4V }֬T}[%(?oY ܃B5R\@ocahg?}/Xt!WBʨ"osIlUdD!N"Kv}j0:P/λXkE݅ 't>[sgl֖ۛWvZO EBiUKjTILJrriRLJ.2qi(M?] 1|ʵ۫R{O$dx zyFnwGk|>n- C 2DSvZ"K"r,H Apq]4ts?yxO\RXVnBJY ժ!h _h L@+B\_UJi$3~P<ا;`NQBNB(0V! *䍭/ާQaM~]E2i4GCГqAZҽiVm:3nqCW$QĈA\ 8!0qOӻ NJ%X+MYJ)c\..aaR&NW̄bn|l?eB(lH0DI BP\0v6"w@p_ c(k9pVW`I7p|mǭ'l_EӖSAb<|jm_*~Y ?8b&3NZiyO!ϳ`BE!MS^` o)=nmOoOa{&*d2͑8vj6p$Qse2) DA8㜁22XN Oa_+t8 }YHƫg!Xn3N(K;܌9nZmqCa jy8StF$PޓC`> Iܡ4?Ls$2vs%)ROO!G h>˞FOC9f3+0?w 86㘶ܦsiy㦡)8dR\ 9`t¢BfX{> x ڈ,lG"=E}g]j"&r.7KeڬO:g~;0",ROaqֶ}Qk4<0Χ0 sNrR2E$q.{0BJV CP}r𖜩&q<-,e~uzz8Ri:m'Mˬ*18.:E!C0<Žji 8o`9Y7C5$ ;r N o}uttć0phXkʄ[o~|ǏN'܇Zlq8 jX[qi`' . *2 Moy\ƈRL7UXs/1q'X59x*( u,D!SpJ2!S?S=s[Y 7qՇ\>E=xxt1V\n.cGyn *L*RgAIɜz  48߼Ha.GެLi8{~8n BH 3_88"A8H8xoZB <_'9/^w7OVn>D,\9,h$\Z׈ ܭn:md a,IŹyI>ks"x'غwSXL=}8J b.HB3)Gi3F^^e'ET0I)vOwe}\JDzpl/x:{fHtF -=g,cT"X|nXu CuI{3( 0!ַäUy(6XRhn?\BfbNm颢d%c潻c8` ~ƅ~^ed@D @ksm?e$o^:,"[O뙭(2CJlO$a"՚V^:flN€hJiEa@ uͿDJՍ$f1k`g(dž uV녅* L&LOI 7rɩ٘APDNSo?sm{m=;5 ;Wqņ|޹oͦMPd"pQkc9;( ֤0#1a}f}A%aNIեO#gg&?dq5  dNR?jWOUwC\g{zii"db篶(+PK='3ٜ 1>i\7?䦉.'/-&1fY77v٤),,,r/7 2Y&}7ŜsqL;(鴡Ɣņ̀o7ILPUE8fǏ;Ki3+Z_bX2R/ <QC+pzpEh#k|JmB[xxR7?~@*pN$"F)!tqg;$ܒ+q }h ~8+=KUir$E,~J& P)sEA f 0$ZyWv_\m;JݴݽZUVT] ]S$7ݍ %c\W+O$9HTT0ë=PdE)vWI"|&׿Vհ,.RESD<gj (DY4#SqN8atMMZNh !Mk5e $Q*@д.Vb:x6ua\ȵ *`FbF~Wiy3zZ|&g.]n9L)yǵ(:-͡D\W گ|52tvczK&6ټRAM=\UޠlƦ?ܿ{}Xve <9Ʊ\}Znr~Չim{^_u'^2.J"0'")"eĶq6>p-,;;z%c,ӆ$n,"/[va"Lj>&tƍ?#Z)oGxv~o_+?cW]馘Pԩڵ2%ʷ6tܖ|2Ma C2͠RtFt['ӌT덏ݒ[՞bSX2\'2FA0wW._]s3x~mZ+{-ZkLtbh<&Mc4VUh4V{ak!)+g/:nڄ1Z#I!HPqu~>k/I_uJXJIou*6~^GxM/feI ciF2>U)OqzI1= q{-jS}Ǝ-%gs;4 -9'I"87Tӑ)PL=:^qЬ繤-_â@Tl1NOiCP*|y#>('\ ;>]f$<'ۼC0xЍ۟wTA!!TT9\:APHzu%V)"F\Ѷ X.|-czb9wb6 +k@a)˅~!I#DWQBGIH&$-rkcIɢ dMED>Љ2b^P,6BSadݤѶ6dAtnOޞ9Gpb\oe~,w^nu3Ud%+GW_#m=xyFy;>s"Br2|J Lʈ74IHCsv`BWEALF H`ibιTb|YsY3pTV@ *K4RЄf~2q;mNŲGv*>c @g5Ni['kuJZ☮Lt=BeĘz";_7h>1O=q<9ï圇BAb[6WOe<(7daz I%*rEWW6 ÚQ L7 m^e1{8vu\79u*׹glQ5iְ],`BfM.Z6 )eR1"(<>Fy}<=~*پp9}Gצ Ir"\H%0tiXiY(PMU"bE;qڅL2IŜF?#O+wFKkڝ c>rby YA!Ju|\U)rQ}9GSSQ&2gi-M Zmz{H Ia>5BӉ2p }G(8 BPMakV(aZOtE/@H(iz{_[(ècyz+2q6{xt6*p,KfQt5 6jmgi´]7}#NR)8eM-eP SiN8m=8iFaklNJy:!h8V,Ar6z|r[ZV^T8㪺B*g\Bu?mq"=xІ< o;x(=#$ctҳ<*hzNoIKYc,! {zzhۅcݴOn22N9p Z;ã/6 Klvޙ`emy%1z+5 ҃LEll}$"%!tG2f+CbݰXMiԪ q a,Tw9whHcڃ\ϣy݄{{z)u*vaYE!^l; Mѵ]-?\a*[\22qJγscM9^Cbvs3ơ+]d2Dƹ0!AH'Ie41gޔ8=ONdc32(`:ӯ9$6LIM@[[a:w* @kNV:il;%0R #c|# [%X[-7HUUgSy (-*a,@<$ &vݡ򴔑^eQ,72a/QOiIBgkT<Fι ESAWB)h y.KG*gهqqbխ׼ݲ0=Mi9R8V!%x^߂E%bܷ2a/#rb2)LsNmRRi&c"QeGTQ+lMu4c\7Y ǔN{0wtfOyi)o8MoܭX鴑Pd a77`ӌ T~j$\xzփwLxzu*]٭8 n,%ʜ⹰SvKMM%8UTsU׻ t{+0"~9R;KqwxM]Jp:mqjn8UƆD -plr(҃)v'O=F{I8'a>7ȶ)u*HLƽ! [;s$z,&;ŪNi$0?bA Ys`:dK\.dvH},"Oo8c 8mV/w8ê_7:ǫ܇WU'b.'Y/۶IE't)\ۃk38>hI#.T,n,MFTC2狘K"_/V{|_b0F(|Y%82>}mh\媌^W¦[Y/-ro?n8I$l6ipi-M2qUD}>0 G~8΀!!@ ZΌ~HUzzhuS9B&rN&&z7سMax,"9Xœgt|[u )  U]n~&-L'*I)G?l[eӂ$<ȋ1kt;H*;.<D/{Vm~_ut"1rmyfXY'0}}~*rx*jExAtT4UTA͑Hq5ºKKx0|ɽ{\lWV}#6/y_dߺꋮYЎ@  \UY!R4̔89n$\WWMC4;惶k⣵zzW47fU,;I&Cv*<'Zn17Lb;$@@4CT1=Q6ēF:iNC:CGmeY#i_]LĶ͛ $ @zG?ZfVRʄ+Zיgr:OUʣ(#D %suk2{e∻G1O_jJAdibEI~NI(sg*^BLN6'=rLfReq2e(AL Zu/]yMI(06yk)_n_kO7-;]dYv-}ҵk7=hG^ t?WWV/mwǂm_;qAQ %TTSH2)氧͗f">)$P-{++7,$BTDU` zja?ŖuAM:]2H1xla:{@jt֪ QBs9m~>OuЎ@VI0kO_ya8ODUaon\rꍗ^^ ;W,,ZV ꭭mWuݧleIl=㸁~8oZij&`t! <a-'x^=]m&eYq*`,hb8s9'shc%vg/X… ؟9]7@(^ݛi{.QoɄ7tI2NNL<7> mV8҃k-tm܇1 ܳ΀<*|p%lu: S8J^oM伺 C#/Sb1!8h(T ҳ+2X\у9 k22缸Էz2ýϞ{ϙՆW;;y"˒@$]LHi3a=xp&s}|i,E*#w1~SZ_<=GEM0!$a"c# gg9@E)ǭbمs}9uv*"'|2U5foQ'jж+~lj򭱄b,.U߼O#mv6fs7r 'L29KS=ē2E!?FmWve38 1UX̩۾MǓ58Dʢ p@`L|wM(C]\zzPLv=ma:;fa/-}}*OQt_*[ODid"))r`N m(H!?(Ba?ŵؠ-M%>ABkOZ@*Ʋ @36f7M. F6 2amVLдK$Iĩm{ *'[=sbPZNr; 6"uKeH!wtp͠D(WUZZBwDGhiio¬^%ۤ \(Ox1%/‡ÿ7@ h:1*vr 4Y)6g,6߹}anZjI ِ=d(0'q2IyC yH` 2OyK2 ƀD4mkf7Ivsk*zު[,Vڋ;OlΜn#%pvu:T`'Cm\׊W8f'(+`3 PY~Kt"qb os%`#Wn: #~s Фۺa޻<̩4Mb4*G1phESK%%''D8X7ޭ oO9cq C&F}v*9_/'䁞L**рe=f"<S4jt*uh9$.s":vN K˶[_45ک?xLzT SNxAM+^.ڪnad$R*mpn:|eP/[fiYf"RAOtE.J*["<9W0,)N,-E_z۱ؔ\6/mso-~Jx"x|k!aZNnF;?Gg8Q!<<ɶjژ WJ{eb`YFŖ˧kv-8uxѕK~?yW6NI9 D"/?9AJI!yD`yׯP_N:DžB9\DT76,g="˱< cֲRnOth}"~:>~3h3 "":Z'?8W,%YW_^ Cs[^|g',b8m+7_n\Wtڨ,A:y2GElQ+xz=#pP4KQ AmYqq݅t],sOyJJăȦ5|PׯQQri˥v<Ƣ9Ql&KI纕mk;ۧ\G5㇣9Ne3'e )M $#c(eְ#dԊOo`PiU Wg4~Mt*F  8yɖjZfjfmzӓ_q&Go}m][`ޖ2p1.F<ʓ7˚q }mC cؕ=,VMtd&5yE(fZ)QdoW1X oTN[O,^DsQH!@X„(6NwZΪLWqd5ڌ}PtP*(ΎD8A)N#Ļ{{Ôj=PkxЊ![Ąq6`=/;c})Ncx(Y%ЏwpQORCttQ)δ?X6,Y+ZV|xX,I kYΖgz$e?VasW iT2nR9}0\3ʼn@Uqd ) @")U8])NC!T(8#2 G㌮kNWNTNqټL>_i :?Ҕ=4g0stX#xe0-'K81!#AQ݇Ļ`s~r;Eھ?uJiSP.\-̰Hjۻkl[qŬY&afvVxb9ε4(6\;e\΅l}r'k㔾xlX|ӴLQ3i&"ԝ;t`F(F7iu&_.0):j:J鄓6qR&si1 '"_[fiw+|# 3zp=E]v" NlSmhD쫟.Dp5T6͂ Pt`vJ Hm8 Og2'Mp ss٥>Z{x{cъi(ӔQ]/;W^1wӿJCIg-{hsQq1Ν LCDVM?gR|#r uenPTtSblLó>6xCENP{͛^}[Ü$)gKj@l OJLS40zK};o+|\NW@SA@Au*6"N=nywGrjj.8qb$n~A$3 1 Pa?y$p5m^^Wަ4+g,-pck۔U6qTt%P@.zk#5[H=<"~a|ABMGiC#o MD&G~ٵsp̞2m]'zzTw#_q_1i2gk_ȗ} P$(`Lʆ]6GEM5t^8?_iY)Y64EQA< "Xf|bDW*vZKP=B \OS?Ǧ'6W!X{)N { :}K%WΡ3` PF M,BuEO`fa0u %'"vq1Op{xbKXV]'bcW;Rjrvwnm(ż|OA3[:nuةuH:f,]nߖhSSqQðE *@Q*C_,ze钤Zr'@4( 2-u>LtDu$ƴHet"1LsO~$ l%]HLcWnii>Qb$<ݜLM-زiʛ8˲fP"~V?[ش흸Du$zA0<%#{οw]Oһ1.g%ơ GqLl+UHumeE a8N4Mت(NeG w:]*Ɋnpkћĸ/g`S[|/_ }уjpfJ3jk4ퟘ8MypeUX2-bZ2:]X%j E%6c$I U\~+wŰ$)NWmst߁1 Gq%C G4 Ub4ljfdE L)BiEfUuJF?Sa,AUb o`;FF$1u [qT#Te^vs,G>%<S8tE`uzp+1s/wmiA΀;8#0ZIPHEzjmʶ} mTqJ˰ _h:JmR1t八ӻ*1pgwOOǷvr+ũ|0橩8Ұ w#n''qX HxeYaC#3Qʰach&T,ll{=_L+q=OOѕ4փOy0#*H5od*A19&ŹhۨPPdYø~U}陦cӱާ&1ut8_<;zpZݭm`IyM67QdwXJDh^y$1t*JgB~ص}9}ql][7ՃS[Ku&5-x,{XRtTNMeU;#arRx" >ћNn9Q$=D EEl4ywO-ϖTqޖ=i)8Uk8g^-!'{i0IHf26-D|0l׮_F1rH4dI,Mm+b3Oo|c_6<SG☦q=+*rxu~݊Iá;qփ4M'GDdbyx]Z^~嗿d8H;[I<s'/~?}v WbZǷm<,@S$l(cL^'Nbq)ŕ1G%v %: (f<92KO]OWbϧ:YJ:wퟮ':VbT 5yukTJB*H+o7eP1HcD?S,Gq=Ĝjg*˦a-C7OtN+^Fb#YTIt2XK^& /p1Cq= -Eh IDATxwlYv;͌H(˲ Ș+0[2AY6kcp`$k_llYX(9gΜ]9ֺ>ՕkW=sz׮]Uo~{Èמzy. ZFHhNWP8P>牤X$85 ]y`~;#zHh?;Wo{˅O}+_}(iq;HwFsRdV,{~Ϸ}k\Eb5NdK˷fmNYKe;#Zd$4ǐz_54d[9'9mtgD=FBsɏzy5,0,&oJ\kcZtgD+>-\5uJEX;2̺=HwN &Y\_rE$&<р) w%Z4n1 Ήb$4ǁ;?Pmayh$9'o;soFBsij6,h y RN vRO1c$4GWֲkj x]47qg 9BЊ֔ٙƷvu[&LL Y"&W$t50;]rҸ vA x&l0^zמ~ aE;u?P7WofX>V?t5OL [Iw:謁@řUam5p(ɰU2k?5^8ŇJ^h~sXl&իڭ1cd ?3k\2$q,ԣP"W/$'3EM3e||hD!0qTqif<´cbRډ XЊD0tOE*7,mҒA8=195u~wc<8&nNd=ʃ QePx:Z9T9-,M(̱m96Ra@8I~ck vN O! p~&/ ;/}ƛ/K.< = ۬1uI75P,x]šJ6rE |ivE p|n#0S9T əIt@" ח9,-(Ԫço4_4_ݽ*6O~xpx9 CѢ$fK3C= `U*SnoAC8/h4l~⪌v2\.JR|aBCW_W̶PpPwb4wç&4e,"B p<ϕ`m3Q>>68Bo* P=/eEʩKtx*k ړ{W{q U21g#wZ7U HhZeh5TiZCt6rk7oYuRE(Yrui"bNG雯ȹQ*Gm}o%Mo *s1hrP5p颫dT!⽪t'[$ēJw:Ic{l#lҔ52*m̃dQ|߼a`vζaVΧlIŔʤ#\炙(zL*h95;_MyS\֑ԠDq y 얹4yz*zIqx3)B\["™ь[t. $ӓnKgb`cd![{Hhi=Vfn Bx.n*qHP:g_':!˘s]_.\DY4!$E5@w\ >7 `V #٧Pýc5TiJN%kZe.; c+74Q.[ǣB2#cT& Wܩ*B9ESoc j͛2E MDn*E ~*V=[ac) 7V?kr-z5֝/ 4t)7}?ޏGCi=UMnB u'_yxC`Pa{4iwNf& |>O/ޅ( KᣡJ+UϞeM%29a_z хq暵=,-&`A+& M%^G~737re"9?1z#GUL**m#rдש1g!nZ Ѡ+a 8b̟ }/u`_y>g ^+g}\@ޡ%b 9RmA[+8^w^5ZsĽ)>AjiA7I<%s iS8o&4?saqq5LoKuMn γ/<|{y$Ed͗)Mx{tB^Wv#EOY`5ƀ'.*B;v,O< Ɣ,Ҧ&89B' H3/?ŸU<b#A4 ̴|fZ.j|cǸ|-1Aa4*Hs~WJ3Ղhmxg"dD0{5l+ V(kxz|џ"iu\cy,tE([kts!45{ %vgnֶfE.PQ.Lg l=[JT7@DD( "sb|"^JD| h{`B^_+ kK+s9iD4ň bϛtQ{毼 N4Mϗ _bL{x~<{'V/ͫ4[5ͽt1Vd DQ$BhXi.mLjf ٨U()w75s]b巣?`,yY\hJO8Of!@y"L&žyVfԤ?J0Dulj-RnW|_T^voPQK%s~tB5 @!ɵ&qDqӂAgb0k1qvu{%@E)`9Qt" B#BzvoQ ۚxם w% wԍ!D7=h6ox #⦅n p)|<QPfٱm/d˅ƨۥ$IQT BҠM0{ӥ 1ǣ\'2dkGϩ:2Kngܼʁ3Z7ŋڞ|,}ŹoG+m㆑3BDܢ:qzvħ?㪲 ;SG^{녁?Ǭ[ J5NvMpw)Lnx0~)mlx,Ƣ(GTqY3~ivUӻjwBJyqEzh??@xZCE 8(ޘ$J+K0aԴ7wt1SM] *ճ~tǹPW=ym'CVf\Y,T|X,Bu0o$4'w6ZQ!'Dx6^m,,dY%MKVAxMY+eA0^9蕈_&]gd٣]^".0F?17y:7{imXn`lxy3ghLP*D%IᴍOfo7LУ<m&u=hBϕ{v2μW[u$ɔyfMi6kƶ Dlp=[/mvcVңz&A Sӯ.u^i;cڝ7^!rXНQ(>TbfjXeۅ!9g,TA~͙LȂ -uG^w|E(Pf,KџΛ2ޓegƝ>XPC|?8*SIn/ k L}r)Ҽ748qv_YڰmBa;z1'wvK.GTv{ϭsis?`L2Ky` tŴ@#gex~laC-e2.hUфt3Vt줙go| LNA,'C/-B`ߍ>y&3D3u=o wΘeOԥ5Qp^e?a{??~D]ҵ{@'oE_tAWRj2U4 ɭcQSl%ыjřG??Ei\nX535ؾ0p [ B,p?̵Ofdo{3l_]=R}K)שǠU46 ΛH͇>/VL nW^k6~k.DB}U*zjWql-;ubM48L Ї%`td:7ZM;5!\,mth.cH^EB.M0BsgqSW'~ }eXڄRљi|'/ JfTJrkH) ] L5A-8o51yLj?S۷VS[c?]pfֹdC^ʽbu)h9\˱r\uނa[pkn>;ض/ͫ[kW҇W7y]ֹeU9{z_{ F\dQB~De+EP+/%?;䵽3U2& *ثS8n֎tb)m۫dWDt*Rc)Bu7oqIcD4ݯ+xTaaeK\A5b4ȼ GhF֯Tc!+7܌aBzM84Bn`͐j@Oyk%jZؤs+vhO_\H!Wb\H|')Ժ=ҝ-ju>?$v^8BYʾ%fyW^r/#\"v 1&I,7W e\œ-0SwR3wNK׷ 0cej%~W-鑂1a27CA\)[w6qk1fI"7L#q6M@s)]r7x[ d,xaDhi?DQޯGעd9Mן~Uyt2zkus}!WlԾdC:Z+՝םx0@X9M7ů-rfXiq9ÀUJf Xh(~aaOE!Vg6!+R%//EeR&gn~Xмr*ˁe[d5`tG,dDU vsȡ߹^%* @zE(8UnXAantXY)'! A__mHÒWld>s/4_+NGml;u=pRdt]xE9KAu7UԎD+Z̛`PB3~ ?= ~}5%Sx)Jf3Rg[>w :!<=ֻK?{5Cgr@F/މӁ]#C;SPs EEg dH?΃jŽĈN)_t3cɩI>;a}sP݄x㰕xz&YfgLY$GNgҳυ=x:p!zyvLw*\+Ƶ%鉵ܟg U2z;{џ sjޔJDSeYVtIH>TGOM ޢbNLY1\>fnMd<Ӧ;W=Ms]I,mdJ:0xlcXa w;ݑNYz98o>O\xh]VroZlagDp8ʈ;w,J6@-f3M:әSj"<۾DGana|#;ן] GK׺c;j9Mط?u7S8`xq 'K&sv);Y_ɐd*Y Apa*Xvo[F:ax-*TtTwr.UUE(M6c(% ,kK~WWD$Y[-[tpc* +nG.Y75 ru58rKR*O.ï\wCjH]KNP=ԝ*EPΛB3Iq4B B,x46q;C :2ұlg/ݖ*e%vy>ihO LH$XႦX|ЕxDsc?"[8[5dŝl o I~nW8f90E"JYɢjds ECed]L * ֘/9/TY3L.% _dm4wl qˮO{rn)Ju`DtFcyNhk,D͍XbAPc.M8lH*+ˡr":@%-+E].%7|sbij3=@QA`ZB(X~WѯUtVwi&pBqBsgq?q|߹q4?~ﮡ,qv*nUb 63 _{e!?._!%Vv'[3wH+Xk O4f*YNdfŝl'歖{^!Kd«8;J[t[n {a`n%e8*EI4OF;1߮/`D~bu"EZ}HwJepsW]w&ng_ J"rsGأ2}~% e R-vT`;Mc XKsq'ҰߝD2q;#죧vHn'nƢdq3zpYiژ $X`qlp'z!wlAīF*O2hOgIӱp+sEvpQZ3:~1bMm77cTYgJ3@n{wkYW P͐lz]VԻ#?g73ڵ|nf; y ȦA;5 0''1fg~̺F k"UL,vŇjK%ڽB'1߶_-@y#|j#[۶8g.>|X&Jcefk-Md hMWB3l2G YǓ-8Ly)T5(toSJ K,BBėSM2q6[[Se*TY0,ov\4]>D)/1 f΅f#jvFEP,$vxxM\iZL!*!RK:dDӁuY49``ai*l$5-sc[b:w$sPAK|.4[}P5^rЭt(4J?&ng8bFǰVT(^y07/eT4x&I4 f]**tLv7@`&nFfS{1PLY$Hn>LIdWKKﴦg13q;Ԥ"\VޢQeqSOOf[L*ud=J1۝ 9`#l0v-K*2Kzc\,X,PyFu~"ɼ{+ptrɆ̃Y >E1;Q-4}9&ngEThmPc/;QtP*j@hԛ lz/(:HIZsƇ|cFkyI8qT>/w5e+G~Wa*1ԚhPI*V)s':ټ-{M܎`L=ZL}W凞֯@:Ա~;+5&ż;S `@`e"Mm')PS YW5gcdXKwޤ2FH?AzP2 I ָ6ARLcTSk,ЁZZgOfڴ9y3?ho9[BS/Q|d&7) xK:df9g'HS UܛY0)ZSڶe0Ya|I1A@ T65q;$ٕu\k ,Do q)c:dxcLK2Kwatn&w6V܎ds2UnG*;6K:lob  !7-3YَTɭ`r`ݯhvjžU6D Ĩ\>WݳZ:6q;`vaf˧bl7.35RXI j$d^zZʩG\ fh')f9Bu3OoΕDЙl7oe; .NfX|( YD Z糤&n[\#` -r bOJ{=m0L8xs '(S&f-5l,x_Ru#ʴNxHFi$Ul]NDf _h1Q|^k!zc p=bc_yS{B+쥻G豳;g^ y/]EGpDXjx3\wV (^ήP6"ɨ,2hl7n%cvFf Xr ykBcSTwOmdZ(S3")Cpk(q6Ⱥb*GӹCkۭz<*ƨT*q!""D, d*{+@+ rh z ׭ ;@bP#'y"'~  pΟŖ*f=*~;#kNefؤ[w3v2Ud #s{R6413\<G ƨ@>}6Z!3NdhΥDJ_\ْ/U@3WURI(żI-?pωξ?A/߱_޿ⷃt;^՘iAQW/ꨤuPe9 ^ (3{#L¹% s@q~,Qj%4X n,m,[PVf6Ⱥ0Lg"/r|}HAҝ1 D{] BQͽɢHmxMy7fy;W)VT^@w&$Ɇ}1kc OE}Gkd9?TMw,wA:֝*1Uppp!WnOSmh[lRq-5-7qEQ4QU(Qڸ}W =cBxۣ.ӓGlhS[wgL3 nexBh 5_^K-X*.F>U(>ew.cw# {3 ߦ4w7")0dĢ$s޼t1T2ʛr:spD5, !Qon^/!SZSKx,8zݔJSKۓݏ0#"fcO_:4Z~m2y݇uf(.?;oOV{TߦŎ}([{;3Y(5&eQӲ'WQjZ&{cB3px=X"7 x2]Hazzy2) tb:`vmOшj]rHIA Bc,˰, pN"`XH4BdJsx6Ikfx=J{+3 L}cmXS;$mh,WFM/gd[R"m(Jt$2i%QĤbahM߆G$4m&`|*!敹U2ae,ħ̄ L5ym_]=!2Qxd*I B)>caX>RyPc#*s9[NmQO5`ܙ{>%HŽv<#Je8B8PO^,Cd_3MV}šU ^GEkYIQhrFu6 6N43{=Y~|ϸdoז+_Vr?Q!1EJ9[bRJisID{PcQ-e *|~ JWӐXx(^<Zܥ{:W/]'scߩ(~[F2zG5-W IJ-1a,fYu 2aeoJI35uj(^^O/wu|\8}@ľnYQ{ <2{!nd=6>~Zdr#ܰU! F*U4 _N(M3=XT2a)q|n7mڙG~Yy4U D*7Ƽ)z}Vt'ZLn~ ~lrIZX,5% ̴(zL@iNM>¦Ax('5t ˍA7mcQr|:+TjsggReDQ a26Anp$/.~IXD3]m[eS %=Xx{z20M=٨"E]sw>S(nmMyPchoŘeY)Atyޣi(^d>,hS&?mxW~Pqb;ހgWClgK=2>_PUCU|ȖY'9<4N*S6'1-{>Shʸd_X.~'Ѓ CTA^I"-jl •~MQ$c4a!E]*cyB|(~5 iXçɩ {٠w7y~w1>|B(v`64-Q @a/G0RQP4Qex6|w;ў2U ݛ"Iv-J_\e5TQ"ho=Ao$1L\8~ gW;S7=̞2Dd[?ru9 kkRts_J0SiZQˋ0@o38NT `ʄ r_h҅A7(~[`w0 Tl2e(mJɘeY] jMN[L }} @tJkH~Cѳ{?\]5cfmv&ޚԶ~ey?jqoAhZB$B+cv'幍VV2@B}_::CT9:=Ia,~;J"oeoa^ `0fC{P3+40 Rvcm[7WCLv;+1Ms¹@*Rϣ;sj7V0ex!rop7r4F4e]oeo{^Po\Sr=*05Frey^)GRiR]L U>EO۱2W8B#2>(Tnyu%/=JԒC \_Lp+8rB Rwy*Ja)tǃ'm}MyPȻ_ґH^-VcBsXV'Ѵ(^ʄ3<ן+w$QAވ$w?sS1fUx(|g{ :!s@L*X99(^L `䨎hlDz*(@ Pow3"VOJ zx0R*NaS(hD#pxc̯_g(^cesKmL3'atXi7QyͿ>';@tvЗ-ƘxCK3ۣ$gn- Ž8 ƢAtҶ s_%#*cXY{6}jWn!w'SeȄAă"'FTYlP;Q^oA(vxߠX>Q3;HGvIJGr=G|i(\;[W6A }ëz=\gӮS3'br/QkצlkrۍQ$o7VKwL _xdz`,Qj4 ǏtʧS֯M,NZrHz&w1|W} _g:}p1#!U(h7|pl>9]}~oe2Q|x!nĪ򉱧G9g&wYWIzz4n1Юm?m'^ykdh.~?}y6(獄f;xzЉ}C‡vSLG<_ŕ0QANGS,7? s=$}C|UA_Z5'ף|7 6QAy1bGO!%:=L o;UM34NBi,a[;7ԪJL)d!阓;)s?,\_XmccLݔ^^S*cQ7:cM}sf{2bw0eptIє nC~tq7x|"ނ@b Ʈw)Xh<&W {coJlgz VFQk[55*^#]He(S =2-~똩 0|Wnkdyx@.cE'76;n[N5Ǟim$ ]"8:}CYIc9A]޻S(&:=HhjcoW=lYKT_//EU)X }#$;x{aޱ'4$ nDxɛ_|:WO8Pb j£q6V0=2{=KR.~kZ)SLqJ_Ar/Xǩ9{]Bj, vcej  K0#6)Κvg] LA'! ƮK(BG֯mcd9h˾sG43FBs5ͺ+@@ pҬHRв B )ƃvU6- cof$4ΚH- "~(| fN'uJG)~mpĻ| M&omkƝuŻ":?W"/1iF;'QēY+]f'Jwjj #V1!Bǖpz *)9l!߻` M&oYitr\BOӱ4cP੗ڣ켾N IJS>EjMM'sX6+gK[$'2biܭ$y"BTVػA7Vŗ}.}yPUV|'6waqJ]u4S:Vy/ˣ6Vf60Ύɾs=IaڶѺ ѣQ0Ƃׯ|@*jSۣ3SHx2{tG:<1B鶻f/+,oIc܄SptMe3B# ̴Ceg܄{v5?F$ѾK{_A{#*~uڋ=n{Tȋ}XV-ҋDz Vf0z My1{s:3l$?AMvohCwjjr^cP&장. c( {BvF0a-p;ƘGWw|2s"]Eo=VvT\dDZC;aFry{~#s$֤{|5xi!#;7dޕv&/G1NOS`)gƮw8T#fw`Mf]mp~NG[ma֝).Q{0>ޱ2ssz1w~[x.~c6ݩ91 ܱױ27= yz ZdxfS\U/=_ ;V^R&ݫ֯# 阡4>b}u /~챳8ĝ1i+`vv2ѻztoߦ ڶ޺uI~{-)VA;|*=?Oצ{xd€fqMK̶G3c#_o4H$D-{xdȾ~unǾ  v'oҝDZ| 9qK5wP|"S `Ew`[ɅgrGTn9bAs̲Im׷3RKXH>7랎3`Ngn,bvU%;BlmXv1&|PH7ױ1w^Kx,x2`,ؖ5d Б<~s;앻zn's:D0vߎVlYqVP&,%.@Mw-u ӒdrcQ܍Wc?!/3K_Ef;v{; _zloBS6'˭Dqg+߶tE1x+NL>WUo+Kv۰WuEGmØBgŻ5Έ~տQUeitܲ BR;r *~c,\h5GIBw罤VT/-~)SX^㵾tֺߕ( õljŰUT.~@,\~u9WϭUGCpsaIkz(Q4**u- vD%4~}X`h߶"Q*`8g={XѶTqګ2 Bͩ mEiS# ,GFoVhΠE^c s`g& NGRF}ab;rf 8*4yͿsAwFoT1ҝ>pc_]N}AcҊ<}*F#Ry\.~(@6lʫ˩4h!LXJ\hj2Hb;bX*%<@W^LTR:"4FctP{є s/KvG(Q| T1ҝ0,-TJgWv)4ex.|ӧk3T1ҝFc€+v`7BS6ÞJsFpT4_wx _[:@:y2k5gŇc"4UtoԧB9vh ` D!x M#ݩ$_N~W/~cԙ46D!DM#9\}6j䌄 J19ƺsKηG_󛺞*4 :,&_<>J~FBUwڣx7MK {!.4eeQ̑`$4]qt*zCl{uWƬTV`B)Wg`!r2xdFB$@w[.ӓ mV ,lQJܭMp/%.6G2G#;. ߫ۅ(Kb1nl*45 QC!F7<PݑY㗜i|ɎKM*Uf+sha_3­5`w}p**_#2aahu*~ue]_٠ۅ[kd7'@i)h(4 Qe$4CP#o[h cnYLf&"#H3hwGЍU\)ƘK! ʉK*39F4GAv?s,mO\&d˦Y}T{6S X8=8O91f0fa"w8ti0Q`4u:s% a:MpQt!S oeg`>|CT'GdžC;bv۴੗م(@;dxS cނhtu'4VƘ;,{u A-;@+.)̍cHhN4Lv[+wnlǺb;1dwgtðlF׳.BsuGGǏЌاRwS6t~ueh3;Ti_}ӆ'{w|~3(|n أ?^&0afD]՝x?[QGg&{k;z(6=?n2_Sz -#*Ne.|ʗع( Д׿o@(8'7fD4Н[; ~>k+_/Y.A_0P;go_V>#^ D.\:5k1x%y .IDATxwdux_U*i:L3 r H(KdloZ,ɒ&s &vOtաr~^G5ڒпz}{9s!q~Үj˸bw-/)=}>[[ahhF\0l{]{dL/ 666nc=y>"IkSϳwtc$*P Q7y?umc|0U!>]a鍍{žH4,1}(AB&]r߿׍LfҊDGR]y,S`펎s{9"iO&gdk50 iILSۿK]P.nOdh& #d ]`P!(}3?|~~n>iy]uYdfY:"}LCF$JE1qU@8 q,At4dU!Vlq!9atuu<ȃ{d8RA`*p `G{#3,1d:6 #(J(86 iVD*9 eP0A`8ɝ 6YbK/0ݝm ņך- 1 $(cF'9 00pã:lǁa8FyE`8}JY{xW6.V ϳr#̧Μ9Q>J/Fds9ÐQn8q>44n رG/VD33g~eZ&j}Ȱ`wg%@ġCJDx uôq>Z3>T;Ba]Rр!Erb}~06vq& Jǎ=z C~ISk+O99Wt`#&|w A/8T&45IR׵*"5]t'`s}WV.]"Iי3_& G_??pG C=w{Nov1A^" }gv d&SIR(l&zCPX6@]r4EkݟK_k H$%gao^(rKQLjQF~_ꟷY> dgg$P.^o66&ry&|I B6^@94Ht˶"q !NP8v  6ҶQ.:^OAMS8aB^ A8 8FU4% ǒUqŘL^}6;Oxz~>?xk?ݭa"dIPABJy]DY`q E jckjl*nw܌U,Kv 4eD"Ghҙ+U!e[Xغk8bjlYC3(o8ܷKpB5 >;OTy(a(o_b}~.-GF>J Tմl<J(u0 Ԯ\ pptw˗^ː w >K Vb+I+wZPqZ[tt PbC,q lKi!ʚf@mYS՚k$U5YHRItE`gb)o~N>?8x0:JIET)Um`(a548J8(zht`ۅ I^~Eۛa/?*? 32rL]ɾN:=CخGoJ1m*YǪ%> r9%Iij(l8B]%A9&N(Jy}PN7}dgwvjjz%b}~^{xaQEa[ו66(][8N#nNJZ$P}nW"مeK dgf^,1jcٶFuC.jjQiiٵ[iM($T'ŠV5F;ի m[nSB4]5Q%pK,]Nxxo.Kwb̉j~m p4\zw߽w¡%z}{j? c?lll|31ɍb9xH 厲,MW?ghnoY6\4] lp :˹ur{9wo+A\M0u8so&ׅI_ G{5\$8p8r|mα:3 `YIhc|Kdb|ula Cڴ`o_靅;B%iu6lRePlMEPQہH\mmjÃcw-.^ iȒ:sЃpm_-WDYi?˥Ր]>!IY^ݿ-oI )GDQ"M bZ~ssgJ"T;xQx.{=zOjEӱUq`pqk^tw6@W>Ֆg-=U2::8t.YRs4[XM@0 iKRʕ'ƚ!xC 1MFfok{󳎍"@+.mل8;y>*I ޾sj3,)"]CrLfeݷqMWj }'3B骤?\ 0f j@8ˍP~YKARU||~%`nf!oTRTo4oI(8v&AAR :;nn6rzQ,<]jy.I`#Cp&)mq#?qk4Z5wkA-'OO%-WE1m4v\4ߢ(➟ggϞ~■(Kfm\$Bpx?#VXZpd0nxlI"?P)' eq3-9ɝ"z%x!T5˲t8fS4aQ^%0BQ%6$r0`v0ǩ`PXX{ײ,HU77K/CNODQ7V)9f0B)'<-Chܾ ;8>UV]0 ъ Ѱ ,K}@Kȟʗ EaYV>7wrvuY #8F@eJaM/#Ç*Zƶ UFYqTMv$m8սl]Slv4d0 maKu14tg*5/@KOŰ~I > d ]v04M(_8 84Iް+l%ؼit k/03gZ3MPa_P6gY04;hنm1v+BŴ ;CU˲ !(W02] dgg_8+;L-cY67L[0 komY]iWYO/ uo? P(\2MɱUU[hDyag/[n^Nq}}xJǶֶhl?zj=7(.rYf0B7,Iae[2CѴ;zqyRI~ȋP*c7B>* /Na33U˱>TTEPKVlCXl0}`2|=;Guer*u8%JRu-~2$UllmC* acc[>󑩩-4{h b*6kB)YwێX zty<>IZN<]*.FIbq;vD`# k+!wD1Aӻoz4:v8wϚx\pQм|; (o5ow_3˚>.dbRSkBH.1B"i&&Hֶ!#ͣY''f oúvoZP'>/+kk#GW/w Iՙ/F8n}/d,HR6%!]eI8ں9Fns z8Ir*M˂Q.mi~YQ*Ov$iggclv CH;śo~CKF v BF([ KC:چ^gRF&!~[A!0qOl3$:r틒T]^:8RyGF2;]AnLz4^Y M$uui+‘0n jj( 0$*k XұL6P\YK}G>k.^@7Z-s6  F$à!g׉CbaͶ`\Z!vDbFU$ ;NVEE07dPP5MV*C3($aX(b1h3?ݿMצ٣Gݥ5uR!CVY(>{=[{3[; \./{{KRٯ۶0GdܒmI.#v&Z/o*OkzqF2m!護E&Nv1 pDxI~aZFx[o:gĕo}jB:&$NjyuF4qEP&$ 4,+Z*CStŠJ{ܚ!غ8 0Zlzק_ }L\*f;fM5`\&mZs.Yt`VPVl˲a Aa[F,"FU"IҶqRfh0JSEvwtlWJ%(5CUhy}-_ٞH"`5Ab8b[ہ_ ?=.-gG+ST~ qN&$˹";S5&U4Mm(ii& e]}²a nKRTi)8=oe,Cմ `ozTt;"L~uhg+W*V8^U{5174Bv'N|z-b›ZB!'F.AHÐ%d˹,X[;?<|Jb#XiTNRn}<YZ:|eG~b1~Wrѱ_W>Iw|;fFdRym ݜEq YZ/"0hZ#)AF!)3V0}L0-TE( HKUJZee>PfIJpZŒcmI^ZSuI]D2A006IP@V*IYp-,Y. 4u0(I˵Z4e&04IyH ݪ4i:y/ ˵͵U̍T5gnF=OMyJ@[Ѯ|!U Que_pJ=FJRunHv Zl4EKR5*)vlK0-¶uðC<&ip8ݱmᨉBa}+OKP$NRe$ u$I0 ,v{xjPŶ24aJŸe| A TˎMRl O HS:|ڋX9va5,4Nˊ V&E1:׸׋|XXiW pa Iv zG,7 \aoY^|]R#cYI40/8\SS/,!؈. رOdtJ{K+mFp0E040 U*$&j8FUq)KdWKc8٦t4691\JeilDj+b#Ö2LsQi4T(@JRQ744 h0B5(@粳&D`C4j5[)ã%[$7lM ҵZ&u5(ޒHR!2JE )g(EJ|4B^c60,,#5orn Hm@(1TF.8zNՉ#`W4V+csl>Zm2뺮KREKpb^a ;mT 8\{{g*{#~c}Y,ړ}_c/,S Ӡ(EMCQTɲtIhFU'.] 9; Ap=UXf:oi˥E𶴌tul`E);pVm(8EQy;ja I1Le|d>cƋ#[;߆;Qe ;:B%5P,T#cT.^P:[UضJ\j5SlB@P.;.b\ @Pڲ!mo,W|.|~YSV$M IYFGqj-~6˲,9M4Mh(>ѐ@pTXA<wOjICjvI=&uf橩4`Yӿue뚮~cx7F ccwoKz4U0dIhO^qڴL)A`h`^#ElhqCR#cY4P9UQTTQ D"?uzŋ:qŅs Iǎj{*,Wzࡱ_zO70m}bno +aȀ`oM|7Tr6 Isaܲ1`Y `8h閪jHA#8/A+AنkZttAQiY^]Lb ]VC/9`nnx,6%AH](H3 "(@],FE0U5 HGQ5t0$ޅA@LHJK^=*[ U71gQ\[𫫗';{#C:֓`cc"ۛqS^l¦c5tׯje샇?;y= S;vBa}~-AbCjj&̜s˱wuɧW.>_m, ksk YeyI#  O^evXl$`3Jv}1|6N_:b]}aAiqJZ|Iϱ'ܣQpt$ ($$Ӣ*yC{0E2 (uXʒ$CiM )WTlhKK .;nD2'_ p`p`g&VI?&uרgF-^z66![/Wi!wk`e\vB`oO&g,Kw"MDGq|/~0T lO7E Q],[AQI8&ck|C2;\_AQTX.4o\:$ űȪP$ 0WR5/ŷ C {Ormy)4rE͆†r2ŀ0E*BCBau u4 cѣmky$u]&Q%BvËuR\hvMtn`Y/ _sl0TIj@PBQd#(V_yxHF{ё8ij[x:=GQ;CSGl)־3+~5I*#*3:MC1 K b$X٥yu8Blq cX8T[Fѐi7vPX_r7c.@Qw|g~#JRQ/]|B[fR)v`Y4IFմ`kl} d1Z4ZmێC8(F9#+n8Ntm$Rbf)M9 C7C&GmٺX"nV\cZ5F}gKiFow[oU du]jl$L960-\ 8@d("jmSZ%Prl֨}l yeY )YC%I(ah&Ha=ۯǗJ B!.ML.+pm^  wk3W1wtryIrE[Knl6h8}z9,jo?t<{onF BV˒H)ƴXάF;L# MCi! ҫ?Td!?xp˦#˵Ź'-FGcewm5EbYWXS0j):08x6$UMHR5բ7dUA1PئJ>h*uaR8Hoؙ3_h+֗߄`µZ^Q(J񞀮2'5JOJrmmÅz6hiC0sF57$Z/ BRL_e4Mk8}ʈaܒ!kafTſo>`}![Z(ϯٖ* ;0PTCE1 Ă{rgEQx6۷0 i0@s$]-MD`ǻ0sӯk%c2e*"xy_naW<ZKXk!2lx`=pT㘦 A0 ͒c0 (HlX =k+6nivl2ti aZu{MFpϾ}7EILY./_mȑGx>R*%қW=6/Z:ah2=J*5`]Q*%F Ar^_oKjȝ`~߶ǖ߄4 ĝ}q[3LlUMA펆#x8ov!L\ ,W\oi>x'F,)Q2-EqDZ-0 8 M Ca# Ѧ_XBaEխZ]{][ F=OaBM4-lMZl vt;e ݵm: dvQ S5رGpyE7d~^͍Ra!0uxzE۲W4pt"pqN|VKtyZwڳ҆ !+5ҖjؖnUݐu]vEU{Jm dE( rYPm2\cvH#aN`mH&Fx^.'ʦ(5hիr+l0͜88+VVt{=-jPE)s 'Uղ#(6LR3+uvPU.8f:$Nq^޶=.=زa.sl A<|,S`r5Ix*!;9l[Xo1@"1ؼb۶$5h"4je$ Fn5ਢXE0uCME$7 8KwǶ-0*+NRj88P;PobЛ5<sT1c*'3>9V8M*C18 cic^2tI7͹rV]ÉvdnX7tAx29_aXxvQT\`91t>|'I&4`\givoUݴbfBRefi[᝝M$frxUHTE8@@%)q%TU'IryDAmKWP,p bBၝx}%.ddg@aPMR" ņ[\#ȩt@Qn_o{ojvz!OVr\7$*C=m>8\t8F0@Q BPa2Ǐ?dӘ˭Z۶Fr(- uAۢzb6waAPJgriMaQviI˅:;'b=/I%!9کA0iY[68Q04*Q,S' iA d_&H7EцPkە\ `z.I6u݁!ir8N^'MQ] ij͹t {c-#MɫCP-%}[O=+SK`}?"i0GF0Ɇ^z^UknOvQ @,m 掟xtWM r\;# Ȗ%"L^9u{qr5~iv?ۮv' @d$::?6AX1M6J%-GwjV(Fj5a`Q,]aeC]ǚĽxXsvuYX8ϯx%v=A>@qr(!;o480>tG>Y[(/.ad-\yʶUCW,0LިAq1a8 @vṒhg7uÒUU3 YC>/:$$o7SS/ ǷOѴԪi!5D$ @n?9*Ҙha:yjJyC$+z'B~ٱu>vo)./4RA;mg|\^MF;G_-4r8|4 ۶_}}>@'Oo|8>'fxekj|l|yzAuE5*5tnbo4MȑRa4uݰ (_K0x kS/|ûɆ.-m۶˲Uh,E:e(0uͰ?ءCo¹|~'&p`oǦUiSWtߎj5EeörINOb[Eq#a9;*GVY㢣p\Y.ьѨe{@+;Owy;=Gѱdj[ZMZ$,TD( Z$,Ut vr%k*MphƇ  s˕\*9Pp(JGC )0Ke-vTJ*7jٶe;!NӞpkSk^W0d&g%M[FXYE4F'WլW ӹ޼_zkkWZ,K3 AپvYe6;#@%Aw|(W(1|=zlˤUJ>o>+.RRb~OsjM. jg0:a;dʓuv9I (l_x Q,RǶf;&I*UAE c#vLPUI0Caz]ad AضrPcHA,8N0 AI0 &#X- H/j"(IR\+Mh$I#lM/U6T2.qa 7r% s"~ח>} Ʒ~rٹ&e|{ύݏadWֶJR/]wva~ ba ~A8F+ TƈB 0]Pb\!@p3xO6 tI+Ҳ?_@@(*b4ر-ڤPYSkIe/@d1 O)B~ii-!ko?2NҗeXY;\5tȹsv~b4%Y-TDx=>s`G@Cݣݒ}m*B5`i.؝N X`_9 ݱ4'p LL<YE 6 7tu,ǟbY=;AIϡ(jYe)MX4Ñ̈́PUE]7!@5$@Lg}|T.g<ݳn5uEҊTegIL2t"MA` U"H Y;bԾ~?/ˊ ,_I0AXh^c~ uizl1 V .-aYC,b vne̋.5m./_j>w ýJ%E(]]ů$S /"[i=;يF}ۯ⮮$UkJEJ!: #D(|{`˽0_[JQ\t*7ɖYlTrYt ]zd¯PR$-J3gpwt./GPZ7FmYn8pmj8&E`%0CaB@g 6k+6ij.nQLb5{{nyŗn1 Yi)Tl7G~ӿųc=M݉UQHS,M]^jB|t{/5$`4݀ࠋo> 3`ss% 'oAЖ%녳ga[>_'7k$ CiuYXWLQ$EEX`'Edl$UEhF8veFЪ[f3Iw62x`wua#clllt]d6=@D`@74uCvz@JflYT>tx8'RِtMY(}h*5LLM>c1&iKK? $!G'Sv`YO hd##6.`ŐuI5 5_+U6uM7ME7SIFXi\Z:#m ϿUct"M 릩/-oe/($zurd2s"GM(TFGi(GF"!߳}_Oz|3U2Py@Kȯ݉]3_IX}SoLd &I5?;KN/ƯKy!qD .V#`[ @1 _}۶umr,+Cj(SS/ ǷFG|兹'pJ3^F$ o6.[sm;͒l!iw?#o&i}'[Z wW!;sԁP#X(Q;Gu}ccc㖛?&JXãp['Wu4W;:FC%zmv=SGuwnk?7wVBy*9Y vJ\YiJspb*]5Cc c$14F9#Z#Zr:9QOH{ H B2 ;. ZUsĆ(ZH ( ;3@ӞB29xK R"q@( ++9w0*l޶ܪVeY뻽i5g>IeQ2w׋IofJ$AޠHWN Ztn-n?'t*Wʗ&$Y/#mǛ/C1ާ_;Ait͋ӡpPEi%f@i/f&<4}kb9Q, #HZTr bmV` jꈲ cpYnfq!`HV5 \^'vr!\zrD!b&uu:6L,=8׿*$`3S x(rj5pu&cEb?z-=c:>w,0>"W>}DSS/9ˣw//u341SW>oY761+0c,1ACb>ɑ\ݡ>6= AbL΋LC,-?˴A |mxh ~,UYs X_%Qt)<{UZ5)J5CׅY2lY*ۍ>6emQ6u6E_=!ux"[S5%es==:Н/ WEYoQ&nX=a c 7[| ?!k46!1 ;_Q9Wm(wx3h3%`kʚNRn'jZ.TϦ7i 5:..?p4ad"vBA3j5Wk'ʣ}O`}K_'M57,1x"6LO"6$Ì>؅ ? &V#Wo^,oKP-o_$ ))YZoP7L@0 v6]2tjz[4 1v 1Xz"M@br9Iup\qJ2['plZnO4\Ni^$ ن8L1Mb`mex{ifSlNz77T *ncU f5`m C*|6u{ߖ-Y5|De?( e㘖EΡ#3Bq~b#61K޽a};oz_ыAF'?u߭&~גD~B~ws&[%WUI3lD"46vŋ?6='SZR1 f6TMAj+4Ć(^o450)APAp5M5"pϽ%%q‘؅ ?)vq BʶubC]]_UMK10 ʕ'N M\ah x#Eb?|n<}g^z{6Y`4e $MFpBLd ^73r0CgP:2Пka|ID[2_slM卯?6K#_xmc>q׍oK%2 Zk$Ixok0ػKx^/Pĉ:^o"XQiuod :\o#0tFV+ ]7Rc7\;}٦=uϙ֮d>>ZJϼ6G~x;ب5>|+fA&ިo.uDai"I2X.%/B0 u #Y8qyܫqBa}sDz!;x>29(f V67gՊeig$lm9ec u V b ( Ø7q 0^Q۶'I\E.4;H8֖mqdINN>|aycRAQ/~S/_մP!_ضmZηԐ0)Җ;ζ>`OssB~c3Sﮜ8F*@H{4xl]R_x=7/%G?u>p˵FBgOo7Vk()*dw'W1 ⛩r u820p$LoH8P g>^q., &npç.\ܛ]0M}[-- OMP&\yGDQyK[gM\B׷dqlq,_j\_,8IMRrfB(3K,,0]Yq (JE07fA0zA./5sewlj<˗6j 8tmSr 92w6d_~,T!fG>]^^z7 I ;z}FJycmm|g{f\}$ξ ? X]Z|0# #GF8hyw,2 yj0P-{I2;Z]ps.M4Cch6shwK,0߾|u9GksM :G۴],x\E|8/;z'fO.TJZ6IeuFoO{l}p -c( &[{y;/;H~{-a?^t(@y9tCw؀o-kWJ]ьJMqy:C#$I c)z"i!Q hɕKWU)]Z6a[!v26+md*f@ 7x]3Jo WqO"]mon㘖Y,E(|\.TgϞ9sfOo)TUѨB0LA0 6HWP0u #Vf&(I R[ɜ,SH:\?1K!shmo5X8N¹!;9ckөULOkk+/ʪhi|wJq 1Det; E^̤oכ%]m*{?䋦QpEQ8W ҄S/; 09YcvX!Ӊl(Er^4 z<-8Naɲ+?qѦn,}O2].c7zej`+ CB-WQj {>~A2߼}ˉKk OTGGxs?n?ud'~rzqӴhУ`5$chIXP̀׽O! Y:_[MHeM[^g/>UplK=Or~~5Qu|iN??>GF{㢛LM209m~ ,pv\+Tj~}}*UX_~X`8y[ C`%+}ԯ|&dn~_}dKtyCThY^vw>dǑ#G T`ul)G*nne/ok?X^hRZsÖj/U/b8TMCZYy爱ku ]ٗn=L? `0_r)4331PknlQ~' )I#k6{^ Io<$ ]SPC 2^UMs?-$!nV$9W]*T/Iy]"a[qaD3ddN0"(Rcqpq"ӿ oΩuPYЩ..|Y{ٛO({_}4P1?%,%@J;G/|2'.rl.OմCo9⹶h)Y6(ҳl\{ײ,ub]`h=[X]f3_/ɲ-шiɻ_xxHL090-/N*Er[.sP 876}-Ͽ_6^|J⯝v#<"9#}|T3ofmc=+L|h,so\PWKȩK 7dffu3P5&1!Wscb]7,;GޏzQdru90ԉ!kRkh~er'B4RT5@a~%.Nm#_W>3ӧnz[[|}q$ꢋ̥R!i dW߰lkp heB1eDby6'"nY2ZPkP8 vm5aVRv8Uht0cF` ERqessJQj(9E+U]G-E [ CQu9U4Z+Dt]+R).꫗u@ `lz>T^UQu.M1L̰j2DPVeX"0kpfR:EG/T a辖! ,.^u5Ž m$K+ɃbŒŇ>(f LqYI9X+ּ. GGV6MMd PENof;eJjkРwxQTmziN޿C#~h,h ϭIca J-;+k.]\[58$>{ZAP!` Q6dLfn޸8 x~!CWώO)B܆Kzn:$uBi?0pӱc}ƧaHv,(N{X m&3\zcͤΗ/?Y<`hp '2L^7̱n󌨢-A>y_k4b:[fZ(ԍ assoWFpdXwB}Op}* q=|{:pquu ý(+Mk ::ƼޘT2Bά408Sش b1̮_{S XdU5&zh0TC4NRTc=Y`ƣFJy125MlsjB|3/e(ϭ$<[涩UYQ8}HҕΖ.zsܱ8##NpGuQ6PTU=,mѐ/pct6W/_n?{y豱@w׫ eu#u=jzGΜ,AZqcc7ԘkRRoZɕ ]n:{mJ^=7 1e;3K\ H d4]laZpӯME}=)lll eSVXW/-e9.TGCҝDPl~U5rYIE]1~?@0]Amb±Mq{(I_/gZ5_Mv냃7HRUM1lX/dӐZFFFDy> (771 s  hj=In^)!6BT\Xepb#o zuE7YhϽqi|f´o:v`+sḺѝuj~ ~{J‘cc?Ű}mK 䊕s3G・YFQ C?kL6 x/tOOST!jp, l?2KS$RDxiZ^O>_S>0<--R>rEMI=0!%SK$ˊ?e%:3+= WYEmmǩ|~EK4㧘I0HwЃ`m$+xΖEd<( F;13nFfW7Sy?j[~`n?weTo^ʗ^7g/a;5I[Hlk~/JŎ{o%q-Uk>,BXo8PT;O^[!Xo?vxzKYE,C}0,M/$Keӟ/5tOO](iA4ݗ,es nw8Y]5+nwx}cIWKb4 aeVr-^ҵب#3!uv5 HbiiDT/HSŎ#}}74Sz pܵ;N ݪ6$1+Be?Gl*1^&pr78}gw)ij+5hz2 pD30Βw2‘e8mY$HW_^(WRVV泓kөz #Yb AH-ۖe)\\Z9?0njܙ߽j(]ӉO e& tn2tIhFOl&46 uQkHڑ+T ?n;P|wI Iіג:KLk܃ZBkfZ.L.vhxnuf%118w1y+dc$<k&y7?C& un{03Ū馵TD[Uzֲo]ߦyE5\ϗj8~`ogch뾶/V5d)_yӎ o^vl`1 ,7ZB~ 3sxu3̔^/$M{SY;O]ai*Ui1x}zC[ZPUc|&V_-,_Z=~m#Ey(5<1FGRqcss 7^D1v tPGӮdjYSSUqs-9:vv1A!EU*lffCxޘ.7aظ.͍ #Gz(βriͶM`M|[Ց}F"mm$*\n=(WZFoF5M( H%?:3q9w`ԋeKcL&Invy5?23l{eɲU)Q :pPNд,}?g`J4aNz \kcr>/V -HkQR1:ԴJV$h4]7GZSK ?JǦWZ6;a3ԻuC]k[c3dԪ֝XL=퍗'g׶bbKwI4?>T ţn B\cwuYT*/tWbɔ,˜dsEACy S wO_yљRԪB1[e5EIQ/[<)J!4\_{ WzBZsv IV>y=.{tSt:]{+xP/ M՟N,bFkȵ%s}&W֯ ET%U t\prd&`BreN6byy5prtiv9=}yϾiXQLCqW>uLgߜx+$~e:X[Q${_|gnScզf責" {pu⅋A  i\`4A^ HIV͹ռ, Fd11e=.JeuhP6;].c!LRUAt}Vl9e<c(YE*@8AÄyA4MN۠˫aR)Y$(j-E$Y3!ȰtC`):IZdk5b@N_PNV.g"\fbێX{ `-qUZ!\.:1qFMjyM-á9nՂo8rGRɌymյX!,(dRwSJ|mo?.Hab!)m:mM̳ FUNa8/U%}}?|X2߻4ETk xAzĥu#XAVM b$+G^mmvn{C>u)u-mh|ѻ=wt/>T$[`W׳=7?Y^pZzDRU. x*HXw"m]-"CO-DWۛRF1eZXiiWS${j2jpR$a suRD[zLfk0Pxg xv6:q"M X]媂DE@ L`uyg^ՙIDAT2L9 ?98[\@0a3>05=7^VӵZ>رk?Tr#b4UVT4ݎch~/VWVe. ˮr\"ztD')q2zm$u;{8n('m0r+|y߾'x<;{|r% #w'A$i+G"WRU`Hw Qa!M4 )F\0"egW6<.'@eYn|nZvÐx*pX^7FG8:3}`p!$.C oXUV5DH۹k!>tPWпW"aZ8]( 7Mݢ ' 1VJt\Dcf~{k7>+Z(庤ҁ;7̟kŊ>[JU?skЙsk-iG@0`d b$*J|6LC}͟I1:>gl6r|q? 9laP3FCL fM\|-Y IrG>Ea'YEP:/Ǣ(*U@Ԣ W.*IRh( u|ynoKwMuψeӺ&Ҵx'1xf޾ Lf5(5z'w ègO)tP&h/0&%XdV&*/ nqKLD0A(qX.]]9wϜۮ>* & 04[vn522 nss׏Y,h +b$+)J*5yEI50MXna90 @Xjha׎^.UM swٻd@u{8w?~uy-!) 7o 03%ng^x\1W(xQr"E9^ T[8|wK'}ej!RL oL/}u`m 4?wͻ\-0HƒPzo*K"J+Hգw?R~Za&7DIԤ|ME %dKًQIV[}5^EIVLRGX,wMFs\48|.3SqrJ -0}@EYS-KL 07<IZ{'tMx'8`{i,E.30{K&G_:&0H B%zN&ℭcJ=@G 19y440BS_v:/ˊ` ,h5mi%ޗdFT@_&6wW!3奥s|"~5qxB[/i]vsqlt YǯN$`g>5]M$mnLMs+V>J4;̳"S$/V{-پmEI`rt=X**Uښ<ŒFv+ AEQRJl5Lhg?e`$Xp˗+'qmIp~$6ˮ B04mVU)g4`4e-*UBe1b]bViYH@|v8W<- r5Z,.Irsgŋ`t㮖ޡ͌^gb~C٘B0sx_ f#^ V %R,CQQ6{)Ε4^9й Ga㮖/?v oyKl;k6GvYtl<](rG{r;\^u"[`O]^\j+E jB3.J^~?|ME5 L{{c-R,{irZy䥪`z|O{n%}kɓzϽnK2 yl"]l ~xQ%׮y |*av qO޿Ls`gG'DI G](#}EҳGmsK:lvXrOKR5$Klm @xxdu1nVw7 #đZ5[m\׊ڥá|IY B  Z]Z-+Md1MĬnbYixZvzpbHzQkgt%b1jWj9JY)2@f5UBTEC@RdPA}0=zI*:0I2$2+60M)/im\f//H收b`ݭcSQE5 9wVkrsf`%_Z0^EI8y@3 t)N4NIBP$U8QKuosW#f p~lU^4mG$VPH,XЧe|~e }q>qͽͯ{5^0CGӹ"'NJf*3[, $z$>t'_yA:yaC)UվAʜtft{ש/=gv&כּU[Ӟ=q'9 E ~sd O;NΕԸڏ3L񻷇K1Z 0E kU8ו7xQio85uG\.I/bK?0ɹ~EvRz%Dʒdb29T0Z-RVbuq|YUpuOyEPyBZ]gi= ."z'2eI_td"'fE>crPf0H±ƀ=)}z* `&yr @Ԫ?fSmK[ah?˳rbȟϫ׎iuo5y๷ObCSn i mxϡ^|ʒ@/oe0VuPdfi@aH/>Ebȕ:Vm75pUU1MTb.hTyWәd)UM$L T Tl0MHޘ1g=߼|NU徾۶8 eKҦ2jF٪Y"*Q\*s$J6;mFM9mkgp Bq\.~D ]Z@3ݻ؆ߵZbf]TQ/hffa0oj|6ĤJnwʉR r5%B>(2jr5 :9$minVT=E/Cp_hm;]`9 rS%nAI`"^˟̰deְw v;YeETzڝ4YQ20TPWnW M-1y;^?z NR ~^Z,0!2u?ya&Ơ+ 8}iܾmg:^l覱{ӞM"J4-h<5‰ۺ]Yw_?1yB!^NSnt QT9M6Dе cqpH.UŅMYђ*Jю,`+/T 7MXSٛ}n}r<_|gZ$|cg)5E,FڛqCݞj5X|B*Wq{:ὃ}?yHaIVfA[-Loj^f=}>>{R j(۳a}h^M o_(\ _xgo>|=OjґˉKsFVNee+4;5L=eyݜ~un-/fg98Qva$ S]NS BX+qTdI6M{~Ƕ A$ Gî]Ҍ}fS$Q<8vݏB&6 YF^R2q<-mm|tv}(jq[Z;6 av؝[\4 m&d-V! xjn$iufܢPdzgh$xAo/?xau=f#9'pt qxA 7nWM?/[ÀDIwNprj]һfZRyx`WSCȎm-NL-DܡzF^[>trם=j:j-!1]1alij!Q& Ӻe9V"m*6i EǜvZT1xnd w0uh<}} 0g^QTF(!a ZF&$A2?sGy<<ʉFO)(\ym5()&+YyQC8\T9aw:= ᏉΞqd<[ޱ?v\.(al%כBIXmH ,K : ÃOGYv#g>PW Qmye$H"p ijRdR jkػjfWr:}$ EJ29|VxI:8 ϝ.׫R0ԽU.1"/Z*w(<_PG@ɲ[cpG>Bɹxз)pS*lU5 H,xݖ7OWH:Mf)OGx}7A$ʊ()?{J,k A$zo/o {,ܕ%@ݲwЫm9p}@gɅ-ia5 oګ94>+':qiId'ԃ~w/HϾ~*oa#c/=Î^]U ,ʲn=zvן/yS"FW[K)ehR p,5 XhdPk ~ jQ _|a&Wg_ ۲Hrb.s%SHf(nEVSN;=Ի,q:[[NGw 5}Z[V5]7B}`?0NfRv{]S5]UUy@#Je+Ģi7 NuQR``8acSv-^eX\y^\0@UGUy.wV+j|sGٙ`XonWB!˩,hֶjE=c}--.w(bL]l1?]+X2*LfIjL-ki (Һ=*S-$-: !^Nj"e*lB|")72ki$)aNdz~UR( 'P*;P4[#7(a%3JMU`Tdi[=+l$Q#;Ket/{a6NǒzZ˳˱ 7%YU$3YOY~s_,Zsn+^G~Bax؎Rb7ߟ%,Lp95}pЩ:5>,J/^<_'O,v0Pf8LaD|  oGRKˈ T^LQs:Gmn{L+UMt6p8=..ww(t ,J5ft%JG`BC[ 2db-'Ibf<0xStT-'лJg :&iҲketUg 4 hѥrY7MSTlnpO/v+=1iMAn q^ kj4aJ4KnVd;v5Nz*#[гEdǶM']Zy Z6AHtC ٕ؆i9ouOX<,IX,WxQ4ur~UQjquBwϝ8S $ijF޷>{fZ|cњ^סCsKbEGKb%WVfgFǦWH[QL 2 ?g֐ahYj|a5߾yJj5C|ׇ6ŎwӼ %3eIa B{[o?71iF=C=Kk$rEQH8osW&YE%E!qt# nd '.ۧN. lמ1Rhw6lMcbTQZg{Cfk8`Ri S嚖*PC /<|ǵiu<5_u]cvBK>u-gFih}>] 6H2n~ޝۺW~/a]Ϛ&D9lB0Ň "/ %1/yp /HʰL^ū(*49NUJ˥x,z_Pj~`ɀӤ_˳l~(ssK \UIDtQ k#456hk?np4IIhg~`SuI-aIhrcTB5ni?l3]ZVM%b*X{>^oK29oRV :TUZ?IWQUC{Gp vCݢg3+qcO[,n3H3n+\r:ج CLXz[r9m4m$/Gs$\Xjm^sor!^;i# 4U.WviYfuF >Z=-a(ϼ6Z) Wer65%,hi-]㠝QR~u4(kmpȊG=\Y81[\ZH+(aeim}j1/*qo=e`ϕX2c0[`(>~&;7.*<_?x݇v}Yʐ DY߸VU״$+{~[474ɪ8 ]5^W,6US\]Cmuuj _K׎E|[q i;# M]Zt9h {^Y%|BzHsz47x2R ?yoOPϿԸ?t PX1Mh`kg D5݇%|yur˙:&HpX͙Q-oY,E664zHVi*Ugj[ϼk+9镵e/*5 VRʞF69 }4M(V /ƀB&); h8o:(.פp/aۦʲb<im۬2J˫2i04i]_[Da,++G0u0m>Ex ="a z2G7j$p56.*zM}Ws EU>! z?rz!zl8$S pݴ}%}L$8z,{Y Z-LsNH4ym(?{(^۟J?|w;;?~%85ME; JUR@,p6J5ښ;*,H*2wnT5Eۚ<w ~~?x` kzz}d l$|ϼ?r`:ψg80csSIG)w葾z9tݿ}Ei=[n~˷;G 5> Lod80 %KKu|A睇<>^I'?r`5MB3;P4HJ:<7:]=w1h|6I^\..AW02 -XlOLg3 WVFE󵎌ܝEW.o鷖Z敥w Z吮]Ng0QPKk'e2xUkBI%E4Us:; HO)@̮j0+8Nd A1 CSLE CX- dzsU˒ #0BZ&5Q#(2EY YpTVYF+yBز@Q /!cx}ͽ^f1<|OY.EV, ڧ .BS̓z P*sO="LbP(-~_Q 0<4ϼwvEPxH,8;w뤃`Nh,q@V}5[o~ 8쎭JG:]^0#6P?{4aQUE 嚠kM[Q[&db A@RrU6LSWeT T|Z:LӔDAv Mco~&nuxU^n6'C͡@<-<'>T`hm\慲(Am4<3V @m2ľG鱷O.*Uz1}nǝN_^gdѾ;wn&üP93#Xp..֙AP^A8bp k޾}W$r%^^{ B ø&'^W2YE :S?x$i'p\Vj-A0LӮ[15uLyչmC&Fs f݈rtUN'/7pBvGbqnY@So۬$-lݼ[A_CQR B% vkm6i,y{PG{v S+(\Ȧ qfBNSil-!5^'$MHQ7ry65 d2˅B$*-/_ر33UgsX$I0MGx4 HJ?HRtx}H=$$RPE895p;3+حau3 q&C0T1&3I d l&_Z$2 c~u%ZMVH尋bP;URF*ɒR,na( b>= ??^(^fUP~wN_9ZekFako}wX{s[7O^Z" }68xg&cR놁H]Z;76_jSQlm\ҹzahf.%L|:@oM{Ju~-;1ZۧW`zO]\T5й*jF4j+&KG"ˢȡ(p +ؤ, z #>U,& Hz4M%&1L+M͞\XFa4Qʪj&M8i^l ^Ӕbmm;w 1Id#q?_Ώk{#`d0povl,̽GcuZd oWo\)c" bqmNwk{nFpLWT$&/aH(i;8R)ski-Ȕ1ܪiAstz Tb˯R4ouʉaa+#w 'y\v5<!hb>պ +&@ur`N%U 089YEqz~\Ů֠(U2:V;; \ҴUR&?[ 4 3@0yzM1\L=t.? C!s=2gޘZX2|~YO]&\pV:,vs;tm4MEECg3oF_zC;܆!R4YJnkg÷\UU)"/M7t`j! Nc!24ðJY(+4M@gVN>yoN CEՒi6tʊaU@G,ANXbKo>qߞ>_7_~ pT/]\H'&` MdY F*r\.X HA Ngp߾GG_u|\bzl6uDmbQ-qѼ}GVF 9Lg+JZ+˅B~aۗ.PGxp֕i .] CB#קWWh^/^| 0F :F6i=. sc+$z?.ۖ̔ T3*B5AЦ9EbIS.ahD$ۚ i@k: *BWL8WTS78`4MUq S}@u]t)`7!&+וhmB0bu)D~SlxJCncڿ~‘hy嚰}[Rd= (kMʄ{7l{/_y>4pJ?ktt CCf+"NUPȑȚ`rU5'SkxL:7zi2zR_|dB5N/v7]Q[ədKw2MK,|m._~mڒ%]\(PL3m =*ekz.M$XN-u\ Ejtܯt:m= e**P5>Ca$ܬxL&cc&;ֶ=Ru8w.-`HuI"pչC7 v{n\&qf,&uݳ2˦(. cTK%r|*(6V]UCQ4L@n[^rWTb CiBƦ/ 0T"%<ˢXin,Of#x[XeE4`*M56Aj2̰A[nyX:WeGϜeGo㗧z0[K[m % tZRpi&ӥwNL0*|v*I`Z0>1kh?++}*r o?7?}YO[H 6/ģ[޶ 4'_ot Bfбc|0 ·|Jћo$גB1#}!5ucb! C%feV1q# Cΐ.+x|k%YPdybnt E7^[>? YƠO7t~7sG"*-mP[.CFemDW߷S\7dljX^P,&崪Jiw)C, ,0 hY<4( jTga@eaD-#x.kx4]dٔ(}}0NUʢX„&*R1LNz<*Mejy,^_L'UXbK"5MI Һ p&DH]s:ܺZ416 Ravnx;)W,&LjTrfeA\XVwꙜ{}#.FR6䫫>8RcɹD|U;i02>m ")[cWj"q5A:we`ŮLLe ()4ijDEVWV ^۳Yab6QikcNL-&9^:9ی"Z.}dK&)f[c Q^8$3sPr= \}|= }۷77\$]?" V;w„Y^WK.RWEF [.xn5xsnkM-5#(2xO}5;O]_*cQԃItEQXVSc\SU{oNlG|yߎv$^xqٜM̀u5% Lrmo,&3esʉlPd[wx%ZJ(gm8n_U EQZ0l@DǦriYJyAP` TV$I(J/5eR.;#@U7t JYjEE0<S)Ny(eMA)nX_%H0O$\y]xT&P&^׉ZSL%x oMMՊNWxϞeY^^#|Sazc:d VL箝.-q[,[oWUirH8=:DN;>mT۟ϼ?#~6ܼI (U$T i ߼+[R+[r|jR-x^@2͖bP}6דGؗq?KUc14A0Eb,7Y5 Ũ} ˦re"h=8h8Ϝp@זSo,C.Aue}Ix4zfiTke8EWLk  {(ҚˮfjҺ\y -YiPx4!X @SGHsTRNmR(JlˑK\63 ׵޺u^B̶}mA7j%;4|/DZѓ o'驣7t:3t:פhvr>SnɩSQATۚlb^2 %FdlQfC+&c"'_O3>m;m~I =t QVUAш{uhE{szb*5.$0da콉L.[3o}s-G7l4ZC~wX;m[ٟ/<|?W?T)[VbwcK3{}[/M>A9VHd$R1-3l<Q &J ή`(1ŷۛC:ó+S'pB |b|*9s@fRC_?;Okwaig`Zۚ4k0T 5M- EG t=Y]$.ׅ(BqekdDw?[˿@Qj$pZ72uM"Ikc@{`e8\T4L&нUՕˋ [Zvuv;(ʊ h"9㘮f 8NrM+.j%!0˜ M91A$I X R㩲)V~ȩOT %ial9O$EBRT`P$vv\ˢzu;m D{rj2ˮǢci8*){Kw' ܔU3]^\VbR}:tji} 8 RYC:6L/&0[?P`9Y T 5R ((:lDa%Vu0a+CzAP7nq9Kd^HrrmdY_XM%3UAqqЮ&@咹j~3=\A{O^ȔbPv;-wݴ8aHN\ppm7mk*⚪{{ >a!آ&Wpaգg8Q6 FWs(u34c8 f NUh:qf#bj墥bBkyLѱ;TN .0<|g6\*CP}u"[o꺮xTR,$躅$l.5;}FE v76]{fTղ6[O OseldH5ժa(4P*&uSWx06x1k0J*Tn!!6Ijέmwv lӸ%"BeٲX  5Ti%t܊.\4@ _aIW NdJ=SݐpvRBRZM4 N^#Aul:w%(HcgUEjj[FU%@8l NE_|(@]7$EIeš˪Gh"i:/(2GV5c)Z>SV-z= ףK ba}-RUinVzBr M2A ;wclt*0d|e7>PdyIkeLNB"178x'뗗/'7{* 0GQ p47jk&E;` b,ry#`eYp+z@d 5 iBN'YD"-i3 EV$ d:MRBk+ql *nXw:7%QZ>ҴdU773#U^Ea8f8>[Aih.j*r TmS]lvMק CEe!‘$i钬 #@q#3Yf 4uTx^7:u9rU{aWVv{^x4;cS~]H2[`;Bw})^.*[Eشn޼m㳿bcg=&=ɡHkU)ʦ9M dMewaΛYxu97$T0ˍƟy!将ֹ /%آec( ٻ4!*l݋Hrq3lz_g<'_6[ؙwOx/Ob:C^[{_>2ah|<gyn|>)[mjvc BVJ4 (^p4M k5NeML(ZUcQQu3VVQ_`Ɓk%8M&4PGWk黭iZU0 5  "'$\ XZ<^̌vGRl)u$i磹\kW(R<> FF慚 w74pm~i%HGl} l[a 6 ݇}$ (mi R輡uGCC۞N/Xi M7bR(KES @1 C 2tۍ0#(EWiњΕc,64ģw -NJ{GWbh3̰ࣺ6Oቹ$lja/B4xA! }鑃75OsJp Etiƹ}}],VUUV вE^KWEY+r)wzgYR\#Rh~Ӓ6 gߌ3^K %Pҙp_CAѳo0Н%y>FQxd3ܷg7>u^VՖBK27$q5C TYUUKU5_VيXd 2m7WC0j״oą=C=Ul#j&_x 9Ύ"4,j] .kn9M9AP%YlM4 zu(=4 '?翱gg}e E5]PnJ L;L IrgE.xnzD| mk\ J\QuձWFTY7@cбe);;{Ë\dE\\f7\8jܶщk s[d}]!W,Yj<ko\k J+G'5QV!Esׁ]]}̓=DYRƀ\0 4mdʹ-HtUJD:kM;ikUhv10M]bbsfbƋ+ F`!Pnw[WEYO 5܏)=p629q/En7 xz~ 럩'Zg.SLF "b́e.g"7u=<` UNb(dJHW$)H&;nzN'uC5M8pb]VPT}[[DƠd,8Nŷu:%+ 5#;}!lȝCmn3l 4o=;ok,/_0@U #abЖޏS&hֶkD.SjWMuϨCHNX6##C÷o^̲,zu~vQARPQ8p5@ym%V* 6'F9bW@cbϕ,tE_Jwrmk=69yΝݙ E;>_{,b(ܲ~"r[g=4tJccojj@ګM7 Luaa&[,.M h:773=щ5YѦ3-alEC{/-#+lSm=r(78햵dv{sO8|5 !d"hwס׮ptXy4MnL[,chqibmd$KJkn3X`rh"1k8$hMϊr(dKSl,.(:, !'6^#/E7$Y!nV8APAL0C~_ƮmmvGR7Yλ{O٢$A^89=w;ci*=I_C>UUQaIˊ5QA=|</}잛 h 566!XLM^;v*mN%L&2|$uC>j`;|M*jmktj~ڶWG_W-> Md "qRV躙-([Z 0A2B֎@Zo,E(\l\ڬh|!3f%6Q4ST @4tEQAVWGQ 3 =j|"1U NWBem(.w(Գ'$dB$+2I:@&8Y ):QD PIVqy`l"~uccUjba5^ǕŞEjtɦp\z:̦2LjnJlv%aV=7lv0`5MB%6ά+l$y>{ Sr4zee, /FRkP9Q– 00UV$Fk_g0$'aw/e؊s[~989: x-]NRE%U69"3D""EBww iz,4qnl5Ὅ0 tY*Juivut`l+IG $#Ik8ʇ./_2lz;nxuF8`Qu4j%'+$q IF&NMEfZ/NO-DV"씅F0DsvyMŕHƍϬ:}ADPPuЫG?yy-vm0!`e&IN!D9WQW"N#i0BC{WbD:?ҡv+I(8P9= e %`HjP'Mzt䅩+S+Yo;})8{e&pp"tRdbkO|卓B힛-4qib5c#LM-ί报GgRP^\ws/>/B& Sg2$I&@1 0QTM 7X6 dzz-_fHip|myx0eKǮv"K<Q ^^ M:$&I0 byV5jt Mz}-?XtPUi#9YWU"p&^s.'QM/5Ye 6R !aIT+aB0 p( ` q|euDMÜ= C;Pn8ctZX]_Եj$BF\EIH^(ˊ^8lT8>Gؓ ֭JeT}]ɹepk[գ*[T,ݾ>s[]Q n"k0}rF/>Gi}`gF+;%,F2F`&L}ΕMѩ"(EHQIp pv3(GS&>FVW0BL !oY]>h8G!㴐f/^eHIݼ$i^BRMV"K[ `weR{-Y>{m c}7?~{̵qtEQg8qj'+]Yz]Y=;3"޹'fU9ઑ?uS.kV!ag yftI7LMWٱ[N@ĵH,N/}NrPRmx̙|HU˱romcϗEQ/y gO T֪i-1 ,OǤKtE5^RR˅ܔA%/_\%H 88ßlhEeG',=7Z,ӥzrryק&^Ă(hFZy.+HF(ԗEasY6me/B\Q$I͊GXQMI1J.] CrVIB#)٥ ?yC8AP{Φmssgl~lWnhʥN}7$EPU߱rH(t"I=d riYz;:WdBėxG a g//6T,4Xv }b4a^:2s@vFw9yq-NIJUUu@88-+E MagxnCw\nV+Lv⨪uړE}B,.]$T($)(3 &I(J54$)8"MZҐL(Y,.Ag"dE gRn 4Bl0r~'.SzۏH$bJM4v0sn CʢCZ(0 ( gHlf1iazx},T0= -Db*'jT[˹6B\5QG:ϏE2E)[ZKf؁*x[w轳+\5M UVP]PFKPDmMSIms+.(*9^_7;)2kDm038xVU(BUd UD*Uur!rʼnHZT'J4nz~X<]?Df Edՙl۬DϽ L$nܽgK'W-DYq q\=C=TSWi ⏾PöNeݭ[enM!߮v4x+sZ(sH3 Õn⊢Xrb!ik°iɉuQ"9I\{itœ!0]#uclhiyc箇Fųl$>:BNW[S>MuK(6PK&l&JX|BIP0BTE*RdhK":]7D4 ]sp 2 \`((~ p:<L"Pqau ]\44VSJNa;޲bcd˒ 2:jN$fm6uSl "oBZ=ȆB.Ԓ AnčtoyA+WFN@$+d.G(M1L֞ iĦ5A_x\Je0&pi8UHl_>GxA<u׻z%TB>L?re&#u #99]Y1W\8pHg8pQDhp[wj1^夗oD $[{zn䃗EfS$ 5%Mp AlfTpaMpѹV+ B9bM "քnQhy$6MC6 (2[?zM6ZT:'"!P_;vwn yu\[o8Xb-Po;xoeEAQ 7IPo3W?҉"[tm5~7婤ND"]P$t&&-ݧ6_^Vs3P['w7`5?>Z:}.. YkdU>oUO? LP[]gZ?A ,d[]c/>(:j܍T3ec? 0ݻ,j::^z\*qˢ4@дU jn^@rA_adqCXZ8xKh{ݝ0rϞϞ}FK g"KUvU3 @ZnZR<>L5S%kpSFU.nϦ*x%/!`a)UܞN1H0[#Hd"a`#ۭV@w{pv!e@m8>R,0dJ2tqb{zP,xM^iB \T+%ӬKkyVȊYEZl,x]8 ޲e`()9@0<|8VWGc E ݳu#TUZZ8HiVQӷ;eRϞ{~dpcBXP5lz-G_ntyUWEYN$ӗVmU9cP̈́/6 5270͉< Wk6;e Bm TJ1@o#_,m ͆Ga򹕥T}ֱ7!ȀQa<8{O" R>T@1$IZ >_d##LNvf}ŢkU]EYinhP6?*"x"i0B̧g^iA\f#(brqzN^R17YU!U6IHҚ"kejA6Z-Y;`yae#-c(`GϞeb%+D`~9I((U F4 L^\,s҇qϑ+ѵpa epT*dE%Flx8$TL2&e)L)=ѱf-->/{XJ6=( ;ݝB#%v]a Wy^3p+<:ЦGO8իol8+RB+\>bK1%!WcVEF!r>։ c4EZh=9ƠZ:_1tA@ohp3b\% /^>j˪Vū4LU3V$H^PvyӮ[\7J4[=\ce$!'j@@acqBd=]ɌND)}m'`& Vޮ-M?@.+ڽ),eQ Wo(^*W20 8jRs`5^dVMฬh[3{c\tq;6{sӠr"#<<|W.]Z:T2wlѻ\ +K(lmkWWG0Boxg^Q5xpsVla&MH/H\1`NƋTFak sxn fn}IJiy6 sBNU&DUq[@,eMY,o?hM)bg \Y!0PX֒,6 rӶvWcE MDI% #_;HkCGdDj*tAdl5rvwlvnvwvvvق BP:RkZ{kyD"Qgs3Dyx{%~I*Xm4tX[&@n.V(S *#}7?\k&pmp0 nҭ[/b(ClJS0>qO} 0LzsglM M$qKvq*5h|xc_ $nymH.91_rl}}qS!-% 0B#eϥj¶nƋC~𒫻0)p&CrTQq_H$ sODCvF8Wl[Wø9^lxiжsyefB$Pq3dʣ0/\E`A-TK%)Q1 v:ѩh? sEMS'q}}gj{7Z͢eCqI/9nbזJU;dn^ Il >]]SmUM!Sۦ)oz|*rx.9b(nX\ZnmEcZ~Y+ZV;ɩ6<#`KLS5eR$`hڴ[[>Pz+WuK՞D'Η|f"GCSk|zO"BXϯί.o$) ܜ_7fweŀ/q CΨϜZ)jlʓI^ᨃmY/>6̯fE_:.St\z8+MضaiF޲t`覌[.>S`xLUz=S,쪪D;caoͺ*Pt<Y? KH+R2Zfdlx5|BMdRB~/'dryq2M"0Rllt&G@Cp]oMOzϗfX /soԳE!SpXy } ð?Fob(26@<s\-CLY,';O6[ՠɉRcm?1ԹUѩ;7a`(L?'6vvWo~Hxͽ"'hڙ]@xv9꩟3=ep b@);O_7Pr@{~ڌ㘖w/l_a CC&pw$:w&Y,-S`TV4+,-E Cu 8av٬SaMM-5e(q;ēqŕu]FQ-=. :-@QR8(a&DC~54{sk|?Ts\,JbrDB\5]7 I}$0 0[d Rh?.@?w ɺ_q.?C}]9HznXe0Xo($˲~6XoTzh7C=~@Od7Uk>8h,D5x~jHOV4P^뙇z"7f3ڳ#3@n#U@q Pۧȇ~> BHXv2}` s7g>O$#Z忤@+|ql9:̉"jUl[7t Ra*KU 9P$MQ-Ѩ$I (\*oN$@4Ev$}#wc- L*Zx z4̮SD)462:*,91 gWc,$sͣ l>/L84%DZ0].uð-/zw8^糅~%9)kgBQE Mw2mhk}|rKR p DTRBahǼ$}j4y{~O,E58A \.= ~ZTC5w d>FO0!a"1Shlw0@`^qcg{f( EW7 u{"-SK$FN8{լ:"*;Nj;eہcl`)d}l2dVM׷"pHJ]}-:F!py}lb>LˌF{.e2˵Zc$;Ѵ$݊תjrqYWˆ Q$nN(./ZfZ!eC|ց}0ͭ)Eham@hw\xS#/^4,/^|YPO<۟dvSmz](EBrAH2vш=F;lO^|b h Dfo흙H.oբaFtߥήnbsɥ H0fY6mCaCTؗ[YNƫS0`j>߆a  !6`bd(9&IaIb>&nX۰ȡW>uԩ})ݗ^^(h#G zWLXP@{zeZeGU HڨX6%ςe{WU9#4Hdvr5cGG҂Uda\ jZZM2IyW)Q+2A1^2ꍒnj}aDEb8+Wl f7gS2z]1i[{UN,vf2?/ޛowMM M7;!tJ}x}ST{.LWMEW6J5}b0dٶ.?M{?GK]wS0Pu4-8(bQt $0,״Vn]$O~yv$nq@r"A?ޜ]{8f[+tӕ7q/F$m;NZ,UPwcXLý yjñz> 8.JE,V5bЉPh@וw.ILO]8ШMS%H4UUi`(\@P #0xrdzG$sO߿whO?|~0zݑ ⃛sF Mf 0ާkUκx'|E5V+q<2~eiG/WG;'O t {/Q$4Y+,S\0u^EWx/ r4޺a9NW牎CI4M`P2 C4IVɤD Fў];w:?=堒ķZufIDATDb튮T$Np=؆[[4׮ݙs?8Z C ,)Rr(>}vEUmY.L|}ry\.m/ݔ&(r"Axlsv([vDuɸ]d3Ԓ4Q֦FdY q/fi?4ٴV龓}vSE i$W=3 r:|4"q)t95MXջ͖L`cG%/Kѓ I]i,riRq>V(^7'`CD!8oxdc&=\.Z)-ňXt#1QAn6 i #n!(&IILfRQ[C\4͠g0-YH0QRgv,^Mv//wfKv#}$$ MJ/ ~+3-#`]wƼ(JݥH|'N@"Ɔ^)Je٢t%>^;={|H4S6cw͊ʮ,7y{4Ej;5$to|aJ6΍gUΙFS -x|hkzɮ 2Hʦq:sH'T[Xo5+ >LǃNQbsw6?ƩShP*5aT[_1jG,8Vp^o1~z\\ӱ۽qc3 slPt;su·ozLw)FZk8@ '|4$ՊS}^]rDw¿+Aڎ}#U#h4~+]AT,E5xN޻$Q6llޞet] HU49AAPY1$A`@iRmX/0ڔkch ! N. #{zi{glJ-yIͰLS0Ҳ5(Idϗ`}mM] YߜTiǁp4M%vl4j0e`ppO5 9-F 'Uaʾ|08dΧ3=o5E66/)N\( Tvr ^R4hg} acc O-.jU'oCOz-  U1P$pkqHT8;ƝcxaW>*#G'0ؽQ1 .FǠJ%aU\ њMbx±"ճg={w_={9q\펴lw&ȠedMȤij;[i]i&BR1ߟX^~wydcK8C`kcyC5NLV.Eq?Wl_W82d+,1OjbAj6/hԯ}߾|PiB"R> F`?jf^ڟu>1}cn߁g&Rq t"rvP"RUPO4 (V4+/g{ڬiY f"_6 l&~Y97^\\sϵJR/j=Q+h T;t:cH=Q!hweɎR0$K C$I%AݙF0w@$4y~v,J`*nwKF{<翫mZw^= z9i- CF;Pl掦0 B}d;+rfU1ބ+(r5hYmun +oS P%f3rPÂzs{n0LKhɚa(B|lY6E"a(\*g=aHHNͳl,+{4p'>ƦH?%C=I|Ss)$Eo8:ax<]\2ulN*Sðu\,` G|z7Ua2$ƻ߻TimYǢhȇ$$f`0. P݅m $)?PZuQ۠(jUob%1GTHUw(S8&`(C te#-E9FAh0p8C~`If` uX6޺J%;Se5= 'scPT!2gx!a~e@Ŷa3޶O!)|Cn}HP_4[Ҷi90 lP0>r- 3U[ SBH.Jz+Q8)):'44yjbdic#d! }<Ȗ}OHn֜n߅oJ.|Y BQ$cnT>5rO>CXof5N=R`Dz$Kru)*eWnHBPW`F>Pm. Y[ =:C&©B6,5QXXxCW&8lfEl j5)C4MĴm誢5۲ME=d{.gnl;n%rpP(VTUtH_(V9l1P!X2:";}›:XoZ-A}X5pL;B:dY(gf^=uٵw/ N%WDI.~cې*0F:Q 0 ''%NOib#C&Dm۲lY->s \6*ʌ 47%Z,0]˗Mt(n j[) (Ym~x ۅP4IzC@a0W 2rp(/&Ӂ@b~W1LSxF{8(I\SSUm2 M p&)&;òQ]+$,d26hlaбړ:0Tq2<\w+-Y*Ͻ0hlxoSpdZO7nLhTZn[.p20C0s-Pk'+';'ښo0q{LH2"dsMQ#@/a=w{9wd1-2ᖃ^ښ_OX7M`z51F!H?I('b>^"j\*i&p@։v*}ڝ''j{(L4R!kGM8R5C`)l/@~I#TRcԣ.iUJRel6 %6.(lC1Tny\ > 0-P)WV?|>-I PAzG+ dE ]wWkB,==8QVpPiT`В$IMF1 L( vV379A&eH"Yl2 8HoNO$Vs%Ӵr&FQ`/AWUD`$](x}bq,pl>LL:,W[-nb+,G;Lku#lOVr IB.ܵDUx]Wnjkh4!xs6={`Tku^6-L#O9vb*3\TvH)C1WCcߙ>2@_.Je ]0 Y!+(Nnㄋ h%UUHXş`Ë64\*aOadlyIAxFLK ڨ^9A$fHE5hƩfb![$n/m% BQ0#I)5~9% mvAOmxrr%Cy\oyN].C) ÑuQjbCVնYH8/$_Z㦘vSxFa@P!7lXh%:0P5vvAhZb(USN%4:s | .qQE-S)@/00s%.U74A-lU&)1$Ʈ_^|]fW$Cb$CxؽVC=Aޘ<\?[*n29gj.}AFo>qj7U~?~ɟ7~؎M w>x~ջ$Xﳏ-?~ykc<E@. g+>oW"I(\k( R?ffaP0xE5wɫ{b{w-Y, "^{=䉧ڶyﴇ"u0.D'݋waMMo"51Dd{PG4P5 8úa%Iae;^ EL%YZ YU.JRg(8@TE;"> ø•ZsW7,ݡ  tӆM;u0+NߓT}V݆`ྵOlK zGGho\#oٺj*ppbjvސǛlkǗ]Zz_&0GFx [^zX}?s6T$XF -` ۶eq,BQ$(7LД0KV r0|V}0Wep#sRIF LM= 8؟-ʽ~owg*}n++Hbƍ.~)eFkW&iA`5>GZ/Wrg~K$jZŘؤ)6_z.\մ T hEIjۑФ%.(8T`/d[blzh</k[8H`0%FZXxTG8`sj-b2oFq ڎrMnq|CQÒl|(L2"0>6!MJU\ͯ>FhM<|cyԃÿ5|#IFIj4=q: ? 8[7[ɘPyٟ7k׮C0˲F#W6 W-۾A hF~;bԂ`BSk)4˻; a@GvļbKL9yӲ)Vg'wSeIu#|WTqIZn?)V[0:;$<Md뚦kXp1>8GMGgeExOQ_I0 4AAQToN'wj0 ^:cfϝCH_%4[ K;XVٖgX1kB}2v }XjC5F<#p/ >ɯt CC`00uM)X6}rt)h,i؎YcaX6?IC)dp,K$IwwυX$'K܍ /bLJ h^o;;<.4(uvFƞjߚܖe4uMW>1)s%Q2 ̙wtz "tqEm |!!r@nn[^)?W)U+j˻ɰǧ6 =ށ٩볻h/nEɊQ{\no>:?·rx5)g`?}7>2?<@H'HN=L(ˍRi'sjÖs':H_$eU353IKKq2k8QjiAnR(wL7C^:_Ͷ~nj ~֬3 ˔XV!Ȓͦ&>n r`u+Q3Ხj7+լe;Psم\v!erEY). Q/uf-pEbu$X|(Lciǁ,6 ՟``Lst{^b2 J5'e0_@NC5ή@,6(\Y+W2Ä[|}Aɜ9v+]]'ꍒmʕ='-Ǣ!ꘛ{MWk.w癳ߺbhqYʥAoEv˓~:1LӾz=#|290l0 vt$c{7``ZUEY3mJPYEl@Z6j5p \:`]WfviE5~r&##p;B?" ^{Trj3tg1%1 _I8d[)6N`_ovvhoN(5妖%K8ROjR^7u|m0K.z(1Z2m$H2Zs^|?tX-( !T];9*4]ql pį~Xȯ Qi'wi`Fֲx]͏mMRA_lMqM({p\AU1`cl)$Ջ ey1?cYҭ}FGD]>p@kݧ8;ZX˾u-KMJƼ$IάrוT6`gfa7mSE5Umxj 0 x׭]T~3[6Iio%|n MۨͷT7nHNKp*/Tq1aȮku2uz!{#y1l3?MU܇76(1RQXz,r[^yg4탂֗d>jƴЕ W`t.~??>t{%GF.s\'.W,*躜Hcy=u!j@>&Rkp9YIbu;엷k| CREI! 1p<:'NMtoKUE12 Ѣď 4~~D(+ܘ~E"߈zȋF6)+=x~cvSeǓuMqL'_XxWVy`Q?`( ,80{ά}h\Hw/]ygzv+3UR8.78po}Z-Ӭߪblvǡɩ/$>}0l!Y˃0!I \n82uZY+?aBw\ ./;xWW?ݹJjio4(r.ZMP=S򮖩JйeEi b7~CZѾO^ ݇:Ң!DG-D F1UQDbED5>~>"Lw1(M]>ucN }r7]3~ 2#45]>>(]t(~݅v9-"1CDP$èbɲӓ4-Ќ A8mJlpܼ*pi7e`G{w>w*F=%Xlxh\t]Y LOWVj-0b(E14E.8 |}O CVy}UMWl5L"G::٭k].6`|V/-ԬvS6YiZzIR`406D(tw]_`ɲJ%U.2jB2P(3?!IAh|.; !Kza?XZzr2nrņZ_{t[{Eb@sW パ~àvѨe劜A7ОkATJ1qS?'870rbZ'hEEF7yXܹ} C]^z(m$Y\|1[|U|KUn6[ zlgV)Icj!ZHMSmY`$CP֮ԛ ӁG JKaߟm1 6x9৚-#7 `؅ -,ShZktv{V6D,[sLL ?2['O>u(Da~S>&O `5զ?@yzԕ[ 0G/$^YP Xm]̣{JCʗ`'׸V -㫏}t}AD/2'fk7ݹ"6'4iWr{\՜XaW '['H$>>;+MWq2kC,SQm!gW1Td^|aZT{E"`oOX a=#?r@-%<0JSbׄ Y}C`?d(}lڽ l;Pڿ56-ȸdlg\i6+!Mm8ð`h,6?wL$WwTjJ&4uM26j4pL8-a YlxX†zcaIXe?d2YNdSRGCWf L ׳bGC"BR,pf"pkl헛 yЧ݅㍧R 8Tm4 8!EoXg:뷗ua{&{$ #]q\81+gl{MׯXfVV'۸S+]$twϣN'SXjÒ/OV*;7:,gqI@&`0o#)/~$ '2_߹U^IIJ i`"1vܷVV>T~}Z-S}`'G\X3 STq1fny P0L)bϝk/z<^q?wFמ}dys"/ɘKh钬 {9)58T@(5[JK2MlQ" ;~/_x3Yڍ=K)3-ۙrkӏN6wK.WgNw KE`30lr]ٕ~YE~ UUE nKG΍z#rZ`]cIèQ$-u}g\`ôot1ɲ07@5'*znz*.b(DYrjCTF`]h=[( ujO, f07^0PK)s\p<׬4є gMmKW$һMV* ˿,]IӶѝ@W^øšcEvQ H٬8 MK7x!(I*\E]= OߚO6wqU`s(*Vx''n/RٺF)?a#N/^ Gz&*9h 8!\S0@4ZiVpH#eׯdݧwK=tD-r#_RX6v7^}8NsJ>ⲢXI1km2V7 GM_#0 BMI8aj.i ]|^e| Da4! P64f:{J\14"c"'EUm5kE"jO`zЇshgϝ}Yp$<1ds5mK, 0B3ɓ_]ZzAཽ۶ yOO}\>Oog_/>Ӳan{xә|g(Gx{rӲm7Ԧd~~j%BKG>o<>Q֏ysVWh8<LE; #OxB%KFtM?.y%X(o ۻcTQ@vO$Fo{I<`'>3e |T`(F;:F`خUsZDl{JMi V*쌪M``߸I3m6CSHwCFО8Veח~0 ~huGTtP@;Ѯ2wK}܉} -^wR%I{;}gw 0070'') ~6tzLK裿wW4802Zh_ϺmKJkOҴL6OF&x]HJ}ŶTA-HVuZio}#淼 bYMQlh'H~q}̼jnoFj\nQ=U@xț+27 u߻~iyMkj1Mu۶>?zВ4bP E r{+h:xq=,wSh=@7v񕩟v#<9^[uòW޹}Đ; ي(^pl|e uY長Dٴmv~9sr3Fj&l8Hf@pjI"I0,vwT[|ZCVMI0옶{$!VaEsJ@_=~[Vuݰ/9MEK ˘\N aV2$3FwK1VwAwi2朞]9'N?3_*ð0͝󕳵uҎ~ec ^[ף\ޓeլxo\-{QOZ@0.+"ذmG7QJ:c0pdg^x>O`ccjb~ IBòpA(CḂe.˩`Uk?uѶvvWV>USpq+c7F}O!(MCnWӥFݲΦm; vA" {=("钪L߸?<A7sH߿峃n$oXۮMe+3ɸPA>&Ϯ`{ʲR#!OwX}pmQM1 !pݘM[RdQTwU] wS {wzFV$=RUH7QTMUP! G[۷tR Q=(a$%hhj6T 9ȵ(kR/Qg|C3=f(IRwi*Ǘ?4ec *ð{Mu ᩓfI$FMEi@oY>̪ t.RKł^$]T5 .BtC1@|*LY!= =9^bcT0ozbN$g*5ްȕߔxꡑ>r?jYvW|/fniڏ\YSMxlw~֛ ~ٳ026RywI!70XZ|GQycQK3%IXRec|#B!ĥj vytHNݕIPTV/^PDx|IE泙zm Cޏ5M4V;jiC0LJ:Ox0'/r\qs$ԍݏww@Zrb'>>IVڹyy7 Q-Xw%bqslRlv9c䀣s G\mJhw*:vb78r -ir8}PNc_~ ĹiZpvSeEsWOͶ}?{nkYu~s7]?vi/^R&zE04>3(h G.v?N[B"s~/^"'& 4Zo(NnZ3Q\:H-91aT5s'u> v=4;Fp~d6eao|!H iI^NrB0P$>kWq ھ[2]uiV]!Udg30ۻamWljt`׍id^߭I8(bE11Dbk؆!+H|sl^}^Q ;tag|RQ ^7-Q y֩ppQqe;Wਿ[>xEd婇&P }>A ی`W|DD_]|ATw%=ev?PCY0[h Cf7JUX v\L$FH߅[[,݁'7|C%p&4;ui`( 0l98X(fdEw^ qA:ej0R06EqRM_s`h7!C=;íc>C)Mfs-AiAB rTPO{_]Vkdvb_WHRQ rʢl#88AږCr( ݜOEC>ªjꜨӃ}6ʽ\f+@D@qI"_Z0-5sEAi:kM~֬^ofE##ޑŋ+I|sٿ}!QpBժ>ޓͤol\Z$ +Wb4:F ý#p&kej0`b~vd)c(l[$+^ct]\&,bT\8ZU?Xewg^xbWFn644)8(.t;n/DFGGjwB~剎<uɎQY5x(0 XN$,;^o4|~>KK5c9>t}~;ofK| El|6WnbT^ ZʉI2 ^tf'!0r xwcoAO:Loi}`/w{\JWeLS`X+~Rʡ^Gl"d ucßQ: "b72J]ɩϻqy{zOc9=ԍ/fTs\1])TEho,̤n9RhLfgIwo(6C-\=_*2qE(*4=HPVjZF0B:O%9ukaW`xM֧2}fәޞjekMvɘΉ M-f>&Wl\W5!-7ƭɑ׿rcU r3(jCu3CUMWTC\{Mpn)$Jʃp* fӪL}I uN4M+|V%blIP5kNLL<y}xroi>Ql5f`d 0b;P2KJ% $W:1̤#G7_m|_`i'rݰdy7[e+ Ӑ=`<r `Ȅ`D#jk&P^Z$I';βi;%$ݹ)[c Q;/ǂh6ep 8ǸL{dYg3P)mm0&zxvp9Z3y≶r3x@U吟-WE5{MYZnƝ^o^g~-gX𷞘rkE5d JM h+P4KB&bO1j C.8`V1? u^˿_P>t\A kLVslGPL bJ4иڊP_Uu%b']G6")nqi:/ ?v4 u~Wb;jZ0?Bm"aV 1r;^.6*-N‘m@H-/!se'& G}XJWqugf^p uuMf2+C̲v=aA{4 +j4+i}RdHNlZH|nUgN{\rmJ$AL&:VnczC6ʟw,oP1ӹݥ}bPQp!tg>-6DzV[JX"s5vY+V-W%xa$DQxsC>cOal[Y<$S=+Yn@L ܕʞ"nJi/RzkZ=Yns4EɊ*Jh$$^ˆEYGHEEt]OBMI@e{;;O| E;x8V6)HtTA0_W @yp09'cjd1/ 41p{#^AC" ˶j2ݞiTVӰct%9ea;7Md{I aHbQpôt kZlU,v `{zkTU`]b\TT+;(nsj{wu6, CٕܶC%^yf&8 K9$x|r8zds7o.WBak7{I*0=R\;ź~/OEdEiٶ %ur`g|{59Y64í×eYZ{#jc:މɇX663 MmK}ecm}kT-ӷny"PIuU:۫8VEO$FL jntፍO]{H+nkۚ7 \;7n,]c>/+/[o&?q%ZK7Q;õj>Fo4xI7aQݮ{vw]ĭ|ؤ 8JHO]\? !IM7o=1ϗx8|TH_d75x{'~MvS% W0EQUSCVE51"1Mܘ@Lx#`'UE{HSUٻV (F"^_ׯi޾S^Z|C3H0[yH܆ SS\1 ?&i==s> Fw (6,yê&=fVF IA{s8_0AۛR&PD~2߼kM7>1 g2-sEGQh M8N7eͰI6Ui!c㓵ZXU#Jݡ\p-!qd&.-7bS'/㸧)YZf~ߞ눲ՆlYI$E{𫿺n8#+7:wLӀ #? El D>:tfP\Izs+:|Ԩ!%Pi0bq /4ftޡJE=w^oXߟoѶ_O-Hv<(w(M ʥr[ )ø6-=L"?Q Z6ZT\l^J*^DQtpҗrCkMK^A "f&7x|vo$:TK%IQ\EcIAzz-*rTg$Ea|6nYUSO?>_V;6;Gõ8Ji H&s\EA(4DrGݝӣD񱼑 Ā+[lX25K\҄j*29;wvg~5wz2yDO<V (!egF0as7Śu݉pP7-_M5}r(\|YRTkBC3|`lv`7JcG rݰs 5lv2(8HTDQT$0L#6 Ne0Hivoܙ})T *<>hoEFJ=]7\.vr+iwL&hV,8kJ%==:TUt^񡋃kMYMXd=;IFo5NoSr 7 пS4)4V=Q H.eMv5FP@0zCCݫe<ݻ}ec,4*I jP92RvyzCY;Cu,KH^"I| oJW`;@zue4pt$Zae{ѝ[8 ) CB8wbM>wG#LVS&^[\ ]C0G q~ެDn8soMthUAv!@(0+ Hvxl,-gf^(gL&Bjyc%0;W ˀa+r {PH튫,Iɘ:,4?9ѵ*h(z6JX o?uc6v iL&*uoҤiҶQZݧG֝¥S7ʿѕk [QL`7Pld`Z{n(~ -74eP5qpm$u}]xlF39NQMւ)0\(V*i={Um[hlGeKR)s9,˔eAؒѤUoe„I>ػ ar(ʯ麃1vt&cmk28;lPܴ`dIHkVX.##IZ.Rk4J F`yY]nm)etbW*8{.h5sPF A  <զs6 /Х;lllGۏ8"l%*JZLߞY_t(]Aȝ4@K981Ⱥ^ SCQ_&ײLC7̢exX>,u~A(@lkܭԵߒU E#.}v'&zEɞǠCPnc;:."A2>_>Lon|g$;X_Դ 7N osEaomoڈ!5iWt4P P4Q'hQ;뻇5ruRXBɮYFAԁp ?O2l+, m`r!Ӵ!D캩뇩OivS6+mr#0$fUpM?ͤncw,459 &$HQ_N"(B! LS t8>_V.O"atu^U2cێiNMيrcHjW |I/FGG}swҥߕeak3K\Y՝.mu^򺩆)ԫTU\"O,ofo-hnη.E5(4% c?wYfXGjh`o# JZ4B\Bpڜ}rKvsZqΫ$f8 3e wCD_J U6 XiIvoժV$:"Ku#(> #vEQ8 T`B,anX![!q7eƗmnHP1r[* h,6̸kkPkhMS[^|fh˲q-E{ 0_T>j;ΥG͂$mˊr9Y&wtLý `j~Tߟ+Hwϙl-ZP/W#U׷ @T30,t6Z |!f _V69A/ʪZ).M (-6T z=Y)n 1۪(ebҌIQj1|궢jdI۶*|~rIZ/NӞZ=ko}Bѡ@ AӬܲmKt`߅߀QߝuvLjUiAlihm8nhln7NR }/6xh96)Iahv$>C"(n1xN.^֖^$-y"1wC\iH$AYty~Ui],ZZRtF2kY{P1߹uw^cvwP2UQRmr~wm;;sR$eB~7oj4{yd,M<~2'q PM+w)}!.g rюnX0 S'Wnvdny" wO+]qx&t#P(?Wjݢh6%˕bs-h <6..̿]`=78t9 ul,>{dE3 PX?L}Ͱ2,Z^VleٶrH 0X 1*ðKc5K '| DIGq1N82h+A3j3yDbTӔRPEՌ=c]&5,2ýlLˉ=88alL `P4?7f6eX64]O\g%թԤ04y}lNvY7 5ċO87c\w"o8i]L2eDS>CBqy/v]4U/vybۦ$$I CCC`ԃx<>xxBXl 25]opǀ+@,6v+$<5Ɔb!MLpZK(0I<_dhcaH?wn i;lvX܁ $ W䛢.xW]Uor8vv+YItèԚ64=H|q=)4Pq_k'Xȳ^)*{itڐ #n GaPC(A?O Э׍:e;{p蛓T%jCV3zO?2Y4Q@<~"A)\طǍ#~i%:J-{ 9aTE6no&9M .wu e'ܱƏJqqI\OHw vJOR^ܾeZ.58tK,q^ϴ!a|C×3UUmrJk_lJ uLWÈ{V,n0|-CWUXqk/8=8xVV>3VQ 6{ue,4Eq`h7cQO_oz Ѿ.ߔWlkWQ~޽p. y Y>m<=ݦa~^rw9kX+6*5:'?|1~cvv0S~%bo111Xe 7MYhm50mUӟ}Td6E#Ju-\Pkt|~CW0Ӳ%&B gs[ox?y򙵵n}5Y]ıeN|]S*m)JVY-C6Ѵn|0]qLfif>{׶D.[f# bAU*k 8\-oTڲ 2fXKY+tG`M))*(q8R7%I{j>,ZOJ%U)m(Л#(`@j+8@*"\4Lv913[$AFBG+R숊?8* 'F+RM(Zbvv/[0`a==(4xo*(~dATmdKMַ/~yDz],'(gw{:z͢a~s5gΕr7|\Ql?qmnW>51?~Q*w7w -z8y ^h4rjKF&,gtCg(<]̖)E qQj%J$KX?Mm۲:WSԦeYPa^߫D}0Uv;XxMLzrDbRIb-im!!PӶ%QȈ ~t}ux(72mTʛPTA]@A/[)u%_qgж@ ӝ~cێ!n;5Me"[xO{oٳ5xsX)mZ2N<ƟTU<===ô0 Z1Yر_o;vXc!;%j]-0O43U3~ޞѬ&7/]u9p}e"<:Xh(ՠi' ~ /]IէOW^#ɺFXnP;xs)&8VK0YG"S$C4fJnwrkc'WBQ$-NLf1c7XM$f3B eA,mɕŢa\9{?3s\S4]MIV`qEC-<ؚ T Mu:CfgL*ys ja\QngC0ц /K-9_tes!L)I` ']W T(a5Ԓ/x\0i WhzY&ỷG?<3 xU%Qab(DMIR'L ('% O|tvf$YjKfXEEk[4Q#li)Ɋ&>yߎt+~ˏZ<×2UTp oZX>ىFg\+EEՎЮեp" rSppu71++0,䖫մ*WLXmXlZQw#,DcE:r5^5lT,8aw=0VҢ{fL&T%ݏٕ@7al' U1T6ȐכU3UE7LX6+IND5<01^ٷDb&e^; C`6](u#*8mʬf:CoZ![]z}@SCWLJ"M$MLtjzX#Kf̯DVdCu)16"p?x綫kW'W>W&3 0LW+1TR4a0q+r4++j0WɅRq}z}]ܞVMS0 hpS"e3kk9UP,,)BcD`IQR9eِ*A++ !V0p8 cn(^u2.*tÑ_E|eyb1ծX)R5B;:?l(_O3-;;36q<08y`5\;!'`plZU|dgZ{[2B0t"I|no\e+|$pd $P)u^{W>DX2b8:91(odcxQPgU5HLGv{bpu**Pc]4XX*N\x|y=ﰒN :1k|}ֆ7xג} q`8 [mo8Ah:p2;m殃#zt߼ZnYKLsMoqdR)pJܛ6|?`'_kq$[$l0V{C~t|dyBlx> 8D`C.|65NV{WK@"P,x H!p}=+U 4dѨcm9ɕ8W/A.꺖[>N; s+!{2NX6H pJ.[-F,h{''0 l٬t8Z !s@rrv% 9^BliݭSTt@[cupH8øbcB">EVᕏI2 7^6@f*XiW)PxM)n'Ta J$KNhPk 5PсzYI F2Gh"Hc5ܹy0cd䡹 ^J$B# ѹaMͽx$s ;y) 2&*M&~˄axP2dyl9p&s#7!aVIQ-\+UjHѤiep0N MHn1tC u4oDs)r H˙M8r0 Z( φ*E U#]w뺪C;I菞>I~q)+vmn={ufz1| }|*M@}+ܱAplokO\KYZ$Y%%v)ͮf3FҖ˥UdING$(U)ZEpR GetNj?|jf WT-(NΑwAPr}Ƚ{r]l;rz` 0tj6I"д=p kVl 8ZbjUaU 0qho9ի*y+e*\A KulDI) h _I؄j4ؿҁ޻N+p$r[(w9h- APam[M7 e*\_5L q"~frTz)X8Qki'gQHL3NGJƕp&=ǯ6 t,/!(@<Š0XEdw+5EQju[/;l;;Ja(p>~f"H:t3Fh`l6yIt۶Ft<> ojiPDV$4UAQd""P֚{ci(MDlFrl,z]jX1MH)x!]v_{10R6WW..-in2p+$ uek/ul ڷ[/3!H #+`(if)mB;'&u^0rxOl üL,)?~O(GF6J Qm\][k)t3K^<ߨ8OɫTjf:jvmxX]P xjj|Ր92Z,DU)cgBAIWƋP`T">c) oڽGYM.ۨEut/IfhŶ6}4Jr%Tk(@enu&1V }[)*/n /ͯPPy6+U7ͺ7 P㴥^YbfeΗ. L`Fc0MeΉ";xQ1[5A`DSVI7Kwd>GKgb1^Oֹ ޱpT@,HڸsU+Y6{m4Xlڎ d h4R.EWm67IEE5M"IV+E\`PoP؛0)*E`2!88}f!dITB_Xube3&pX5\$ lҗeRW!` q\y}}Y`![,_Z<:jӻɍND%ѭsL0}oOOc(o'n>?~B(P7fպ4؋Fr./# 991C;lTSSjd}%J,C}ANx̣G.^ݫ,(b@Zֱ !53MC7KcKDogȚ<2MIUI3Wc?A$yv9ɵ<{wluJfbr7ةеɫgȪ( NjihJ7(~ Iy}݅IvXӂ",8ӻq/kR5D]$/H.%ϱ0/$ TTA. w /kZaӚ.Q2R*/G!acv-=pʥ1 aðaz[[vOL)C{'f5Mudܳ$pR hm*ցsy ]v;<=$]'p&ĹPuFV]nY e΋!fuج'lPHp<"S/a(..x-6qReqZQ-D$*cHNA)hdɅQy ;dy%+ŢDqtچY6B:y]-*X0{Ӂ%J!hjͅ>JN8H 4| *uuV lqa(•lxŲa$R'n_zr4ɚ0Hӗ YQ,fg$A `љ١-M葍pbb9+U@g J*[oou]Y4 )TQ볅r]T^t\0 0. i%Ľ{>;ؖGQh ǁô3PR?{"<Ê}JV Ap8[WF'yI38qiAc x 2s+(#NpG[ @.]Y:hs3^=w~fdw!y}}T;y-'%j!Y)3@K:/HWf+-+32V{*en֣0 תŚ cj9*+aB@U躍 3 iʆ@Hޱ+?1OD&xc+g j *պf <iNoן/qu^];Z6Z~b4U0Ze#pq<꺮v{9o/U8QnTT`sYD m+x彫S#C]t-'$k+D}n$ZPg]7K,/]Hf0D1֡Tl \[Zx}a8Nd! j eӊTDoQUon:pЗ{:UT]3WS vTJ,Wj14MU&1Eb_:S5 p;=AK6+ !X3YK5Ȅ90@tuWLb h896/=B+,3 O_>şۿb,vUQĀzgsV'cLߺj=v{ wm1+~SCnZWVK ^? ןaEDI7M fDܱAa wM/I xQn72KR֐SץZa\Fr˖o1,a4mcGC|0;{ Ab(JFGrx С6,7E6ѱfkiM׭>նpz{|i(m +q*8ns%3'Uy klUy٥$c]Z]?~Z5ZsDg)M@b5tP,$A)[~kÃh$Ylm$D'T i}[x:*%sXmM}[L?/<#0;ɛϓ$pZdMS"zR@[ʐVrȓ-aW^1Mf Hg.\xǩMXAvIDAT0 PWiھ,03_0b7uwlB7?wӱuK:/?1_;~~ѣ#*d|uX̞v1TS9",\O_`R$;^{jO3\XAՑf#/^xct~%%f{IYaAQPD^8qzC4&;F7,6ڭLoGKnkbh=S`=Nj4U /só>txbaJ% 0ڭ(/A M7fW\ݗVC}mP1Ʃr0~K^޹qmM*$v`/;8C?/4~<#frR^ /&tK MNkjB9j5M,@!ZvÈR)QJ=0Vb10NܮZOO.E@̰ ػعiYhl|,=NX4_IؽUVtf .%Kin\dԄZ[kIV (UDY5ގ/޼|JŠry'j@OJ$}e22,)n$%HeA1u-_ ÄaxꙦ!j>ʤn_(AAf_]j]QE fhS0(Al"I4TaNWˮ]5\zt]㐩liɤ C)W~"Z 1YV l{]Vw8}s>~}NeTʊж6C:5o4YYPd_1PWtYYa∬(je 2 a|vOU&0^^ C3 MJHB %?u1$ F8@|me lun!rŪ CA煱nh=vf;9+-gLìeEZB?&2=~5FY#jG!" Øˋ'[u^Zlwk}mB ߪR]?cERF,u峏!MNݫ()|ʴnn0Ԁ XToREt9غ;\)EQ?Б^xO,*3ߕ;[NѻtxAZ.O\)W4^P5) Hוb1^.LZETYC,Ξ"Ps@i跖\,U WWIu:n>1 c 0B߶{/޺Z\oX+sթLs:߲xB#xf©Yz45T ]NԹʸSzbNqD`جtGMS)Er5s.h}}"Akniۭ]F2q3)5ubi;!ETjiيVo:X6]|>" ˦ yt:t׏jLV#ڱcaLLWaSɊcj0 # jjqΠHKK 3CyiIbj3M]UDZkk  dx^aMB4Ќw&4YN!Z4#Cc+rHR>PKУlD6C? }Y$>nA?e\O/+:@A({;Z7[fNDC~C\ΫM~rsM>69 MDbu5p}jav>:-t0dune*uέ;5j467eU:/b|`>0MC7LA?ft6 /mxAjmZ73lKuld7Y[l**( NgS{Ng0 Ot]CMdqUEɴ0vwhj:`!A,Y[z"낎ab^(sݾa@۷c^~~B!+![fbo}|I-~l Mb_{rN7)u4: A`&S;VlM88JXٺc kkXٷ^GQzwx8ZVȕ֝JKg *inٶ>c--x*,i lO3,`1Ue "4k-;;G&'?uGXlCq OuLH=֮9lx|_ܽq. A͞ TӉ !"5Gj5'j7L(% #1ܹF[]u4aLfe˖CJZ&u1!I;QMOBUEvIo>ۂfqUHNVlHA dRi;xD Kd])wa5!L9b¶-~ǧE6}ӋJMncyˊNFZY1ԶCom<}alXˏ^~f뮶a_$#}il$ }ȆVE$HQ@(k+]KVA)YHax`0Bӕz{th$*20=~'.  ±tW[oEk<Ͽ^hrcsR,˼$ 8 k@ F`^J.&$cm-S CoF,W*gW<>[-V,.vwo7UZBLtQñrs%Y֐c5PX If_̾7>G`0T\+Lڇ㊢kQNٿe`&[!I &ZK6>~桑pԌf@*jo=;/'uZ0l65 47NϜGⱱG#yd֎*_$s*Ξy1'fⱫBo%3tu]  .(E}m"֭Gx!V::wwtJ"1I%Ltk!fO5P%K~JN(ls};zՕzO\\율50ZHJ]ޱETT}-2b@Qu0QNti%WNbw>c C1^Y-WT.r,]&t]e(s:6jdkEb-*N $~_7~滏 73ݱ v7^D^rm 2 P %YDEh:L$TF0 2Į^ M}t~,)fi’,C߶;nR$jP{wm>۷79A +Wz:/| ˑ ;*J"ux]vA5]sE+RQAf`0B3Sl TuvlboW*::w,$Q9維G'.-2}ë knj$MTh$}36OGE=M,Vf<]եTnw)E1mp|EW4ɪ57BN;-Jj}^^`0ZJV_fs&  ;.LO h|IQfX6p(/3 R^"Dw;n aidncnL:8l9 aWҩUt2s5ض(WNhJ-[U# 2JW}n:[+MӳsmF '`+3E ߒ،Ls\q0/qUUjY23SE r+=C L pD$j^Lt;-]msWV=͏' e !d^ ǫ(S!ko\ior4:hX( 4jƜvxo#\*$E`5scXsE%ġtDrE@`qGo}|q|f ӗo˯ _}O 3WrB[~W?ښfn~3qUM/jji_xMd]?}TGKO_Z1LilϹw஭$ =?1@z|bn5v m9w}Z77{gVaX1־ζ_ ǰUo~MZN/EQQ:QkYn9;nb(cc~fu)^J󋷮jv;-A5WܸtflOh(cŀik#Lcs]EHe6N^jcp* W\ 6|e=QtbifxQdOy+v(͝u6o>ڥ*:[S (bK0@ԬlblnMӲY3:%4j,r*u3W8ӳ6LmyYD!hC5j Y˧.g>o~v2W%'f_0g/-Wlw*n{ !B Y_pMx,5VRd;'f ah?=& 9| Gх.`(5u h>5N9eD:?tX8LA2$3P ^A-8UBtu}xt\nMj-0`*%2Zl4!(BThn͞#1r4ssmsʲ)Epq^I2M*1 %Eg>m!]x~mN^D%]X4]!JFc;ҺUhdM&t8|MUu>7ym*6fe0GKۮP4a}nd4rTZ;Z-X~ CVUqYEIx}0`ol?>Zܠ)/f[`+|y"YqDHؿx'w5+U$|~- iY*5{:jQ5]N&ܨo c%@f 7woPw[$W'/H7Me#l<\4)$RMQdk/Hr8+|ɣ MΉBM_ 0ٛQIa?|}dzy8K5C7:ZBy3Zz2tM0f<ƣb@l(+o~Ӌ>y}f-->tdCw4>/+kq#=9'|,U\E, AAnHku&q)WId򥁮t[hAP X '( K}rtuziYնt-3/s?q6"P qryD Eן_]A/KfxFXr->>;?a\ww}|UDJj/wOnoJ竍fm͞Ռ(@9Kafs&3l3[iEH~Ĝ%IkmijN8]l QZ z&.Z/MBNW33KH02_wM nMNQ4Tl<[Nc0ή}54t) ||gŢa[6Na߾.^|]7E8x콃e385i$Kф=Xހ!O`fJDbX(hecB!O7MÄHA,ld*$RiQ`vIj]aTM n QpAQ|r#WeY,TkȹAQ =!IE%5`Q@r8޲ZTg(Ƴ^`,zqi, `&A]&a]OISU,5dsjS`룟1fqttb(\,ymlwGRAj{wO_i Tw[s4./|+S 酷N䊵\Y"Kix47T"o~a08^[jˆ:x>32 ֵXfx(Ic£?;%PNk{ttq8VRq;{rE.JfX~TMw4C7({պ$4>kE|-xBv FS 'br9@KiEC=Ns>~뒢w}h6*RM&p[Ngp߾ߗD6?)~e3&P,VXS';]3F ]$KxgȦi">Y-c.W߷bʐaL&=U*qlnl5t޶B!`9Lo < #oon(-]̒"D*v[>_AP"F vHŧK鄡=&$]T J P~d'Sae ð,Ymn o{2ƹv% dKH#t򺍆~5;-*WP0wzR,J*]M "_ HaVF7u=XuMk=u#YJɲ~ϡ=QR~ M3]Άu(@O3Kպ$О}bK1s@Goɽý&"!#vYVxJcG\Y5MM /mK8/‘}m ?|4E\[sP$Ujb$Ÿ}FЪTVR8ȗ 59뼲g{D4䷐3Iu0!'IVH={BnT뢕V#WuԵՙ|2EVYO}}7e#V.u]ki Qij \v9/SV7]0FHE玗(wlRUTJ| .M4]丒*+> U\<[cyU9-(+Uvϭe!7PhԲnh7/o{k63 iQқ:' J5\GcYd|Q\I"}{/4nn*UE9LMiFspk뀪*mmCMb)S,D5QO3Iij׉EVymEs&LJ(u#gM@oX~=賞/UoXVl! oJe"WCͽBYb8]DjFlm:55|Lk욜 awZ.Oez@غ;Yw>|ɅJKdaOo1snY?===:-+Fn|qf|gŷOL̯)ȗ7]en^ɿϺۛRӋkJGB]-R v>Ӂ/{nfO-UjwIzxHƳal`][_ɗj}N] 0;z_?S.E`~6kO:H& /\_E`!iATrE”GdE^LTji"+vjXJrM.U2Q R˛ ζf607 qZa)ѭLTIZS \@̙f%Tm3 K jA-PD8^ mlaՀkeG]' 45sF\+/ (C9^@t8a "0)E 7_gMtfTElU4ajguu6Na2RK  ?vfչʧ0P-n<e l}nݺYAeL.㓩lBn^B.]Wbq]-GE4`4.skN/ ]yȶt̔TV F><3u[Cd'g6*bdf8ʊzya <Tc$:͂* kT nxF;&cSsJ.Qp&0MZB(I`EU]2yi,by$+2M|=hAjC"Bm@5WXCb0ZUJdz c87@f3KiE`loW"Ep::R\S٪h9`D`4OA0oгkci۝kk^OIT^= HSM^UdY kQU9D[T^L CW&wRp.Mk Cy0[LLp .㡀{%Du׶L@wha-#:A{d?ciuìrPW>XTs(fl6ǚ59_ Nf"'~an"b]@Zz?=`3/տ?Kjq5f* DQ# 2W&lW/=vD2W y+q$s$e1MXŗ9rmzP{S 34n88yy6-(zj4Ug8/.Oʊj{#?yóWswN|{7 =Ξ|:[)5mi j/޼aDo^d"]FtELF9AX^7{:sW  ӟ}t|=̀B^`_hz!W*{S<䅅rU+\e U٪M.ke(`ֳUn9\lYN,xj HF3eUH&ٵg3NQ*SKr!"> :e/9M2- #=@"%L9 -H-5^a0۷):Sܺ[UYN TPXuD X\ n^/b&|%~R͠(}4L :7z4ĖQXɗg'x 0ϳrD7;ᥥSEpعa++)B1|x^U\vuul2FZm]{Y6P,⌮Q$%eY;T5N S Al[eŒ̰gkp3RRk \ /HoPsS %kۆ:_^54YN/=΀׵sCT6l9-՚f/?W$wo1ЮB1ϖgK .jV;02љ#[74%L.m{s86Wzc'ΌN޵*O?kf!v2kӑ{z2R8CW76ûVֳ9M~s{M@ 㱣eYMQ޾ebnY>+8 (/CV9dՠHagt!,h~[Kӹ>s Y#HTzާIt[[.kBn~iy^2>k* /3ͭFvIΙyЎqaT7:X)?+eQzNnzM+VhVu np:10z`'첬@*Tr.KfZ- uݏ (fl6 r:螟;]W5%:to}#|Z 1BD"^e].47dxR)qB PLI^KW) Kx.%w[ә(VIhv+E`3/ M~fj!_I 5_h:v~1̵xgAA5W]+Hw)F mE`'Vrn'cч 84quzO_˕y$})t=9O+MN]7C~{DE1$Svz}>v܅;1]=ۃH ?\.E歛|dqkx.иz4YZqpכ>X6 8kM7{m|z-qlHf ]Ztl*\}R)Ymn2OPn 4'2iQR 0x: (}*eGv>MQjAZj#,# eY hڻsFw3 s0IҒHwvqfaZ<%EB][+ٲne+5Nsrb,J'geY0f?dw7nܒA i|JhHKZ1ܯ*j] xCt `BDx=^ʆY+_eUIVL6-AI`Sh(Z_{Zֽ?;7=8 4141wuqlZ:/$fW3{s+)YѺ[#an4"wuA\KkSNknNc]5֞ķ?PԶtpfQ 46QLP2E~^k}m^'7jS Æ$+?ydrfӪGoűj]je⹫kL R,K, 0BUp%{({+$ Jco|)x\M+AlTSTn}#VjDžA򓇞{…뫊Z-W0pTIb y^Q@`vKşE?pR)Q( p6*Iijhj!Rai"\V %Ei(du>UU\h&S֡R)(b\8yYa"0`j @[?`&3Q}|6p:%'KVv75:7b"`fHALEh1L&bq:Uɭ~dB=nA1yV40PLvY5sZZ.Wv߁}O^}jļi~; 3VKe {_}p_PA`mr%H5j=;1RK֭5Xd3QAݰǭ:A5Uɕ+,;sтGUSÒ8m{{OGU)iHL4w'ӥHqk mC~{/}q|5-~Z Kdt75s+Z@ -JEEirK^1~xZjA~G;]71m_|gSxA:}d 4 *o?DQ||n!B6j%ij<O(VA0nkja-HC?KzK'w=G☨h?y]X\ts9+U9t⼪4 \պ6dɇ{cп{O4$Pdn%b栓ZMR4/~L3I9_dQ8:'`gk*n nj:Ҳk7 \(WVV.]lP2 5-}["0&u'RsȘ4㸢,[۲vN]Y9kyN 'ZI隢ah!p#UK|-+aK)LdEQUEʨ$i)Xu'RՍd*&&"$f V7M' T8& b<~BDP&,Ã{xRRdiy[0\[T5k $uM(74eLIŨqk5<ˮ$3Q Iè褅F>D/}.ECpR`_Ð%̠uj;qaqzhz\nq5[9"I]Z_|,Bp>>08gLOg'[%ef|r-A*S4㛟=c޿ j p`fWs >(F*~K}.3Ż_[i2S`KZ4 {{o +al *)?qZw Cwm=suRw{Z,H=uSaY±Enj |XW#^?Ǫص=w2ej*Wgo{#<+cGolfϟ|+k &]\5F.;"F\%0[d #A??ѹX*;_xHMD{:|4ZIn Maܱut"***sk_`!*kBԅKGo,gu(Tf-ݶr4({_zch4Y 9eOTnA>iN$+8N9cELDŽ׮,-ue J(ʦj#t X _z=G!Fbx u:g<z`++T)U*Wp90xi҅n'm-\#AnZ  Ljoo,WU)>V,!,gߖ;}|>R,FP8x*׮JRi-TT=VM8:8 LX߶ |>*aBhS֦*Q%f#s30b4$tz1kNXI [Rf%:ϟ؎NXqª([Iҋa$ÚiONtxvu #>~҂JJEqft+dweֶؚiE.#iD( m F[r?{rקW޶Uu SooN-7~ ;˗u Kiیc(: 'n8v9++GM*dz1zybaln-y]v MͭDZ,-3oq [lq={;Zn>֕h:}pbUH/B0޶EjT#\ڵM9lW44Xflv]/>~#b*UIt6 .Md"(&f4xu*r酨iv+Ff!9{\L9kˊh^Lʷ]J6>@`F&mͮTHxb9V7G P5 KkWbhd^K/-I9bal$ӫ6+#KTRqUM8\];{z4ܝ D4^0A0+RI-wm9I\ ru2ٵ`gc!hf92}]=8`X׵z=kZ!xbq"GWWGru  {J6Xg.A,Aqg\쌮b~ziyL/xV:u79U|Æb} ,_첓\Jg UՕHd,(Wk$[RUx|eSVtivb< Cm:F剹ZOJPa 0뉂eY))U7Q_Z~mjTnu@JγUALC[: A'p mMT$Q-Kn{oLI/x}xׅkaǒʰ;u]I8^T.-0<ГO>}~C??s^_ӿ}ynkT8R-R;Cs6_rHg4UZҹM Rgkpra8~bGR8Id_~ 0u#:[wlO_C`>icLssl{_yp?G3$~zǯmg)x;~"#q򬢩Gv`+ =~ӹsNUTUik~9=N_;AU{Lg32GJ:|,|pj2w>zώ3K'dgaHEV ;5tpז7>ʗed7?wEb0lsI(&:`IyK4 {r SҒcεXL\D+gН{.O' C M:t0Ͻaq}_n@8>uy"/szla"Jʟ)*U8].H`_~e Mp;[{^][_wA~uKUW[?W{/:+c0!wnſso?pV3<Mn}8~ɿ}؟ן֐3Ss+Q2DQ0d9|tnع9nHSZazk_ GO^?#+ƫx%HvNy"#MM7e{TnkdE].+@Qttlnںm~nwk&!'T$9,JAVT g(ڒ+{zX/fZ7 Y@LY.k(\:/;lV[2IiVS1$impnҥ_Qv{z%`l:|4 VEtr^!`^64'4^]U$ha8v:Cz$:UŸ)d\Sjr%b #Ji+ ^ut}T ]e@(Ey:zkX%1۾DbT6;β [m\#WNB-Ko|fr8#2 //y`˾_1 {Fz:pj\7.0$H*џtHYtFFtpfD+_HݮFWL U|X 恤6 UNn[\ Ai*uY5vlmqJb_}3S[v;·>PW[qDI_uLJIoj mƉ/,/GQ\1 A@s>2.(n5>8|ZQMS{Z/ͭR5^4Ȳ,+c(&\L~z18n;o<~ql}{+h-O/^]d ]F':l+؝ۚi~q-b8%h.ui-]"0X~ƹGp~hWSȗEqeJ.T 0 g!v'PU)աPFlҥ5]q[o_^>^x߉aAj 0 oC>4MYQMli V!S)gfR㚦P*pfe:;(*]B(_feA-80^ jal+0PFR̩:P$UtHR4G/"! Ģ޻ݐ-u߽ Y^PUAXXX낮s/y,(b}h*$ `#6h ]4:xm\lVǯW ){N;+q2M-<pR&|TSUx$=:}tvFQuv?vOA /H&qzxz!TG6?_ q 8$K2۱ Av+TQ4N:ܾoz@QFO8~{;G- ŊlyA^:I7rӳ144:`B6dYlza{ȗ^}0,+P (l¹B/F0`q M8Jǁ.HJƏN.\^1 H CۭtO[p֞*A-ҿg޶;KO.5썏3y]RB:4P?kKwg]HHrхՔB*h$QEmPs<ʪ当S.gHWqTXgk@f&}=$( D 5R&J #*5NcͲ;aPHU%q<ʲs/rs&+vPGpRj%50x WWn`auN9eb.vYaC`ރSLatVB=Olfi|ܵY/CBb,[,~YEz[0TUflq"y\h"i X:SFf+pt>TAUxMSIBS4ǕujnsEUC҅VALcD8_4p$:4&fc='}7'{:pԓrTpe=&,FDUG‰&MF,ټ0q*u4_y-(i AOCzq-Zq QAQli?@7~:W>ܷWMg;4 쾶=Oth'Z${n?wu-4VӗSמwso<_ñtj5eJ*UeU%P_eo?).;0XÈ#ml ATO\jG ꍽW퓗:sW5cd6O 9&7G ѫ+^.wu.F:Yښ?|vUVElUEHj֢y}]/uƉ5ÅrieaKnz!~`gW^'BC48ڻ驏,o +B A.O3o[j7E}3'O miصtA3k{/Ʌ34!,Ϳ+*i\N0Ɓv!սt**D~#>8ܹq--CQ@0 Pdf;vܙχy,Ԅѹap\Q4Uj1 : M>O ?A0˦t]@fUMj)`\i;IZv1a/@͸w|HUŅsj~7Mx Q S$Njx쮖h4YZȺ7o' ΉYQMUA HdꛭAУ "u;f *46%벲zFQMI)/4@Rt-k3Fh"z@#i~#"j=Wd(úg[ߕɅ(i8lJE:{<g*khj7bR/=:q˜ 9< R81:/u,4Vd&whƻq];݇vm-*\mjas-o~6sͯFrرumyh\:\ 'n߳Z,^(UGxAzյXje=\O[|鉇mjᑻ/dőV"iAAxZ*W^|bU:ީZAPj4vxDd: NPgigs+tC0f!ٝfb!%IN;YcΘ&n3ǹz2[s8q 8ayueAku6[KƯQUu]nnH&E`4epaHLYS9 T4EU:E9:30P7Y3 IuUVCaX63;.!m60J%#K5ȵkCCG}@ezY B/ӢB0#Sɩlf0 20NMbip.+EQR.Ȏa!'11 8aO -ʲJ%b 15+>Nv}&^\E;e xljD=LyQe;4nC> MڬlBV!&Y VZʊc)WO21BcNePXAՑBi>i<89A2-4,cg}_L]]pݓ.N4}yrعkEg E+UNcɌGw 2Fd6Їg{,4Y^P{x0u vS =Nkj4>h_ ]V`oGGs`r~Q6k3>b C}ӋӇwmAQ̟a:_0 0ߡr8ZHBOf4X?<{=*"**EO?pG:qa|?zw,N-ZdzB4Mig Jvp4*8jHਕ!f٢,0JP VD8:VgQӋC9AZO!?zt͏'W%!%-PGQ,^/ R&Zp27\E(Txe @+c|nEK-MJ"hr%]>Mp,KhUFTyU95 jjO$2^aNutMӨTBV/ESXZ݃wݼҲ≥zTaN-ܸeNv|ݍ0e3s\VI51\#tu==m8aCP|,傪$i*(ZBv%ZymmMTݾd'HCw: CKᬪ79^zg,;]}tCXSڛ$*Bzu]K4A EF'.//C6/ݽc],s:+ևZ&AMLݺmשgAhs&p!HjJJqJb`UUי-- uK |{il3budkO/UX1 M~ c=gZ3{䎻|̕_u}q-ΝyBKxW'$>Xq0]Gz[^)8 1XQi1ip2Jak(unA$ H$jaVs`(gJcx^@2L,=O0%sf13vw5NOO3]IZזھ,ɒmd̳;C;=̕IȚޙ~?Ik?W莌8q*/"Iniӹb M(Q$Q C4d#y㜦CC'ۛŖBn6U2 v|DPLWf~k1axk1Nyy+R1 7s%`5C x BJv޽)PK]n $.\d(\k?_5%+[ǷCo$5RUȊ&z"vxTx; 0 {챳FʻqCWj,inO3yXK2M #K]IAHaE,vb_7ϽI⸽ɏO>]&eᅳweh5ӴM2DD-KIod$U'@!7o_ZSl7:̯Fm!rj~ss0z]vQa˂"JLfB(v~'biPVW #gƦ(5J+<– <`8 M\Db'm&{IQtU⋗, 7~`5MW5qD1;!Hb0v4raSQ^`s8!rs8&[J%~(t$#@Jvl__NfR%6=.F H(KMWÿG_ -nf L1Ia4]͗Gn;6r3I1χo6&?_x(x^(_"ɲ" v8r^$ Ǟ}=bhPA EVy 'HIۛfX2_oXe5ӹV>O޸~/uϿ5Nj5^Xߍڭ<[D9S(sۏ34߾{H=%c'_>@|" Rhk/-$)VEӄߜEckpro(G$›5^7PUQ%ŰI_w_8$cZ5wpqdC #'&~9/x`e<_ +z Aнj%i" ]8X*6\b^P,. @N\t݀?HB"ӁBjY58f1!f{L"nm\TMƞ[ƶ0@GDGL&a7cP(4acr0MU[Iby~%U3Tݷ]r) zP̚JnȲxfM-\\)$"8NLQj5-41ni3Q$HWx,[ʼβEATز<1_MX&8a2Oy0?lY!$x~fi[ rF}j1ij`s#@wZ_(7>⏿5IQ>Z\73R}WvBAdv3f,-!tNc}SX H}\4.gw7*'']--cbB:7X;mF{4iI&6rl |p/_)#z/=yEď^}%ച${omx(Iv nNfǒj Wg.3k&$\KDVa*(Ψl7=fp87d&vz{:&t K :GU.S21̫Цr)]fqM&I,תk?@Qeq`TU"04E'!yE!?;v@ZG*:Ybws9Ua`v7Y,^Mg_qs|9Ԫ,񂤪\( jJɋDHx d%N-V-7_io?rA _Y04|>WV(.5N,#mGaqonh<(* fs5Ӥɥ`ݚ7.kCʹϦ!l*'!EUc&jo2]&EPbDj&WCMͯ%U2WYe@Q{}?}[}{}r9L|bqPhbyc7V/ҁ Z'R"' ?}R^4I'Ƈ.{goa3[o s۟{WKŪ4d$PBKp:_2/0($1sP~b'o̴W+59ݤ A/X,$ДD^ݸ8vr5R7E zmMU}=HRRr?[M7t]S5)?{C^( $b}uFW JfYH.ӽ+;ـ$TFг'B#,8x51"0]wf?9Y1Li[gש* gݮ}bXRR5}cYP%0I^QUH-.WCk; kǖʊ8FQ&Br` 8| jukcS_Q@濙Oѕrq@(mu87jB_Wʕx.WwC&$WfQ`ʫJh[c(A fWq%{"MXVFLUx}>UMrY$,pښT$W,u6Y4"Lm2^o>w)&}PFZ)6)86GflM'j<ÿya{M6+;ᒬ1*b of9|duz)LPOQU`C4UZPL qf0`| surzG ?3ۗgo IA+5ێ{N*ˬaƖ l;AD|R7cYnݯZ{ō}}gv*sRXFm`h(TkH钂jA;C|n 3 niIr¨!N{sg[kPNͱ3Y,F_zZZ1 U<4tLWZ[8^t ^5ngPN߱hbXEۡÝx)u6AMM& *˛ a:E( sEsԿu^}䎶wlc8jP2n`ˢ"k'yV*[`" cQJMX H{{n5*ÿ@V}|?FuQ2Ǿ}yvԽխrBA&O {:n0DÀ rL}D&K !hюf`Whǃ]IR;JxէP C7TU>@~,#'Ox.,~xGwcqcraXݧ~z&Fv S(W\O{=':[6.\_:slq|6Y/'DQ" ,mmSYQ#|b8Ãp*W$bw"ŮVo" 잢&(Ux %a%OCh< 6zmvof%."F`i't.[n+0 `C([+qy*RMp NMNW"U !( yrsPihvԆPcW^BbvL;I2na ުV"*jb#{HWdn%>\#F\WPBѶcǞl*ٍQÉ7=n{ dM$7tCLZxÖN3 C $i>謢 v3iܪÊ⊉%$ŐvAKղ, .OoVMG]/i^鎓] >;S,6媪3\t Kk0@[C_D1bmǻ+qj̞hƃ_VTi%x*(A0$jSE[(U8}ʆp l~PGG׶sJ(ikMW߹K>>cve3f3¡>^_9W;2l貉1v솓\A   d${ @> UbheQL[#LఙuMu u]6*Fs_gK&U1H?4}t7][Ɩ,ǒ.Mis;4U *sُFfN|3rү$D5]("F7M,,F5ز"164z۱խP-o]\:>\,( _XY1a(XMMmDl[T F a^_O_M#Mc_tTUXޞ >%lzdv-~&|!;\6y~{*[ٙT@`f(Sjl;DIe+TrR @dZ(qkumk?v}`nUދoNf0AߙHleA #]@,bˣ(*R2xy$-b==d2{}} D> ڞ-Sq2]ޭfRrTTЌCLnE-G=>ƻ[ICRU%ÍyZWV7?si7] }Cb-+i([ٕ)ZBh>ֿsujx| =cmqT qX7/\"ePn{+sIe|}'DSia07)'h2RTEq=6`P CR+ E*?weq֠i*ruf9s8"{RWԽH5tX)`h$N-n$*x]';qٓ|~PO{ё>E5&_-*]- 5}WgW;sTVj˫!&|R<ջxO8^n):]Kj\:ݡ^oiY19Gh,vZ R#l9ߝ =d27m)㊢|Qvwdw4i$)WVX^6Gbjl (JjY rR!W, $IY[4EC\.( rvwwZ 1ElƨֶS$f <1B0kVMg2[0jGV_mtvu+ku6fbN 0TM8hj9wzRiQdݞNgSyXL65 ͽZ(D;:uwp\)>dS`6(K/$a$ #a jlWƕx:!H Ap*-sF!`Q4C5bVT+)/TZVj&]- MTUǕ!C6l),U[&GZO uu 0Jk:(oX.WsSb:/Wk#gRdbqsێF V*>,b;<_ \3l9]](HRjop\RrLPջj&4wLpaRVII}JfcceUCfjlecO\ud ؃"ЇTZRWlčѺ32X\]du:>RƋj*vmm;ŵJa++[rML />s[ۼ,%|KH[(>cwu`("ʏ_$\-[hvj!H_cs+aE0[ +\iHBTh3Ye'\W<[Qwފ"/}p?=_~68К0@"S=uN??Fķy&8+ti&JZ2fVvk5{NtE"֕R)[T{ۣLs\/=w,Os+q=~hޕuEe%z1A׃=\:_F`6vSTS5ɇ~k5 ueS, QCWu]V.TU!EU TFL4( #}vE-xP1 Cz=z08"5^T!ΐpđIJ(:WXYzM+cTU9gaFQ=Gl)[.̿06$`n{l q46{؄Ü1x =|X$r:>;y}󳧿WLej)EdfT.]2_RU8,vkEw0Ii̔z׉TDLVuCUf;:45 lYѴfA0qDo}Rf0[n?f0гv6S)Q%^v M߯k:#l.k1FXʉq@HY5F ztX#1s{ˑ!pcx*Ȱ_{O܎u`>}C;cg{rqa5}ggUM-E|d%e9ʕ) l6+S`Hp2d8t렻;9lx|nӅɭD"H"ɅBb*\̯Az\)0f(F+,14]%llml}@C Td8|#&R) 46Zn7X6ܹI:L-5{WOjt QR.d/J-66׵JGי |ho*Z4Wubkr,UT@C., r$ <33?Sbm@L4|#sf{0eID$Ib@jo7Y#eq9@{15UbEXQuakx 8ʥǥx[L9w(LXdT,D{zȀmMˎ&uŠ% OKVgG ^({AՌC3o^emB6[ي)—\v[(2COb*B/}⾥~;0S,UC7\kkKItt~ܕz f!pGQ?=?xTZ[gfys(*Ɋ JN=g9fAxA|:Ųއ!. _yk?~su{A3y]慵 sd3Ǐ6b qw6Q.y#pN8%IuHhnMVp͆vw:G&FWe&u=-:]ۛO%P$e)y4sxF?5S'JB^Us}ĵ{C>w۬L(48Š$ByTkn:q5 .a*EߖIJWMh䌮8^Mjz}y=6r[[Ӓ㵷~{O.-HUn'aIWq:۽˾ƾpx\ "ȆR," KXNQetxlU0+'u|/TYTM exA`0Q0Lon?nLhS$r8)9y+ b5<*:}dfu]YuD= 199:w[P4\)Q @:=oz܅rϳ.M9,pwA t2ywcq'_hT\0Jœ?4'n0Pw3n,6۱$ӷʼuqhĽc a,CݞZ\ZZFGodglHTЖK;ښ;)I%I p}d ʱѦ3χ⅁VVOsern{|/dk/ FvosWf,d"9vh#;lo,xNU5IQ]FU3ƞk?u_K]͇z>~5bLtݖ"[63Hœp"fo;O^%ꕄ W+b@4M;>p_?cb>[(-oe׶FzR:[MX*[` J*W8mFɜ*/j!W>uz{/)f7di'p:iЏ ^q,)kbxdFYMǎlv57$U M\}]Y~-S`|.) +p&+Mfj,n%߼谚t#*5!6~0T0J*0  "KS+k;߼su4MWFypLԷ$O=|g}FL4uzbq(` N yj Ӄ{uvNI8.I܋fj^ێŒe7&$+gwM-6 ]RPY.bbgF2Q,Fi\*5 /b͆^Kė66.EӅNhoP1YqT* cm>bq8(+BxAPfiIfics*\ !ݙ Qqbmm?68pkaTʊPHe!zaQ(,Wn4-'N|^ 0pxV+453%fR  f Awǩ54NQfI⊅h4Ln2:<|IҜN]ؼ@_ӟ s6kvaCՀcstH b"p_nJ7o{{/TŵX{{m'w٭j$B&C/ʊ1ÑdfmMbMk- Ì{mk|XֶЦ~N&,J+(kFM}9AP4ƖgNGK+k?~ϟ9͒BD vw8 2vFXUϯ#WfB‡cl( 7V aV;AStPo=Ƿq]]])U8\d\3\85Cj@9e#Jχjg?vs}̯s񕧿[?-W+3<+Jl`PddQE1/~s-4I(Zɿo_\XUU]mvɱґa3ĐH%`hYL&qytG#B*/J|x"UQ,Swbi-Ec%ab,QCzQ}?usT9O3((RRF 5gGk{sWFj06v,,P %=|>Z,渲"22r<dLjI5;F @H %E2?~Ę@`tEy(_Yyno?a$tEʧ$W`mnOOxQ6r0x-=㋪.?(n΋Px\?:l?4ԸLR:ehacDQ ݫLa=յDG/\k)N։Wg47 YA 70Co[cB&TaD yu̟~ō5m#[ڈڬƻO>(ީ^:_.3uO&2yG-.v9||bu7hvDfÃU[&^OgrY'`40S*Fm~3ɲelSvWVߛh |.m_ C+L\6ۭGݍ$}ݎ:_so[G:t]W=C$]0drnnD#Ŗ^PZ({ƮLH&}#[^~gxN #M&+|h6y4$(kD<&Rb dY6Ufp~X\|#]T>My|>Jb,M=iY,b(FZi&tL,qILlϪFBf q; 0d5(DYInS$0\dĢ"ʊ`pD*5n twEë˯@` r%g`y^[t7!." >gjh6 -s[o|F,fK#db$Hr$ǽ 럚[ٕ} }+W6eY}#%$LM~+H-he 5 Zي?xpu,/$I|7?~n$QqKIUIwH}l<i[76֕Cu~ <څZ5"}Y&ךhTO=pP_[ ad6HxsW-H+%#};  =>vsA67K7_e4|@1H/zn&p05(IXDfYww#(r5e5S^ Gk=;_KX488x'ׯ?AcOr\)[VrJQr|e&Tr `kIBzvGbTF[Bc/A*xf~%2>"JJ1kۗ6b_qS69m_,u7U)6I>e݀,Oe@Wwi#¥Y ʜWx_4Q~g9Nj8@ 2/</"*$\o;>zef-,\u4{,&^;ԋr2,/׽E N4A!(Iݬ^tc}eF{s/~pa5^qBeE؋e;D@ M_xr* ܟs*WH\x* \EQ-/Tj͌ylFǔ(iaB|tEU8E$"݋%U![ZQT+qbW$1Ø( OI(eqҌ[-evov/nk7Ѱ PhsOi[ZznErZnd ]^pKsSCXLpM%(W%,aT)vtL oT1Xپ@jy032ϳ,fv*T %"[j㱕tf{FH@k8ql&EղuM Re嵶F(2bxZ/ FeEÂI+4m/kkv "w"&6b5/k䟃8w?(b O} ^ +WWOquf|xrj柘v|?IǿIa2ũ|uG>~|OwaxUt0GG6g6 Go[+; tAN8qjq*O&XXom1hv0ɕBVeH`ۗ;OM.|SMݜ ,Z]N;C>73ˑ<[Q )$92ՒHwv:4r"lѴ]TP%!IUyv](L&M[{ד˚V2AګUN$U*K40TIC@QSx:BrSLgY FƖ]Ns\)U5A1X>_OS0ø j;BMR) ]wX6u18qDb MS@6~Ajg;:ӻy].#d> NA"5]S|ae6&S(!RbG=8tOOjHxnH{SOYOE#sPewq8{שqPDA Den5U0[L %BH@ PTN7rڳ/oE0 8^d̦/=}Yw'kAgA;ZPd!aov^>wBH:uxo|摯̻ח0?{NjZ }⍙3ko|iW|>SuDa/ܿ< #i>XLu6nɳ;C懯(y0+uio^k;8]]]XIdr zݎLda;sl_~Ap疼N&W:T2[iO7 CSl)k&&@wm}yall6t4GEdǗW_2 t<)DKմ*dk-W`OL8'w4{6)^uқwC[l _}O?Kf3s尙[sNo$KuWei#xƊCܾcc7Pj gBā;7dbb#PMTbYjc7/%ٸZ|gv(b"オ^[89Vn?vt~5r-x&c}7|bIDQ $n2 E1cl~ 6fn8NRL&/S&BA#8Hr3:GO578M!>2H&7k5ia.W߭)\2ˋ C ɲ,|8ں 5`8Iog2[^2Ld3ۙv>fw5M1)IX8JKba\> p iy X3 γN`Q(e';2coo>XM%J唬l1Y,adiS*3]%I5U !c*\>i90B|MZ 5HgthwZuMP c3+q:XNf\M$$汣wlJ>(b`O{73Eʮaڋ61[{9ED1KzzN>? l\ |3Y0,CPu=44Tc EYGFFTQę!>|1 #)\,ywˠy<=_gCrZ-/V㪕Jdcjim;2<|XbTa6G`rSUDenmdqcD$`UU#`k<^ u4;U86T E2>ԶEp+rM.K0O?!IN0}b{}k3{qkY Qũ##C`8@3H>:[.E]،A@!IVaaam-[,G 9lm^[\_|N!CC=&S9vDSnu^6N8yPxyj{d9Y\ߞ\M0_Q4i7Yd"8eL57s{B./ۆ8*U^3 `y5`8N1&> IS.5lFQf`zj5u|yvFmlkUMYXE`bMMC(@I6]oz[:C?P$S0I1 AЇ)7KgI [b2eY4&˒"k:[Kx;;1NW|>NLn5EeYHI(dfЭvP(A@jiX/p@YQXb=Yk|r|#XDtt3$0G_7IIEwu;Hf#}ke]I(Ue82 u U^Z OO|@2  \QTU e.b|h JP}^xs~/V%)d l}?f1R<Ϯ'.M-]߸:f.,𢱼n/$.sfy A ]ShnqI^/V򹝭ZAUTp劮k8NʡO jV2+&G ^cmv+nbvŬ憐p A~'U, >Mq 9Qxd"Ti:To؉FMW+/㊢4Xڛ9BQ2( gu2XH*+w4R4+Ij<] NwN2յ_6h>aHA':~H(^ E+j4:^6/Ϭ-VvrLph_;Wn,!(IyƒT&Ke6XZUk/J[So_}:/JS-G]3KbML-mϯEn,/n9XQSmv &l:_&q }đ;fDImۍ${X Jeq#w,o\vsժ`d/'N~c]fG{bd!]b k@`edR*Cj`b,WF&r8GXh*T|2ƦR)Io qY,4x~a^_]d_-7]͵WHhͰދ (RFYI]kETT ϳ<Cx`l{/c>MUn,ģX^&_F ~(`v9`5P)db(V@`8+Eoe#?&uDխP/'h |[&_TR!ah*Id0`ي01 tU,Di Z]\x@nD"_1X4 H tQ$Ld~2 9 C0M ia5Et;̼4ѤAJr $O.Fpw|;/^0nV5i|Oc\Z.D@{ᆟ9JM)&j5LL4 jmy./*+O cvzo82x> ᄀ6OFͮr9qN&jPQuY<ޱ"H8Ng2{BT߸=("*x>BQXQ ֵܶ=y[[}ƈ9fnSkPv-bjMZp d_$QH8&>ȫ,.J$Z8'(*'vp}pATMƉO=p[}5SsuHCv# EռN O}d {1i\妀7?߇#o^yakr[(DMC雯7,YLX#p"w${6'L4q$ˏukM,F^_M-oM)8u9&wcUVe;r䱛=jh ^+:NpScI3Ǖ8ZSPMCR) 75]L &cU8laRUˋ?x`;nn=='hZ^>of|.BV8S' ó^o/ϗ(\tC5M Fi*UaOL>f?>>y.MztҍPWί*s^k&f nz;w;]EQxzWO7/vBG AT+՚Bdo_\~c5Ta}'e `'9wy5-w2c;LS7~|EW'hfnZ[ `aLN/,djk#w@^}R@ԑ"[ \)}X.tM.l@)flU\ v4?2,,E>OgR"''H*fv }p[#3+[BF?+Vd ج8n"Fo2">1sРm?<}1 [d+ %_met]l?u߉g"P<'$Y^ވXnlrɠ,U^(ګ㲊(iR96F$ 5Q( 2%fA=~O>c6O;$ c/,r\hbljuuȨbTGCZeNyI\\* b H|#6[ )BRhrcĦ_uY&&ㆡN}i#>;^~#XGާ`a;Ltu- 2VD?2-G.Mͦ򕾎_ȣ$]3ȀfjUޘ[4vW|wbifB?ȝ.u~mSӌTxzbOOL98+ksk:rn_+{쾾Ζ`$j ov|\77U>qhhkt- mPT"pww]7.N0yίn_]ժt uU#FGhk,V,4) G`20shH+ ()r̐ln(3E-O2,6{SNN}z&V\47C3 pN<*\٥dbIi>_gSPSӠ I /Ua4 T7P@>׸4AX4 A@Vd {4Uu8[1*;o9JE;W)4+6`Hd%&`c'NrwmXv(F؍~vvw\8k97clDQ$PL<<]퍄nLhYێ+ p9i]G2NC+ʉJ|ji\{[$YɵO_!gf~AuQC'{.OMuzqpχdo_j& CwXX_ۉϽq!L{8}*H' JJ;ɳ/HΓ:[|nuMg?>u髅bs1"0j饝>=84D効zpcq]Sp -W;t' |BqDU b:5M,o84s;_HR̦ h-;xlVItBAb1&W/n&,[PI6ҽޮޏ|vQ4@C(W㋂Px:v?S肮Cwh _bqvrt6rzdֶq%_5\.8uo9ܾ87ehb}7{dqr~mc0 M-Fr'\Yg>OxTaa-fft92Xވe)`>XqE͔^(qO?tta51P{tf)tt pm6h@|nn(L^dN-G2JPT2|µƇ\GׯSF1^+u,0W_&039L*sh#%UUNCw 7={HSيpefX?_{D쵓~ Ւgݭ+lUFvvNϹ`,]D%O>p5k[X%P+4׫ۮϭN-nWYQ*~}tl \vVvxA8PL S[{JJ! |ƾ.O!VQW%ټG(ʬAXns@0Z jP m& PhʄʅZiXLHUeEfHsph `1 MYmK (3BNp<ϲIe2Tb9s-X.wtehrRUdłc8 /1XbPm8N&˩;p  -q|l99P%Eon9:0@iOg3DT)[L楍]UCD}mX\7Ѵe;:zt8=/2G>Aho C5ej~orI׵NwkQ6<76rl3F?r'{==tmJ*WknmrZPqrno8l\ٓq 09oXJ]v˕k &mb7>(aWgW6~ɭ`fZءގ: MS4ca?ͧyuDz1ET97ða,G#KX mLo\dVc%F1lb5 #]eDl(UBY1t㪺a4E{h3>~`ߑ֖֦$=0;5;824 #t,|6*k6Yp]f 2\QT\2 5la-\+Qdr_Qxj@{z|]ʫ!dCCebdi u]35Mҙ[eVUBbqM}&&GLnoS7wS W(Gے|4:lL(ˊKvR[{JXsZTvc!.U'=.[FhRd|6 E}X8uvBt#> -&ˉ݄M+T.#ݷ\Mݽa>D9ȬfD1*Kh"uhVe39lCz:͓ ;'o]\ڋR$zzHN8*^o/ |S|vWwB4EKcoE{djK+AHu`wۥY9<[?{`uqju]f~ҬL:<|dgc7|uv@\YvX͝- .l"LJ# \`w}zbcwXPKn,&RI/0 J:i2"FJ bV{Ko٦Q_r)&НM~߅4WKR:IYM?W!(t "kBn'ى0آX08e6[1imS4lc{5sTN+%Zdy7paMf//[u]v;y-9|';5^jR$8v<&0mfjբ X^zDK)U ^OD/j$i "c)adnHTj&ģ3bRTaPoc:W.8U3/oC7BL&zE!f\ʖ;[C= 7Bİ/b/O@0" ȔI޵N̯%E}V3q;v+[s"}e+ah2]eqgOtέD #xdfp ;OvwmS_6 >_x*QP,W,UTU݋%ي̀b)8~şu%˖-&{ozP$B]u}zڛͮ\R6W NB"X*KzڍE\nW"ɚ,4#Cƅ)>ux01һ:p7!LG.{(UV]B{swuzJ Mi?㶮qb8콋)]d[Œ\wqzdwd7='vbr,7uYb}H/h)z>|Ag=d[ ED&5:ɔ<{Z\U*w9[!'bfkYeڜZF|>;A,#/íx*Ew4deCdò Q[m5+srԎǢ̬ys,xEI0>H?RZRL6[ia⚌|CThR+,$:j0xbٜVI)d($Lbpng LFڢ1+kAʪ5M&cv͢ϰ)\_S~A}A<!R\  :SY8E`tUDCm6 EɃ#G$5kT 8;/Dcs-$8ݯP(ykMF=/*j)Ϟ6E1_8J27FdYH a6 dwJ&)ycטbh4_ĥ+]C-=#}<`2hˋr.Ϙ+p{$QشvM\[ϐeo PS^8|  6yէ.8|q>O4B8[{'L9|Yn`ԩ&pzCṘ\|h ⹔,FQV" g50~oAͰ$uRgm&ڊ?$sod|=j2"M@Y(:ڊ5efMH\^Vہ $;@YJܺV.|AeHb1O1(&D):CIE9Fc١pxR@ 8,-(3 |P$&_ǝ!7`~mqGXME #[z$/ }叩qŨݸ bVg}cQt +KF:Ӫyh,П7?M__?{IK J٠ ٠%\|(ʅ AD |nCm I5Le9PɋHS* Vv B>.d[nݸK/P =ibsԕ`L1i՘Rn~[$M}K k$IZƺ];Fje4HL;6磻 _so¸3[}NhO.{N03t D5yIQAe(:8QA͇7aw+@M`uU%pߞKZ  y2fDey3Y)*5dO2a#%&D!I33+a$-wZkg8P(!1`&~*јUZL}r╥^ hM tѨ7R$9VcJ˛DoXf+V{, Q``..n(.nFӼ Y0ѫR .(<rA Jc^N*%APTomlO7HqjBa\2X%/-0oXY{efі t}[ O :WN}z֍UGYr'p%S)fZ7^DdY Z H"l6z# NIy-%gVM5=t o|xget:T+M9[;/*%rW-_%ʒW-qB('Qrd2[MjQ?dY?cQ d53y7ai5Ý3*;"1 3 +0dn]l&U_/Li߽p06mXTZkOdaYPdO;p:c@A3Hy0tʲ %^RWg4fut ǭ @`H%A I@$S +p P)̬ 0J[ɱsLQd$a)4CS(4T3,ߝ <()ŕp X)Aj\?X oј :8rN %ܶwϫRY-7t|DZ4#BC2r4)b %/*d]Zy+`j4+^KRVY\6RfZF[}Y6+dh 8Nb:bseYQ^d2J2DBZX.vy#ZU%پ0r{h"q}2Lz8^#3k F[u*7OPt) 䥎1 0qQ+k sL}#l&CIAMW:CJsn\8M$Ő4ꫧ ,Ƨvn\j=y+I A$ȖbCl0äW]v fĕOʫH3yÓYtI=6j \s3 疗do]k@@(( FZ{$$2T~fpVO\h.p=D(/N+E{]ɜ _|-3k>0:ib3e6{KxBH(/Y^,\}쓶P0L$єBdT +r9˦X&8T$RȰbdX@H>EUaP:7Rqu|9ot,% ufU@`<q1\\d3Da F0"IǓIAUbf iEke4AQ4+0m珌Rc> $% i*/fx7N(EVM [(Q!]gѩp4ua4Rщ~ /B(Vhq\Ɉ,F-vO퍫_֖:=)Q" Z-J0kt9Lz"L03MƝjW$5zޜ{I[{DQkM 5եp F4񸧪$sh,'ܬʒ־T _]=/\(W3e8?+?˒HH8S8<15L3Q]hx>I˳oL2\2pd0f0]#×2-}OA+ʹs|k,N֔e=xU;o^kQ]'$Y޴vvn[;0DJ($w&c'ˋ8^fy*>jAPY9{>FhMahNc*,)Yؙ3&AT&f@fES Z#n_dedϫp<e( dҭe,jx< G.(+*EӃdLTR11RD7+ aeUfV=foPrkwMPlQwff (^ð'/5ݻ}NKt?Ͱ%RK19 `A_2fmœQdW #;(Pș.+b!Hd$vZMjpPUJ!*a*A 3F'ީ6/vu91 i qδZ޲ dQt( (A,xY(Jy'egLK T<5`sP((=Cc*j/CXpO5I(a9N¼Y7;єAT9y0ǤX3tzCdô!ĹTT9'RvnCM KAڇ2pd\%p(h=e24>AQuL'jz#XF3z?gިPA ѩDFf-C?P]GXd`XAy9J̊,҄(,/_njf-05!0<-7Lb-VU ;a8][f1]N(?:tǦ ! Y8@Z{F,ݛˎ1Qtb@l'i9EKeTZ,(iuf E^QCsF0rJ۞eaXf+ &,\=Ma.WK=,i0:Ϣ%Rd|BiVR)q@ ɀaIL:a&hVPڼʒڙ[`o=ŲᶶK@Q,vwz84 Bu-O:Sn_ȡhyYKQɴvO G62HQ*jE-#RmuwV) pYOpb<㳠1AvSȸ(/˄c3MJܸj*IR_]U(>n1g{矁 %;n^ARsM0i}nYmjş}?nM. Q?k>02Uc D(j#?}i%D{-) O0ql~;(R2Fn] 7{;4j AṅO7᡼Lbΐ$  GS+|@ޢ㑪RS Bwh2MzÞ@$Eե+o QUA?j1ims6YPÓAOqVgUC|m]v9{GBc> Lv妥 9xk|p7$ l/:>c]Q,_45[ZOw[mS!ti-r\S F0 "Ib%%VD1 FHSN\ I2nh*,W*911:1vO2 qj\Yk1t GS02E ni˺ *KTJdxqrEch" )>39q9W>!I ;ed8F4G10,'I"bEeE6Q:% ;x3 /xe>G%O|K{_0ܮ  E"d<ǦA\&TT?sU:I2 y-Pcƽ$ǭ&m~)'O\j@e[pY鷶lJ%@ sqYmu[o\3htX}W/s㪅$P4~HR̫'](ؔLz;W> EZ) gM،-=vSmr7JO洳{XK)2̆H,ĵ.{7WI{oI^u NҴQ4XzCGyC9Y93syAถa؇#TJ ]M튌;f:ĢNAS,R (r$5v D8j BICzؚQ$!wz& ŋ7$&E #  ag]U`dܟ$"=~qDPVX S[i(d"LdD^10d>V`*%>)?Wpcʫ[J)-ڵv#g$I  /NL(:21I3ƕfvVZraMiOZ*4j( ܵuk L#:< G<]ukߓXJ ǢpyI2\YhJAȐzY:L=t-+Iwt549ݎ8FDQQg&7wH&fˉTf;eVⓂ$,' a&= OQ^VSG?Pfji|q}U{eya(X~ӚMk\I1#89Mvϯ6lV# W屜t9) 'Iy bZi%a("E B RwS[zF/P!`$@bœ;7ySfñmdjNYtsfa$sۍ9g)zϺo I` >qϖeV-YҤhcCD\Cb}yY0w0>M; *A2,^|;i˝^g`)*E/(8 @8Jz\٨r(HJ'_{hY~wMUc4+$aٹmns$C)'\]ɅA޵uA[ˠEDIf+9.oIV%I^[6x ]G<𦵵NOdh܇|{B_.~YE@hcX(F,F̯%[z.hJpvgyXJ8A"Ӫ_P[K8c il EbEyYזQHx8xAcx*jʹ^jm+#(F`X>oOeYgEqiyj{rtPolЧ#!+8Ax,CZ* O]j=|{`D$\*+*u㚜LK8(J%|mk̿q +)/5,s+?#heyAM1,$bq2I ޾Qg"")*KۮU`bpl"mt Ϸ ݞܼU(?sʯ}$Ŝ܂T0OG iV"zaq}K&PI'TfxަTb:]۟JmemKAcIbKt7v͛5+o̭$B5X<O4˗X;\HjQT2'fۦ?8ưB׀n\Uqm=.u'S$,'9*[Ēܲ"LIf(UkEYQ, AQGH+Kz*%\[cԫG}=rq}vzq`te9@39ph7i1 C@i(R3l_4B"P_Pd;%35K?S9c.=|[.^Jii/_l#VACPߨӨC.O'HZZ8wnp4jĥVVP;TQ"ؤ7E Ed,nZiKT 9 +tg 17ҴGCiOc{( %y8ar܊¼,3˱HO1l4/"$ :դ|2̆#gY*soWNp=Sc 'g8a֋ X,l[0s s/(BiN\j2 ߱b ^p%'qwZQR $)h' ژJEI?EEm`waya}u^sST)2MWiͰhMQ|._ayV9~}g"dHYeyޜӗ; s8fIKT8[n1՝no nY96ah'Jbn'IƹEu8&R&ƨW_n HHfX8ts-[EOh\eǟ؝ў!ǹ枦~{,t㪆sWG' C~i ZQ9UCы fie֤S}FVz1 UȒys(RS^ni&=Pm>Tɴ.FIQVOϽ]{Ί"gtRM(= j  sP[{㉄7%#p$e/J9z c3i䥎H,& ÊYq%I~ș$Im\|aXO{,Af 4MH߼zܪ s.I:yV2 @((x1_,u:ɀјZ~ymyrsyܜ\k׀aWnX^jԫip?P}A'N,ML_3讯 jK_[T?2\< Q+oqnnVЂ|)(JFIU̝V 1d*K.4Vw!HavVIDATE>>mW'+30IuDē;<ܣR*]^ mkk$|Ge̗\f?Q{MtSenX~\~vƚus+Sow{U%J Eb} %Ԃrb^}0 @ @?uQ9r"uU% jW.SjS( ^6"ILOL;zs-z}ϑ@*A`Xpam%xC%?z6Yw@@';BKIQVU mcS&]8bhR&V)I4%bAcHkbk'^عV퓞X<̋JA3m(7LI1e޲~' Dr3o^{ OMͭP(PIp h%ѠJέ\6vNyp4h0zF*h*ΐXw$uwB4˗.F}~V8O/JA k58Yb=D ՔN~׀ֹU%0?0pz-zqڊ?G@[쳰df[?r>CF5B+ܰ|QdiMl*E NoN)O 29̬YxR HƙeJ\A`~MYAdo7)/Z:zW̳p-*qD:>Rs}R@GW :> g/U󆢈̔E*r/za'=H&IK 'y-.8veuKjlН&\$g*Ku{RI(\U"pW>aEyz4ÿ#IbJDݾD]TtOg;?PcqE^.{ Ojԯm÷=t H>S("2K:q4 8s ht޶iڥeX^{VӲyI"@8 "$غ,SRU8ywV;{NPJ 8;¬Wr MOCϠ]MdXmp>Ÿt&Y^zY@׀dcD .JA;Gjw4񋝟o%O@bNMX#jO>546H24pBg&0SMRWsMdfZ5"l\S}#ç>Z#ҞCH{uU%(@  ̵è*y[T*eqc D01pFb$I N-&s.Z*&S9d"12/J$SɠXDfQ:k8Ȱu9q FdPhQ м, /Q*%42OwOPk r$ xG{?=#qt+E6!( i`1UT\&JNJ! Z FRS$Kf')k?yn~/_P.Ŕ"IR) O^۲Ũlx*EdlZl/_]]lD`)N>8?9' |*}I3c޺8/+t CѽXO`R XMI{?kD`d _:L8Mq̈́rPRYcJWM>2+dqx̗>82ȴh \E}cQ&)E$jquqWul.FvG@3z$V˲fh[.\(64$Mr uW?K^;:"&};2PAhe!d mBDQd8&UbאgckDd@QT҂҂4`P@[D%IP0؄٨UNWgeZMuU%{% gQKw7LSagtϡ$ͣq덫G'Fkt F?wWߵe @aXw `޸fV&cwo+bI/ F5|&I7d qBKį}i}/w-+T( +;<4zI+Hq~uxB$)Uqh-ݾqzlkh:;wPKʋK[^\_3<1:Ny}r-Ͼ~{#4df-$=(‰qGQ<~wUoܛܸzGZ(u6ouy8!ȸـH 7d5f_lIœ~^uΘ ~CɇLBY6*bqSFZ-I-7 |`8AQ+.[P7mT^jg48 2|I $żqgSB|!5i P[2P|r-?6KE/~pRP)ڊBFxALQ, h 2C#iNiVEl҂Y4uٍj.EeY͍#?{/~WnIA6P$޴I1#D*L0V~uU%S/s&/i/Lxٺf95̶FCɢ6ĥ@kf[&/mNjwb׾4 +Qs4ke2 Cc{&hl-뗦Oo&Mk4w $i$?+qt߽k- H,%I }i':FEQNޱiC o{*%JҬQ?Ů}η ?#K^O e!Ͱ#R?,ggoX^vv?èUIFWxOtJB7]s~ pλ>G5t*tӺf(O-r-(M88t}s MPK0 &\ѼLC$\v !.o4ds{ɠ>t/+C+| XcWa򅙋#L4w9de q^%Q7{߽ał҂}+=`y~ɼK BA FZ5E#D8gXzά̕`48,`9}CIJJ3Ը+Гn(zLsCMNWܽƪҫ[{ˋ᛻M[̦ ] 2R]5൚qXE#g$c>W^l }=&lMSh,Af+ry=;L#,ZƝlAG9c RC gaVTtn7䅵S_yY!/!ã#zm\j=|5Kg*J rηt &ܿ}~[?E9}Sn}}AեOw۞C}#۵ظl~Eڎxy$UaԸjQ}BQ~dZ;sL[czH(;ZUCxTjj]Re͢7Nt1*tٟ}o&E3f5=cm8 yY %O"7Zޣplտ{څs=}pw?,14_hqB,KWgܨ*y󣓽w}vTtX!N0< GR$7ݽu3M W0@H4k5._?#8a_b*}7i$~ eEmݵB1Kj+ ;u]L?;O^) l%P#}f1SwL U%BJ(λJ s`WWU! I3b!%$2 f/tuFBUYi%?qIvo^y$*߾}=E02I=qabaIa=$25'NiHDcQOx1!dyqNYV;ayU-HZP;TPY'/OhFDt|.oB3.Yvu4o rJ^t-a4hV(λ*fi]sgڝy\N I1c3Oo?|Z$፜q )g҅K Kt<O(̱ M&~EF|(9k'%uΊ GxdaiOX(07]gv.ƒT2I$)bqIғes3TD"ɈBRoZ\W]zqm} Í{]޳C.O>iSc rzcﺑT2&Hx%pmO)ϢfV{Pfl >sʋF&&{n L^: >JGȤ('cfGϷ"ŊXNA`eu4kL;FHJe3rA(eio0NTGc|3~m@srYnsoxJUj0ձ30pF&tf5Ch|AmEI~>P઼LCNr7^RSQr]e7]D!E֞Q/0oO;wx"N+ɏ:MI.L2K7T^c3M{0JҶ ^YvN^vziw>UO#Eh\iZ-/w܉L% ,7?$ѻP$7}i&C>类oYnPIYW R^\ xXӅ֡`86˗?ͯ=3O?P,?>;r{ЎbEvV,m+j#d8*fId[{Ft_>qr;B41Ko Dc1!Ԅ$U%_mZ")2'Fz=PLy+}O7LzB? 9b7(uL\n FbE3M,`$7?F`Aز. [zGw3iƩLn´Ef=t}Tu?pLzZZ{&'3o^|sEV-r\B 9{pxp̝i!yL0脓o!7:!)I1Ͻ#V74j%&*JG I%4˲)3̦oWA&+<攻᱉SBHd%ZT=8 +V8 㒄RP" +)!tۻ&>'k.HGVVװtG$XXmv9T*tne־#P DIWx V9oN>)an~M2ͪ^ )tڢ ~*mlYIFiI_OXw|;~_({teg5 7{_},N2*)ްx?iE> IB4ӂS!a(,oYPCRƎ WNY,YE%4D9 :!KF) "Y6jSMYV%5I[fw BR֞`$eЀ[6h=~ O]{ؿ~lNxbJ E 7w;|dĹ_+axabN^j2 v*mYt߽ ;#Nd(:)P^aX SǓ0֮δV4<;_ǟ{ÍK-Oϫ7:#$MSVbx6]ZMGYA!  Y:{G^˾-d"DW63< EYYFL8⬺v;`NyVSv;MYF96bߑ 7Z)vz#Þ̾K{.fr( ЙaItIA'\@ЮX$T/i=s@󧦩0dݴyQTUSskAA40*AѢx5mBM`[/ݺ~;N_jc*\VSS^TU=S1f}CMacQLU~9a_[Yuݒս{ܙ -=Jaz_O]RKaA_{{DM޺jz)Tk;q>M7}Z O2bwyqP,%̌;'q0pL  P)x4$5<~6Dӻ?/K7Aj0 o$.{ڌǿf8.>%a'iQ _~wQ^%YA5>s˿0 $~6#,]elWe8)I'¨3R)dUʭky +`ᱎnG̤GXNX\~H\Tf2isx㑊" ˱p?c3cl6d߆vիӟ._i9||c_D}ׇ/u px_x`׀}n#;n5ES 0G^sddAn]kne? #.A O޷~jI YVh4h8H/cIΠ#r2 :('p%掛(V"Ly$G%f0P[UJRJ=#㦺7VN=翌[<_zg~sַsĹ:3334"VM,[3%$i͒>>982m~̪x zq?y`p>}2;JA{hG(`L>~tj8KQ'q 'egdFYS{s_];w~rؠ1qڵ%vY'wn6 PM`8uDz:\uU%&>E3}WdJ^ݵyhV6{g4:IA>8_~nT^ cg]e1ϥFaEܛq'@H7%OE*Q*Gvts2 LӪϨpCQ_?8qµK+`(Io۲ML*2KX2 Q~g=a^ #Y/DZJ"'uR5;iebYd VͧiG'>=6[o_W ڊWߖL8 jjlAR:F*L]{BlqbN"0% +D Z; f5jHȮ')tKlvXfk{T)uΝ;wzK;+󪊧ËNW4?3Ο7,)?6OԤOηLf1ټص冻CZy RC ,_i5W-;3ςgM_jc4@ LW@[ itf͢]Dđ3MuU%W:ilYjJwܼ88}Hy0ذ,{szslY=Cx2B_d"I~p_0fЩHZiյEp;6ƒc4åH ST*p,+D"r$ARJuQ7wGEC +-uK]h>۝vsN6˲$HU%3W))B4:E0A@ĭ;E6f+o߽ƉgRYՐg* }PYwU3;\ GSfG5,`,4gjdӗY]Th,jf#$IߺQMkĄ+@ <{:|Q}o~¢QgS`[Htb|wXVѫRO{˵冫J:k:hMkWeg̛Svgh|:AzQ!y^Ŀ|e Lwj6.$RdAN2҂U] oxBFHU `0sRS[ϠN7F&&=s+ ܿ3 e2 "j|s(!;6_T叇х=,Q(` \;/EWjpȚOwϷt䝛S$Ŝ $ FS2xdh#qN]jNor"I%|ϕ 8{dU}I,czǶo_S8wn^DțT&C%951?1NVQ)##12+B]U'(/T‘hW_{;wq妦K-x~v}?Fn&Y XHQ`ڝ5LIK;yYZU[֯pzij#p¬W~3UI G#/G}彣&jJ, eZMUe:'QS}?[]rqd7X0k.o0Ǔd׀j+gm X!}û[7T1$fҿٙ˒$IgX`FdE!+pӪU 'M"Z]%@$Fz)z1s+p UTw/`8i2]:IsfUxSS|;~co_t2~c ԨUBm[w\Hsr$ngyCͩ˭o}|b) [6w~鉤Q@L{&N$b5%2tBO`YA?lR .\sJ,'4p8i5tnu?|qǖ'/Ǔ|yQbܰ|^X߾/wa`ܕH<-8t5rƮq=B[VxGOU<0c$皺tz1 X  B$?ʾ3(z֨he@`8h5]#ga2/K{Ǧ#D;~卆HiM2JT)H4f w 8CQzq]));ѳ/}u5,$W_}uo{^$2Ta`$UK7os_ܲh^+U |g&U9Ҿ$ mI߾2UlZ O{[H9t2u>_FKdY߿T|ɒAF@Q ͤ0Z`ټ*'3<\h [o,F5bv经}t1gOozhnىF2]ht"S+[>xiDe[-(IoqBSA{nlMQ7a6(|KIAl77fs" k(V 3zf֮_MyafO]|RRo>P9 ?+ e ?#`,/Lg,cԫg6nwx~k_TeTESgyIqᆰs]~elV0<7,DX!~r|S]>ybeIzB * uDՄc5,0).z _&m?Yiw8Z2-ʒ4:(vמjMf;7xWXQGSy۲nn":YNCI\YkMӉ&6q(zQN^rfYkIfIݕgS'v<{#%4+/HXp:c h* HtJ9E@O5jiMC7_,I ˃nڲnwkp(37> <̰$7:񂜓ie#4MXz"݅I4w9,&teE!KaE|ouY\}S(,,|]ÃM]/ޫ4>pGϾ"H$Ta/wE,YEAj+@R̟>굋[>?1WVvnKt8ByYV1$c 2K+s~}04MRQ+צSA7P,lAՖuKfu͡uU%@eIY>ؕ ŭgR@$Qi҂3?ˍ=.xmjS( A6dI&L3R9Fd@3Q،PeaNc;~k -FϾs=+s>ٌV +D^ /9MayXV7_ L  eynܵ^ΛJ 2EQߞ>SaU+!(wԢ&TO3bh-+!rB MM#uUIO,Ö7hN=ncճskYUR C O^hGh=[쓩i>:*}út;eYctZ6[yҗ&&! cF`e}uIZ:}kpr` rmI`J%N]9g :NfdQdZ$˯wo8;ou Z|9Ƿ~A皆IZ,@#~;AR;WDb$x^NDINv>W?'Yf}O,Ŕumrb'ypRTf٦luo~tW)f#0D *k5]>\ҼMFPRWWE}AqYy^eEUW$9" *ɨGݾi2t{$w 0P[]S+M_0_yˮ=G:{ז5$M 3nod (Fbwn14w;eEKE2 aȻۿ_O- rm(Ò}yw*\-kJ ;}ηP iV>tU*YU%9.P4"iɴ{t}ҟFge:u$1fwx~G8i<S (Bz>_M5Ś ^ &RL~힭W%A\ {+]Ct>9vn_ը&\ykrtVɔ )gY>EN=una~zw+a CJ?v1&YVҎ~r->r ^M`޶]Y!itxJ:yJ]ݲhyCͅ^BMdYnң6i*%)'B?zPS&f֦5K|`a8Bq O߷u vl^IOʒcΰ^9řpll98H4A'b.;ƶ5w@yזy wħU7֧IXhNp2 ??.aժU>ؗ}MY9owRˆ^֪ψ"PURp{鵙5X͟*^gZM}sP$2,ubv9FGnOW;ߚH*K}^Lm(̱ Z(W?rxFxe܇wl:ԕiޓg[9c,+6u;;}(E(,L.Db H&anQߴ0o|_zKwi>0 -ĒwmY LM|v5F@ 0M$RTya|̵~ǺʢwҞC.߹P4'I/Ͼ.'C)kPAzIvI'\{^H;56kl^[䅷SJBbtw9v9FmMQDةr Jfƥ,jj  dמ{flX196k_d7f##-KvlY4uOz͛ 'zxkuuF&5Vڝ7|SpfQ ?~Mӎ䴉LXGU(cDLQS$t bͫp$;FN`p_}]U?~T7~/oLo>@t3<[qB7h9=/]$>ig; \T⃃ iϴ|reVBxR[X[H(YnyϷt/W9gg[IAsxj)e9=v\A WB]=׿qscxg_J>$|,JK9[/{J>AsCzS?2D3]\uWՉch21r̳ 5x1{}˗/ww>g}ͷŤ #n_ש?H'[IDATxӹq[AaƠdPEY0|`a& @Rw13Ƹ[_> qk8= @DJ}FH}G}F}E}D}C}B}A}@=ίCWϢ %tj":zXΫ^CUI-tJ&:zP]Χ.ASԅ\Rt*u1:H]ΣAQWIԕZt u5:@݀nAW7ՍVthu3:X݁AUwA՝^tHu7:Pm@SmFXj+t(:HmDQmAjkt9:@W{.huZ\V{nheZXU{eծhU/ZTT{%hE?ZP @h95Ơ RJjZH D먑h5ƢE`P j# ʦBhЋl67=&gd4$FasѸWl*MECL4>' gziZh"桉yhbhffYhjhɡ9hrh ffhzhƣBhpBh4Z"4- FkƢEBc"hPJh$Z&4- DơBBah0RhZ*4 - BkƠBcb!h'ao3L.6IDATx=r#eaWU&!@2{T@D6UK,KsιVgO׶$wݧ?:{{|p[w7޽]FoR}ޠ"z{ꋸ譩/㮣@oJ=ސzw"6z+E6˸{-7^:nzBՅE5KqUW.-ET][^Fu%nz}ZոU蕩qЫRVWnĭEG݈[^u3nzf MN6tvu'n#:YݍیNmGUvq{9Ղ]jI>t>(n':ZL-ۍNGgR q#Y!$jqt wBAM;#Y͍;%zWO7gt Ř\O ;XD藙硉<#oZ.a_g^Mb'A\S(6sqh;4Ui C3~KbF_^&gH|f @չK3G '-Y7=]<[.tifvs>P ͛y>h% g4s9'4)/CQg~:??R %G䯟RdIDATx9nwa!}JS&NT!@Z0*RDGa|-3dʘO9_?Oz=vO+ϻԯ ~\wyC߉}C=qOW➡7>=Go\}{޴e%z그K譪qU_.7]AoP=ޞzw58:z[I ԓ[ q7ћQnAoC=ނzw">zeՅ)u qkV⦡׫.MDV]^7Ju%n:zJ Ե9赩q+SWWDH݈^7u+n>zf*͸%q՝eNBtnu/n):Xݍ[Nǭ@'U֠s qՔu|jRJt:5)n-:JM[Τ& @QSFqCI1jz t5#n:^͈VsơcլP5+n$:P͋S3Ƣ̸57n4:B͎Pƣ jAh_ nZ O-mvR6Cqۡ=¸ jiܖhk8nSZ-T-mVmS+6G[5qۣmԪ&jUh.n4\V+vBcڸH:n74P SvDԀ=5 nW4BWCvFՐJ5&nwJ Q@ը#R5,P ;-RB |5004W;SCDи# 56P4Y ;MUF踣5s)o3O h}ҸU@ѷCO@v8z")P`x35⹃a;=2B `>NͿѲCJvpCl;M ;9tQ`G;OХ{CWB?rC~ ]0tU-`;f]ѵiC7L'q`[j]o3'{xﯦ_ٯbJIDATx;#U ,yxA`5l܉)㰁`cNj)VK<$h2o-ݿ|o{pӻ};w?~<^w~xF?w~)}rO>{޿\zs蝫_˽@Z})g ~oN;ީZ4z[3GΡ;ޛz\Sʽ|]) }{>Vʝx=fMM,w=2K\_r'~Qs_ԻWF?N9c&=7qÁ=+7Z3fGsQٹulLec6ztχMc5cx<)m3f |m]|ɘ>n1%t1;}94vJcֽkhv1.eW9KCM`.ήcǬ5ATEp{̳btPقltPؒ+Ƭ?OTytИ gyJ|lѵ1c6 :lc6~>- 8`̺reeK/}0G-EltP;cZpl1G*kي30lH5ұ5 Y"h65hޘj5[mژuM}E4fCgxel8cZylc6&֢c^HlDSZ,P ؆/,PWٖobǬ+4Qʱ-h %{?lcV u lۗqcV yl7ac֕S9z{И MV4h*A#umdjAcmbjA=a;nj`sՃۃ h衾}t9f>sטIfw"Ϙ6L4P>_7,hlO1沎0h(Jq̤A%f6fa1zXL4߷AhØɃƠɻ{ L4PObFc {{dr4A{=֍*h'OBLP'b5c q{:|̔A6h+~VpAu6f0Z6f-^PxLߥhɘVE{PWbƣcf Zuk1е13w=f2fhA ty̌A (f 4f֠eZ3]3kВ~Kc&cfZLBgtP+bf3cr511s].f:5fKheDtb\Ag:f"z9fsZ33_~[bgc :6EOPc&czq11s==f66fhGtuA+f>2fosuAsj@!c袿+ˇO7~1?×d熂1IDATxڹqWaTɑ)2HKSIK `*J9(p:h0k/o9_wEbp~$mgχ^zߞ>}ٗԇ#ux<_H_xCO㾡ӸoqqѧA}ԗq?[V_@_Rmu%e[V=@_S]}#tض>!_Ǹ{6{lGGʶ{[U=FOǖԣqÔmJ==LنԓqOУmG= 6{߀z6)zMg㞡')ۀz>zի#㎠öԑq}d +V=GSfuteͪΠ )kU-wV;.Eh9t1e E΢)kN-w]NYcj .py e-Σ%)kG-w-IY3j hQQ]D.e)kAw -Lj͸haʖV]DKSZ5n:@w-NقjhyʖS+-@SZ;nZeqСmz&e 㖠U)6[V0nZj˸Ъ4nZjӸehmʪm)6[V8n1:4[֧6[66[6[v[m㖣M)=㖣m)c]Vm)#]V)}VC+j5hkj5hsjUhsʰjUh{ʠjЀ?nڑ20nړ20n%ړ21n%ڕ22n5:,[̭ƌ[v̩[v̧[̣FۀKa֣)3a֣)3q6)36)6j-hDʴj-hHʔjMhHTjMhLjPW  JT JL JH  K@j 㶢q)+ 㶢)˫6)˩)6)˨)vC5gv44e 5iv46eq5i46e15k48es5m.ti)y)v)v){vKMMHUMHYH0[f|ll\1&ۇf,ܾfxl'DSFovS7) ^4:e]P4ۍƦ,$eؔuɟ4l fȔu)Ql?PRh\: 4,eCc_y4(eC4(eC4$eC;4$eC }C;4 eC?eC ;eC 7eC0}^/v6 KJ6 K*6 I 6 Ib6]|_B6mO"6mN6mME6mL6LS)6mJ6mJI6mH 6mHQ6P6NYCX6e=aʔ; FRV64/\w6IYC_ٟâ5)[Чǡ7-O">t5HYCG|)}蛘b Z9hYjz&E)s蘘:!&):-&):+f)c$f)Z C٤C4t!eC4t>eCk: ~#:4_LGRV>t1=LYе| eCWяe]W\nHW@R9BKf^N\}IЋKSv?t*SʮnC\͈렏t-/_q~?!Pr *1IDATx͊pْe[v(c HBQA76F/za0lH >`U d=<ޡ_]jY3 Is}韧vSue7o\{׮ԩϞ>y|_ݸy~oBI&Ž߻{2w447"Y$F/<4OvC7{ HAb%>fjھkaD?g]yZ`p=f9 I\q _XD7~F$Dhj|t' %bX#XEsʒAyX}PA{Xn=yEHhEJ#屉 &II-i]7͝˗$-i#z4Ød=n=H 53d 1%g,E$=,; bbw&{e߻dL1<{&[f |Vx8o5#M&n?8vso#&l$tvK~]]ĄOBD3c.n;$'M$I81N&K`㽗ꇃM$$Iy}7IvI[BHB?pNWn Ԥ$g#$03'9kv*$&B zbMƓ88nzI0n"%Lgp[co~P5&=f8`ě)78&8[aMfYϮJEn&]S~j};FzvՒNrd3O$Ioq@ BbM kb"d$c$md51j25x$K>b,&YLuֶT5bd61`Oh߽pG5KV2]lL&FMƿhHgL2?{-E-uzW-O:YE7n} S)࿿iB *뽑t.QLta|o|=NW<5Z& D$㯊3R[8pjiL4HSzFSNfCB]L e DE4 =L1<$Xj(3]`$$S$Pj}Dfrd&AR&3쁗xBqGj>yjgtfRx|/ﳯIX SDXh#45s$2̄ qO%aje`D!K ,1w[}D@ ,0 k0qQ>H 7 '$5~DmLHk-Y$\w٩q+r$LC nj̺m620$h+Gj8xe`V]xz@D$$Rt I&>It <'(MٕMIu(M #bo*D \2Od$J 2p$"GjbRj>wD8oHT_RH-__7ɗgM>?R+S+dM UH9E)r&,]ע]YԊYb.pDOK\6)'M*dRc%M)9p甼$8)N.pmdQdj"τ U6q٦#5nk"5^+m+&M\%ө1KIfu.0eL#5~u4:2&SUP0N.'L5#R&]mwT "A.phZ85IEh"i>L9I$0&c`{vO):05Y?o"kQLm‘EOMآt])v;wmyI\i#.c#5MMȖ[I@J>'5yo_fo&mkϮ}-'51Vс:M^-54сmM65)6J$65O8:$YS[Skx2it_Fjx7MX>Ew&HGj)5^E>ڻȑf΁15|z|#iМito[<\{z:z]o!=)+OMw.Q`0HDyMb n&F1_75. ߤv+ۄ6q[$l\*0m>pM3ML%LЁy& G[,#qX&,eqLbxc,?FJr@&1L&꥔arP(c=O&N#lrTp$h(I&uWd#)7@\0QLevۼNB%7Y/)n_8b&Rr&rS~y=gnŒ#5NaV䘹QgLvGTªUK2c]cĴȆMW>OI*$IffʤIʤbݕHT"ITɓn{Wɾ,6=+ۄy4i56=RTGS&gpS&[SlbIݹ&%HD5I%&gjFBJdmIyE&'IU$LZD|>4Kiִ8m:$f7I⛸i+8D69eݸJ8oT+s4 ޳ݟ_,$W-u 7n{ Wy "߹ǿ{:T*1YULP἞#pյULP%MT#V1B1b6Q7I@>}7X`Hma&-XqW"=DFNNw9zDw/z  LJ80<0zE/OKx$rgjL9dGГW.D:CY`F> 7QWGjԽW7Q O%h7QW I&ʊ\D],%a(qukM r6Qw$<mlʌ2@9&~2DA{y&0v&>H-lMMݸSIrh`M=0ID玚h;qz6tc z ts,!zfD;$k5Q8qj2&YPTٝMsy&r#5^EcD?h.w*ayL&ʙ+LG&2k$Ls&YU&hAܻuHH|ŠrJ$~VkD7wv&j+M*}f{ﳨ"20C>f[ ;R6&QLt+GdO%~jn}$ & f" VK8FWLEuZEI%+IDATxϯq8i8[Xq`_@BЃO5j!XĹ: :=Cuq)H IqJ ~Q !ŕg7ݷ)7)_}e]~!kD"{$wٮ}P0)>>H$;6#BUNw6NLwԬI';YOemD&^'򻇄!hryc q$>|EPĦӉ˜ȧDauƫmee'dD_ʻa|-b,*h|t'$G|i*&z| !!ɵc~t:wqؐLpD Jٯ+' D1[Xȶ}F/1N>W*&OR,1fxIl"$;r7"\ Di'ۯ}_}d"֔#I|H&voyR|\{p}y1-,GdwS_,4!yypړ}AVLH{ȉ,U5|Ř(Ab}0^}j|81![XHdWΫJviz. .sܧz%CpbdE"RTflEe:"ٞHؾYH`'z pɾמFpvUrD/b nE"QJ^%y0pXy^ˮ=*lOoԶ*BP=٘]D=7?V{N>mSofU_GFys2{WInև/Vzjs7O@AYb:&SB7_OMW ͔vfX2ɍ߻N+.S >zV{1V(mwZinۑ82:N"~} OA) s(HL8tGQ (8˚.0 PaH4'K1rChM A^lLCemЗ?x }ܠ:0˔Cb$tf?Bx.QqeAAbFVJUw>PpAoD%uv3I6$|Xk~|sZDB[.8E_ 0VDS$ǧMߑmz`^CE򯛩bW]Îu͗BxȮ;{ȃ rjLLO(TLQ$8“gzF֋osD@@!uP1 @,L q+H:, XrDf2k̄!1r!C& |ݽ2dxO #A^vVhDghwFowy^c0 {_ٙ 0ܘ-',X4~_)VCgm aVp4)dȂܳHRc|Go=O"5 Z7lf$<΁6@B  Hm"ɲQmFw(HNcM>JHKWqpmMW: =$-{ " n`qdo.k[=1`XY8wsA$C ]YJvo<,PIf;3bc8WfLH&:Gp8"Ywz,>\Yj =&guWiL3x3Rdܥ x2a!SÊll#1ҮBy3~- Y\URyS2G:ST{:c{RvoJv#vqIPH͜LQdp؈a dr=H>}d.J.ʄ|9SfxS"8 , gGr6$xp~ f"ȏqHoN։<2?;l=+(Cꈿ)'DEH iCQ@Đ ~Z̓wPW>Vy0ꇥdT z<a3碘9TG1nJG^9<0hW}ʆ_YDJ5w{}kz-qvy%## b0_ #bMzvA2a^pNI_!L%RsmuD2s8V Jt7T"(?pg!x*{!亂n!H}[#KU# 8-¸wDr@g0ʏEî56LEVkm*`* -+!^zxwIHlaKMt$nk c!nFGswMňuYd/Psv#Rz+O Sgr!bxpKo 7 52ERQ7۴;K5zmw cl)S';oՎrDLv>xj㊩ᚱX(b7QH ݍ @oF Owxn[Lx2'8˔-Q":jfwo}=ڀTŁD=!SdSf2_8\btvA vA1VRfj޹,3ΙϧI.kǢ]F AҡdO1䦤[CC`}涽}Lzې6\z:ߡ+p$Ihf6=TOG2%_ZԄ-+"AL ;BOʕr,UJ\4Usw>|3p7`_)6{ HkDԜ5/"D̎".3_& PR^N$S&o"y_ǧ *ez_b)s0Fa A8ۄEw4) ۤY~挿7G̯QuХ%"Iq"kr;-Fnv\6Ѳ)&E0uWWnx:(mH0I}YC/fP͙-jFv[2iAu#dyq7YlYoj\s2U&ynvBBrj0IY"%>4;3?3˫'EwCgy q#"S2M䄅3u'0j#MF*&.X< K(Gqb HP43b<׫&짌cCٱ$DP#H630-sR+(\i$k錫,*(1 5I `fP}̥xj4B:ryr|mʘk E &KNA]'( ?jHPs idk4sgU $;\kF .C[EAa~L86pTMYif^䒠pKe$j-*oBCBIT$*$Są.%"4f R`y @&RdA!+~!b?|d$PUabAP%`kQĚ~Y%L'$;h_<ØdofH ش|B+Uwb:}B@_\Q!\DM-| Scj%$iu ]:ԋ}(Qv*XȔHlCk\JX$Lׇ-4+ہ)•Eyg>%t aB2Mjbw SIDOrOV# _wnKTP:~%SID>4,0X^ ]k7?"I-=w2_ʘ9JȮvo S7B f_" ,uy]ΤAe5qQ +X |-ٟTW3D.z=5 I K}JJkq WeTi  UYbϗ_/gbt&  6TOwF#DDU1~fag%(5H8'}j^e%F=;'1+<ؚcwJT?L$)gai㡔B|Km,-2 I_PHD{_RH{<$A =l%$rsՇ֒ZHQ|i#J.#nIj$̸>Oh;LP,KmgysB%z&Hؽn sFxƝpH^KjT3DŽ1>{J[rr3Q;k.nk͜&NwcRD_-#!`)0FWyؗ'V1h&ܨ ^UNaCr^:6Nٜ<:$=,ғ)9$#5u gJ5*Y H@{,ɇ V|9H*(yHb{m^E]`2 q=̤D\Gr,ڥmo$2[-؎ȤDiAbE/7M03?-wO{*0ёMMHvz"U4Նb'DERjC2]~Drk+jhe="ׂĶ:+j$Z+Ϣ5߽De )6 #]6vfs0|}vf,j$emcqq)'H6"9BMh-i#nWxX #*H%.lm\ --L$UUH.hIoUu$vmw#ml喭H )ln(Wݼm]BA6jLX$E$r@/}\οL*f䗐_RfnQCs-P#a𱪻@%(1:5ѕڄWG15"vw?.0!YZ׷F0a1u%Oq-X~?!uסmMIʄl<0x*#ѼP>f'][y ao<2.!h;,n̄NLj6hCRDpP^8Mڇ ɘuX$㥔+Uo+Kv45#L  +g5fpJ),/6/];Ty$ER.0c0)v d>4G2wu3k(I Ko~ `qb^mTGJ*u4Ibqf1^R?"ºLéGO!L ܡ/R'/\y$9O )xcT'< $^"9Db%kZ^\v%d:K B|gb HuHFsN<m͒vcbHj[ҡ(Qxԛd+aw.%9OįLqrpWZ{v-}%"yjA31Ԇa.ۣnm'W/~wN_Z5r8E$^>ӗ^-.f PH7$S+/nKԟXx bUnnd{-O.9`]Qf z^RdƭqBCҾVܭ}ᔠ 0HVTąSH*NжTKB2nHkyXVR}O?D=Z؈íהE|b\l=J6xH LZ3.+ "mۂDg+nVU;㜿;!xƭLC/"Iy5)L#U"뿊brA$<Q_&}Of"Iuq޴%T#{զw5HPO# iqmT7D\A HkR*YlhHL_+7F,"!1$^L0vG@"0aםL)!FVLe&@/$<3u$3TFLfɻA2?o'!F-1ɚf*Y7pLѐTL%c W=i Y!l]/ZN섅DsLMx5qr2?9!;TOq~۶ħGjJZdL+Ֆ")`1),K@qIODm"!BbQg⋬"sM7HiY.^4UqHнAȘiw0<:m2 +#=s3@#sB4+ nh |nRl`b^>9CLIPjyy" I?S|_5Z7%N{&!$9O$n|nS~n11Lvtk''21X$NwK?M|rHv&WlG''Nk: lJH'.w[\ziGt$ =(z[J_MIDATxO%G|Yê".V՛,v'9tz25g*D ͥ^ tF?lsPQb~eJzf{/^77/]mH<{=<UEon'iAH(ML)%$ ^h迊gcs51kor7Ⲇa 1zQ#$>Ga@@0zM Mw~ĐpT>ai)}mO\`7@Bˣt4Q1wclu ӠP"g!A>Qˁ:L SOGϟ%?}ˎ&=(qusHȄ!d8kWg}.)dd,szٽof{ICΑ:!7BVL^Y <3Jx;`w 5lms"( N<$oiL>^!o4Q*# ez T-Pj4Ȇak |sGyݿ? r'.^=&I>[˳CU(o2Q=&ڗ<&^/o}Ӄ mi|V1(1G.DbIqLÕn2_Ed3LAR f3β*D!y1J,{q1n5o q_X."71ռ]:"3G88 tyN ?E 3,r?\5犤x6V28^ 5tܮ0m4'惉E/yvӥ|vT];s$adĤ߾q8tNu3$N$gkdxzJogPM`Gk=ûyr?CR'&?Nd{XDCHs{SphVK7) Q>K"r^{@b)[]L\#%}6,O&l_DKsЖ>`f؋m/ULi90)*x ,]zL'=\ȸtT~#6$%}2g ۥJԮr+I";1nM56*VIm}U5T&dϬvJVBw9^]Є(x97)lLI40aXenUR[_zۭ)ڕy"KjR|ۤa@agT^ׯ {NrR_vuh0@iTZF2dTe?=cHwv8Ix|QڽIʫ/N7vYEMBnǝ-i'EjJbTs{8!10XI`SLce% ObnWi6Hl}cRi3!'X~ϣ."hp[QvQE  "gsdEB_(&'dQ&r$&>kxILVEq`s4V0\Ŏ/u]hB'*3W} ~1M?ߣ%ye;=t]SXs`Lܑ.C/iaNq5&V YH ·ŤbfE^T(<^yo!o  j,oZW DnV8`E1ÏƑf h,✾ D{H U`B/p@*Hf 7'r \&0rHӎa䢵QQX׹pߡ9 WH89ׁ!eۓ=(HI7z$ ݛ(=QݘgVt%_Ym q~uYQ]Og^v0 m{2M"eǯu҈0F1ƅe6ޭ*jPoQ}8KE}g"G.|ƶȉ Ft hI< `3WNI$;~]Γ, ŋgb1 %iOtlgjurMF c=V#[ML >ȺR n.A뽬J$#Igu37HK|Y8SۏB1Qσ>q8ch_Oн^X1r;ig9O ;@`uml($%%!>>Վ t_?9 -w..$%(3S^{ G1Xq:~@.!I7Q'XaHWdH'_xm8.~ݎ CrVvB!YӣCb{iUQ,A2*~*rP/p)m+,Vv]OЫ2T312Wnn$"opLUxnɤ˅;⣃8#Ӝ˳+gSQxDO YMX&Td1Zm067{ a=} i`̄1Ȃvg)}kDSXjil"ՅG's x= =^!)=B(M2'pe :@(LvrBel,An Ӕ3 i}@#WPIᗷ.*"Sck@㾳iDzb|sokY4IٙMwZ*A0sTO2YB1OV<m;轓R@R:vH"Ï\UT>XG u˂ no6 0Q$k/LpbC4NzL;I=1]&^/9Y~h{O>:'P .fHΦƼd!'`xdT> ԿnxGFR7Nat[N!Bο'0AHV[ 7׵~Bh|'CA$^i<=fo4/a[vz/@4`b/4SEuqPGuu춃bsAٮ ^6&+OV /"g-1ټ0UcČfy6ĞB;Aӵ{m؅[WyL v>aV0竳ȳE̓%rJkoalvLQi '8MήIf{sI !:gm< )vºgT46m t jd'9 a|ߴS@@M;lL)O׆-_\WHEc@S-Ȝ*VF𳽐0(I0v{9Qh BEUrͲQ-Ja˷>&#ݏeL;gIbT/[v<'_r U=p*weUܴ2YLgUjit6y [(<./}z]uL,5$*DӋe.ZIp,~A2 )N47]I #q`B&>U|GʊO" '%Absѐg[, 2 ɼoL8إmus$\̜aHO@8IS,W IG8gхϽGP[4MTnN`d}};֐F<,-vu6tG}"6- ]a #t2SVH?:_<}H fsbl) +w*X&s*:IժE_j yܙ(2o *E-Z 0g W:6;5cP sS\8c甕~%8v* [n *)D GϽKf^@n-VVP:HV(>f)xF+0\4 $%qmjkUQjn Fw1q`ōx5fRD!]} D̨vX1 U rt\qLR#Y@s j!Ls2tΜT_|$UL̫\9%lyR4@bSQ,x}w~Gxʯ 8)FT2^lG>ċ(/cGLaf㻧.>_Y?һ$)gxXVeU9QyIYQ9NzE)ϨA]Ze?h FI?#OBA'!otR2,|X6m0*xzBh9zx;VWa'[52,A֦hLmXw&V)\I{8: Hx'h_aKLAO4%GgH ofH8o=Zz 1cruףH88MbHZ@K{.BSdLT]>gtiT‚ 8O쾶C^uΰj.VqqZkDlK&?$5pP1`D2wŹ]^b}iA--ٞb*E17 f .X]PooF?E=q,3ws-Jl絠s\S}D5-n\0\bq|N7"X"Lh&97zA{ ~zt95L0'd[4~/R$%ZYIbTXj2Ǔ>8wFaK`%bBr_y5rtq'XQnuQˮ~oX.ep"asYX $1w</kC)vĶR8䴝߿'ةv9FCHj3z [,JV)#"*|ςb(N`PX9M+e3+]6$!mVهHfZ#sڛ{ CE8)$lniuڍ zdrU2VUĆlbshKq4n#R>?V6T`Hwwpi}V|N]HJi7]kN]׻5fZ6Z=#R^su%Zg`s8SuxM>fS9n2Q\9 k _ӵ 1LY2 zHYH%-ۚ^x}xqa9J!@xpFFKjKD=|?l4WH ai"l& GV420F_ի]N~W*ΛZ \od2ǷC>d$!w.KPh v /h-qߍ*;~w8qә8I#"\ v*׊FUÜ|s eE{H8E8\|HQ`Wvt٧մ>>>kFێ/R--= ҫ0C_}I}KJhqaA쇤QB:0i6C;,(e _?L;(pu>Jsht`u6+Y| i;j+!YεXɷb]2);EtºS-@4;vIJ6W[Ιm`leܮɖ[T 6g)̴uj{J*q"b@N0PL@\=^ Qm7h;EWTEɛ\@0{2C΢\h ݱs)$()9jK̺0B;m7?u^eg svKX}Ô:6=$ ܚo0+d?]eMo"It{dDf^o̦]N^?lZ?n߹i4R 9PfA˭#pY ws '#*=rVϤ4*bys|P!9I 9%M.hZX!Q&,}41MQ _6k—d4GG6_FɞqFK7v@[61DnW~Ѱ)k_4DU^!`V[tRb+|rY^7vS.d=x)GOϼOYlW}Ìtm<`*$a? i5R Sg$답&8c BO3hJ; .l@ cS IKp}7M!ᆲAh޳BBZܦNe]M3z_,4v1} Hcմ)4uLz  :lr7ȣM.S!@# s\l[qx3pF5־y+x[Ti ~(ZyF8/nWI=sͯ 60*RLG>Qa; K[bhug؃w/$M օtS|K+ݭB/iyKOfJOx|{rY1SdMٲ|8#;~H {Տ#"6wJ9\\ j͝Zhn7O`ڲ;OE`G@"KZ Vmlbz[ uljjZvkMS#%ވV+jr_l]y)C|_ ~5u/g)J3Dϼ'kzKTk(n""l/hVl*)E,}Z_^0Z޵P֢$ ?#2Z?ur]KXT׾@хS~>0?yw5:TILis*Xq' 5+6Zt b)H[aAEcƠrOnndJv@({Pʯr&,C}}>G~//[NgVlo9勆iX]PD;W*˩;DKHtd<$aQFp(UAkV5?Tq{6XN)^YSaf.!~6}lJ{&< @7oよCC,t[ ZQ1tj-ٙ42c#6(wﺺ+v'}1 { y+׌̟<Ʈѻ bZzխg.|%rS6 ClO$7QE#)@7zK~FtaugA(; o]#&eeJ |}n/\Ҧ2Kfx a* G66=Q}1*}9w 15yQ Uy^iCKj* 6Fck휥Fv'mpLSRs k3KS$阏}аdI;+-8&'P%;:EkiIf~]'P~ՋiZP)&Ɨ_xYl|R0~Vu;L^I_.uiҨ3+Y,5N^iT.R!9wR%ՙ ގ/!%5'GLΤɀǾ,/=SM@AưFHwd,"\$oFu"ecSu5M$X$GWڜIJCZd˾+7T?kRɑĜ̴uPJo$nRؾ&/d+I,>XB4#M0[R `5 ilXstW+T!J֞"H;,Q#O%3 UpygZF;GYn5O|n_؈D^1Yv}ol_y8/ ofv$59qGkwZ.n$t ty}0UZ$R{ITd&Z菴o!l՗I:l]IalII}v3N_wcQyzv>*qs5/*BXZ9JX{V%ixٕ5:\ONUtSmp>KL6 sWGQ;WvD5Pf|R1HBL񌃓*^CjJ#o`Xߓ׻AxAwAڽ#rJB5.Ud?@$+0W#N}kCfVRuhByp"9 #godطq'^4kk ^;VUZ"X =r,:Rm`ڢEy+[:]Jj*  ΐ!C͝. ik%kR2^3XLmjxR;9^@ܕLMQ٭`܇Ë\qGbHD)mt:uTSBe8S vAӁ+ű"_KY+E (qh4ڝ9xAzp­I|P_Iu-~;R7qqU{=$5i;>GF2^W@l#@'vhA&CBp רbWkMRMP9+'NW/L94motIq}4t9\I%{diz4phVbRs K{S*9 :L.P<2an> [v a-SH#ZYΚ%C[&F0٪Jv=;Z֫@$#1l|I~-2XmT2#/WAlP1朽ysvP [=ԋog7=4x;Ra noW՘eoqunu:SaAIW{[Or  Q\ 4:JɥY P69h k7&HڼK-z_>FH*VjT?]w?֨v,bj}=h !Q𲭦Z ^nuOw^J^ 帨M7M,=r ("4ǬlǮى| fYt\rnUu %u[QmCUt$%b ;*Fy֝ H,|n^?T&a3vX dodn]<;6O0j 뱰m[ q'qk/: a?\Az0j]e6<Ǐ]7K'0?δ_yn|es*a^̃uiM@DUm9׃Jc{Rnٸb3-Vgݭ?*W =c٥XB%׵715x'U]`n l/U+z>W3ፌtَ%QȸAUEp@/ΚW!닣~yp- ȚKj2h-'vTb :k(}4Z,ÅK&v6_ o6Bc]? @}TWӐ0B;OsQAr 3+hoj:2@ư%^۫ڎlR(&(>6{ >HB *SԵ9x۾25K,ƵQvH<2cM[{ QcˤEx!$_[RwZ_i3\1;-x;亲o]JԶȎ|c#̿ O}e6zn~x!N]wCt].3e8]4`g;><8:=)m~,n-jHzR_mw{I ؂O1Gc1i>؜_+#)qNu>F&Q˹_ a!u\P.O|lK.όö211#2Z/yh㍴ц+Gh8ǨV Q=kRxvs,9pt Wr(EK+fЁm;=rG%]w'rY;c nBQT*fWx|^N᜷WHj}x7) s]UUt8zb`й?ڏH0ݵ='%/.2{c)ǛZGIduKqdp5@=(vc Tb sqTb^9~*+k&p\)*bsn[O&.V8^fI'^8E̸(pI?~VYR̖F9n[uC񡕿>s-|8Urg:(uaXqHޜCvQRn):݉+xn,50ikmil+ʃZ?V11S\NNFzqj q GG4@sR qdI-~Mς&hԾB%|a5 nZEWIjKg;ԺDcAJYJ ,k÷{Fgجʟ5Tc}vPytaZk\M[ޖ-)d8]ɾB,HU6Mثt]WikX0*i MڍeIѺ\Z\{umij%tV@۷|yeߊLIuQIJ^)a 1 7N/λϲRNW{ +ɯQ]îm7gN$&|TB@J/#PG@X4-ʎVaeojlKlq/Xkidv\XJatfMyh4@J/kmVAU+S ԈCS O8$i%1(ڌ=#[5*Dugҙs:j)ō zp5TWLo7&?HlKf qȰQX9He)\@S{.kMPc|yӃ־#<%9Lx6:U$Q4ixu+)#dh? qY(Ԓ(N-~+#LJRK+@h`ry9 ],5|yaU$-Gġ(Yv~0S[tCAbkrrWd3CZB+4#ERI`.[~ :pZ#G /ecvS-Uf( ǴvZU/EF,,1\wLOo4%58\rw4F|֡H- ,Έlx 6Ԡq+K" EV%]iSf8PE [7\$Q&QzhM"*zʠª2ț J_صZQTVi@y5)g/d]D [M6]\"0 缝^2ZE.W8bb҃|ɔX!FrᱬXլDY1 2P]b;=ןg+|FTQm(Rڽ-# aLƞ<Ëmjʰ{j4wWNG9&(~׊N᢭uGnk4R@QF[AR~q4Fu߰X, #cR*xx#N-Gmf#Zʏe(kT0ۂ@:?zۨQ>W Mf^it (Ps5l(k'ƅ;jf (LrW/}YA%iRRёX >u!ɇeݸc"Cb!5*k3,eDL? ɬ 9M&yIdנQu2*Adh[i9F+ÕuZsnk uAmS3H(MgpIsi6;݉ g_z.k? L6L3X|nDd!W_ ߣ CHJ,^f 4hzCܽW"6".:S KʑK1CcvdD\d5IЭiŃ$C xv:mA |BL\ԥy{9`5֬H >pUZd!;Ƴ16]/vZB/j6>v*o]eX\2xgRGpm&d2{8p%58H,:L/>aa vn}cS pI&}|2b!Z2B[K?G) Z=*]X[%Yeuw_QB\8I͙%Ꮑ'yXE=YƘ?_OipQ{}k!_7;*a5ϐOW{?5]wc+bwR~s/P}{7GtH)ks5ɐG.;fBm$Xvv8]l~vbag˞™/~bX o"-wݯ^ ɟ };Сb`|ЕL%AR4ƅ ;H.g$IWB"k88OՒ".4EҿGݗ)q>m@8cZYfrE Kj1(VHY9(5cx,WWP(е1Q[GT'{DUr20J#E[gmNl(Cbq<_Jy4}!6(hB5El-}z.r~ڜ XQAk$662@4[aHV&J5}|kO!ZW`9sNz5O&x*f+ǯ鑥=Wf/C;y_ zO$rt:0mv電Q5hB*]:!1kMIDATx_\G/nvɑԢDijdbkU ׆. ,łsޗ`ḫyσ3AQ3#3"~UŒUu_FFxm__?5GC'7 ˗$~|$/_ 1$3M3_3$߿O,1:_:L~+DΎ/yqc_$ewܱ43G_$@O0|˅ ˛&Z;y?q MLӞS3LGG@oKmCqńޅ:ɔA D/yC"2fA"ߥ#b0i,3l_3L=QK|*Y[ϑO,y) "e O0JL]ƙL^| e^9+LLY?2%# <I:o4$~y{"TG#"Rg$$Wg$t %t8HRp Fޟ^/7koD>bC,8(yXwȞ{c!Iń/'愉>nsAOODu֕'f]ɔx{?LB@)L󺁜 & .=J6yƐ.OYB"e(kәֲF<;"l/}>_g83gBe 3?Ȥ 6B@YRO/REPb VvldL,0QѣL1V~)2dz=h|x>+獞9Cȼ{笠%tS>5& ʆz΢L2k@&4uW,ɬIFLy C:KvJY߶qJ2)N`uST1xƳq+-?ogwVstEw2,g>¯<&bEV~o˔3dLh c4$XjpQ_z'_yKwX'zɱ\v#Ӫwz+A ݪ1!)2&s̴-Kk%i!0HiD _d?lr\xlc$M_'E}^=4kP} bozH MxXVV h.9(3 " otz cwa9pC'+֔wm/L1ܢj`.)/F(̓ }f)cx7" O}ۍF[*QD`zeN 8B\w>Imy&0ojK`lzuP. ;D5}0Vo^8-iT~}PA9a(4Ʋk]QLoo- b"N,umf|:gpʯ̓:sg9QWau Es;D.@Fc;x'ua&E%rvdag5=/e뫜AYz"Oy]A~<~9H!aylZդOk'JCH~J $hbk$g>R+1fMЍ'v_OOOAؔOCc̞`flg_ѬF7jD=Q'ıdϮx4{0GD{FPU '.=U>`ecggT*6wbNvn=‘uo 5 =j7͋aKc4"Uy}Uay%j_ˀm*0$x vHRH쀶HϥVPmKEd9JM ]$8tt+̛y#"+ L_ gT,F}Ne"F$'(@x+UO7 ǖ+31˩Ja AXGxF;>Q<&P ,"Zj_h}O)9k'IXE/'TYxhAlB2l&;~ @YQ8qdYpu7O*O23O SWYB2m0]yK SI$VipnG]X!a;w~ &}Mz@ D -(ơdDD%HАgD2XlEtEQvHRɡ@u+[$7*Bkn/peRf(O#W)=g+;3am}${8Y@S(|f) .L - qF;AG7Cn:gރv?kpdl6cX=__6NcN|:*~٫j~"g؋%M`H%M:K2Хդ[K}x4Ko|@żBpʽuetxuhC,U*E]iD=A xݽ!oz=߳yt݈WL4r?;u($߽hw d,tīRGʉ4+y¹oQn(PNhoקy:Ԩ. .* mIJMh il̴@[bv/H`My\; icvÀsxtO&tSU >)y1 ;^PL a,c,hE%_#L~mEg`!Y-L^ώ8lO:TRN΃eawzcUU=^%\}l%~#o UVuTOS$G^э-<)Ӥ[N!9UT|Uԩn6|Sg M)-BA.`h]x |uqrǂR؊bUϒ\aAB[-uRw ǐa֯`]̊md0e!ЩhKM'֕YdcԀYhSpKF>!R[L6dY"'?jN˭V bSpY!v;e<.z5ܨ?7FjW,~n`MRC:2YM>Q,ݩM' x2YF6 U-^ed㏌o 5X%TߠjOcQ V@Tmø*Ij KuP֡B4%wy盦1}V2q2L,r o[XdP{oY^۞-0/Q:Jڂ.碄cUf !(tg刁i-:av;D>!SޒD3|"|l=G1|9*TeErŖjZ >7~Ѡ\"AOӖC1(;}R֦FgYF>fxS&=γF^|1-._^ji$|̥9ä΃zi]yA;藸#? HXDFqѽ%5ұ2a33C[#H KxFSPAaCzAI0H6O9 ~)m^"$}j=*XuHrbխRydҷ(T >Sb:4@ ^]V"GX)2=x EI5!(t J|"HbTo"B8mdmJ4S !cR F$LU Bzv? D  s*,N c= qAH ! "͐!v(.P'y8hfj A[L<'r~uvigq5+EI 7-2$z&풞G@kpѸ`^0f70]X /EH Ec, Sd=Զ2,[43%h"rI w* E`^+%fO$҆{OV9]b|zG1x=^i, AS0w$T3|c^9foZݯ 5YvnBg4ߢeIXm 0WJ(,ؤ%/0<Hr +i«=;5'ieI4J)ָV-c!#+lB\%o)l- `؂A![D,Jz PQ@l C uu/ܔY89?P&j<7LIű`R葎щ9ĪL3<ث~R#0-Nq\$1*~f{5WŒ -uכsNHIe8ϾcY UzP<5V.?ZM^/s01`!fH#}+E[ɖW<|yYe+ߤ&yF$`V>%Y͌,QŌTshqR%5 I\͌mN0јGzʏ"uM\AQP!bGDtQg$t|,b9PYڻwN<DHXG3ТiJ+w Um,h| ԃ!iQŋGR9a$h0[RJ :q 퇣պ͌g۩&]e#LIeRo뉜XEH[vjkZL^Mܞ/^ҷ0kNӓt~a?Ƨ?Yߧ3O2?kTGp\cIx q}OABRO> sUǻy#tqPѐ H̢XKM 5y|Cdf8C( .q\p eQ{i13/!r9'eO!T6Eڍ>v`ņ̢zDQ?+S.{d)G %Rh"J8n]5kGYc<9طblMh%{k L65h/qT@rkC*@ׇpZ"P <4J.az{_':RCA[&X)P^rf69'"}@$'.ca_ӧlG8Yfidc) N#dtج<jJb[zc>(bWћb t{&vͶ7&N #Ak=f}.چDj+rKSgZ:MMt-ށUAT1ojR~Z:Sxe$]|y]`,/LkT= dRͮktV xXkHDC\kB]_((,R/֯Մ"$_v>wbY0(iκdOuhl-ML7Ƀ{0Ja9s52'i5وXtWqʡ XLު5o0#%0;!w񆾢gb<ԌU-V_Rl `TK1euuY&R~iul|A|0g~Y­\?>Xiv) Uugt rw#Z9KzaEmSÚdKa}Z^-}lZxaǎ6{~*o(1$UWOO#%2,Qd.ڌDF1C{kI9r)OBc#}CAV6k~>?ޱ/N4q Eɵ5mңd iUX/ֆH!y6W+x`r`;f wK/oS%%[n*$sTV3 ĈBjPJ DȊ>&ކYm.ÚQM@dH65/7Vۓuf`xTYD{-B:4TgxReIEF7^ݤ $/"\1FoYq߄qj?yӁqX>I 0RgԴ-g7V~I9M`KE8z?0.Jߒ=&L[mlRdž9k383 V9`])$mL&eJw/C.7Ck59Qsp+o]TB5%; MGo'8? Gլ|q-`&Qu(VylIb(>P+zaLX#TxYc,u^TIL` TEv5_=3ڄ,͒CZU#$"9ίe݅zCLzś#ȣxSstS;*8:7ި*MԤqo4n%:2z,?[ۃI4fq.CII;xhnyWZ Z : 'A0𦼒.&1^<ULȃfD'KZާ0ViZ Aii15" .\"QuXzzOWOxAk(ȃ9Bf#8QUeXdNF)Vhm6֚ԛ/S!tb;FK8vn}CD@MPøl}CbOO,ei8hk9!) Vʶ,`Mv;!}؇{ز nrMo@GS(^EwpܼbՊ}[s3u傭}#,ĝq+EUG0Uf{C$t|e(KRe~\>Ŀw;![Ón'\VbSa$*>UXŲaKiBϻifRNDh#nͱyn'-e."?*VM@"H~^v&Go$1XXj_@e6'pAզlWWE]܊ Nbsh;_ HfçX4a& nEP"5^)/;pX+C涶y Q DP/&s hX}/m`U u~g+c+vw\/{S6$LXbyh_4bwTj`15:Lbu!LsN.uҖnCbc2ʱ8~Kt>[Ô.Z-TS(75PM8r/Y?w}k-L-HάflpߑRK \v0&ƈB4WWvZP!qH~pAF .H{j1יH޿ ;\`mL$Ӱ$JBGiURE),G'D$S4Z&x ƞCo|d)=rAKͿ/v24_TUe fnզ _#aMm(G1!X/eCL줃Dt.CrG:6BcJ) uư3 Y8;IM׮#Q7J 5G\%e=(пA '12(|Ny9_d͍ OT95%Oz[릏|~U )_n, 8ՇM[Ar`dRC"I1~7Zp;Ve+%} /`^Ԗ+[i b[I!"n<4ka1>=~>xXQ@+ Yp[yް`gT˺Rſ76zE6Пigne )jd49zWH~2)ggSԐrr1>#a1(}Aβ/D@X8>Pџ'8]I ?{&U:jQj|" ѽ2?~&U蜺4C`+//Bk":ӇFr`G'(oÐO=wSv/InG>97xek7 ~ ( QUXm܌j_Jr\ΛXJ0$[o"[[/;R5i.Z?NVM~Œƶ+(Xuf+_7)֣Jņl_u8kA"ݽJ?Hּ(e6bj"pWjp{1ZٲB&*y~{I^'}ʐ@AJ w3,LXc$.z7ZǀhQĘ'D_"KjIYbVYB M˲ [B9lS8D1mvaOMP.NqTZ۫*'jB~էS@S$$=mGQ/fkj.Й)*A5aZQT&VBMB6;j!i 2-pmzg+!x$^׹xx.iyK꺌уAl}-.ϵ5iBeK>_ca~R%(l<* gJ[ڟ%dVO0#j7XD N=>9Q/g" x{ҀluJbs<’';ճ ?mف^0CJY;&e y6##?!ՉXL|JR86g/%׿5ⵙPX\Z-^zZ܆:̾uImyWך ʇ7uB4O*: u.]Hđmn @upħ{wkc6,<0,<.[ 9c y[.ɨ+1Y#UBWm$[y#'bumvۖZt/jh 8oҊVBM;Z_6iHDlc\\6ڀvhXxѣW|kJoZm L(jt)$%=4ֱ0kb|@P@`A~#5GmMTX`lmVͨK޸K(KӼQz=~!~)3::9[,$O:Jٔ*7ҀXTKuT7Ԛ4X_0g.j7Y;h j0]1ۅ弤 xGRW?P{]de ~U+YtK!>WM\pPyB":ZWWͶa铨@JZ݀ɢ,*W׏biZ0 {Վ$|%1'b~.A/F3hf0'a!+Mb D._m?pҝY:/~M uHN̗MhX8j + *J#x7bu =D4.b,`jԞkI"ڗԶ .K_jOA -(Y)gD[DfA#\+"\D8<wZ C#7 z5Hk`l1VJO&:i/lp̀4RX0:Li>Zg& D ({r)VsqJPQ6.-MMJyК[;m˳@&7)"81\݊yJ BVWk'=D"'%]cV$%r? "cڶCIB|jKۆ޷fQ3&ڻ! "\ӎI0H8Kp;<>RTig4 ѰPh3]Ddzl*9ˤ;1bm<5ȪrWMb5R7p=ˍU)'wsJ@67m$D~DZZ$͈!+j'u bQsu +&k,2؎p7Ԃ9M߶9'wJjK/mc\^OxUMmʠ42n^k[=[} %ĂvEvTAovy?$G?OM]ȶ1>= BHD7N=#{l֞OWTZuX&Tl}Z{X~M`TOb^fŽ։a{iX ^ P9g Dak՘~{[B҂0ʋ1USd d$AL0kZ [e/`BkHD рU&yf_m@2e+V58yz?VѨ0{ll%d嵮e«Twʜ7]!d=Ǣm'!,WCˇ)SJSaCAS4nhS +׌:GD\ow֛ylPBÅ rwKj s._ kFq/N%&V,[vx8üh۹<)6QJ~ ʗP/' ̶ǡ`2ݒZ$X1/`ɩu;Ompw@!5dsȚ)/NB2)Z4D"S\F!6]bUynIfZf)Bpf8jX _nb:k% i y5@+0HeTv}7+)MB̺@&2(w&wD5Pl,^W7[,˶c$-ouwŽVWe F2O0q R@xSnpJ 9$tˣ ՂE;gw#(sskFyF".m0U}&蛅"׋ZMc1& 9*A=*Mh Ql<,1K7˼tjC,YWKܚzvJT6¥Dtk0rv H8v uo?|8hॣhY1p j-O|t4L"n/m*E[uvrQnnt%$զ7^ؖM/aҧo22_OqI DzSX)ٕPOP?( kiJW kaWa,]NK$5SaGfqܣ2}6t9s%7LTykFImW[gT'gbsf*S"JUM ![u3q;z')ءzk>g qIcx|}wxBkR׳Ow>o88g\ZdŻj>%V`K>ML38m#~-4}B-m;,Fbwx6ce_F%&"M1RjaF\:݅LOW6Y6ZKwseM@]gzI?Z+-w%f v,ei}u@f*uYJˡt+E '2͠٬" Yo$ R꾴jxhy'T˟Т(] ;5Rvd#FPź>/Wu'֐'~X ֕]X ̚bV^1J+g) ~QWՄ2UqkNuO y cg4Zc*UƝ Ȧz7|$ޡKap*J7&<E<(0MWڌǏ+EF,? J@Tc|itn[6M@cs{ V$TEp[uA]bXv"̛x {uTRcH-m짳8|k5!ksѣp <;jdi&~T!)Bn-l+YL(C̒D)PZJ-(AZ_rfvw<v:UC<*\RSyj Ŭr^Ht5l+(ohV1Jt4; (G8읩1W=զ5iV"[\VtTSz{PN5)+en@q4ds_xn3k%5nkFވ];߲FmVAf&T$vYO GS=aF*t%!,rSq[B2coFʫ~t)G}!lՎw Q"|&D7`%L_s+6ō}C\0ǟgN@ު^b1sȌ<] V;FM,p4!y\ϧ6 N7\Jݥ:lܚ=ªn E!*kD s zIDZwq='O0PJH&lhi;2yBWIj\soKo6PgBn1RQJEז4HskT5tt.My|HㄾTmC;@*a iFLf%f`ץbBqOvO'G&m+lj?P1Z&'4_+EjiRuEs!]pLQJD9#&t.Ƌd-?dZ$_VH`ϔ1mk~8Ĉ/#)&4肔oYnjuB.e:;z\ I9w]lP"~E)nCǶYm鼪;ZF&YQK31l#?J |}* K!dk] Zht}Bػ78=,]*iJ2L *I[Tld#᧋$E&60ՇVa;S#/:Ol=|0m e ey!HJ P:!:i3:޷*`F3g}M:NHqŜp8fl]]%.c \@ҥ'N>CcE`E5HڝC]}ZMj]~4EՅ[E7b~fWb[SBmo*rgzHA3*{ . qB%=~<".lQiM8\$E-6䥆]No^%yE4wךNZFG&'?cWE,BHE<{n<8'gAV*ceb{yկԊZr_*VRx<ӌ:z$;a-(gUEhKp[W% J){mARs+[yHu峵k[c|VRƪ K*q-RI7 XW?Tojt_Ja#'Agqvɤ!"aV(%==0RDQ֤o CeĽy@buG}1Ld;دg4bZ/feEǜB~ϱLr?ыYEt]q l{9A;gJ6u"&S?M42E@AJLqF3T$ͩ*DyVە65pkb,Y$$o|Z:3 QyIÆlUW8 ܵg@ç0s$_iSj}_lDLo:󬦚L5f8#*`N+.&#kfr4miH:L-ГyԹ)9|?F`wW@2hHؓf59rɘff# Qa[I}{A&BLiM8<aR+"i{ ȎX\M+>2K޴hji-ɒ%۲w%qc<.! rS;7nra!rcL j >޻\$Y^uYduq|O3i}k_9mG<}Q߂胰???>??? 胰???>???~d`GLf3~?a6a-`Dox'Tø}j~WFL,] o[Tfn7 xXǝvȡa[w$9}=5w_ϟD?}Ǐ'DT^:j61ݗ#==^ Is+"Uk}5vC"r2 C m6ws]>,خ0Vs.v '3Bts$",p2tzNXka-a`-Gai6WuUlYPUԅ9Z?~imǶ'M=ǰNLfd66Fz* :K41 jx>C=P`H8v"['_e]=4v312>c*i7Rkjl2"--u0kM۞C-@H sT l:6kga x(.@]s;jC@`1 23p(ޮ6g. π G<6/̍}hLs$"KQ~uU-{ܾi?v{sˡDfBޠr$:Rf+- 8L:U Nm2eMf<pW 2 f'Ҧi>Wqn|)>ʍL)ґa,b#JYD'TET%~a@CQ56˱Ύ8%+&2Ol?|w0dr;22.|cE€~2]3}JIGrpmRQeAB ]չk]n{?+tk'Wbtw#E'Y`@}G8 cƱja CL/sÛDl7I^QTksG.PLR.Qr?",TN&D4 g S.o'0M) ˠiҭ^yY7M?FnD#"1H* %).V6ZI65xGAq`z}K=|` ΄9Œ5%i ᰱKAc[̶rHjW"ګ rrgxÀ1ផ2>H*/Wl8lKQ%F4V}n"Z1@3e:7a!lWvK9WYpr//,,O, g aq73oG^x*>BVXGCO(?4.UYjW53悰S?|"O0>3;a Q4+ZCҲrԓݯQ@ُN3DiQ(se㇙vڮc|؞K/a iqVgtL06`qHEIa}6 #t{\ksYEʿhW+;3>MaqJ33"B[y񛸫g1>9lރ~En^tUƔK?#XDՊDc*duOu%r窴`*\kpoBP\UϽ 67@ ؜&Wzr\-Ƅ0pٰ8k u_`u4V /Gʟk/|NR㛰`*巌C[y\!9D'ԯF <݉ `>9_ 'OD5d~} KՆݞx Y2*-^+Av;=PWPg¬nkWm|y7awO)Cѳi+[ۍ|c.^\b˜0V\X EOflD׎!ע7}WpoYP^*oRwƽI^|:ڲ69h<ʻbW & W1b(>xqg#Co]V%hHL܏mm3n~ɚsi'܄E^=~LAx"i׵hXKdDdZYwc 7i6FKU|&)X~r/3cc=]s/?Ch׏Xa"#f}dP}.X\(0sʛ|ָO2))t+ƿ+oSte||V~ס׎^HadLdO+‚ |U\sKRLy"r-F=O;o:%~?Lrx9``7,%cׯomcZSFW{֓1eSp,\.nkHO7ёprJ0/z\O~{<:Qׄ+/+ea1BMg~7OHv_y%a5x?17h fsDBۄ.Z#WAػ%ck5b[̹7uv'čKv zO }VX]W.*%jz::'w%b, <0com\7 7Z_d#|7 w՟ۣc o಻1W#o䪫C#i6b݆{ZE@>0>m'Xq0LU];o'U`j <-G_FoS2nt.Gjqr [~!:3s.#t4yFA<>t"q!c/;b>i׵݈DKIx]S nѮ:~1>ra.DSzO˽cU'*6wBu/󯄈(GcqqK`NlGQ[Ν|=|U,DƲ<~gk?Hl^*ǰ L8)BK\FȆȨRdlEFWP$ /Kʨ 5kBd)7ClAEB8 CuNE4̸Wӧ6 FO@a͇8Sx:gܳ(R֠c_/3#IW_cX/ 8[o Ī0aVr8ϊ, ?_ϞXSdV9DtE ҌW+ ,9 :ށ <'}HK pEow\8h);5zZ&- S'};i\ނޞQ]3"q;9 qi a|u!OqCk'WH~9kЭIj f!ӰyF;84߆| x9L$f_ÇA'4+CLTYǑ(J%i* ,_+{ kMHs.#.- IU}NHQKhLQGk۱;ON3vgMg A? %.$rEc5iWLx9hj)Ow3xC=Nh/}` 3؎N=Y(!yz.NC(α?i ~;B\5kk^zrDѬӄ6 ),'~p:JGFʙyݒelu4a.{? HDxOkwz]Jh'ERl.V=iM\41RPR"a2zC{3+FrˀS 苐~ EoFsK-譑t t1<]z3^QПAW58}]asgO5x:CtGQDsIһ0k{?`v4y&z=9e9|iyNS oP8lsIC.h;n {,AӅ_<&/N+ΟJK5hb wS}좾y K*ȵd BfםZ,fab 8s2]Zn&Sk%8noG"~誌6{8,b4ɹ!r=+ѷE8Y4΋VB ۣ]g!.D(#=џDס19tlW;\͜\d?0iZ%3`rm9Ӕf0aO-kt {-dIaxrWf1(! O~Aak£6=ƀ:hhৃƠ&ȫ5ۄ[©!?a-iԪ*(DGv"8*ݕ T!Wj*LNV׸"x:{Z#c8)?WPA"OGۜZA/:Uq}0IL`1d#^R5h`F7&-%3Il\ͅɋs`&r]i^PH/#09$tzMP08z.Q6*F8CYeMƨv@rWFbeE½W<*܆ӄ;۰Iez/35w>e2aokhā2!I"A@7 R'T:nIDF97)/HdQDU@/{M̯\&Ԫgz^E4ZJadI,1Hw<=qz\ ۇ݀EGttygah6 3xQ*XCR˼AŗzbQM?.:82AgLc@qoYZeh`X[vle\~rrr5-^ˆyLZWVnԜ /hqw 4η)Ж]"htY~hWB .pt`U\swXfb&-1# uِ׉,U@Rg^A2q:Yzsɝ/S0P'%][m,1Q栫2)/[WfW^Vu(:Q$9A`0UC% lzJm&^XurN:Ygv4pc`{fi\)v8!c vʯނ>R.Pf3}ݳMvXʥŠ:i2QR:UE˴W|zkk]$v^j1|: ?iJ;ŸS>N"Ө@ |HP[lDE,H:"lITLA&2Níֺ0ed]jϭֺz㭩G9ۥQo poB#'߂z}ث(zْUno|D=TɢQɇ\רMx6Û#L:/+ r1hOc[i@@v`;hC9Yl I>J-5NpK-RbM+:NbZ۫ӎizYpDgyŌG$̮O% 1$AiS !pzݘl@Tu@JmfA|ٝ'ks 5{?6vcvu_Bm/?'UqXTÌIX55л#ћӑ%𰓴ێm!shĞu8yKk}̃) R֒QQX'lRAABw4吣f*ǘs|s]M3|N }{^q>)M(1?l7|xBiicHx0*fL)T8SCVZnV+_B K 0s A͑H?_*kt.4w+ӈv> oPb$L7NݞѾShuMY|-K9 ]SjglVoz#|~+}Uoi ,K'Y(5r<(Z03˪lwcRoOe#{E%xpuDw >CT9cPo :2׏htS;ڄ&~wSkc;hyNZ.va0 g2)CȒd&xƎ8jcǜjG `')"(gM8f ~١mڡfJY>c1[8Ic ͱۘ+҆(ۜXEJ)[-фMaR*eqv!S'5762^Rgnj/)mXi+2 Iyx'SB_WoS&̰(2)njECʨ1hJ  ,D] Q#XcCGϰLqu'N.4$PԵc8αV'Y1#erИ. o6 IDAT3^$aK݆+6ʈp&FƱyRUFtF$G4r6t,@hpx=b5M Z,2][Er8)"VJdg,E*E+ e:̥{-]͡ǟ;ю_zXˬ`۱a;)U Sdr&ȉ۟gDټY8><$6vAյBdj\kN~Q`M3&;6qk<NJ LGՠpS4j t[9i\i貭W[hr9CB+:)`GJ s(@(} ;A>vc裌csQ V:Q`&0_0EM?hy* 3A\YQNxq|fL.AG>QW_Yڨ%!hٸ .m41Jxׇ>Uy2%rv)Xd~>uD۝<֜ɱ(̍x&NBb$dATHW&' z±#Ӆ]MfHdUT|:Ϊ=WSg]rQ|XragZ 7P Yl46*gà3[E׆*/WSB0d/9x/FN\yloxrUCi4>@]p5"^|FդZKɃ0 4{}9::p%ܳ6gMݍ׍Ktip I J&( # rJuכZseJUSxמ(}ȚSGra- #\=>{ %h"E&Ddx k'>Zbd2%jQ2CyNi kL!<0); -IXs [9+~Lק%LEuXXZ,p gGg_MXX0%+c`E2 ON܆pO Yϧ=T~  `A8]dO{*#Y IE:={,ܵgO rbR?36UґR5ܜd¬ԊoآhAOe3{vU@$*8%Z0{q;7@iJ$ 6GͰ [ta;,%# ՏX[nEECؑd̪ӐɎ}5+iš0=*نAP2vL R{%cGysKʷ8U8UB9 ^[f<,I[^gY'[ nuOӐY ѶS$:>Wv2@JtO!{҂`cݴ>d!(,0 39<-蹰Χ\* 5*H7(Ud섪j5X}{TэZ_=H᷈am=OtPg$*EaS^P06 w0&z ""3V{۰펧pÓkF7>lBψzԕcŎEtDGv:#acFdD`seH,`&-a[wZfXX,l.`sTX*)µyT|,kez'e49V>:?5S)|w˟*պP 8Ћ{C_Z;%FWBBMS "Ve)49VSb̬xnD,G~CZd*usZԆ)W'A3}Td֍ Zqs@RU=tJɔ4#l''.GD#^NEG'P (yp?@2w8=4G$<73hBҹKѝ:MY<˸ihnjцS`єx=5jpٺd8S8SorR^a`"2qtO~tL/* @Ҥ̵뾴ߍfw lHhK ` c&rt]aƢ۾G#u1ӱ]QI׾zVž{Viݾ-MnDhԭ[$ &Ld dk%z>-r*- =Cנxp Jaz8 RZݢ4Ab^IWeמi$.^QiU ֫'IhӞ&[q#ִߢWT-W vYp+yB<ǩ#3 ]O|/lz:vT >Ԑ#2,t ,iuV5 hEKeI7YpLn8WDjNFs%x'xs ZF_+oWJSbDgHGxv@pIyָKVG8w90ݎN&"n]gyBk)+Y綶([`O^ny)9 ޏH}%q G]YZ|nM=`#uQe}'NPG ٔbćَŘt`2Bda5ۂ`P`#S蝅("QDrX;fTCN'+;VTgg1p8-&zB0vJ+>D\%er:>B"z&L7L]V ])5&KJ8kvF+$Hk)/SB.9Mي,XS{cS{X[k̬%WHq)Mrz[TWw;1kyyS<$O,`!: ]XI]BcÁdb|GҎ^Mik# 8[خq7³;>xJeԂusqr㭚)ɔx 2k{OǍsǭ{kjZ |ZXtߦTX_%|L{˚Q^eil'  :)AK4Z29 TL">^ɺzxQxr}GjVE,?\Ofꩍ<Zp@.չ$>NK9Ak]sHm耣f#CLizp;7HsmUYcCs {' ,Ǿ\yRYiW)uKŊ\{%Q`|61 ˅U֥Rsjʈ)^K4-x ~qp$jǔPOwGߧc.Ձ~292քtc}Tn .LzLO:u6e>OVɭSד ' %s:bHT^aQ'kdqx-@&/Cc#Ҹ /EbUXNR'ЭԎ9k580 6 ك dVR5AQ! ~#L(qCC\8hB\ )lVjI9+D?_e`@ؙ ۍm#& O-l4*|ԭ|YǺ 6^ᦓ0 faQ& @^n6F)EEg^@2Cd!dwxw(3zIt~5f!>p"E;{=GQ/"9pБ39J i( 9cd[>Le.~8UBc3I?\9B3J 6X9LUSOʷP(xNjM$FtB)K䈷ɂ%wH1 n) fUc%aN=05pAY'h: Kj .cfM8?TC-;M,Pp^2:s$&IYjۮQl=I| ƼYc UY[4_@4~]ݴl%icma2_"7pr&Q kr=Ԭ/o Dl0rԨaÃy^OONi{-vW*tH`=c ؟PnאYA 5ו*+Wޠge#݋}ɂUrx'S[+3ZzmRFlYkϢ#(oR^I9 *^S][MYE.1Z14uOic,1Ptd|uvg[*Tj*Zl"ʍy~pKur5z+[+3"pZlˋ ^;yN_nI"vi,t6$ia Sjʀ1c`!MHkpثNTD 6s67YiLycyg W)w$|Rל*s7)5Xe|US|I><6(W>]Se\"vNǕ¤Z0aϟ2՘.͹jd*|[B9'aE=Xf2u EC7*jhƵOJҔm]ZeZRLkﺁY -s+jDn%S#LA7bAmYeflsԆY<8Y'6>0wS0ۏu"NC|؛$zyɩ YBebem(6h""=XX@zoTgІ;5)_9 ;Eޔx2U״|̅;;R[TXDiOnB7c0\73͗gW J7"ukHK^Etڧ] =e;n֘.^[٨ sjqJy)XD SDH&D ːeMQxzl#v&rzW78q!`,@Jfhā3d`;8V,O] ~vvdՀANѰg3)-ʙ g:a/HXw 8/Øn5N6*-72&`J' 委kbNtW>'x"3IZ#q̟k[1yeug 2 ӑU9aik,džtOc!XdWG8 ƀqB,u6oJu(;ME8qO+֭DV;ICUqr7W ֥'l78ׇ4i ]f(%Z)6`+Qqp:Fu)۱s"Q8>e!>tM PJn3q o (͉Nqy v5yV;kfLeAV {>c!Ē: G{rrS5䫕o%KꐙR?|^`s#dw0~]$w˸fՠL97OnWչ )u y.5NXKž: fW/:oqf+7Q] IDATʟ1s;Ru= yN(2epZT0Q^H z.e= zPj\(B #/0JY̪Rj d?UUŸk_ËiˍJfgF{NfqxxVDYѕqJ@uUr+*˛hkzݪ,Ǚի[.rEݏspHQ0T7+Bk-cSjAE3)Z2& e]\n~hӥL( <"ԃsLŸ= =8 GSĎӌ)03 I r Ϙ#,k OEi?O6,/In0F pT/q[Vv(o}V^xxs•u|mGA~k>^& f| Mzg0me9ueN> I A(ssЯ#+Y[hOõ%O,"jbY8;JGI"7+)BzɗȾ\J̈gƪW0:{ ŊN*wV,Na*IN M!ی]!! u.؉_!XZɫj>- _l "[k4̊;k^,BYM7aSR=;>shgtFJДtckz%_(1-R6u'!ԝ{m˗-XS tzOߒ}.Kpǩê#SX[T=Ͻ*կ:{ O*aLlٔ?+Fʜ !~F{_^׆M&t'o3NEu>G#k#Mu\ lCD0+1,d4z1Ar\4 cL6hw isFcqҴ[{baی сSpdzl49#¸/Ef,  jV'OSd/)]:hDğ+RD76u7Yf&.bQ0vvoޢ, hTPGte˝[ܟbRxU{n\Î"Q{z*ufRU@^\) DMF!-(_3I񯜈Փ+g`EbkZ廓WWG.2ap=sY"OF*p@D9VFS/WxO1E-# r3Q{"H.ha tܧ,.W̕+4ZZjUKg 9{H=%2gHFR4},7Q~2iX[cY g%E {2}NC SDgqa\t̓=lan'IXz؋EkN[{˕t*zej-rԛ-(S"ޮN.+SjpQ<1wks@R m$ Gu:ZHeV~+D5IWbDui8(ɭՏ<Ȕ՞QRuJ.S>*Z7JlKXV6UƈsA<ׇ#j.t _>=cgF[׿jm<}|U9\j'@'Gh #Ѡga^ Ǵ0#?g m\憞nҰ=E`n"dG+hz=i• mZgY+e讨sNUx__:OZoS>27KSͷǾOCw` n1>Hr^څ%ѷ+0"E+x7▼#'ErXT-v2ZsULې,Ì+Ą+H`gzRp%т%+1'8O9 L S5]3Bⶅ)mNG8FsMAI`|}!:SEcISn讌p~f+;73<ThYcNЌW9`MuhaXsOu+h.,wR5iOuR_+"!yb?/(g -}ο0a{?ģjwQn7n2 RJT 'Q {ȋZ n-ܼVqvXB:.NMtOjR%jLsn4sNlԪ&ݹs')֫>UZ7+alJtIY,A0mE>lN>3Qr\9GIMI!1Tƒ(`*Xgٷ7yo=ZzmY%ٔD%S 0bH9][UsVuu uV~oQs16-Iu`r1iԏ${:@k #&%B D,rD>T'ajG3LwR|3Æ"ZqFJ7i3}Ry\WJ>҄bh_[),O.VjpdǼbX.م%-˝zAwʼ|RX0(EZi r ϳҬ~Ot' o4|5-3vK6'3S@dDwt-~in]RCڪVRf j6")4ȗ0"[$?A @J][7L }!|n*tA-m `z8=2myL SQq A` xpB8FAk›&U XTarDLPԝr29B|nϨ$ulJT,,X"<K-~[yH  ؏IJߝ[@XY;PvLPP,v0Vh # {T^8[ݪ տS=wU2.Hoo!O+/? bxw|MA%T` v)4NtM4Ë% [0[1wi1 f0tVBC1`zt1ͤ:3Ex39.aEN:Ә1RsHd #,-Z0Zq4`$&ID.O_{x2 /ij=*(w(Ok7+Bf )B [gXk",tSɘʗ p˲oSFUœ]_3F%15x{0%5›_a^ŴΗ`}1kaL YؐE5>m3IӦ.RQ:@vӭ\~`Jc8(əJN~~C~:l.ɖ_LgJ UV.V1lz|iV8=+t4Hoyٿ} Лn)߈9/NꛘN6YБhqDX+s?c8ݚ.Q7~d*%ueW+ef RCI^79{܉|Sm A-k=妵hnH7 !\|^d/ q,DbUa0{CbE ZHZqXe;Mjutćm#7sҭXʵ(JfsTVPH*v[×yat;c&1U%tÎc>#gR~ލZ1wllwb 7O&j}>Tdך<#>еLBN(Xi ơu4zh%00yJ#579c"tUDt ÕJp4ltz[W^ԗXW3*oSRoky&Fül7%2Y?<Oyk$xS7h wJ/&,yM?5UE'qss{ ˅)QEK$:$t_=2QVZVrrFIǦamZ~*ߖca[nɰ-5aFJhhq=U20S[,BudGBkgg:oBwLzkNM5o=%괊3|l; T|FTjjH5:erIcNЁeJ#LBآfI2SԞ<,>مY鵒^gOQIJ?ڒ<3K (ry A#7LPy [ P0ûAZM9 + t-+fh 7#W$m,|RʪHYKۊM=f~ lUgkXx%|~[xsalK7KCWTl3L?"ZdG1\ b@kao;0W 05}.G dЍ\adP=9mWz{4299r 1$w0B*28aDZzIqorclTѫzz0CLk1$g;'^+o~@f-dTd/gAzZ{[G ą!|ASaVG)DAt9alB9*Q%@Lpe]hVx糑.5#w50w;1jtuR4i짢!z+ڠ65h)!RB8e]KԼ,IRPi_)M &qWI"synb2a5rx {ܽPH0ΎsGQO4|NV^2XZ_c"ѬrAǍRˇQE ثz-Ӌ:m0ߑQ.m'X"\Z\[XUGی+SXy ULO=yDxrph6ʃmS8 ܆>c>af"0נڥ:rtnjC&"hIX1tZ8C-h֞-*w(Go,g2OijnW*hM <)|h Lv̇cfٿ5O@NJ3/n3/_(i'şk+5;sʗ(^cOİ w`4N~N؏Y"DP,NAI㑉ț%t<293cc/ĕ–e\PZ0F9g8o8WN*cČ:/Wv+a"fa-B+ fŶv‹ZSFB3OW8GPV"PLI[ URZ g >~/V@95bD5Kߩ)טL*cDa~.k=!"w1}} {B)ʂvTi+OEmtw38,u<:n{#1﮾Xի}lF[4QMKy1U8lNk+Xw|M= JVe SuDk$lQRbнZZvPVWӮ$u? EŞ]O)'tؼh__F?nl>]hO5}&MgP^f#ף\BŐys8MOvQ$ĺJ{&f<2{ُm ;W BRZ&xOʭӆ©K/;Aa[/b!B6)!0<ꡅhBaQ~eNw  D%i+LѽǹU }Qϕ/jU3 774~r}-<km2OKe#¶B!>=> z5["rvU .bNMqOgVf2K>kܻt :Z$aː>Z00=_gJaI 1W";ۥ:`af#1Wy.AƠfG0!̣o` 3USӘZXRh2/™>j0^ faV3Qا`o?W-f@g %^ٵؼwɄU66#0Iba,zrzUZroBxD}4C#sMhPO V)wu{_j4#Yt3ỻ6:Zt xǻzyz}!KGo9$n9$mB %e(yy, S#G絛Z:̽h \8tG(:Aͫm s9θWRbYrl`.s2t8̛25Y^×)myBjYerpЂ pڗD9vdqh˞tP1KDx9eJMeKbe (-,yUL3jX" vxV(+5sIEE- 0&&8E6O6%V7,v)&/ ӄz!t KYM?[wL|;cu_ecDko jS+YwySTRǭ7$c+`"TʟZEo)e5l(ֵIoXNau 6!%wB߉4vkr;lP*0H7VD<9B\Z>Wd#h FX,/.`2r#fʛJ &+Jc_©R67\2e&`+3+W;K>w'23~nְQ_/Nze^2,ٵR# *| gsqJGlo8O1pV! SrdPwf?ubwn7K!RW`Ӑ^~;pI̟NNq6}{ IDATb0t4eHP$mtM$GFa"{>Dp6Ya{|t3ּuV*AAQgku ]^O^Xܭ|&5fFaw&,rSpdQkM:g,s+f+~tO<_zc'oFG< ӞQ4Ut4h,ӽ]TP}fDE<<.FT驩5w.4zkq늷(OYÊ;N<XIҼn@l G0ӑ9G&/d3g0GiXdCs<5BB iӭ=5,<< JD,k J QxUir%=&2f[dCi}FKrȽ72!MiJ/7UxӿM4}4KH^T^146L Aa dS+'Hʹ&b*ӧ]NUll 6mJ\X3n;+E˗OȂY6аI.1=9!G0wDkøk ;ѧ+v:/R 䵘k cb (/E-bNw>9I~5>Pǰ<},%]var.v+W*;u Π"eO҂Ki8rvqɻ^pZf2AN4òM%u)kM,5MrCܗ6cI4e1 T"`hh #ː_`'<Ғ#zOiUQ/MW%>vWg]=L;mM7cLUo;AmlV ;=$]kQjr¤qrd&_ۍk윉p rMJtRl6EO8'[y }3> ["Ɵ-WLoǶ^sI' ůrE [O~%+?~p\/+٠¾m;f]A:5XO ~OI2%)(*`B۷|ތ<1<)5{[#Ҋ~ycg[]<=^mK+?e ;T ',D姐-G,nKg}ȾPڻՔ!ؒG.h| _S oG1{0r/3qgi'm$d+НNtwqkk)>G"cIzF b<]#zqҦax@h~,>.> -pR>( Zl6,1*I8OSP$\Jטkh0CeW5¿A[b$c9K6V,OBz3&Ўu)h{ YO (V &*CgJ3)i{{[5]RA $K_G:G0GAߛ,mwKqWg^e 6 H^#WNƘ* 5,t`@x@XCH w9lD A+J nQ*)TvXo2,ha;HG0/CHPVƕ{tS44JB3͖ikS+6#tKSUdǷhC"pZT)ːm xU*UZNrlP wv]L~Sx(赱-7?J EXgOV3|p9 y#Y+`G-hG`bZN h2'~3o܆7(ntj߯M0p0ߌwE;}NsjH}&Hi1' )8fb_HԎce-ˮHKc=c pa8PCq:P념2R-XcXmX.?kꬽ(xB|HTo?)\&=;*î{(Sa81el\P@f&X۳k{Ž:Z43xtlvh73$`33LSv*QfPEF_| )a{g!w[Ϋrh9َف vk5_kk ;0v^$LG L.$$.O.q")Bo: ˄]<\zҚ<~Ha<)CM WK^6TW^4gE6}r|E=Uqc}lX;pPjqMjx]c+.IfөvfSThE+C^AʘzC);ZBC"WAAB0µ(j}ZՔ,~nRD|Jڽ(KuiLsz5 ^,g7w߆فy/)<ނ*-؎CcNi9}.y3I(Gmid '6x)=l)0~ޢ1rK[Ramx8q8AIrg+3 KW t,O4ۦ_VBUծ§N^g0S$5 ;˅)fmLὭERQ$YWC [nhĻȷf cе|bx߿mI{׵bP8}eq _3Wcmj1-_Жl_qfmVe܉&vSh @wcv; -}) @aH :ldѩ$D=9c' hP8njB. Ж '͘\ω ӡG W+'yp!Hŋ|*fݩlǷ-(XKwp#:+>f ¿񻽼_kz5`hnԅɸ`)Bw8XxHYj #v']ko ol2z:4жjifI~W=o<$jK_^1J+Acr {U /3bh VId:/.L^\Gk~"jdPdgJϠs[ݘ.Cvaf1zc6ҧQTdv,@:ه2`wAa 90=pY#I_O(-%66 %>&5@7yϰXfbܥ<ܩG:^`>!BL x56ofoBx1q- .>O6Rf,&R[s&P(KueJxEzOﰑGȦѠ>өR3Y`(UzU*MokɴW/._C*9x'2#a V5X| }@^|/F{P ^t ˕^s ;00s.G^p*|/B78=o58JtoE.ÌGcsqcNBd`a8@#ә^&*(UB8j8b}.La1cߦk9ӝD'0{ҚO=՝f2=ŋ HVtT}leF -$ԕ8b!4pr^35UMl§#vyW $iZg^,-etg/̹lxp5m z h5xp^pě@F=@B딫)WygiP WlEꖝVSYVByH΋YtP#I#*]%5S5)([[8a9¿}$]D1^A^-=ފE[v9Ppm}JM8f"2)'3(89p x+ՙ1ᐖ G !L+!6 iɘznUy߭4ڭ 3 L"{%{okȅO)_QOs}5&,Ɉ#9ojLG[M۩=vShjȤ݊U4uqlbmRҐ==AN__U+"% #w1%M=BH;z8URi2ߨ(Ӟ[ Y ',2} ]V}8k)LfghfμDR, .(ڽnC F?=A;ۚLEvɊg^EcH Aۏbӆі,?l!Dgc '!ŌDDO!DGuZdC8E#ݙm0(*ak[55ƌ7y YdPY7H6-!%/ls/HƽR>\_ _fD_3'ikou ʟ+3F ']NBI~ycg&AJUPMI?=4u MfUVR V~_ScCT!R5VG'\]ːZl!sɘME|u_ގO¬$^ p r <Xr9 7|ɉLB9=5' <3tL ŅnlSN6Q9cLs0Yh*-&5nfV a)rۊEb{U6 ]RD˲Hfe>ȓNlFڡrT'@cK^W`N:~/fTdZ@qZnp< Vte6;4nTѼm#7n:._IǾWXEq^1'xUc M? ,Zb9c"LH}yku`>ڈz3'{;v}O'OKs f$#p‚0{k$xNKp4|X֝J)]I!9~t#څEFcP]=$6 Ls 2z' cřW@XcY,މsO/ogv1%Eh'~I<3" ST=nćE Y05Lf+=9@XT|F3gm~K25xxhHI\ =MCYqϭNM{-Tq;EՇUt 싆4MGV>x2@5јKYhԨݲނ܄}"_"Y,ƶ2l?a~9ò }6&[ZN皘\mV\Qݗ;6ϲ3\+ qhp uWb&Xoɉ=y |kpl1)~a/bQޫ3*iCPx6>\ RCͣA迡'|5 m:k(8]~^u,X˽l%*:(`p0v43+$@"!!$bKI7i%;ja9'RNfN%H_L!zj5Hb pi9VddOX Oc*E2Lt@WjH)Nrnp@i, j1C!B@.axҒF@\#GP>,ȶq7ŭǬ55bgWy%2Pe%!JLd $EpB61(|Aq) z'Anj^H`'Qb&bUۊ^D;>#U'S1 {{6wT˄dirmw%ף0dh^vʋ rim-vjNKAw%-d@9d8b eysLԗ w(B[fRa,UMPP$6rzG WʢIFFga an 5jËaË7n)ﶝ&86mBúKZQaU׮Þ*bj& Zr`w^݀A{vyؠ=Id=siFG:x 0)9erpxBqM! ' fDATa@on?coR^H3wvnW2+} ^7QBaɪ'SS -,3R>37e(!}z?+ |@T kEsC#T?|_p-%ϩ+lLVZXWgmnZO׏6YzEN﷠X2f3[ޣmV?rjNœ+V|0Rf$?| } 4G;k[bʕͣz}jvXy3KyԎ\ژf>uŊ~4mXqt[~8wQD+V,& H~y̋1/`^̦^Vy 25/C]Y2]nu-1#z ө(h3sҝiL~N0Dޤfgha>G}jI_L''c&sÒ2 ANX4V8mR+ z09"{W')ɬKCfeeU fͼp #Mՙ^Hsn7+xvNMJX,f柍'߃y1 '8:YM&kW[{1ț1߾se?2̓SpV#5e,)5,sӢ3EAReZMIS#`sG LvB 4Rq9 oV%#ꢠ}1Ljp:>#b .̈SV ̷i$;`ȉ 5*EM+yͳ*]ģq+ҫۛ\!GA̪Nh'&k4HpUF$?.GwfBX IiζИ͎=Eu$>ٶLjm 6p 4Äp @<ppS#pFBtq?X,%I\ 05UO;KWo@kkD226.\ 1UA: <75;xկ;`_L>XYfЏA摶,]=E:%cbu$%Е @]Tm:߽Sː4;(B;JLl2l6يn3iK<7Q.Q+kx&t.&V$ڗ#G`'QtCi Mӿbժ4J<}.6«eYcn:y흸YKZҊrv|<>KG,Ie.BZIgSUw\Uzk vN%e>C`up\!au z& d:. n]OK[| @$vD|IL#c^ } `!N41M'<').Xfwx z]n˝B'#Dԛu_[NdJ$LB{\wrq׊O eFk5:&eui64q:EoN ngqvzh"+ܣ,l>?p::q&&c.*v -AhqcTW!S]֎װ4laeTcYeGnFT^$`eg: ,STUajS_L=ETChD cKkyi @hba0Os'cϦϠ>A;"70r"řLO7:FBCF   csòOnJ`YAӅNUMEre1̖d\lZ<+,^=ʣ?S>GA5=FmZoB_wھ2Q/^D؝4I~k9T- U"Ȭ"~3mce)+_:)QdC2TSd2`r?:r:T ҋ/m9ILjx%2d dv.B^˵lUF `;&;ѷǖ1Ou3 q&\S NA"DɵA/w9P !Q8WN'.LzgŸUKWPtUS!62`K mD{ )0 @3ORz~#ʖ%HK_ghb_&\yZ l%*tJuDzueժU9Sb3UsrP,ZWڻ*jv R,7"gnEBBq;w'W0~ Î7Qw݈s+V #o'?D If!k=510k 1=1)4$701 ك^wAAXљ3hY+g YA4F2LNl>R^apx#68 Uy_;D OmaYSB/;5uV&wVG#O4.uCəm,A7FeWbawdȦR/; 8.͔2=+ fCQiQ]M-QP+ b A%H 2K@1LXii=mH 2fL/e W~}A̜` }O m *cbI:㣘ӁN WBkpSKc $ij1]љ$;eD93x41C]9b"n"۫UsEoT!8G*;O R~l50i 3L,7>E;q]V e_2 np-1ICS?J$X,R#Gz a#E&ʖ[B:x᭣hw^WEt;sVNݝ*~d"8@W賘gm a`eH->ϲC Lt$֪稵-lA?jݚ,nKbDAct"70Stn`L,F\]dBNuڠjsQ|\l,2 RarTY1j { 5cR3^ kik1(._PF-2mqFi?ZmR;Di+ׂOova^+`WP;u {m2*\2m凔lBaGMLE(XQ -/e ĺR~T,c\ƫ>pB_QZ>E"A@WE+2+ݍil$/ȲyD漟w}/5&eV3qL3ʏve7Gt&Z!q&-6I9޾\i3LOUӾsZ 3,Y^97])e 5ۤ hm3̗B-GGcj=kO#P0WʼF~[KR|OX7 l "Fkh[OfN+eyP$Qvfs"߻~*@uCl䐶ݮ;m~XX0cP8lM|&]V5mێ%S{b1ӏ+VL*{e_3bժvf܂XfoA:$caa2R~nćHCA [6:Fws)`;IKO͜ynsE4g⤣33~ry-cXq!xCTdZVQBɅf#Qu57/SjjYɿg\cc"Hyq8d $\&lrhm+v'/ vg&oYA@P`FCۀ(#zY Η`òL+iC9 G1mX|^i0fMznexeX@Z~1([ [M>w);Y,L3P>oX H ,xymt;BI-0.tZrH[Ttؾ +c.J;K4Mq&2V-sh.{ykw;:Dy?Ee-ʰ?~AcHN͑֊[O!0;0s[w/Ř`3u֡э`x8<Ůj Dǣg })~zț}LPNh>YST|Dwtaz3ȱdemtɶܦ<[JJ ː![l"G7 V2}]“]a+lͰ̪U5,Х(^H}Fi$ N(E *=Ӆ{wpv(Kgpj0ŶGg"v (x1 SY/1v33G*Y+O&o9%bř9X]S܁ى_܄*䳓,C_IkgGf_n5_\8;&Tg|I' %kB 3?LTbb{.;y6ϳlѬhT>U+u`˄&{ 7jV\˅Gd;1GkD@8O.dIIIaT:hafw^ӝ  ;R5uU-9bgIPvI>7*ul)K=(Rٶu^-Î]jG}"3٩ފ> y!ϙ'u~ ]MXHbcyHKp\i\?|~ pNVVzzck09S4c9L AQBM5ȞqU!2hZ -ì8lD"=6`6iܢ<'H_X$ppDBW*.,Gn1GjR O W P&J†D pA*ߙ%|僆g"K^0NlV wX\]:.ҍzC&!==xQꯋ ?UB\1`W반]R hѢT[yZX,|1ź;J8̣|7h:.2PbTPFtu_kؔ)Ɉ%TCƶSE,1Hhܩa%"b>J5l0+i$C3Koh_ܬ

>bMGK;;v \+LGh5h/eE!<#8(:sŶwbCX\_6?"jpW}5Sn|1u;[Pq#ǯ!~&4/$̇BP,,'l )7g>ꁀ6AZ=\28yu/x2*$D$Cg~l1< 09C-b֨e L Ӕxd蛔`So)gl\/ld)48 a 7XQWObx8g0 QΎXX!t :苖yOu Z~e8_w -íVue(8EaY#C|ԅkAKQPBB/ ?!IvKP? |gEǙ ^aJdQ2΋PZY,$z# _Yx2 Ղ#chG=j10Y8x89aT~)kFlҙB@.׾l7zzTrldPۘx#͏wZ[XF_ @AAXhgi/"l;1aWJJE]Z}8c X,LW3[VU-XSg:vVQլbYmTn46WQt^lz䟬G݀=A˯ y7|9\s_KcBC{H oFRKKmZXO2mziUg6yYS . HzNyiOGECW[ A$px@~pbUS8;!}([itf&~Z]ON .~ϥ Iį(B ,lj8MRR@AËYy),VKԼƬb.jU.ɟty =dP BKB;仵@}jC5j{ 5P73漭#*c}d5v> Amt=**9g f+U;~IH KQOM|T?ʷ@J.Dm3Q9"x;PO;IJH {SQ){0m0 k0/,˒/{jO G4 xPDxV\%]i_tV] qF_ۍRY9WbzDu2O5S^1asd3԰H1-:F\Fa9 ݚy؋:"ACA&۾%TҰkoh硞EЃ݂޸m@p NS`mn+ifpTMx#T$Q_]#)\+l< Q~XzC bYج D3NFkByQxGFtޚZՀqN=hdlƳ۹{dѶSs+,Q4uSݢ`uuܥ}u>_Aޱ*vT5vFekR VZԝvRHsO7oZK(/g3o`eO_fu]8B=o9Ɨ!ːeȃÈ) yT .b۸rO#F3]'s= 1Q$ +xhu  Թ ifxpsTۘ=cpB +5g P.>uQRMޤIiۂ'sAJqU=J#*zBYpJ evZSEm,zhc-X1[VcE+$XVU]k  hw#&XֿrQމ_c7cbPxB?d3Dyi,][:8ջhi9yݤ{؋>A,|/TDQdL@2tH,fpXGݦ-}i=%ۻ]viЉ=Mz,:p*VG ([ usT ٠3@xKIɢ? zTGי5Ev GS}ȮSP}sG0mhQp:W1RTyeG ǣ5 - /lu^ekeINKhgCNYazk *$EV繝= h@+5˃hHDU m_fX}T,Z}4 5?Ū ۟ Jc ɍ<_|f54ÚEhҧrih~C5đ&3d:,BVl!czY9яXA>)0 S2` ř٦f50ɮĚo? V\bEag"VD!g=[DZbYu&__,b]}}̾5B6mŊe`nH]~ PQJf޽%;zkRӄso@=r56Ed޻ڦ3xI/23xȣ "Ú[ئFyʋ'$aGo@`W!{[Hbwg1|d=m&w;`4 pgl!#]AHx0404 382̙A #t{D|zv7l~q^l91dX}\x|*9d6F~|%q G6l=8xkTN<}Ż()4UFKR8Sn%Z 4no6=;B/fM]M9A'E+F`9v[?8,Al6!ά@._oGd Cow>yN oӿ 1Y{)XMGm8/!' fHud_p9Iѐ$a0Q,4-Ee_)Qj~&Fy..g5ȡPl)/hdmɖ*apraP墓 WW [<-,h'#x=:|:ͽvVPviՐZ,mGH8Lcn+h i;U:F"毦ȋ1QPnP?hib[FE3 sY0rAߏFy7y[_B ozE:g2H dʾ vj"|vڰ $=Җ.AEĢ* BiY6mfӛM[4-CQ$M8EYdI*bx2Ug 票 H;0l&1nIMNړ(m4F&M h@@E,vljYO OaM ph࡯ʒbT`50S:J *.󀢵`/&`6g41|ݲaqY`Geor vōȠW䅞2סn@QIvR?6*Kid_{lj d_!Ղ 68\*м5Uf' }?>qX' Y'=ޝs|}9 /tx"| V]))gպ f p v,e `XU;Ȕ̫F;ZgX~zcrl6*!Kx\}RiWkPNYϕI1߇nge΄5O"l\FI<`#|Ed`g%N"{1~|c:jke?5,do ۟ Ϳ)eƥ IXZ0acMKx3p7qN&i?`lZX7XJ١9Mefs}̊Po rypp_w>q,3XQXh/m0E}|CfZctntccv4)?{ZRZ&ĵ7{N<4@58tua5/zcrjǻqZTku)^s q$PFRiv&[S#4 $DZp X1j襨go4`dٛ߅BT mDbPԟsCCE ILO6ޏ>9>ㅢp*r2`ɅRH˾"TqdT1E8$zf- +4L`x#`K:g݊}a|,((^tl'P~ aLVOd9y͊7뮇SL+6 y_';V,-Ÿ;R]'j#ڑ̜{0ajMQ=WwpߊpDY9lUn@}T=3m@y;u䛞 .OZ5?(gh@{"$pT"L ]/S)jr,E  °0,,Ε$pd9 AŕWTlY3TDGFAm$D1[-Xek39F,*lX ;VB%6xuc;9)zsj(6Î%ܽj7x v" d2#-x7.$!_CUF MIt γ ȏI02 JmDgp=f%u.ʌ [;3;Ox!5uCgpgv P_Oo}uf}LT`syzI8MJ_(Wp4+  g*4#M(u Q.γݍ~Yr B'?0Vڃ(26M"c-%l6soO5'072qtʮ7գJkS3ޞ(_%LT M*1x#ȇ^=ȗ @ߊ-\QP`RT u\FE. P<q#?7mQZi;szenEV Jv34EQO 8x޲ Ys1y(fjN f6"oļ6d:j6ү:íl䭒ěMp_(&)xpLQMF7$йfЂBKX:ybjWY&5qP0a2j2aQi&RBOC]ZǪa >44fa+\H)Ww`à58TEa}>a6PT-;Dh,L}ji~)0>u4@V?SIې93x}!R1w#}-SO#g{Ũ %Vu7r y ֱtoGf^<܆#9$Sl4lȤ@s<фLsD8GaSt0WIz&>c3kMѨ%CB WH|ˎ(8D71x+2쎺=;wzF:7N k(D-+ irIL[V#{żPoH^ts֨ۅxU%w@As G~I y_8$X'oC%y:ߌd8YKQDI @|6l700^4pd$Y/]~I=CXOBe-'W.F},"E>~Z$?dh[ qgX@cmE3)<|a5l hyKH 'f" BS140u̾n`II*N'5ڎ3;$*…°̊ Z0_qi;UwDwh^%YBJ 7 vhoiB"+U>|݁uڜͤziH(ƃe"_FCacԩodn*Y ep7"QswCM[;td"r:{'f xkSm6u$o[{DŽIBhhKq7C).a|bIUځΒvSA,NXb0; 0pj6 lj`AƌB嚭5+O Tǥ bϕ\P=gT%M]gV&6 kDǬu]D֨*#T]zDQ6Dk:X4@xGUo h(, IDAT'"w)*wWSm$x~=B?u$P΋LlSm <ԏk7C54D~j.-)<g"jh,"Z-xINFB̫5<7-l6IqcfZ0E1Wدs3),Ü^PY6-Ͷ虊%Wλǧ5H$"a:a>Ly)'g ׌kP.K;j`@`-q\sCU8ձ 2cꎥf- ?a6o eT_K! LCx|nU굙PNխ̪)ޏm\w @25 F&ЫUy:d-G^DFV{|-rlڈ>9y.j%"O!)o缢vz&j/zTwA:` k v# LAMER؇LC8蕃IטmT>݉'+28szf4!%WMW%Nt7٦%" B 0@*E$kQF>a"B#_E+XҟC~h(R|Nn%[~<'wgKPA?51cyz8<u_<$s|}j"Ԇ BeoPa{e Z,f`=r|aCh˓QSP0x=I(&} Rh PBQxM%O)t4t|$ր^gBWY*l5EV#RFQ"Iic*^j?>( aR "V78ر!,(H_T@nVF:c[hR©c- Fei5 -_Kd;5 >vJH ZFeoi,N,mlUz~VԷ, w,P%։`wg?p΀}4n_㾶9$/ ykx =),D؃Ϳ317<w!)Dt2jJe*1 IA]PCLuI,=H@fV ,6H ]oǶB)?ׂ;Ls;fP c.ɚq҃Z@44hC5?+.+ {H: \0/;s%`v?D,VdNoLdj,Z[s,:jzb4Q%|Z‡w'V,{F':A"AڍMG?~+q[ع}#$)+)Z\ZyuȦRKLOνd-9:$YH/xW35-ϐ4_9~!tSՆ1cK<KiYV|KTa%a]8Y1_3HK=t(*848M XȨLȟR,4I=ƟxǿBf|T#`7QXoW!bme5,#Rbpc󦺍,UWov PQpoIדCsb9Y%gR6[ZFG|/%Omu^z".B=-C,RbA=7"M[b ;ːc|(u }! 둝[V 99\$1FLcoLf0?4``s0AqX󼣺mMMsjFؘ|aD3#0@״ISyIO~ɸTxn4"k܀zI5下֢S*B7JG3]M3&56=Nku8;^}:*%|i,DxԶ)C/!Ұ8ǥ<ޭV>XHK'G"ףnDwЋn/褍 _H/E).a% E.f{cݏϠA=/Z$uS"&"F@,Ev=X7l?"25 ųQ GQ * `b]ٺpwT<9"ppPGr ;.LU.lbyǝ9HDm6Ղ$EW1ۘ:cV э;n#QQr^Rs#CDX]u=[Z}9Ƣ/gkt.T\;hVJReؓ 4@@`/ ÿz( 4$6, 3C͓ oOO,<}-uo ǁy<טd-r.2lҭVN#'4,65>NB`?29>N`"jbڢ HpL̊rWrUv}^8R,1sb%5In8O07_#P7"0ȦI8w,10Zt65=i_Zu|AWp.˻.pXvbW4jTDR 7 3G1\g>8\I3%Lըy{W qaӨGi)P`¢}@,loDlh^i!j zK]<}BQcNCؖf 'Y/=2YCHG=DІgmI@>E$DH <ǕnjX!?=/JgÊ\aX' LGaoю3gJX4Ee콽B۾zAj%+Ԃ(|Dtve>\;4l4a^>:I2j;G3#Ǒ=ZλEȜ)\sdBI#o#oE ]$e Z`\G*E;l%n5f?A5{ V|J݅+Q~WsA}-3 қ0*{ΧO# k5S4/!bq,&>"]ʾ7Xzh,hz +@BjԦ8thcC/}LEp[y1%COFc-14#HeiTJ,"h564a swX/(PYٯ إrsy o PF\J}+mͲMGtpq(2*!{v9_ uW~9;Wz&[9"GiTa=$ y mmVt!;Ħۻz#r2 ,CNELtCZi>5HP&ӣDa.?Kb`"LW!=945h}OKq.ئhX QV?s/1I^fPTGesiޮHGuAVgF+Zۓ#[6opKX,~@XJBAl/}—Zߩrkg[A7:} ѽeBU,A_ 3o >}#K6?*, ,K<"d-w܎-;}#҂3b ҀeˮrE}2&#A/2Y8&ՙxi-8"ۘ,`fV~u:9||aγ1,ܭ‘a0 ї\_4te0v/ "bh0D=_`/cBJ{;cOqaaVm>05Txұ_5=(Tj=iR,h`Qᓞ>*UBF_G2s-7?(˲wwZBl2^3΀-:qlYqafU&[/  @Mw7"ggoGyFGA%60|+:w3-lrVHm1Eg5]tI/'}qBkֵ!Ku{W`H9qHi++(5|âj+^ȭJ/8Drxow,fxi>hΞOp#=h֔P So3 >|ԫ]̉Ơ`Yp~UԅoG|ӛ_z;!oJ ~9/ >M됟A~y-Fb~ h3'Gr= O"KVS#zƌmڭ 5Of'9'RwLS>Ou!PIO ;^Lczg..9&޼S9k1mCx*|`A,95 5eIعiEfAi.)i$2Sc4+A!~MqJzt *鈲4Hw븞Ը$WQe,f68J QlX WK1SI32@X(PK vA)tS&|F&qQc8 x#} VN6:^(Uث-WRc?XUyan).51^L?>SfR"+I>eG Ei|5 *_EEp!"TO!i~!O#h>g頭UP_SF02*dD.@AYb(+Ӹl3 AOV^X 29b=F{z IT(g1tOgj^DtVl9Y գg)2ءsAW.v77NCrl&YX l:&b'"\D}Jz}(kfNq?V5ۺvm[hW7#,Et `r'>Z'?>WeαEf2;עE]Mnk9%N <ſ,FE Jϒ۳3 "<nGA%4EJ=E:M -ԫb AQ(%M87OxQ[W3K+5GIL57>s%n&MS\03 jIr H֪Y]M$wp-0_Z S22bT`)rQ5B͒mG.ka%@]sGGL6x'p"|Y% IfI@N>|£fxע~ٯE va1Gs1b!y}u֢ ϯ! &pAX-Ghs"0Lh*/* >/?@Q̲/ԅerʽ^fv^~d Wٗ96/!ɥGO߈W=MCrw`=-(XcR f(FcWHzG_@0cŚ]$VCSj;GG N!jxauUЪbk ^W4a$Q6NO0ڇA^j]kMe0"yQA%\}^ȝnkm[+n5=]Gѿ$yM!5?C9tBH,uG<<(Ei4<|kX . <0T`pz}m}g-x11{V3s D!)&;ASS!N w[n]$ kaGjDUャT-@cV>qWӓ*R\i;9( 5c ނD' ޹(Oj;YPpzC!x= F y҃C3&|RTO4ѵQ?aRѲf, 2(33PgmG'۲Sf1E~}^3)GOAlU=8,Ʉ7eX7HL.fɪm>ا9]Hg#1ϔFmǽ{eÊ^2)a}jܡZ‡5+!$!RF BJXנ߃܏" <|;>~}߄<6(t>"E .7=_>j:/t(S񠗻k} :yOhh~݇-\kz>QC8tVl IDAT$-`QR I qS#MJ|)ӤLotqVW/Kɧb&x0W{ˠѱ4!.ʇCA1ZˠWj-w۳G9Չ^r/K<^E+t4wiլ)nS@ hVzIGӊ ?CBe COo?~}"߷P? EߨybF-&|//D_B410҇ ۢ׶VMmΪꛬ8t4?~%0|Ԅw dBiHO YHU0R;* E[p/ϐw W0(ݞ1s izJ)$@ 9V"Q(* fW!W"W "/F-ڒ7| |O1#]p5#Q*`*2чK^m++Фjb-=YqLsT3EB ~MB[q@J $wz]ޒF,Pdr :G#HqN:ax-Kd(:#ԗRk19+j垮NtSzfzb͠Hh_jQ\+ǤQqAAtYтDD@ףس:eN{ڇ|} |aᘏ_E#_»鋞C'S?=]Kx-Pކفށz Kux jW-GЧ##^5g"Ήmr$IЎN M4Ē F>tͳ٧ќ)ѣ3KV.n$N$̠(%Rv/8CA-1Gk(@^=EA.:9d^;'inW(6*{EfZ{s|y|y*E'я(T&Yz-k?-17XzgH$.?{N Gx =LFoIOw}v܋@[bH$I=2,$OI%wBs-4 [l){tOQTlR}}™J !_uZ=gP(c]ґ\O[T-g|SfSu߬Z[㨬l['&HI ަe ژSDK]rh미 ߀桘kL#{&IsgᔣYh5MAnF>D6y/E˶i~uo!ˬJko {chJڧ3碾B4Eg`"s,n QѫkKbQ_P/T!K(;KrzƀfRYQY){9J AaZ8-v`aDs@5& dT@dx1+eתh-+m_!8": v.~LDqƒPvʘ5enhn+ԚX:Jq }XN)$R܂Bl&)]lfNEjkȕ@D?{VY0ǚ28\O,/d9rW/ tT!!O&sSPjZ ̊v1浦2>rv3nI:ӫt(4ll\Pt%ݧ٫9K鏳c+A$v,q±`IMuu/k-J?FxPs~۾e󰨀T_{/qW38Xsp7U}e.uGɈ cfS 6$R-cB}gNLQQџZQ3` ~ȭƯF]v>Ѣc?ȿzvkϠA=Bc}g6Z,Iby7/ҳ&H`4v PsVFȡUw)pk!\ngVQLC L,.-E Y̓zX؊qd|\UыP "ls>j>!hUq+M`5Gy^!1r2ٗPs@Qd$C6E 1-hi&)+ta 3M1MYo}}̛;J{S$iB6p?S`oyeYVzJ-2[4|7.d0uצ# -3P$zB0iIx_iW Z1hiɨͽjn;miRm͏RM210: (0)2=oD%orzGLi fiP)ڃb {)hQ XM4̼'$$5#p58 0E1"LQ\Ƅ0]RŲW4효PQ6=8aaQ.CUTuzyHi!vV+)$ ^/[v<_vž8 ,cZe XeeP^s*GO|d asL2ƫQW湆-@_z h νe٤kbu_곟FˣF W!gB`Mːl[>#;GzNCދeCoWd8ޓn-e=i::1GN d-0A8, biF\GhiCI()# >V+ ΚeVtXs IMYqGt,u1KG UtԝyUuVqaM-%a ٓ{"3  ".(.#* n(?Eߛ=B}' 5~{Oթ[v =SPT=Mhz:]'O14<ʡ0.t3=CeygMe1K)b7Ag:y_B.BW0 Du^]K1`V}͐6^52D-܉S^KW| *$˷8, %/"!|a^&pDQdm'<'l/O:kj` a9=.İ2rD;b\ d G Z#Q2PS s,,u~6<#7KL\Z}-mby#p IH#8s1UV$KMwf}`܍]CI:<y}Q3!q^!nniOZqΰȣȞȎ];()3jߍFdjuŕqޓ>`ث-K[/El4BCק t\D4쀰$SڎVgj2(:8_k5Rv;Lhlگa#CD*9AEk5LMQً[7jFcXrxpL*(6;RQ'{(XPrMtf24S01tM$ YC~̖Ѓ1VPq0/iH_݉I.s]qufrz'42jĬZ19Y *1: #S=)itda;N{CGܠl'4af4m VnX %]vs](x / X Cmba9 b^Z,e} nĄkV]v3s%.")l8yO_=v«PC1ppu:$iNrcdhn[Kn7;3xLtz!2]D{&ox\} $B ݣcfۜ b:svwɥ|eavf#zjgb?O@b8t aڽsGRYQDjSk$ѽkF MnqAfQ`X[ ҪnߏfWi ig'!zɖHIeo%2waEXI tP_;8 SV9gz{N-"n.Xތ,)ؾP*|̝2-9D41-Oф N!L(s ]+J^3Ry ʾgF drbaƍ$N UVo@֢Zws/is=sWͼwrAODlK#X3o0+#K K%^7fyل$ qKb8`:̿>Gwzy4b`nVEԺ W;^p`%s1/T PiQ__ӌrrkƫl_]TbR3 ).ωMQI!df8bu;֌{NDؽCY%)De_q%۴ x(|b dy؄yt1|ݓ eМ\A 8L3ON^,Nʊ#0c1Cj0ƭr/zҞ9= 3}XF#~nS։(bo:^urP|e0;$/7ƅoTd3U1{+!9mK%3O< z}4{@iWW̏ E0pݰ|t3m醩h y9MiBD02*2s]*!U~9Y ݞЇ!kb\<>Ȁn#sFalo}1jc,ݩEćG1#q8DiȓX2sh ;퐦7 >S0<*#M}^ct0:9B^MFr'ՙ̀P`˕ڍzlI@`g--GAt* : ZqP^R,q%17o %EV,wxJyi nCFǵZeu&;)84Xeb酪UpbUko.:940?|?J]Z8:-q>9 +O Q+v%M^$EYa7Ku45D E2w"/<͹BI$GGQ`2ـ=LQ77F1,Z]?>W /tñ 14ŋ!TF,xcdvDPY~a G<mIU_AorMgj< JN-%"ʊ;Rhp =q/+R*k)[f,ɲK1섕&&A,|==ޑIg8D \f.Ajp.)b 4ܾJ{pHY|u%}h`h zg(LwwVӦ8dE -"8ً?Jd ΘHGD@l/N_qÉSj̖DBceaʳ Ih{-421>>mB nM1TO͜E. J*Cqj\5 EQ_z<$?V/ʁ BW@ŚxS!{ h#[+Ak o~U&-u g W$}¿יTg,n͔)qPfud*?o"#T}.]C(2W)}&33v.וp:I Vk؃fYs: 5R D f<G%''Θ]mFIt{̳]ɧ4#bU[" bmeV$#M":rp|$>3И^ͪ ;E.O }m4tG#8X؄uiC_j&c8^ޗeڌ<6/\W쿺 }܁Y D'Ljg'oف[ɑ&:wkdR֧WP0m.ghZdàhmxaJilK 29tL*CF(e FTzA`ےju ȓ? j(#J{HS=nق6n =F}}#ft>DSZ)QB4TG3}.|9G t` T̚ojV~oyU(%+'H:z}tǶzK:܂BCQVeN漧 XrDdC.Х9ȍnޤVpSN^`9# $/<s2Rਗ਼,~@/F$\-¶p[MT JeJlbLKk]H!kŴ^o T31REH_OI3mю;{mazO#l`v_Q;C_Uy 4X"}lER乯Մo& _s +sB}axUo.q)23s{y'>ܱ0_h;S]%^CH$c1c1@Lg&qENB4y.ڈLq6l Gb8Yάx=y(Fn$rp?ː́ xz3HÝsiM%2 (1uk(![ˡ/^[1IpqC>+VLV@Z2J5| C"3.wo5xRkICI_Ps ;c³T qhhwRaoMpnø:S ~f,IA$W/ ..4]ӯ5{; R∳Hz0DbrY*.e  1'Ȼw"Gb# }V BV͂[m;HÝK2>TȬy, IW%<gg>t+]{ !O9aI61<4a;$J/loBҍW4pM c< 3]@+l%}ERYr֬L1IP\H5o;ImUmSuD;ѥzbRԳ: }!|y!/wa\mMWg xXrwA~7+ +TYS8jqi*\UTјfP"DV3ro2H#pm]s8oR` >dG2v aޅEhh"/sUa3eUh"dfs̽iIP-J? Y`&݊wżyOSh /C,ljHϢϣ#1!y#01&_cԩGL ބ^.@ހnCwLDb.cOݜoj JbX>ϚV"!-JRw^Ugdn_!|UXS:Ыm#$# '}-NAAA}3ȌN 7wPS+s30Cm`??ƅ](7 snoU3ڱw#$_ 8LVxgdCCABn0J3N@ڤ4ގ AZF6vO"5xr!wY:pt7UCbt6gQNhV"OARn6%Gq)h |+taWo̬l ҇/Y5(>8%i ?NOp@P@]V\F g=*G {0ʊe8LE!I}QD <@_\7ca5&lA23]U?)Umz>'+ ׼(@q\x{rpRΡ8S"g\Nܦ3UҁS2|-G|)^u4"4-+-VY@Zvt3Ąu>U~UPGo[aX7. o~JG@ܜl&ՙq1Tx[ܤ,Xu~z A-['҄}b7}1 "7x. oA.F9Le< ssN9Bs}*U_JdQ 'KAwT ;\z8i CGvy08l*Pvlyڍ>.lH&-4bA £`:z5Mhsht\傜ʉ`F Q sSvk,}S8Y^\Nj5To4fJ.nIUض#3LV<\Pܞ+`HeWUxrgSh *˕9M:p3ɚ* SnF>)|jM8"Ap w{L,r|H,O:Jҭ@OAn~["owL֡'骣kX2Ӄ1Lw}b|t՞D$CoCC6 3yiGM-+_c6%kX!.Z^֮3W2Z8lSP劆;UN nnL0>3P%Uzdᯆ!ܩN+h%4 Ӆ+3}A}RHeWHSG⦇0}_\4&`dV1KQz::jI6Zt_c1 `8w{lr$LA'{5{{ |x3%=ۃqPҗayZAu'̎'1Ϣ#0[ ]p;zgV8aaOq^yXQ 0O}_UJ>U4!_jOV8U2\,q.F\Ν{0cw2o `2C"[UnVVA,\ 7# -E=i "\"|\Jڏ qL^^*}Ό-*04y]&,FB{1gsU|c߆XZ6WJjautdb&"e95[)rz0F7)zfd eCi`/tS, \zuDK #Zb a FL߅/<^%L HKO"lk=S C,,lisVNOC#mΕQnd!fh؟5몮0s+@҈J@5«?uiSYm8ڋH:@S81r<X5M—g5iF&p=3ǫԯ!#ѯsK911, 9g d葘7"O[ÔDXGB"|cww{icp\0-6Xd>^)A[[?+vy4o5|d^#ByME͛=}&W)ڶ73eU 2j>4`fcmȼ*9y>d m.oVYQsYEPܫE*^mMy"erjO W&T( oSVeJqOd8P!/rD-B+t& lc0/n '}&Wn0]  v2K%@8ӄyZŬBoEߊ2)ypBAo{0=@c/ba(9هz4ZFhU0&7ΌMo@U$aC9zzukZ~w[TwZ܊(9B C,oFDmE^tgZ$鴋Hun1#"&aL^f8ZW ?~*DYU6Ixo (mt&\$|BHIӾ[Lԏ6aQlo桓w$'(1}oJo`QnNY ʤEKN[0Ez9pԊ,X2fyDF0QIfJE\6ɠB$^\#\IlV_q08z%4)KyB<!үpmKSj >5MxwN,S0]m1mw><=jO&Q\VX{ zfCծL{/ޏ1 =0 sù9sLލ.Hڿ{Z.pа9Y)s+!܋+ɯx fwefW wGj9o34z:$@h׺`.0[:m[ˋ3aK735d/.U2C*\Iwc0C8nXX,Q^&?J<#{~%4˄vB-L#FxbPxeq:2l8c!'1H-"u7 ن}i sQKGb.v<"" ]V{]aةUy 軐[ếA2-Ìuҳ0jG3op܅KCdd79YD)+^X I'O:}#Z^k2/WN]f+"td(ZESVf QX|҇ˋ4'0Iʉ%[ZPV&) !j[Ml\{XXRgtpxa/RގUn˝"a^ZT+K O<9¥>) Ӕy0`  uh* C=f9O6qwWF8迖V>6ނOwr{Jp<_#GbeE_C01;ZBP[,Ҕn?]bd,83ݯF_ChŢ#LJ-25[+ӷ$Osa4aʋUe2䲹/ IDAT6 ۢ6,r[jTs nW̒5csod&׺b2bJ]Oك/Kjß_s~9X8IapZk Gef^ԔgN[5?oe~h @bX)s&|^ͤ&!/"{ {8Hْ#M89i ܂zh k&q*qPt3f#w"6cD3b8\^//0y9 ] sC\]=ȱn͒VGzy oDƸ0G~ܥ}'|(bh6zNlC3M00<}Kޚa.yT8<=&3} ӄȂlB0`!i~y_.=οg`gd2WE613n`809RcP"/2 gC3a?\u`\BB.Cnr}ˑ3+C]y`{3KqinfBn@6(sS?p7_8ѦlHvgׄ10ny&dWG Fs:l^$G(ة-LEQ2Q" +-5lB2;SgVIؗF{s/tx ܏>ΑhB_If!JD߳L<;b 6!9!`a,h.4dZ~P/8H\!Љ!k xTO) f.Brr/NT*k4/.<CеW&!Gn`FL5UŸ~ w7Ve a(J W C,O04L>m_/hw +|-mVsj/ leV|ޛo_FcC)3O11̋!g!?p#X,2zsssw E֠oA"}Z8aGL"AnG\UF`6zfl]S,aƧ%7ED_k)IW|&w7IodOO{ ;Pͩ0w#!8xlaVn]>B5g:Ci}732v0YTX+2QD,G\jB\}n*lt=e" `ؕFfz?Pea) +"o)Ӯ,"5~+!*5er+Erpb$eMG ߤ{ЛO'ѾLȜ~.LOL,Br\Qt=Jt%Z#A~Pd#-Jj'4VS tL of4 `+Ekː!O\8< 'iXĄ|t+:\0 Yx^w1DdOg fq-Ō}0 G#z3Q MÛjřY;bu3JN8܁0C3 ViE2eSgCI6Ok^hw0 jpcy:8p4 L0%N)k7)FOdi07"Ц>,|[@,\,ASps4; [ڤki= 332r!b1Cgi= U8)&:iȏNK߾I֭ano(5 (.ba<ڱM7;s8&=SCpy3%ٗ#:iېfcW/Gf%صv~(=]^܂jQiRѢ>^quIZseU:netnAÖ))hהY\( kE2Z)Omv*pa2 Άm[DŽ, LPҴM|lt*fE/FE&c05A ӑ+W"B#L3k7z?#ozb[4J?k±H KЉ-'=gS.9rwyn+B&3Ĭݶ(X"oZOu{ }8-ޑKɣ|2V;wy 5=łw\n +"5i?-1RnkLznb5z\,?4v_Km)"VtLQYȫ?!у0M+RGf"<7B,AhK*d,[Y'{`-uqK|SVdvÎ/h@xpV8-))s}:)HEnϪTW,jEt;mg>:KT Òa0Sܙ.JlO *\SNS (*|#`8pM5\d,ȣp&xA-ɬ‹Ӕ_aW'R?YR3tg "+ͬR `u_ 7H Lԑhtd5)g8$UU틗bv <"o['ڧOTRc>^&_ݻCp* , J͢`[ӶWtEa%԰J,Xh5C#V;֔jǽkʽ@ r BXS+ >~/ř*\^2iB"feap\YtRǖWߕN oZn|pq-)gʬH313]~EX d$0tbbtIJr\%%glw+o}]Uqs˿c %LmDDg \ǽr ~{4KY`rӇQVkEMɣ4@Œn#3QM>#Ņ!V~m/U zlvM7pZ%>m!frH$R{NpN!pu:ꝼ8PVA!opB{yO\4މMeD>tI^SL$Aj0Dn. Gӿ‹ڞh,S]]$eKۛo.ͺS/(8kMe,zȈ'yQtVeڢCt}!"apa-RI@5^-\ﹽ$^3?o6Q`+3epppD ~g[(7x8?S9XZLk] & \7,Õ%iV-҄7 -l# lK3f1NEpj5yޘ5|[9F$؍ ;/:Drs>k]t*peg9 VIQla>Vyd?!kŞj8\ڒaS@2ɔ*(f,rD (0Ik9·Jk\IkE—y! =+awbu䣞EY;}qH #Ki\\dl)08MZcyrl.; `b3 Y,B=L4a424as!H_Nv=B;Y%DZ/y1xCLK4~)Cͪ$v+vam||oo#]G2lL<1 ' S7cO'(E6W td1:6eaDYѩX00^uGZ&Z?ҼtUt[ R↓H{3 by Jan"ff)$.E,G@ÜDW A,YC^¬fIdfS3T,;3%=ZC :ʵ c7t+"LKӺhiE*_ q|1m*UhVL: &fa/+l;IvC FIDATOͺug 0AS7B`{ xӕI ~Um:-ʭʭOծe&R‡i:rkL*\V 'HLL >.Ґw;\^\YKЍ1!oނYޖ68͈֣Ga((<pIìd`(O6; =e\Ba xNi6wM<l37Λjjn[z;Q}S8,52yth{0{1룩IQ>apaP#Y,!{<D7:u1[5rHJ߄mpRiKbqI:tr^R0уodc 4Ћ9蜴wLxA=Ee82AV+=v;4eZ#0G 1Qm&r:LCF3gy_% ?ÜO&t i4O'Z3ucR(5_RZ*:)c }!Z2`][8蚲W9NhFcc Mሄ9 zapb} {)0Z(kP8vQok2w(8lVY)GY˧oԱD2b+ d& 0BDzg6Xj$ٻD{<~鎚N(#thԔ`%mhLYRױRSFN,IVVĻS8! ?M^hS8R j^ Å>72 mX|RņPxT1&,)elhͤz`\nX6FU­ES1_O pNQ_`{ՇZKq\.EIRDകs詨_e\p>r d"Li$8SOwf}y Ӑgr7č\,@XцiF - 1q`cm0 쳟(e|@#]ɔj[] ő6{P.{a,)& -.h͈64;Sqb <\蟙{Ŭ*ӄ*nլ<-\)ZY iM2I`M=IVD3ҥ<+fzQN2|1t0j @9Gm 2PQ-1ä{sm?sN4'39EPwCC;"8dZnq˜+_OQ}UF¢KWuIݕ,%C]G2fK7FR[ omɵʹDZy!yUZLS& +ՌJ 9h'')^ xTfqH2p4ll>9&vpf ׄoYlNvHGLg^rFAqMg gBFmFkձVdQM27QQ\u N^F0Wg-8 egBm>7ZeK{{P;8ŽJc~],z"i~+L/bS(xE&t%pFN^܁_}z?)vGQa5Aŝ%%|@F7MoNͮ :u!<8Q$F[=0Wk~#MZP¤D5kU$%uV tV܀\:Kn)(uV*J!dPH/S3hA?DJ54|Eoz6FR8 Y41(s~q:&hQY1 'T >|vdWԖiU¶arӚ)'`1vG8@5kV`fQe$%ޭ5%& Ɯ%0|*̑Q}ΖJQALhQXfK1' I!20Ѳ_Xfk\,݃¥*fy6/|KFچI#WBl,UkYѰ(̣> ־f!|^: uwdh>2yȯW P;cL~FJ@f ZW84M,JhvaIR0j1EoVgauc6C۔EcU$LZPm׋n#ZVb"XQ4jv~u3 pp0oP-u"j^Sm{] \؊e>L9n͈I"6dpšre8gV}&w?13ڙ\q;+54+n72e4hѲMˬyPջ|ն}.d=PƝ%H֑:|itԉv0|Xu]wuҌcQQfeRm{碸@"@XCfhS>rREDru9"vw8t@)TqJm'EaO#Ou:ӏ'0zaO0C߅ʄӅ:F3Pj cP:H5 kitlX8krJ"-꬀HO׬~ |Q+p bjXEOX%DJzMn6FE#7YD^=t\&r#j?B%KpNBѿ@ G/i&zlh!ǠIXgLG{Ya4h]F yGһT@_nExϥ*";g׊kExPl&s}^i"i"7tQE i5ma./D_>(PC[,<\i_܉p: ԝ69 2!G]l0,9 u2*m臽C#_"-l琵ߣ{k_̋uV+v[YKƢtdҸX3FbƉNQJՁZĝur/@S.TmvLw`T*XE%WW*N3=Uq/ᛚ7Qtٖ6)+Mxi;cB4m [Dy!YZ2- ?.ȵ 4 .FZ#\ì4fEֿЩ.,3(¤hXfnx3B / 8˛ѽ6KlBoA8Ę[#/-m 8"dx[܍\c30y ꥠs2L8DTǺy9) gfE8bI`ܪJcCs_) mbdT8> CC VthucyZtH5i^sF)l*(HCIaf KH K0)BTC@Pp @F3WhDM^Yq|i_C"~U)|ŗ[npwIt(zV P˃b.Kg,뿡am/xsO:!= 8C \lE?hܸOcloz y[/clKQNb7zW ;K,5aE'֔柼witEK1S\z}3<zTW3|o>&BQ9GM:3]⮃:zO@xo;ÄV>Sr>ŁХ0~(&FQL=3hv)zs4/88,R/4ۭYLcbw4ff/6o|>=50 %لk,wQS_B Bgr,3 94ze`[dZ^n/BͲY:` 0igOC/@R 8."OJ~lYHԼ)n )DdZY: J6]E۫dr*7fJ$v[*r¿.u,=蜖MD]rE;}"M5/(NCAb-5AA~'tffGм8P%mʈZhͺ Jaz efڄ>>LG-t9r!71_{!\34v+2Z%t$zf [.Rh@C* ^IG-l2_G[Dْ !IZ8k#[/DfH  {L$4 1N3Akyj)oy\2til;ɩ`6hZ  "nB@J]YT HUٕ'-ィs09.X;r[[M 3BO[QN7*"U?FЪ}a*aQ}P$٭?/ :  PyF ѣ|,v$g OB"V8כ3Knh&`^`y R3&9?{—O yYފ P45K5K!1k9q0Q݌\a,DQ-XNTii!UocZ{ZnoQ6[~{ihk;IU@`.s=-s}%XNR/#:(͉̮3Ӻ+*cr3yt0 xR)+u30BӌBw;~mh6B",l;hV)Bx&\oQ =,W #- j_DDI֠O͒*=^YMSv5R yRRY^ԋ͝H 5**G;`tJ;x(|VV:%sbio!Z}]=u+}xxG Or&a0=#5gwW8:;8+EUhh(&edhhvggRy T LLȶFyJ(#C9Q3f(xmlF;%ɁGj):BlȕF~ 6.w! !r'xZo?v-/L'*xJheh)v/Xwy 7"zWtwM-OvZZ-u-#w#]H+>OD?& # fφ=~qB,;̝P?bkJ^ՅhC L%ựSMO(䛂4|[F++9- [OϬqrvcȥ ߜܾëu9yyOoc=X;⒪"hC$)mPndT,sih^uPqeB^oIdfp𛒕3lEQ:(\0ѬW̱7rᮂH9Vj[FԧYQlauHQ}Rx&*Aj#54kوj)MANjfM´Og cQwg>o v Mvv:ލkUc)A`t8@w&Ƭzh0Qx)K<B7闰YmfTBPѼdH J(fb9bzP:#-Iҙ"RJhP ߏUDVh*Hqa JٕL &igLAl:5se87M[@X2煓N[.Ǣ\!螀+Do#IO@ț7Ag.Q9{:c@9țcGѻ7{Y@T@OϻzWT##o UnKЂŋ7W?yOϻoSw5(S?|PFbBq܋tcG&XW^HSNQ܁Bb,́‡Ջ}zJgjO6+ Ӆ"/YSÒäA?UZ22u 1¯k܄@͞t]b u{`&<<=ᾤf Lv=i0_ѨQD)G=QzԣG=j G=QzԣzԣG=j G=QzԣzԣG=j G=QzԣzԣG=j G=Qz_Γh蠪IENDB`dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid2e.png.license000066400000000000000000000002501511655130300264670ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/examplegrid5c.png000066400000000000000000000010711511655130300250510ustar00rootroot00000000000000PNG  IHDRAd pHYsHHFk>IDATxݱm0P5AR[0l#vanªUhmZ%3Wǎ ح?@v.Tn~sm=]n/S9@(Tny^ykEO/T|zihhhhhhhhhhhhhhhhhhhhhhhhhZc[˾ح榡kEn-n-B3tkEO[@v/T|44444444444444444444444444t5C _wYCIDATxŝ=W1&08 h5"[N5#@LHOpLLWUgZK>Qjj7>}˃'qÇ+ߧi8^}//.Vdoȟ.I鍲@JI|EJ50'=+S>(k`FzU& ^50.]*삌KAvEF+e I!cҍF{eݑNY-4 e l65pNSNrNQi_9viWY#= e II5X:RX:P#Xy#PYe e IvI5-U6I-Tt^`ɖtZY҈rȽ4[iLaCVR4\Ar- *kRW.05*(/lJxl .8{}bGջe/)Th`Xy=bI JwnGD`H~K Hs_m Y飃Ψc3vNऴ;gޱ"#}pJzpI*>8!=8c<>!8O#vO J' "T3A'}r+lv.vө}Y44|K lHCjFBVlNk6cg7p^辔>+&+VgԞdf3 YE\ M4yAކM4y/}-eFwd~ w7{y.~_p{c[K |qZ~R{[&%FZ.O=?(i Sf'^؄>(se/)XZ/ʌtz{2.NE i \)g -eLښlkLKKNG۞PK{}+RTJퟤQIp{tx %[y9X::QD0CH:'|v %p<1;8TI"(˾i P}N){gNCZ'mi$[mHIKല%5˱i (h^辒r+/ V6(%0\K3{,hi +jhi L(6lR/[TKS~zu\;_gy>.WOno-76u͍Mo-76 xo-e-2 ([E/Jz~|Q2+> &'6>(sK f/)X|IE z/{ʸt;@fQWʨt?}n 7ʘ5p4SF;6g줴=c'r^;Vα"%+R`S9+ퟤl$OR CJ!UH{x^|ǜ:5#<vJZ\ظtĆ iS|IK W臥NI7etRf; (HZ짯1}F -ujZgV8`l#--uj3vNڙS`_$)-ujzNJ{HJԩ韤bI*ZdRIxXJKX:8/AWP -ujFH:i(-ujƩ/HE\pj -ujf O:9T +-uj/[:}d#-ujf>K:tՙ)-uj^H8;0fHKHJCn :iS˱ki0Ǯ`_#-uj}) G-NM|[JۊL45R&D+R&K;V^NMv pߺ:5奰yҩy<޹%lo([S͍6 's{cn-w7/X:8/+3F("IyƩώS_:(Qg&ؙ ȓNA /e_6;}K{eٸbg>K:)`3p|K ^8{}b3e/)XX`\~=b JJnGH`L~ F/˶δyi{ͱ;)}|pVڛ3lX>8'hbJH"J KcHIG';ҧpgǩ@t&ؙ ȕ>5ؗEP6;}9ҧ{bg>S`[:4|iHlI#jFBN\^k6c7h^辒>'Ɨ+V̞df3 EU[ M4y>?xfaM>H_x//'~ٺVgWeko5go _ _)Zn/SZJZRJ&)-wfSDԤ%;T:5 i |.J&,-Q%p~TNMHZ7t?)jikS:5hKۣҩfFVڛN͔vErFLHK`R%#=:)cҩHKaqN$ԕN͡q8tj%pX41J+-Pt.R:5i *򤳩ҩiJKd-NMCZ,i$[U:5;i Xtj6*k]Ԭ%0WKKSpma)INEZM4R:5*mҩd^_*i LWn @S[W< k@?5}IDATxi-Yz~vw{}o1+BI*аz5hNA%D!(%@-CJb t$A @RHeHTfd{F>~gn܆cdž/#?]]f|<σ(`m|͗^~Vs~'~vP}xxNG|l92?S|w~1W<'HDqmM*CdQ0m7{uiמƗMO7_,ywjDeۙu $Cjx~9/_)ѩ KpBbUso?!˪e?9gG_;W UbشWaDBvO~+Bꢣx  PkՐzJ{kl?0!nbA!5 87=Gxڸ *BoH7NGQy+ kk*O:xq>4kȲMtɒaUc~+{lOKt,hp:"+UuiIIw\#M9j&uѩj0?X9ޏxY!(PՄ3,vOT]v]_N{{FgWݴcC-*gMBMCB|ʞ$"qpw!l%(%RdG!?)eEojH BFBYnj**RD M7vV>F[H$ɶ}@ iՐ+[/ :OVUvD)aSC7g%: Ӗl%#@[/n@Zc泪<|$DJ6Bdj*eFen펋E|0.D ^ņ.]6=ukszS-؏]Yt,G4=>G9]GS3,7L!(Pq 2F!׳lXivWZgN>X0>X&[L[*uwzWOdؒ*0{#M׷<{Bw2Yɂi{SÓ%cvUqb&W+[C+3dёDg2 xwJtPh)k,0F## D us!hTFp:"5 !@1mX%D72Γb..-C"v7_)}ZzGKs:VAЉ#FSO*L u+j뉪(DLF& <),j\,*'lw ˆL ޺apQ,;WvM5(9΅;FCO vޏd4t= 6³E*]=腍u\?yUC'~˫6yΓR]ݜo݁!C&ZU "bWBiK-|9ZA0J1  ^ myaM"w'w'O~mN@~#w䵛2Gz &hXYt^~(񜔳1y&wmxu4_uK{t Kv\| Ӝ,ѱ}؍(O, 5-ېD̃ѓ2Ò71 q\l:⃋}%\UմrXBGs ASYؙ0#o&I`٦EϹ. Hwud}4y2ؓ:Kfw= TP$a#p1~.ΓEYAbÒ]s9ÖN{ VlAtK.w0!I覢)&̳Dsvɒҕ‹0?#~4Ȳ=qhH Aw$K:7}0?5WvlOJItDD(+T٪!vi bG&ޏ"ϰd9c֘w=Saɟod6CYtmۉ>Ix01MPB>)ԣ~iC$ă3\CL UlItOJxwWɟ刪l*CM3l$]7qSMf) (T3k&/momB(/ ̞ k+%.ó%|68/,BoHڍr=tb,b}L?iKŬ5[Lb}S$!ȝjfV!$ʐr81{Wuk[$ŲϐQs9["ݴkTqma(=?Rpɢ,pj9Y_w(SHTg#:)1S ua!y# 5Xrcc KWe-;6Yz1f?1T""euԥduי$L}~: ~0© /!* NC uZM;φ*kec$ĸ@Z`ޮݫ—[|,,?x a& $ìB|ikfB]Jxy2_4EimWq`bxU5Lȓۨ-Ue SRQ4oz:1A[6 ]{Σi92Ɨ bڒd\6\[8 wB]Gw>YE[d{m]l.ܓks8ЪUʖLU lw\/~Zͩ [d- eX?]C8.ƈSܶh[i%Q)ԍFK"|l8 4P'WvU'4KԬ!\w&ᙄM*Ņ׬:cN剁2ؕ5r<ˆ$Iv] +ҖVnl̟I>r(R'<=,ѩEq پzs\츮!;\AK.Q-JѨVͽ)CTYgH8IgK/IH5;8m=<\åUӖB< hO|_YhC .UCNy7wY|̰p_{cr#J)ml3͏M .O٘5l6Zzڭ??O .I 邠YlZiKKSbyqc=#^Q;~1IXH-Ǜ! $С*TT31g~w vbŸx`Dno쵪᳄ ~j\үg?s@ʽϵD׮#->diЇVj;:/_mRs};Ms\ " = !: / ^IVz-S薬q]/NI1?>;i3 F-zVFk g^ Q2xF>d>QuG 5vΰ_ $TUACA/cC}ڝ\/H0@x@Wgk2z 76x?&A^/ޏYKt:I KNF種{ !|v6TEt\$\_شK! "4llv]Ш/ءJwK.]@Ѻ/CB#qi"`{ApOuTuOeWzD71{ɾWcjB+ѬdxOc舒4Ջ=`182o o<԰CŷW+mt\׿ncDɞdɇFN.FwHMlO& KEo-ے6,9@ 3%3PU;[;TutX3xqtv$ !|] k`tq ̞v~>dA$ucH XktL Ȋ7uP]: AX njƂyW~w@Co{']Wg [!DLƑ*D\E'JZh@6]i@RZ@\Dt7F us9ʒˁNuOz:{ 8.j\,%: j+xahg;F[OCBwYyrQIvtKtH_;i!&)$ <4xrg9< ؎ $IbX,)b9\]> }8v'Nj 5+{1DgvN I `<%Ε]0քl2ķ=n7P҈@ؘn`w؟VE ,BtYXTkmqs }X7cg0z.%GG/.!D@KL%(% 9is!kV=A{meg{P7?;(hqɃH [iΛvpV~}e+"Y2Ro5Nvh?EV]QeT[n,kP-ѠXjzoO'|&y'&eE1JM{{ef-5 cݓEUeC)FѝStx(uNS׬񾥹Z3kexMSj2o/Wy(ԍ z/Q`Q,Sgyd鹼<`ۡ:.>W(w4*܋?fOԪ! (y+%./X[wk4R."vdMBOXXƆ`5xNƶLMAp?D' $ xPw^)?FbeHpqޣ; W]ZAD9v*C.m!06f_D픓 k9h~'ջ]D]&fg|h^L p݈wWw<E$ xlMc#t #)dT5Ú5llku _|XH)i&4NՒ26vDn9,.iW:7ony八ׯ*?GxT?f?IZOW˖Jqmq k`5ve$˘ % ].A\C[5Doq/wfm 0Pm7уRßMx"%:v?ۃM+ϏV]k^ 0O T[QDɖ튎 xpq_4Z"]Et#y)ObO$ $))78菼'vU5Sh^ϝEPh)̞,:~;Z{9Uͮ (w 'kqgk'GT'ʐKte%aDn.Ԇq1e{;v;x:3}?@;zՔrW'J'QɤX(`NIҪALL{Q]mH <,)cW Z7 ݡqRΓw2dj*Vm_J[ۑ"t'^2o& $c &p~01{Uvn~/bӘ"{.)g{g6u.זyޙF䍛GYvLH< !.z_Lۣl'g u8?X'TUK7xhPGq^IFf˭BQˢ#$|9p %<:Qdzt?Zuy,ۉ""'3"b6cE;.a̞2%%:q1QEX'<~A?Il$^]miΓuUT~rŤsǝ i[a^h:?utqR^r?_-&,nH6!.h5Ĵ`_ϥ?x3@_ 5 : o+tt\<ҵ'oo쵪wR ,̠镐)7]|jֵlCO~q`ZK:)/?nZ8vG7GGK1FD-Ӗ‹3x b60Cp!V]hVt\{vTUs{3BK2(IrR{q:Ͻ()DP#qƾ`=)CH R 4!'{{3Noá)* #(Ρ}Oq)A KܹmVN|B]gQBfHOj?y$xEg`CJ %:j"nqr猚A Mi:~?9ORPqVp( uX B]V92C0Fo }<p?<)eؽ|{? y Iތ{ ְVBujR>?w_kx9Ĉ(JrAC~k3߱L~ͣ~sۑB/$Zםk@q;) ?P7'?FlRP'H~̟B{NԹD~ Z 0~c>"AM;r,:9Qrb7<;~_ܿwFՙ谇{ւvC4&tBaK""wwMA4kr<)~( R@yY^_9ҘI&Oݡx_ 4"&u F>Ynm\B]DԮi[ .? _??@݉!ņC~ km4OU}}xj*H˕w%cȭVL/%f_0xwIwBmM;O!;uaDWY>YmBD]Rl6w|:B?m.5.ﹲ{w٦ȁiKJPyج=3DQ4DZB}zEW0 +ƈј-/TGK͜(,i,6ܜA uIA/FtQخ #w\IYJUE3۴s L+/7+- s8$ )?#JN{WLjZ_~AwYr$o̞ /=ʺ9⤄6ȢƭV,QIΉ:~1Bu>WrGY^T~+o~Uk! 0{흓 ij? -+KX8 PwO쵅w9gE j]g~FfVv~mxqm.co+~w_'5:Wޜh!Cu3=rS<؞ʞCIHo0dVUghGQ{90׶FSJhDǐ!7cF'yN0 ;>DBZkRӔ%s ;$݁7ҽހxx鋭Q|G ?+kQU yTod\NE)'2bF+{&mhNu})gAE9b}8%?<\GXijy;W0sɒj)@}w@ WǻX$) BgC~(&G .$T5'} BL(J1U?PNhiXWݩq5x]˞cA`"̢+0V4$Iv]'5"NuY6+t]:dy`h7P'}a>z VMev?<&.٘Sy u~+xW&חOdDnɩl?M!4"Q%fq!$V ~pwW,A I]F%"d 3vNJy3yk􊏱V׆`Z"k3J$;"PuLQK˜ j+{Xv:eYH["1SP,b$x&~YR-;ӿZ*Њͨ~m0AyʶYr\^h̰R B6Z%˨\r~cl.aJ6Bd:1{JƽQM͛"8&Cx(]$f-Q uхӥM}{/-y/4CĥZ7o&buAJh f29YQ?/nKRh1E<9`Γޏm mQmގzN.B ! l9kJtSD'zygPl.Kr2 %Z555>*i*DeIq]'_a"v;N"۩U՘3Ih8ƣ0.B%0 <ҒS刌OW;$lQ "OMgahoL?=oo:,b#1uP3-D$,On*/>7b-Hơ}׷|8]diٖ-<2-FB2d+Z}s艝խGZP4(֚4jPD T+AydžʳqP#ݫWAisKLL\Z>EG}7nIGGq-SP$ D l|WG8+3@rm?m;ڬW*i|-tiI==)7.[zB|'޺U4UēJUp& u}2E߼?3q3rD]{S(*̊VD.A> KNCXUpBT9AIJ(ы#BS5@)N'e~~a ~KQ2") >:QcA;Y7YM"f}: Q +:I3?\"d?m^'C'e&\BD+,O.;I}zڀCkõY E\.w"9eER.*Cno2EQZHgN RmS`Au2hM;Ed+xR*"Sίk -@>?v oyOQ$ihB+׺5uƣMKUN&I%vx9!t5a"ELs?ƪ"eh%rzf;s,1"Gԁq-B9o9˱I&kL mI8ԬyIp% ٵqTOҗgp\sNq#~~K?_D91Tkvpը/JJ&HZƵ5; *޶TBV)@b;5?%%֤&癜qZG<#uXj3z?P3WsAP= Qwnv22|VTZP:?~ɬ#SBQ09? ƈo?:Bϓq Je{t0]G| ^_<#;܏c$4kCˉo<-)Pq"HR?ݮ⨷WT٦[FI^8|9I4DG<>Bo4{θ}ڸK1.{ǃ;?o>"lG ?CRGׂ&G2@jo^d{ݙ?ÍN/x6L ,KB@S"_8v06o(#΄شGrT.:<2ߍ%7@[xV3Q 5m`GA2( ahFL 7˭~(^J7vucу$DQY㐢N傈c @L.~[zýWB[yj61T1V/n2|puzjUťDer>M^{-lg&.yjc6ȢƫJH^;:/:'O_}u}z&Ҩj TuGt\M;Ծt&`R2!wYiMZO*s0xr"x 6!KvU':ʣ)Andļs~8Жί+R )A #*@[͖VeV" Ѐu2@OQvC0^5+C<iY\B z{8y`ZE')%G9pz]OʡMc!m|bd٨TTĴ%YM87kȲU靫k$o9єj/i{ݡ ')ݑ'^IT$~"M[zx-:p2Ե6͹S=2SB6ɾf nx+-A~B#F@cg]GQeZ$دHzG*?c cWPCUMU Uk ;W TYrv2_)CU]aɧj0RBNHZŢ͔6Ohnm߄Ijpo4k^;NMz$LC,5zEnp?0_B^;Wy T$/]Za)3a__^b ]EJ jL mQ4$bIE1޺&@=G) G$ +fg|fWl5rMdѡ>Jxns⪦(Z]O8Za! ZYy,Q-uѪ5dgxoITd-q"i_eຳY눸hhI[,:I>J9 ́Ӵ%R(|69?wE2}qs'XN<9TC6mlXL߹mVNm;|R1)OHh0͵BU_ޮwa7>%f/2ҵB/ahќ$$w˫Q?}5dIjj*.GotS'xqD]PGb$ `~jzuep.*i i䵶;J>C-%=Yʿ^-,s UFgMm ûԂ:Q^Tqք6DhB[HvC1)x"Nal141@V*ŧR ߱Hcx;Nj$J)Pjfڒ&j p KRy7r2WP]ϳwOLJgL9+Mq6ơV֎hcۅ/YяrM Z&B#QglWdL3@dNS7J5 ֤"Erf_"ٯ]DŇR!KYlw*"??;V ŻO<$щO+@Z[4ƱOŵqhdOƌ) pZ ͉̣D$ʩlWV! BtM;VGk/Q,PUV 6Lhckh-Ӆ5JIs}ͯ7s I!Gv.BwN"U/{D0\ԥV4Z2lqq߼]FQYCG,B`vS{< \t%by82ich!Ib$:QG|B]EwRmX3!n&IVA2% xזWNOG~: Yxy͜i~ʻ_P¢ߠoPW^4ڢʣy m"!];-y!Ib-C(D,sZU&鱳xN1v ?8uMh7/l}jFIɏ|9Vg!CyWj\Y߻9ڀ m/]șN/o+F2ݚrA`<m(Ѧ`u dV)+8Mlc'7keqfB4tRfE֜߉ðtD{BXw m6`B*mn>mUݳ^M>Yie GiqM>z7iDc*߁L붡һ٢>6t녲?jl2 Iεgίi{=`yA ӟ" ^j^.kyuN8q$\[= }zh6ybgΰdUOίB1oFo,W3%1qhGUBSᜨp'? w4Y:dfj5 N f'c e Fvoo-dwmt-LyUoh ANU _+%#] apfk7_upB4~^]sLR~I$81b{EH*ҖJB~tӖ8WԜ$?3?\ZdiV(s~+bTHhmme mQmsBd pǎrt1s-F؃/O`ZKIXyTkB?7 !^xqQ%ԉ'9+-PTs6=jƧ罧΢Z.-yÿSC$ɐ%J/}a͊$X늜3mXsyhݴ45Yx3t f9]x|*-j˧ ڸQ1>fW azފu Nz41^D}q f 9ӓrrƉqvIb~4^YYlw)0P[a{ 9 MZك m<ژ7b!C(؅:}⟪V3Ӗi35G Py.P G[ӜzEZYw2'm['nM1"\`,)jNUCژl! [ޒxB9eERlf&1RMu$T۱ʓHO wEݡb+1yIhl 9r~92|kP6f's");Lޛu+ :d# H:@[lǖ ̥X I.A_zy"ٺTa] ^ܼ́LA07!.) 6&eQDX*Ӗ::~bIR 8%eԺȏRK-Pa )ZkIaX2igi+W)&@v#B#rho) 6f'AB],;HD?֍g.8S3GO޽o6 |(R[BE32ox)VIXШx,ݔ?cg0A;cD*iӊ$Gn<)%ѽ/9m 2ܴ=H9$Ns~L)זOV )%2!s.da} ~ڕO~s$z[H 5́ޯDCcWZ[uUx&@7+,+*U^ؓE 9|$NLv}RT:ɷΜ$~G*+;a]{x N|c69?O6QB=T+'ELnz5/=Zt un嵢 ˹Ak?eT.B.6֭kTLb/b*rACPwX<Cl[mX!L b?ZMiKwwdžJ6Bd(@r[t0ދr_B/[CrN&m<5^]B EPDw :\pZ qEυ_k5'iR(Ď+@¦gRn?EHZ7CuI:ٴ~kk2 ԧop&L O77nj7 lPZCONE.d[R~ ,^jPUVo?+cs~ioys~ 2 6dT$]:ӗs^|1u>nӟ.k7=k~Y$=5lǺM GᩀU5Qs_Y?*|ZUYxXα]:+^F%G7Os"TOhB] ,4'͊9sb$*CubiwmѮaY .8#T=N9j$/mTT M ݭ4Xj FLV3\O+mޥX`lXzpcyt\2P(o9Y Bn֐e{徴uRQ&)9C}1!ub$i#و IJr1 FO#DYlہ}(RU@`^=gVdT5@2Յs?7bQ<7COh~ktQNGd0&tNe[O"cѝBB]`?Bx1⚖HyswN$iݬ*v|*U v%K̫? 2eڰ 1n7p;2W:ٷ\ɟ}'K-ցjbP|m|b'qj^m;gM 5E kctI%SΜX0 tFмzES:{P^m9r^x3o;$QZMEOflR۾ 6 ^B\A9_57I ){nH #Z?Iq)5-P'ckc]J`B^ 1!wt:ψGoK~9 HqRv";z]zxN[ |vR0ݴ;z KL 1z:8Nf?c=<5S-H-1GKM03ٕ{3щW)=.a@̚>Ma|a4C2z]z^PôHh4m'X_[>Hlv #{*ԗ(IJVFVZ 8(x;~YIdj5EIY]FlL 'uC<: <ƫ(5E7yhc3[λ R҇#dqj }fE`~*klחNtl \H$VEIɉ.#, AkyWQu?_ń6`Ko}[Nab$zſov A}w|3M;+]Re-4̗Aڃ!O-:NcX7x*iWUd!(y .(rb$)ވ있'/;gz)8ڮ֭}$<81."ټ7cwc'ޛ&V|QƉVչ[nugtӮ}T7o &k(7>oldX>Eݝ+Dn{Evbsζ=gu5yְ"߀Ĭ_rT`8ֆ\|É;ݝc8,tG8`#Hde qI91^) ufNCqsB Em\L[7y&B<8#kW\Jg/-Pq{GՌKҎ:5jZ:$IFPV ʲcg{ K>跂*.Nn’tS E*3%A26Ɯشt% h/#`Ko:Z>WISEu5M{Qr~!ç[u 8N@γYppǺ&"oO DpXtNQW&Br%ZcEdh19ݹs{ 351"ܖmZA xe*rQ/P$Ar{=Ih\ڸ8B:8Xh}}?SbNP|Ÿ;88lX#`)V9r~qm֏F$L ojxtNXSk¹S[0%I _KS*vz2$7a }i+ʫ/kϰ%%6s&!0jb(l9.uc1?5^{!ϒ%8vWO N&޿-+z 8.ڽ5b$N^);Skh9ChUV3!JSh\Bdhw0&ubLwONq\5 d;pN UcH[G޸y$$hc Aђx~ݒ+7!8K[!"yX#P) {]ug3缈'NL\l)BM3-@HZ5'߄D6]XNӖ<߼DGщ7oSg6!rydZE!*CBޛvʽa!$dG T4;Gw.xH_W> ӁAS$+R=$8x}_[ueX'4KfMn;Yy5xj(ײ&A`/TmN،D/C(dIU#9O{b T8tݽuYonׅgVE}ǁWVx]7aݜԴj`L\ '閜h+;6nՅ7oaNi=)6$CP )͵V3$YN^wr}1΃1Uק#xzU8WlN wlOJ~d^+NS!C?хRS؞dT,mjeZ 7lm,3$Ezo& Ǯ=@ llS],5·"ىf)C{"F$:!8'ɗB?r2;+H;c9۝y66NԽ~+@G65Et l#uO]nۿMKBQ;9)GuE/Hav>2ĂOڴ-£CR&@ǬƱ me/{_#u< fC9^v.rW6ImeTQm|bkcR7A#LH]GHtO ZV?߻\+Avb[ً kY+q1FİXOf'R i"]ZU5'+0m(Hoj_H'Am<5/\BuPH~N1MTY8V9:5OX> {ybd? ?-]js.A0CPw&n!\YιٞIPt)馧ݚ6߷? )U XXhw*ZKO9 ZvwCߊ%k)PeaU5Oty k7^7q`tp3ߧ(6ΔЖC7 7GvK5BQ:QgRL }K#E"rH|H7n"7wGr!5:y3,zUSUAVO jˢ0ݒL~P06fLkcO&BE꯷; Qq1{1A9G`0{a/]$`7"WwёV-O7 ץ*(MOaaVH~W+P?S@2|NNuP2}qsmAR'x1KVӼYcΕn>pݳ?:XNa`?OlF`?e۞ÏMnj 6r02MV =h*ԛmelNz/T+&8E- qCIQ'pt2W(gO^_Eڢ8uGO uyIE1x(:פb?wFbW1d2 !]n. &fc E+6趋RjHBS$k$P{J 2D݋ #iW6ۡ,r$bg2zEW0 ȋqy}0\5dQʴU zRKs "ZU.Cvy%nHhc#FB0֒sk ɱ rt1%f`$yHNTtw96[U^*W|ϑW/膓AR҆Pⓙ3P6̣"9eEʐ&B.1RMu&՚4z51E5QJj!u48 &[.q {]f)7}Ź3Sڒ6H$1;Q^/w Ϟ{%CM;@]iz\ti Ixzkvi!: 9f-ɑe;g5bTXB7moBLmNh)Eiu+F8'tSzæ0j`2E;|Bqlx΢n9vKV3Ŷd+xR6*ӉnW50]FA$3ɒ" VW( YG'޼/Y *EQ)`gp#3ث?*o?;L`3(,PeRPMvƆ LëK'[?ERo% j NmLDtAOrjr#u!TL #?mZB!{GPluSUj?4>Y K84ߏ-T'd |U$Ds~E,O{5 I:v~m;m "*F8y\ÃX? o~1*=5TQHLtSDz تU?z[QM0@M;GZȗ , hq):Npp[@Jw~g~ %$r1 aX x!Y:8Tk($}qcj#] @yN"F ]lp]ω6 5gtſMK !V$eƶ yK/%($F'.oUS4BoocdV,Gt -WipQZeJe5GEM5WCLуt$&bZ;\= l:7v%DTsNeƺԨ橞lEU],j2߬U^m;04$ǵGP[GqrĤU~DO{tj=8Xq\XQq*g/ߋ|m<[M>ex,Qmo̯꫷:<f#(F2 /=ΎϷo7kU(߻D7+Bu$ʞYb[= .Nk?>ZإcjOT^qC*C(D?/rԍ a}ۤ,C+<,o/IOh|z,2?aX2ׂWJA0oMTV$KЍ&!wy"v:,IITӔz9THh)%Mԅq쯛f!f,=wg3߆57VxK^HKh ޭrVEM?zԌkFu'y{,4_d1QS ݄=6vHy[u\yBhN{-F؃=a-ЪUZun!ӫBRZ@7NB37 I?MVgͫ"vx :.ea|m|*!9-{D=] KzpIP uQ ;43b3򷋔XCy6١iƝr TYUkLK/ӵVtԨj͑HseI5>U, M %Gp'OޕUD&'~\xI Z*n,Ap%d 6  Շ"3P yfWF8H6$xhYh/|ǓʃU*['LU6wM;*D'ae>cKU8 n4) R^5L߻,H*%$lOA0Tdry$Fb'ޛ\qK@d\Go 3~$ʎnhђYE8["͵^(B`Wbdi'CA=Ta&ݠܴ9!ov"' K8Z'kmfaݥcF ?.[*I]%k*KTgMBM1OiKh5|;}Ä糟 Zh;_ v- N[N|@Ψ=<H"aC39(t@:>=MdIȱBE~h[p*j UaY>c1D]Vm\ b{o/v` )G9+$\0"D!m~T,}%lpŰ,YQhYV ?,kÿ[,V0nhFTOeco@@L} 8p៨̢p=Uw9}yu響<<\ ~%5ͨ&[B]gUAj^w;xˢ7 C} :Q>W)*L9j%r@6vLذ^ɕ>=L[5EtѮ4c&??}⢆V ^hE_Ckւ_ me[wX?$[}5E;ͧgʻ;+DlU9+?ɱ2*Xm9QIxf 4؟!6CcXPw)o7 ".ke}2 [TVL0_Vtj,V+ԊW -zyA'tK[$l9BB6v\\_kJ/u36袿O$%~G?֝>% (SgVȤZC8⒤8kZB$(u7r=1T;L|/7!KBnlHUkB̷:؟i_UDbZE[5ܪWO_F!K[;V>ܛ*Rtj>I_zo]Fv~e^o\^յiK%o5XJekcF'Cpe5?v~VRocߚ]ЀI TF|bE1_$@w^(yFIf GhaAEUɭUWANŧi^œ܄Rs~C8dT64E%a.gF,&[UorVTN q$sHCV]V-U"SSJ{]W^_O7V:SqRBBxyxhG?fp;1Ԑ`?[ؤ?SKtQfG7lV?z(;`vyQՌEē_x4Fߗw6'5rWS8%qtlcq|mV B >X~c8 bDE Ӌ0 NVܭf~h2WYc 2koO3?-r$qtR㈚^>w.2{NNB0l~?~B($!/@u*M5ӓr}O2u?,/=,WVv\;-M; Pw ml}TʚaeH@NaI.{ (ӵmÚ #Tz@m-00||(vkUFxڅՌ~we@&ڠ5J[Gy M~CG[ߺ$ VEH&$1kύ n=yLfy ܹ)fd!99}N||D T xvO@@jFm&Z'@hШ5<ʫ5) 6\9$᱅ TYXh"C8YQP՚iӎ:Rޗķa-* 5o%ncp>L88k?El/g. ԫZx ~gJhKV6۵~1e2gD|O~~޽7I6zE-PcjF"UTPZ0> J $/6YtS~ow9xR4b EzBrK9Hw__B]Ava%'ۧXKfr.=*żN{4Ĵ\Ӗ$`XB] b¯1-Pu|2Dߪ-K'8('v@a8!E~vX sG&C:Ő6 6柨 aښ.q>]a/VջsMn`"ɡ@{ch+ e$#ֆ\();_{u-f1:]B孱k-q'{chz/xͻeU˱ku {uU*bX-)Nt\l'7 >3Ɓ)PWH`ccK:o<!]쿒deo|r=k:dۉ^fQhjZQQڪk:@_YU)v7weyL9Io9xjuOYlrxoUUðd-GbHp J #f*QuoOm_ zx?_z7z_Gا|)%斚JJ`ZCL.: ˁcoxhDKH HY=?P㺆)t뤦!H Md?ÁӰ䉡HhK-ԅ6ehNL+tl5y۟d\ /+Gl[7@fUjV//gFIEU?wQ}3.@ĸV)&xlp5ޮ9Y(@Pj66u7G#vISs|.a‹0NW?ͧ_b4qccMZccy%'7BM&TғrūؽI0mvGe;U _Ҝ+'=Gik+{p(@j0_D Lvڤ)D 8xkt8yB 8-3o܁4khu\DG(%~ z~|SdM"֝; igH%?8X ndXN?- &|&A'EbߤP_[7 Wy2&Q}O֎穅~9KC7~]G(ؔB]<5dwPjz;NBlC'r?lj*ǃFo99khEg zd  a9:Q6\[8 wYJ/@[]o}wyݻOinglM)VIXyc+:uGt3ħ﷚<)E쾸JZ}joR)  u:+` $)d;%ֵ+[׮?j7u =z}gIx(ЊuUxP*ZB⽿6*@qe&8mL9IF֋Ǧu^o@C;$XiڧZ;6eYTd1$޴cEM; 'caCV!XE9Q@U+J{!_yx<< ?4 AxtS7e2k2VE;39N ]iCWPe˹y4‰jc9!?QǓ3{Z-]8Rw^{k/?{}ћՌqr:Ÿqퟘ>1"j]Ǟg[zT?h<`ƗP\DHg{.yD\,IOt_x|5TJ|rDP$aeVM L;=KлOƆZU -G;ȶz9%WU#3`oj?^RL'KijY?Wpł^Iɠʚq. IXm5<19IơyEr~z eLxxVΓ%⫷ )ה25d^M;o^QKP֯6tr5aɟ$*EKt:Be_鵷^z-He" $dڴ~?}~IqTjU#\`6CmSSy5hרL_P_B aOqꞹd%v/S16Z5l2 "6$bʒ2NC贐*yڽJxo/p=5eBPg3v,‡PIi4^;_χHZIⱯ")!yl>aOgEh `P8.8>|g8p$K7`9.r (RS}Tj  "? ދ;A_z_[t4O:ONy%t}j!?7q17ǟ,e&bRwm.67Y$IuqI(M]nI YP'S'tK֘g3W|B*CfDh?W]j'ѩ3g{gnX[PӠU鴩@.T㙨 mGA5?%(>!g"V|<3e'YX\?6moK`tkUVWUs<Ž!=lh7NCkB8YsyVyʴ%6̇DG!\fٰ&A5 T! 9sYPހ$/"ǁ2_s-(8כYY_T\OKQ'n}껾CvC7 }V]TτdI-ۛ腬=VY| O (m4ϰdBΓWy,Ar`oZaͯ~7ǭ~>D=kXS:1`֧m-тYj U g `ڞ?H=pjXt;c9.r$m''C]?KJ G.{?=xN(FYP'b6r#/2<:t&|H0Ĵ?>c}?`8UKtQ<9'?0}9NJ?2:[􆱈/Z(ҖVnlTH9JtY C.O-9AnǶbj:_Z!+zf P{Ѕޕc?dES9LY/}I*9ˈ"᫫/o^wHYϟB^)EZL[ZZRa򽍳.a$zEW0D`=7 -ǦִWo?T/Zxr9s~cnחM&c u] gWj7o}<5<$ ufYm^E0gs~cL>Gl&oO Uݿ=;cܨU~3_$dI!L"ť!zOyD<' +~>y crK ꕹ7֞o>(`d/0x1WB;1 ԇE#>%(?(|9p0L _ex*BdxNIq)9I>LΓ%9?H?_R,*}Ȝ'Kssu?V_D˧>/1]0߬9TwrLȚK삅dxN8C}r+ՏIg'^yCΓ%9៣di{E7&w%GZȎs?|vT8OK?|-{^ˇgT=KGyD<'s|!|IV?]n<'s|"pFSY6IDATxg,y>ֽuMF #$ A(FK2ΈV;gfhwHfxfF#ˑYH" $n7uWeVzYQ.}NߪȈ'yi6=xt{Qc<c z/R0}y>/s1~w;=(1"o9"U%~1#<ƣc oܗecFx3c 3ֽ,S:1N) ~aJdY=?#r< x~քߩR3<Ʒ%G}~?_&E Mn'ЗXBȳŒP {_X_^]zTGxL>OZCGz\\Tqv_k͛o{htݿcLIXZ̟?x婋1 <OhYy21>)=|glo˲`Dl6w{_yu g1Sς0^`nj0g)(syηy;;R7ȥ3]RŲnjFs7uHҒT‰ʨ|L-/;ba%ԇ|B)FB*/+ey&'xwݯY,v/5J͢&j;frG~y{XI;?"2c:C|*{reKw]0XZ{ϺXxN:poɗ;XZ[U/,ηya gri ΍m;\y !ZTˁKKʹY G+ 6W~jWj70WPWʲEۯ?ran,@ާ HtbOFtOno3qO?e~OT~:·WEyl6;;]sD&!mZĿf?] ShZBsYbOެp^XK =Z&* nſEy.,|!3IsWivj/肙ybE͋fmq^yzez7^{]njH]9ɘvqQ:?'u>}뷝SUkV6Rej!3gLB@ K/|?ۿoa?u*Aϕb/?L&o.w/4ʬ u>2d}/1fꌳ~aؓu,}PW%O_h-bcF ߥ>SO{f_X:Q] ț,k@Vg YɎ^04%6P+ݕJ'1#w#XZxO#Z%ʌ2#{/XkDehI?*nS[pa ?q>WQȷ0~_X,vgnVdY=dL(:dFbUkSTyD.r9+Rr"cݾ]]D2?`u59|q6[mNII/S TiʸOTJ1$}LD'_tU|P0wZ 1ɞQX*f2{& MNTqA.5 J1#R ht/׿׿FsW^rB %Ocw\QGvGw o^2D Dm,/lB5g+&0py&?Ʒ/π6FΧm}\nO#ϕ9fНVԓ { ;MJ*!*۵vl?C:}cԗ.+٤Uo^ RΠ0@p 21û?Z7u4'ITREfxƣKUrY]c( .sTUBFJۼujf~=E?|E RcQC6)y@ӟl& ңrq]f^(>W/π0`L ptO|a\Z?s!pTѷMJė BH2O.)@T^dR78ۑ)`Rg>EVge6x;"vTQL'^ba)U?R 7|8^-g.$; 5FgPx%Gx$.N 0qQ}2 CKE1J^cUh7hX!$ SeanvQ>Xt>hfs(@4;]h1gVL#!pː=s?JåHE@3e.1C.s S|C`&GY1/ˏhCvFgi|H'W"L!p=$5~{o1LE,oX!u^{ov S<&%,=ΊjEQ_ЏXo߽ Fi)-eJŕd 0ĿoK2ntzeC!4A3.B]EjyR4zzK<yπy]RU_h#9Ң2Q<^o*b媻O۞>˿nR2i@a6z 2I7dz3}@/S/+Vy^k{1. ClB^*JsQ_饊>Ir#N)`wgӕO]R4~d2ʥ`igRRQN}~w#Ye*NŔ`Վa&UdEӺ\aJ]M:/~us󀡹fJsCIϭd~:mq Ck Este~cl_0ۓ=eϒũ)zD2]ZVE [du%Y0UJaۛݹkow*$8@2FZSTXVNQ{ wBѤE/( HX`(Cl>|10E*T3߮? &tto;S )<6tX槬l_6߸/$Td5OMϯ=t,U&].|d(aYQ3 S̱TiUߖ~\^`MڔƧ|u42z\$ސ3_s@VGULfO)C^H3 S4 3}KKEef~dl㷥5>Uo#hɲ=0GoU|g dHtQ*B/"$)>ގTħ~ 1}BdBG^^Gu٣-UܑKj]gs"x|[R4Vw$Tĩ'D8YEz(Vi.Mgz%c〩{OrIv/"D5Oa6$IEagre"1.800mӢ_ڬ%W~[R| ,G^XڤR=ҐΌ|>!SMՄD@)E5+եdH2>l.j=<5#sw"Y˴4MC&K#veYm^)fg~]Hr1#_s1{rMߣvߖNПyvG<ć }Wp9)#0B6Z.MVhA"FdEka 8 iOIߥ0 %.QuZbdw#QqfaISGk/^V"C;uN)U[6=Y1~^.IWoR_z\ZDˌ>|4A#DKQWoF'YQ!^Zݫ҉xZ̰9m.$ IS6/ƹ{.S}R>S^}u$1:8 J6a)LB~vUpx2G<_Z̗˹KWo;$Y 4Q6Yǹ/#XPEsJ]h8+(P5Me$+X%gj[&Z|_1]oSvQqupJ3Z'|~@Sn O\zg=ߢ05m.siP>r)U_Utys5#bS %j(!PA}I MJZVv4SQ1)LT ~FX~ pR1[n!`d~^NN\Ѻ؇Æ:N^V LBP7FV@n݁(S鑝[G/r[NWԎ1y@oWO1FQG>Z)YKm(p}>&%p~jG|kQIث?Ib5_54ջ0נ),Π|@FWɻ!`QW.ӁH6m,J1wP6O7FQcr?E< KIO_8j=,_`:8pj6e=UiE 66r111ϡZ9Lu%5_1yw1s1%LߊN5y9)[3?O%;jhkƞB4 j5BBkta(2B:־4L l~Njw9q).)N ”*X[B{![-7Ĺc߇;͏%#ZL)̕ (LN6zW7DG3 &)O;FQcE;O2αIi*1!*7NoTTR\U Rʻڝ="/~YXv)y5JB_Z.%Y.uٯ1XFKċ[9<‡)v{0"(() 0٪JqgU؇#!]I_Sk-SkãT'F)y&{Wc菦|J=J Atz0E5DQ]hJ&ʧYN SOn!0xzӟ ?O$(ĤIyb{K/{gem{ ,mkE+3T‡0ieˌ?WiPlXNo6C?C4wQx">h= II1.XYs}>N( r^j{7Q c'zu" D@Xc,LQ)ul!7O>ϓU<$8)Yoy BT|=OdVO8R% #Ti"J~8&4mjNo}54k] $DEOb"K SJ MvɃ}nJ3c;"!pc?_HUW:ʫ{-QEzǠ e,pZw,_ɤ2=:!^MӄBIG"$ՄZL)5YKza(AkSa}_1&As_T)ſ`o7,g]Y ;̑%x/[t/F(j諀??7h+magM.i V5)mT@KqC6-ƔECOBWo"hRZ#rtR!7{.u1u4w:>N; A[ktZ7UU%0&a:%= *7>'#"UM=4%/}JfB{|y^٭\JD K&)r JM#Bksxye0B!DUp) $N !@"Ff6Nej҆iA#y$ސm̵1r b\쎽Z|0ŒP04g8y<'x jDI]_$p&w6pU0u>ت40)#}1o S}J aY>3O!:z"UF, Eޝaf(=uF@3?8 [㰇{3-1P_\A:&noS* CԈX 4 < -Jd416ڰӟ4h!dtb#LS*FJTod7(F-;S:bh?tdchQxx;.m)R@ӳUqޛ~Iʛ3ai[]hಗN߁VːM,f _F]MW؄d&G-,AS^-nKTWQFy`%F>$5hj߬?Miyyٱ'Ac5Pꭆ1Jw\_p45c7ap yڶ*SJD0^ܞ=Ro {Kx.|m]92c<4{YO験$HUܬě]!l;]OؤdgO˂%&LB 9Va[余F8hc#IfT8NJh$fHK޼4  WNI I]YtpZep`)jyJy@2ՀME,b9#fԻ{{e`M{VPřEӺLNWi~rE뢤vs$t| ՛eeS:l$TSR@}%bIq،J+{n\*S4] 0) \"#i ;Re.%{q!r!@8ڮ,DWӎZf@U#8jBO'reZ}8`RH+'--AOqf:X#{3~qѴeuFN1,S1IPa Swb;}?yw$P6v;?P/,Y6bhX5)#칱O=OXRLNr\𛡨fwS޻ 1빟9VuOSE-lJwSR1v[l&To~uX 3b)RBaO}T9 vg~.}RG$yoN-Q3*r[73,UH0C@r)9TbbJ {<^)_ Ѯdh?tF)y6sxw'bP3GQch͛ 0g~F>)0hZe~~q~^LM>L1̺^Ouԉvb!Yí3kBI8Bce@TP_1ܩ")DtmafI2U}]Dq^Xw6)`BM%coSQfC _Z4Ŀl멯:j#fl:3O?q3oTfNo2#F@f=F11@:SA\ilc123 B4N (Ƴ90 U'A;U.J.}J QS(Q? 6;LDVJSkɃJd(Y"XޛN{f E!n&2$3˷vsL @MGF"`7e4V/=,fbAەkwhπ|S(A M h/QK #8|"_XZ_9w6~WJX%yR1u7'oe\Q!lF/2a'u`2utZG6xd12@Ή(Ib)}e]&+4$uc"JKjm!ZLQ1_X=Ty+hJth~t/~ݔR"I KFGV;~bha :\p:-\68

::pi()); } // get name virtual std::string name () const { char _name[256]; snprintf(_name, 256, "vector-%iD", ncomps()); return std::string(_name); } }; template< class GridView > std::string doWrite( const GridView &gridView, Dune::VTK::DataMode dm, bool testRestart = false) { constexpr static int dim = GridView :: dimension; const typename GridView :: IndexSet &is = gridView.indexSet(); std::vector vertexdata(is.size(dim),dim); std::vector celldata(is.size(0),0); std::stringstream name; name << "vtktest-" << dim << "D-" << VTKDataMode(dm); if (testRestart) name << "-restart"; auto vtkWriter = std::make_shared >(gridView, dm); Dune :: VTKSequenceWriter< GridView > vtk( vtkWriter, name.str(), ".", "" ); vtk.addVertexData(vertexdata,"vertexData"); vtk.addCellData(celldata,"cellData"); auto vectordata = std::make_shared >(); vtk.addVertexData(vectordata); double time = 0; double tEnd = testRestart ? 0.5 : 1.0; while (time < tEnd) { vectordata->setTime(time); vtk.write(time); time += 0.1; } if (testRestart) { const auto& timeSteps = vtk.getTimeSteps(); auto vtkWriter2 = std::make_shared >(gridView, dm); Dune :: VTKSequenceWriter< GridView > vtk2( vtkWriter2, name.str(), ".", "" ); vtk2.setTimeSteps(timeSteps); vtk2.addVertexData(vertexdata,"vertexData"); vtk2.addCellData(celldata,"cellData"); vtk2.addVertexData(vectordata); while (time < 1) { vectordata->setTime(time); vtk2.write(time); time += 0.1; } } return name.str(); } template void vtkCheck(const std::array& n, const Dune::FieldVector& h, bool testRestart = false) { std::cout << std::endl << "vtkSequenceCheck dim=" << dim << std::endl << std::endl; Dune::YaspGrid g(h, n); g.globalRefine(1); const auto fileName = doWrite( g.leafGridView(), Dune::VTK::conforming ) + ".pvd"; const auto fileNameRestart = doWrite( g.leafGridView(), Dune::VTK::conforming, testRestart ) + ".pvd"; checkFileEqualNumLines(fileName, fileNameRestart); doWrite( g.leafGridView(), Dune::VTK::nonconforming ); doWrite( g.levelGridView( 0 ), Dune::VTK::conforming ); doWrite( g.levelGridView( 0 ), Dune::VTK::nonconforming ); doWrite( g.levelGridView( g.maxLevel() ), Dune::VTK::conforming ); doWrite( g.levelGridView( g.maxLevel() ), Dune::VTK::nonconforming ); } int main(int argc, char **argv) { try { const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); if(mpiHelper.rank() == 0) std::cout << "subsamplingvtktest: MPI_Comm_size == " << mpiHelper.size() << std::endl; { std::array n = { { 5 } }; Dune::FieldVector h = { 1.0 }; vtkCheck<1>(n,h); } { std::array n = { { 5, 5 } }; Dune::FieldVector h = { 1.0, 2.0 }; vtkCheck<2>(n,h); } { std::array n = { { 5, 5, 5 } }; Dune::FieldVector h = { 1.0, 2.0, 3.0 }; vtkCheck<3>(n,h, /*testRestart=*/true); } } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/io/file/test/vtktest.cc000066400000000000000000000156651511655130300216660ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 const char* VTKDataMode(Dune::VTK::DataMode dm) { switch(dm) { case Dune::VTK::conforming : return "conforming"; case Dune::VTK::nonconforming : return "nonconforming"; } return ""; } template< class GridView > class VTKVectorFunction : public Dune :: VTKWriter< GridView > :: VTKFunction { // extract types constexpr static int n = GridView :: dimension; typedef typename GridView :: Grid :: ctype DT; typedef typename GridView :: template Codim< 0 > :: Entity Entity; const std::string type_; public: /** @brief Make a new VTKVectorFunction * * @param type_ Type of the function for use in its name (hint: "cell" or * "vertex") */ VTKVectorFunction(std::string type) : type_(type) { } //! return number of components virtual int ncomps () const { return n; } //! evaluate single component comp in the entity e at local coordinates xi /*! Evaluate the function in an entity at local coordinates. @param[in] comp number of component to be evaluated @param[in] e reference to grid entity of codimension 0 @param[in] xi point in local coordinates of the reference element of e \return value of the component */ virtual double evaluate (int comp, [[maybe_unused]] const Entity& e, [[maybe_unused]] const Dune::FieldVector& xi) const { return comp*0.1; } // get name virtual std::string name () const { std::ostringstream os; os << type_ << "-vector-" << ncomps() << "D"; return os.str(); } }; // accumulate exit status void acc(int &accresult, int result) { if(accresult == 0 || (accresult == 77 && result != 0)) accresult = result; } struct Acc { int operator()(int v1, int v2) const { acc(v1, v2); return v1; } }; template< class GridView > int doWrite( Dune::VTKChecker& vtkChecker, const std::string& gridViewName, const GridView &gridView, Dune :: VTK :: DataMode dm, const std::string& path = "./" ) { constexpr static int dim = GridView :: dimension; Dune :: VTKWriter< GridView > vtk( gridView, dm ); const typename GridView :: IndexSet &is = gridView.indexSet(); std::vector vertexdata(is.size(dim),dim); std::vector celldata(is.size(0),0); std::vector celldoubledata(is.size(0), 1.00000000000346e-12); // Write algebraic data vtk.addVertexData(vertexdata,"vertexData"); vtk.addCellData(celldata,"cellData"); vtk.addCellData(celldoubledata, "cellData_double", 1, Dune::VTK::Precision::float64); // Write functions given as VTKFunction objects vtk.addVertexData(std::make_shared< VTKVectorFunction >("vertex")); vtk.addCellData(std::make_shared< VTKVectorFunction >("cell")); // Write globally defined C++ functions auto f1 = [](const Dune :: FieldVector& x) { return std::sin(x.two_norm()); }; vtk.addCellData(f1, Dune :: VTK :: FieldInfo("scalar-valued lambda", Dune :: VTK :: FieldInfo :: Type :: scalar, 1)); auto f2 = [](const Dune :: FieldVector& x) { return x; }; vtk.addVertexData(f2, Dune :: VTK :: FieldInfo("vector-valued lambda", Dune :: VTK :: FieldInfo :: Type :: vector, dim, Dune :: VTK :: Precision::float64)); int result = 0; std::string name; std::ostringstream prefix; prefix << path << "/"; prefix << "vtktest-" << dim << "D-" << gridViewName << "-" << VTKDataMode(dm); int rank = gridView.comm().rank(); name = vtk.write(prefix.str() + "-ascii"); if(rank == 0) vtkChecker.push(name); name = vtk.write(prefix.str() + "-base64", Dune::VTK::base64); if(rank == 0) vtkChecker.push(name); name = vtk.write(prefix.str() + "-appendedraw", Dune::VTK::appendedraw); if(rank == 0) vtkChecker.push(name); name = vtk.write(prefix.str() + "-appendedbase64", Dune::VTK::appendedbase64); if(rank == 0) vtkChecker.push(name); return result; } template int vtkCheck(Dune::VTKChecker& vtkChecker, const std::array& elements, const Dune::FieldVector& upperRight) { Dune::YaspGrid g(upperRight, elements); if(g.comm().rank() == 0) std::cout << std::endl << "vtkCheck dim=" << dim << std::endl << std::endl; g.globalRefine(1); int result = 0; acc(result, doWrite( vtkChecker, "leafview", g.leafGridView(), Dune::VTK::conforming )); acc(result, doWrite( vtkChecker, "leafview", g.leafGridView(), Dune::VTK::nonconforming )); acc(result, doWrite( vtkChecker, "coarselevelview", g.levelGridView( 0 ), Dune::VTK::conforming )); acc(result, doWrite( vtkChecker, "coarselevelview", g.levelGridView( 0 ), Dune::VTK::nonconforming )); acc(result, doWrite( vtkChecker, "finelevelview", g.levelGridView( g.maxLevel() ), Dune::VTK::conforming )); acc(result, doWrite( vtkChecker, "finelevelview", g.levelGridView( g.maxLevel() ), Dune::VTK::nonconforming )); // write with filename including a path which is the current directory // this is for testing the parallel version of 'write' acc(result, doWrite( vtkChecker, "leafview", g.leafGridView(), Dune::VTK::conforming, "../test" )); acc(result, doWrite( vtkChecker, "leafview", g.leafGridView(), Dune::VTK::nonconforming, "../test" )); return result; } int main(int argc, char **argv) { try { const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); if(mpiHelper.rank() == 0) std::cout << "vtktest: MPI_Comm_size == " << mpiHelper.size() << std::endl; int result = 0; // pass by default Dune::VTKChecker vtkChecker; acc(result, vtkCheck<1>(vtkChecker, std::array{8}, {1.0})); acc(result, vtkCheck<2>(vtkChecker, std::array{8, 4}, {1.0, 2.0})); acc(result, vtkCheck<3>(vtkChecker, std::array{8, 4, 4}, {1.0, 2.0, 3.0})); acc(result, vtkChecker.check()); mpiHelper.getCommunication().allreduce(&result, 1); return result; } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } } dune-grid-2.11.0/dune/grid/io/file/vtk.hh000066400000000000000000000011641511655130300200060ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_HH #define DUNE_GRID_IO_FILE_VTK_HH /** \file \brief Convenience header which includes all available VTK writers */ #include "vtk/boundarywriter.hh" #include "vtk/subsamplingvtkwriter.hh" #include "vtk/vtksequencewriter.hh" #include "vtk/vtkwriter.hh" #include "vtk/volumewriter.hh" #endif // DUNE_GRID_IO_FILE_VTK_HH dune-grid-2.11.0/dune/grid/io/file/vtk/000077500000000000000000000000001511655130300174635ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/vtk/CMakeLists.txt000066400000000000000000000012271511655130300222250ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS b64enc.hh basicwriter.hh boundaryiterators.hh boundarywriter.hh common.hh corner.hh corneriterator.hh dataarraywriter.hh function.hh functionwriter.hh pointiterator.hh pvtuwriter.hh skeletonfunction.hh subsamplingvtkwriter.hh streams.hh volumeiterators.hh volumewriter.hh vtksequencewriter.hh vtksequencewriterbase.hh vtkwriter.hh vtuwriter.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/vtk) dune-grid-2.11.0/dune/grid/io/file/vtk/b64enc.hh000066400000000000000000000041031511655130300210630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_B64ENC_HH #define DUNE_GRID_IO_FILE_VTK_B64ENC_HH #include namespace Dune { /** @file @author Christian Engwer @brief Simple base64 encode We implement the base64 encoding (c.f. RFC 4648 https://tools.ietf.org/html/rfc4648). @{ */ /** @brief endoing table */ const char base64table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** @brief struct representing the three byte text as well as the four 6 bit chunks */ struct b64chunk { using size_type = unsigned char; size_type size; char txt[3]; void reset() { size = 0; txt[0] = txt[1] = txt[2] = 0; } int read(const char* t, size_type s) { size = s>=3 ? 3 : s; txt[0] = s>0 ? t[0] : 0; txt[1] = s>1 ? t[1] : 0; txt[2] = s>2 ? t[2] : 0; return size; } void put(const char c) { assert (size < 3); txt[size++] = c; } void write(char* t) { const unsigned A = (txt[0] & 0b1111'1100) >> 2; const unsigned B = (txt[0] & 0b0000'0011) << 4 | (txt[1] & 0b1111'0000) >> 4; const unsigned C = (txt[1] & 0b0000'1111) << 2 | (txt[2] & 0b1100'0000) >> 6; const unsigned D = txt[2] & 0b0011'1111; t[0] = size>0 ? base64table[A] : '='; t[1] = size>0 ? base64table[B] : '='; t[2] = size>1 ? base64table[C] : '='; t[3] = size>2 ? base64table[D] : '='; size = 0; } }; /** @} */ } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_B64ENC_HH dune-grid-2.11.0/dune/grid/io/file/vtk/basicwriter.hh000066400000000000000000000412441511655130300223270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH #define DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { template class BasicWriter { typedef typename IteratorFactory::CellIterator CellIterator; typedef typename IteratorFactory::CornerIterator CornerIterator; typedef typename IteratorFactory::PointIterator PointIterator; typedef typename IteratorFactory::Cell Cell; public: typedef FunctionWriterBase FunctionWriter; private: typedef std::list > WriterList; typedef typename WriterList::const_iterator WIterator; typedef typename Cell::Geometry::ctype ctype; static const unsigned celldim = Cell::mydimension; typedef ReferenceElements Refelems; static const FileType fileType = celldim == 1 ? polyData : unstructuredGrid; const IteratorFactory& factory; WriterList cellData; WriterList pointData; CoordinatesWriter coords; typename IteratorFactory::ConnectivityWriter connectivity; OffsetsWriter offsets; TypesWriter types; public: BasicWriter(const IteratorFactory& factory_) : factory(factory_), connectivity(factory.makeConnectivity()) { } ////////////////////////////////////////////////////////////////////// // // Methods for adding data // void addCellData(const std::shared_ptr& writer) { cellData.push_back(writer); } void addPointData(const std::shared_ptr& writer) { pointData.push_back(writer); } void clear() { cellData.clear(); pointData.clear(); } protected: ////////////////////////////////////////////////////////////////////// // // Methods for writing single functions // void writeCellFunction(VTUWriter& vtuWriter, FunctionWriter& functionWriter, unsigned ncells) const { if(functionWriter.beginWrite(vtuWriter, ncells)) { const CellIterator& cellend = factory.endCells(); for(CellIterator cellit = factory.beginCells(); cellit != cellend; ++cellit) functionWriter.write(*cellit, Refelems::general(cellit->type()). position(0,0)); } functionWriter.endWrite(); } void writePointFunction(VTUWriter& vtuWriter, FunctionWriter& functionWriter, unsigned npoints) const { if(functionWriter.beginWrite(vtuWriter, npoints)) { const PointIterator& pend = factory.endPoints(); for(PointIterator pit = factory.beginPoints(); pit != pend; ++pit) functionWriter.write(pit->cell(), pit->duneIndex()); } functionWriter.endWrite(); } void writeCornerFunction(VTUWriter& vtuWriter, FunctionWriter& functionWriter, unsigned ncorners) const { if(functionWriter.beginWrite(vtuWriter, ncorners)) { const CornerIterator& cend = factory.endCorners(); for(CornerIterator cit = factory.beginCorners(); cit != cend; ++cit) functionWriter.write(cit->cell(), cit->duneIndex()); } functionWriter.endWrite(); } ////////////////////////////////////////////////////////////////////// // // Methods for writing whole sections // static std::string getFirstScalar(const WriterList& data) { for(auto&& d : data) if (d->ncomps() == 1) return d->name(); return ""; } static std::string getFirstVector(const WriterList& data) { for(auto&& d : data) if (d->ncomps() == 3) return d->name(); return ""; } void writeCellData(VTUWriter& vtuWriter, unsigned ncells) const { if(cellData.empty()) return; vtuWriter.beginCellData(getFirstScalar(cellData), getFirstVector(cellData)); for (auto&& cD : cellData) writeCellFunction(vtuWriter, *cD, ncells); vtuWriter.endCellData(); } void writePointData(VTUWriter& vtuWriter, unsigned npoints) const { if(pointData.empty()) return; vtuWriter.beginPointData(getFirstScalar(pointData), getFirstVector(pointData)); for (auto&& pD : pointData) writePointFunction(vtuWriter, *pD, npoints); vtuWriter.endPointData(); } void writeGrid(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints, unsigned ncorners) { vtuWriter.beginPoints(); writePointFunction(vtuWriter, coords, npoints); vtuWriter.endPoints(); vtuWriter.beginCells(); writeCornerFunction(vtuWriter, connectivity, ncorners); writeCellFunction(vtuWriter, offsets, ncells); if(fileType != polyData) writeCellFunction(vtuWriter, types, ncells); vtuWriter.endCells(); } void writeAll(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints, unsigned ncorners) { writeCellData(vtuWriter, ncells); writePointData(vtuWriter, npoints); writeGrid(vtuWriter, ncells, npoints, ncorners); } public: void writePiece(const std::string& filename, OutputType outputType) { std::ofstream stream; stream.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); stream.open(filename.c_str(), std::ios::binary); VTUWriter vtuWriter(stream, outputType, fileType); unsigned ncells = std::distance(factory.beginCells(), factory.endCells()); unsigned npoints = std::distance(factory.beginPoints(), factory.endPoints()); unsigned ncorners = std::distance(factory.beginCorners(), factory.endCorners()); vtuWriter.beginMain(ncells, npoints); writeAll(vtuWriter, ncells, npoints, ncorners); vtuWriter.endMain(); if(vtuWriter.beginAppended()) writeAll(vtuWriter, ncells, npoints, ncorners); vtuWriter.endAppended(); } //! write header file in parallel case to stream /** * Writes a .pvtu/.pvtp file for a collection of concurrently written * .vtu/.vtp files. * * \param name Name of file to write contents to, * \param piecename Base name of the pieces. Should not contain a * directory part or filename extension. * \param piecepath Directory part of the pieces. Since paraview does * not support absolute paths in parallel collection * files, this should be a path relative to the * directory the collection file resides in. A * trailing '/' is optional, and an empty value "" is * equivalent to the value "." except it will look * nicer in the collection file. */ void writeCollection(const std::string name, const std::string& piecename, const std::string& piecepath) { std::ofstream stream; stream.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); stream.open(name.c_str(), std::ios::binary); PVTUWriter writer(stream, fileType); writer.beginMain(); // PPointData writer.beginPointData(getFirstScalar(pointData), getFirstVector(pointData)); for(WIterator it=pointData.begin(); it!=pointData.end(); ++it) (*it)->addArray(writer); writer.endPointData(); // PCellData writer.beginCellData(getFirstScalar(cellData), getFirstVector(cellData)); for(WIterator it=cellData.begin(); it!=cellData.end(); ++it) (*it)->addArray(writer); writer.endCellData(); // PPoints writer.beginPoints(); coords.addArray(writer); writer.endPoints(); // Pieces for( int i = 0; i < factory.comm().size(); ++i ) writer.addPiece(getParallelPieceName(piecename, piecepath, i)); writer.endMain(); } ////////////////////////////////////////////////////////////////////// // // Filename generators // //! return name of a parallel piece file /** * \param name Base name of the VTK output. This should be without any * directory parts and without a filename extension. * \param path Directory part of the resulting piece name. May be * empty, in which case the resulting name will not have a * directory part. If non-empty, may or may not have a * trailing '/'. If a trailing slash is missing, one is * appended implicitly. * \param rank Rank of the process to generate a piece name for. */ std::string getParallelPieceName(const std::string& name, const std::string& path, int rank) const { std::ostringstream s; if(path.size() > 0) { s << path; if(path[path.size()-1] != '/') s << '/'; } s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size() << ':'; s << 'p' << std::setw(4) << std::setfill('0') << rank << ':'; s << name; switch(fileType) { case polyData : s << ".vtp"; break; case unstructuredGrid : s << ".vtu"; break; } return s.str(); } //! return name of a parallel header file /** * \param name Base name of the VTK output. This should be without any * directory parts and without a filename extension. * \param path Directory part of the resulting header name. May be * empty, in which case the resulting name will not have a * directory part. If non-empty, may or may not have a * trailing '/'. If a trailing slash is missing, one is * appended implicitly. */ std::string getParallelHeaderName(const std::string& name, const std::string& path) const { std::ostringstream s; if(path.size() > 0) { s << path; if(path[path.size()-1] != '/') s << '/'; } s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size() << ':'; s << name; switch(fileType) { case polyData : s << ".pvtp"; break; case unstructuredGrid : s << ".pvtu"; break; } return s.str(); } //! return name of a serial piece file /** * This is similar to getParallelPieceName, but skips the prefixes for * commSize ("s####:") and commRank ("p####:"). * * \param name Base name of the VTK output. This should be without any * directory parts and without a filename extension. * \param path Directory part of the resulting piece name. May be * empty, in which case the resulting name will not have a * directory part. If non-empty, may or may not have a * trailing '/'. If a trailing slash is missing, one is * appended implicitly. */ std::string getSerialPieceName(const std::string& name, const std::string& path) const { switch(fileType) { case polyData : return concatPaths(path, name+".vtp"); case unstructuredGrid : return concatPaths(path, name+".vtu"); } return concatPaths(path, name); // unknown fileType } ////////////////////////////////////////////////////////////////////// // // User interface functions for writing // //! write output; interface might change later /** * \param name Base name of the output files. This should not * contain any directory part and not filename * extensions. It will be used both for each processes * piece as well as the parallel collection file. * \param path Directory where to put the parallel collection * (.pvtu/.pvtp) file. If it is relative, it is taken * relative to the current directory. * \param extendpath Directory where to put the piece file (.vtu/.vtp) of * this process. If it is relative, it is taken * relative to the directory denoted by path. * \param outputType How to encode the data in the file. * * \note Currently, extendpath may not be absolute unless path is * absolute, because that would require the value of the current * directory. * * \throw NotImplemented Extendpath is absolute but path is relative. * \throw IOError Failed to open a file. * \throw MPIGuardError An exception was thrown during this method in * one of the other processes. */ std::string pwrite(const std::string& name, const std::string& path, const std::string& extendpath, OutputType outputType) { MPIGuard guard(factory.comm()); // do some magic because paraview can only cope with relative paths to // piece files std::ofstream file; file.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); std::string piecepath = concatPaths(path, extendpath); std::string relpiecepath = relativePath(path, piecepath); // write this processes .vtu/.vtp piece file std::string fullname = getParallelPieceName(name, piecepath, factory.comm().rank()); writePiece(fullname, outputType); // if we are rank 0, write .pvtu/.pvtp parallel header fullname = getParallelHeaderName(name, path); if(factory.comm().rank() == 0) writeCollection(fullname, name, relpiecepath); guard.finalize(); return fullname; } /** \brief write output (interface might change later) * * This method can be used in parallel as well as in serial programs. * For serial runs (commSize=1) it chooses other names without the * "s####:p####:" prefix for the .vtu/.vtp files and omits writing of * the .pvtu/pvtp file however. For parallel runs (commSize > 1) it is * the same as a call to pwrite() with path="" and extendpath="". * * \param name Base name of the output files. This should not * contain any directory part and no filename * extensions. * \param outputType How to encode the data in the file. */ std::string write(const std::string &name, OutputType outputType) { // in the parallel case, just use pwrite, it has all the necessary // stuff, so we don't need to reimplement it here. if(factory.comm().size() > 1) return pwrite(name, "", "", outputType); // generate filename for process data std::string pieceName = getSerialPieceName(name, ""); writePiece(pieceName, outputType); return pieceName; } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/boundaryiterators.hh000066400000000000000000000144521511655130300235720ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_BOUNDARYITERATORS_HH #define DUNE_GRID_IO_FILE_VTK_BOUNDARYITERATORS_HH #include #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ /** @file @author Jö Fahlke @brief Functions for VTK output on the skeleton */ namespace VTK { //! iterate over the GridViews boundary intersections /** * This will visit all intersections for which boundary() is true and * neighbor() is false. */ template class BoundaryIterator : public ForwardIteratorFacade < BoundaryIterator, const typename GV::Intersection, const typename GV::Intersection&, typename std::iterator_traits:: Iterator>::difference_type> { public: // reiterator the facades typedefs here typedef BoundaryIterator DerivedType; typedef const typename GV::Intersection Value; typedef Value& Reference; typedef typename GV::template Codim<0>::Iterator ElementIterator; typedef typename GV::IntersectionIterator IntersectionIterator; typedef typename std::iterator_traits::difference_type DifferenceType; private: typedef ForwardIteratorFacade Facade; const GV* gv; ElementIterator eit; std::shared_ptr iit; bool valid() const { // we're valid if we're passed-the-end if(eit == gv->template end<0>()) return true; // or if we're on a boundary if((*iit)->boundary() && !(*iit)->neighbor()) return true; // otherwise we're invalid return false; } void basic_increment() { ++*iit; if(*iit == gv->iend(*eit)) { iit.reset(); ++eit; if(eit != gv->template end<0>()) iit.reset(new IntersectionIterator(gv->ibegin(*eit))); } } public: Reference dereference() const { return **iit; } bool equals(const DerivedType& other) const { if(eit != other.eit) return false; // this is a bit tricky, since we may not compare iit if we are // passed-the-end bool mePassedTheEnd = eit == gv->template end<0>(); bool otherPassedTheEnd = other.eit == other.gv->template end<0>(); // both passed-the-end => consider them equal if(mePassedTheEnd && otherPassedTheEnd) return true; // one passed the end => not equal if(mePassedTheEnd || otherPassedTheEnd) return false; // none passed-the-end => do their iit iterators match? return *iit == *other.iit; } void increment() { basic_increment(); while(!valid()) basic_increment(); } //! construct a BoundaryIterator /** * The iterator will initially point to the intersection iit_. If that * intersection is not valid, it will advance to the first valid one. */ BoundaryIterator(const GV& gv_, const ElementIterator& eit_, const IntersectionIterator& iit_) : gv(&gv_), eit(eit_), iit(new IntersectionIterator(iit_)) { while(!valid()) basic_increment(); } //! construct a BoundaryIterator /** * The iterator will initially point to eit_'s first intersection. If * that intersection is not valid, it will advance to the first valid * one. */ BoundaryIterator(const GV& gv_, const ElementIterator& eit_) : gv(&gv_), eit(eit_) { if(eit != gv->template end<0>()) iit.reset(new IntersectionIterator(gv->ibegin(*eit))); while(!valid()) basic_increment(); } //! construct a BoundaryIterator /** * If end == true, construct an end iterator for the given gridview. * Otherwise, construct a begin iterator. */ BoundaryIterator(const GV& gv_, bool end = false) : gv(&gv_), eit(end ? gv->template end<0>() : gv->template begin<0>()) { if(eit != gv->template end<0>()) iit.reset(new IntersectionIterator(gv->ibegin(*eit))); while(!valid()) basic_increment(); } }; template class IntersectionIndexSet { const ElementIndexSet& eis; public: IntersectionIndexSet(const ElementIndexSet& eis_) : eis(eis_) { } }; template class NonConformingBoundaryIteratorFactory { const GV& gv; public: static const unsigned dimCell = GV::dimension-1; typedef typename GV::Intersection Cell; typedef BoundaryIterator CellIterator; typedef VTK::Corner Corner; typedef VTK::CornerIterator CornerIterator; typedef Corner Point; typedef CornerIterator PointIterator; typedef NonConformingConnectivityWriter ConnectivityWriter; typedef typename GV::Communication Communication; explicit NonConformingBoundaryIteratorFactory(const GV& gv_) : gv(gv_) { } CellIterator beginCells() const { return CellIterator(gv); } CellIterator endCells() const { return CellIterator(gv, true); } CornerIterator beginCorners() const { return CornerIterator(beginCells(), endCells()); } CornerIterator endCorners() const { return CornerIterator(endCells()); } PointIterator beginPoints() const { return beginCorners(); } PointIterator endPoints() const { return endCorners(); } ConnectivityWriter makeConnectivity() const { return ConnectivityWriter(); } const Communication& comm() const { return gv.comm(); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_BOUNDARYITERATORS_HH dune-grid-2.11.0/dune/grid/io/file/vtk/boundarywriter.hh000066400000000000000000000040711511655130300230660ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_BOUNDARYWRITER_HH #define DUNE_GRID_IO_FILE_VTK_BOUNDARYWRITER_HH #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { template class NonConformingBoundaryWriter : public NonConformingBoundaryIteratorFactory, public BasicWriter > { typedef NonConformingBoundaryIteratorFactory Factory; typedef BasicWriter Base; const GV& gv; public: NonConformingBoundaryWriter(const GV& gv_) : Factory(gv_), Base(static_cast(*this)), gv(gv_) { } using Base::addCellData; template void addCellData(const std::shared_ptr& p, const std::string& name) { addCellData(std::shared_ptr (new SkeletonFunctionWriter(p, name))); } template void addCellData(Func* p, const std::string& name) { addCellData(std::shared_ptr(p), name); } using Base::addPointData; template void addPointData(const std::shared_ptr& p, const std::string& name) { addPointData(std::shared_ptr (new SkeletonFunctionWriter(p, name))); } template void addPointData(Func* p, const std::string& name) { addPointData(std::shared_ptr(p), name); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_BOUNDARYWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/common.hh000066400000000000000000000243161511655130300213020ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_COMMON_HH #define DUNE_GRID_IO_FILE_VTK_COMMON_HH #include #include #include #include #include #include #include /** @file @author Peter Bastian, Christian Engwer @brief Common stuff for the VTKWriter This file contains common stuff for all instances of VTKWriter. */ namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { ////////////////////////////////////////////////////////////////////// // // VTKOptions // //! How the bulk data should be stored in the file /** \code #include \endcode */ enum OutputType { //! Output to the file is in ascii. ascii, //! Output to the file is inline base64 binary. base64, //! Output is to the file is appended raw binary appendedraw, //! Output is to the file is appended base64 binary appendedbase64 // //! Output to the file is compressed inline binary. // binarycompressed, // //! Output is compressed and appended to the file. // compressedappended }; //! Whether to produce conforming or non-conforming output. /** \code #include \endcode * * This applies to the conformity of the data; a non-conforming grid can * still be written in conforming data mode, and it is quite possible for * data to be non-conforming on a conforming grid. */ enum DataMode { //! Output conforming data. /** * Neighboring elements share common vertices and thus have a common DoF * on that vertex. */ conforming, //! Output non-conforming data. /** * Each element has its own set of vertices. The position of a vertex * of one element will coincide with the position of the corresponding * vertex on another element. This allows for multiple DoFs (one per * element) on the "same" vertex. */ nonconforming }; ////////////////////////////////////////////////////////////////////// // // PrintType // //! determine a type to safely put another type into a stream /** * This is mainly interesting for character types which should print as * their integral value, not as a character. */ template struct PrintType { //! type to convert T to before putting it into a stream with << typedef T Type; }; template<> struct PrintType { typedef unsigned Type; }; template<> struct PrintType { typedef int Type; }; template<> struct PrintType { typedef std::conditional::is_signed, int, unsigned>::type Type; }; ////////////////////////////////////////////////////////////////////// // // VTK::GeometryType related stuff // //! Type representing VTK's entity geometry types /** \code #include \endcode * * Only the types which have a corresponding Dune::GeometryType have been * included here. Dune-type names have been used, this mainly makes a * difference for vtkPrism, which is known by VTK as VTK_WEDGE. */ enum GeometryType { vertex = 1, line = 3, triangle = 5, polygon = 7, quadrilateral = 9, tetrahedron = 10, hexahedron = 12, prism = 13, pyramid = 14, polyhedron = 42 }; //! mapping from GeometryType to VTKGeometryType /** \code #include \endcode */ inline GeometryType geometryType(const Dune::GeometryType& t) { if (t.isVertex()) return vertex; if (t.isLine()) return line; if (t.isTriangle()) return triangle; if (t.isQuadrilateral()) return quadrilateral; if (t.isTetrahedron()) return tetrahedron; if (t.isPyramid()) return pyramid; if (t.isPrism()) return prism; if (t.isHexahedron()) return hexahedron; if (t.isNone() ) { if( t.dim() == 2 ) return polygon; if( t.dim() == 3 ) return polyhedron; } DUNE_THROW(IOError,"VTKWriter: unsupported GeometryType " << t); } //////////////////////////////////////////////////////////////////////// // // Functions for transforming the index of a corner inside an entity // between Dune and VTK // //! renumber VTK <-> Dune /** \code #include \endcode * * Since the renumbering never does anything more complex than exchanging * two indices, this method works both ways. */ inline int renumber(const Dune::GeometryType &t, int i) { static const int quadRenumbering[4] = {0,1,3,2}; static const int cubeRenumbering[8] = {0,1,3,2,4,5,7,6}; static const int prismRenumbering[6] = {0,2,1,3,5,4}; static const int pyramidRenumbering[5] = {0,1,3,2,4}; if (t.isQuadrilateral()) return quadRenumbering[i]; if (t.isPyramid()) return pyramidRenumbering[i]; if (t.isPrism()) return prismRenumbering[i]; if (t.isHexahedron()) return cubeRenumbering[i]; return i; } //! renumber VTK <-> Dune /** \code #include \endcode * * This function is just a convenience shortcut function wrapping * renumber(const GeometryType&, int). * * \param t Entity, Intersection or Geometry to do the renumbering in. * Basically, anything with a method type() returning a * GeometryType should work here. * \param i Index to of corner in either Dune or VTK numbering (the result * will be in the other numbering) */ template int renumber(const T& t, int i) { return renumber(t.type(), i); } ////////////////////////////////////////////////////////////////////// // // Determine Endianness // //! determine endianness of this C++ implementation /** * \returns A string suitable for the byte_order property in VTK files; * either "BigEndian" or "LittleEndian". */ inline std::string getEndiannessString() { short i = 1; if (reinterpret_cast(&i)[1] == 1) return "BigEndian"; else return "LittleEndian"; } ////////////////////////////////////////////////////////////////////// // // which type of vtkfile to write // //! which type of VTK file to write /** \code #include \endcode */ enum FileType { //! for .vtp files (PolyData) polyData, //! for .vtu files (UnstructuredGrid) unstructuredGrid }; ////////////////////////////////////////////////////////////////////// // // which precision to use when writing out data // //! which precision to use when writing out data to vtk files /** \code #include \endcode */ enum class Precision { int32, uint8, uint32, float32, float64 }; //! map precision to VTK type name inline std::string toString(Precision p) { switch(p) { case Precision::float32: return "Float32"; case Precision::float64: return "Float64"; case Precision::uint32: return "UInt32"; case Precision::uint8: return "UInt8"; case Precision::int32: return "Int32"; default: DUNE_THROW(Dune::NotImplemented, "Unknown precision type"); } } //! map precision to byte size inline std::size_t typeSize(Precision p) { switch(p) { case Precision::float32: return sizeof(float); case Precision::float64: return sizeof(double); case Precision::uint32: return sizeof(std::uint32_t); case Precision::uint8: return sizeof(std::uint8_t); case Precision::int32: return sizeof(std::int32_t); default: DUNE_THROW(Dune::NotImplemented, "Unknown precision type"); } } //! Descriptor struct for VTK fields /** * This struct provides general information about a data field to be * written to a VTK file. * * It currently stores the data type and the number of components as well as * the name of the field. */ class FieldInfo { public: //! VTK data type enum class Type { //! scalar field (may also be multi-component, but is treated as a simply //! array by ParaView scalar, //! vector-valued field (always 3D, will be padded if necessary) vector, //! tensor field (always 3x3) tensor }; //! Create a FieldInfo instance with the given name, type and size. FieldInfo(std::string name, Type type, std::size_t size, Precision prec = Precision::float32) : _name(name) , _type(type) , _size(size) , _prec(prec) {} //! The name of the data field std::string name() const { return _name; } //! The type of the data field Type type() const { return _type; } //! The number of components in the data field. std::size_t size() const { return _size; } //! The precision used for the output of the data field Precision precision() const { return _prec; } private: std::string _name; Type _type; std::size_t _size; Precision _prec; }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_COMMON_HH dune-grid-2.11.0/dune/grid/io/file/vtk/corner.hh000066400000000000000000000046101511655130300212750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_CORNER_HH #define DUNE_GRID_IO_FILE_VTK_CORNER_HH #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! simple class representing a corner of a cell /** * \tparam Cell Type of element this is a corner for. This can * essentially be anything with a type() method, in * particular an Entity or an Intersection. */ template class Corner { // store a pointer to the element const Cell* cell_; // store index of the corner within element (Dune numbering) unsigned index; public: //! construct a Corner /** * \param cell Reference to the cell * \param duneIndex Index of the corner within the element in * Dune-numbering */ Corner(const Cell& cell, unsigned duneIndex) : cell_(&cell), index(duneIndex) { } //! construct an invalid Corner Corner() { } //! get reference to the cell const Cell& cell() const { return *cell_; } //! set a new cell /** * This also resets the index of the element to 0 (Dune-numbering), so * if you want to set both element and index, set the cell first. */ void cell(const Cell& cell__) { cell_ = &cell__; index = 0; } //! get the index of the corner within the cell in Dune-numbering unsigned duneIndex() const { return index; } //! set the index of the corner within the cell in Dune-numbering void duneIndex(unsigned i) { index = i; } //! get the index of the corner within the cell in VTK-numbering /** * This requires that the cell is valid */ unsigned vtkIndex() const { return renumber(cell_->type(), index); } //! set the index of the corner within the cell in VTK-numbering /** * This requires that the cell is valid */ void vtkIndex(unsigned i) { index = renumber(cell_->type(), i); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_CORNER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/corneriterator.hh000066400000000000000000000101071511655130300230450ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_CORNERITERATOR_HH #define DUNE_GRID_IO_FILE_VTK_CORNERITERATOR_HH #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! iterate over the corners of some cell range /** * This will visit all the corners of all elements visited by * CellIterator. */ template class CornerIterator : public ForwardIteratorFacade < CornerIterator, const Corner::value_type>::type>, const Corner::value_type>::type>&, typename std::iterator_traits::difference_type> { public: // reiterate the facades typedefs here typedef CornerIterator DerivedType; typedef VTK::Corner::value_type>::type> Corner; typedef const Corner Value; typedef Value& Reference; typedef typename std::iterator_traits::difference_type DifferenceType; typedef typename std::iterator_traits::value_type::Geometry::ctype ctype; static const unsigned dim = std::iterator_traits:: value_type::mydimension; typedef ReferenceElements Refelems; private: typedef ForwardIteratorFacade Facade; CellIterator cellit; CellIterator cellend; Corner corner; public: Reference dereference() const { return corner; } bool isDereferencable() const { return cellit != cellend; } bool equals(const DerivedType& other) const { bool mePassedTheEnd = !isDereferencable(); bool otherPassedTheEnd = !other.isDereferencable(); // both are passed the end => return true if(mePassedTheEnd && otherPassedTheEnd) return true; // one is passed the end => return false if(mePassedTheEnd || otherPassedTheEnd) return false; // none is passed the end, do their iterators and indices match? return cellit == other.cellit && corner.duneIndex() == other.corner.duneIndex(); } void increment() { int index = corner.vtkIndex(); ++index; if(index == Refelems::general(cellit->type()).size(dim)) { ++cellit; if(cellit != cellend) { corner.cell(*cellit); corner.vtkIndex(0); } } else corner.vtkIndex(index); } //! construct a CornerIterator /** * \param cellit_ The begin iterator of the underlying range. * \param cellend_ The end iterator of the underlying range. * \param vtkIndex VTKIndex of the currently pointed to corner. */ CornerIterator(const CellIterator& cellit_, const CellIterator& cellend_, unsigned vtkIndex = 0) : cellit(cellit_), cellend(cellend_) { if(cellit != cellend) { corner.cell(*cellit); corner.vtkIndex(vtkIndex); } } //! construct a CornerIterator /** * This constructs a passed-the-end iterator value. */ CornerIterator(const CellIterator& cellend_) : cellit(cellend_), cellend(cellend_) { } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_CORNERITERATOR_HH dune-grid-2.11.0/dune/grid/io/file/vtk/dataarraywriter.hh000066400000000000000000000523651511655130300232240ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH #define DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH #include #include #include #include #include #include #include #include #include #include /** @file @author Peter Bastian, Christian Engwer @brief Data array writers for the VTKWriter This file contains classes to help writing data in the difeerent VTK output modes */ namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! base class for data array writers /** * This is the base class; for an actual implementation look at * VTKAsciiDataArrayWriter, VTKBinaryDataArrayWriter, or * VTKBinaryAppendedDataArrayWriter. * * To create an actual DataArrayWriter, one would usually use an object of * class DataArrayWriterFactory. * * In the constructor, the actual writer implementation will prepare the * stream for writing the data. This usually means writing a * "" header to the stream. In the write() method it will * write a data element to the stream (this is not true for binaryappended * mode however: in this mode write just counts the number of bytes that * would be written, the actual writing has to happen later independent of * the writer). Finally, in the destructor, the stream is put back in a * sane state. That usually means writing something line "". */ class DataArrayWriter { public: //! \brief construct a data array writer /** * \brief construct a data array writer * \param _prec the precision type with which to write the data */ DataArrayWriter(Precision _prec) : prec(_prec) {} //! write one element of data template void write(T data) { switch(prec) { case Precision::float32: writeFloat32(data); break; case Precision::float64: writeFloat64(data); break; case Precision::uint32: writeUInt32(data); break; case Precision::uint8: writeUInt8(data); break; case Precision::int32: writeInt32(data); break; default: DUNE_THROW(Dune::NotImplemented, "Unknown precision type"); } } //! whether calls to write may be skipped virtual bool writeIsNoop() const { return false; } //! virtual destructor virtual ~DataArrayWriter () {} private: //! write one data element as float virtual void writeFloat32 (float data) = 0; //! write one data element as double virtual void writeFloat64 (double data) = 0; //! write one data element as integer virtual void writeInt32 (std::int32_t data) = 0; //! write one data element as unsigned integer virtual void writeUInt8 (std::uint8_t data) = 0; //! write one data element as unsigned integer virtual void writeUInt32 (std::uint32_t data) = 0; Precision prec; }; //! a streaming writer for data array tags, uses ASCII inline format class AsciiDataArrayWriter : public DataArrayWriter { public: //! make a new data array writer /** * \param theStream Stream to write to. * \param name Name of array to write. * \param ncomps Number of components of the array. * \param indent_ Indentation to use. This is use as-is for the * header and trailer lines, but increase by one level * for the actual data. * \param prec_ The precision type with which to write the data. */ AsciiDataArrayWriter(std::ostream& theStream, std::string name, int ncomps, const Indent& indent_, Precision prec_) : DataArrayWriter(prec_), s(theStream), counter(0), numPerLine(12), indent(indent_) { s << indent << "\n"; ++indent; } //! finish output; writes end tag ~AsciiDataArrayWriter () { if (counter%numPerLine!=0) s << "\n"; --indent; s << indent << "\n"; } private: //! write one double data element to output stream void writeFloat64 (double data) final { write_float(data); } //! write one float data element to output stream void writeFloat32 (float data) final { write_float(data); } //! write one int data element to output stream void writeInt32 (std::int32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt32 (std::uint32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt8 (std::uint8_t data) final { write_(data); } template void write_(T data) { typedef typename PrintType::Type PT; if(counter%numPerLine==0) s << indent; else s << " "; const auto original_precision = std::cout.precision(); s << std::setprecision(std::numeric_limits::digits10) << (PT) data; std::cout.precision(original_precision); counter++; if (counter%numPerLine==0) s << "\n"; } template void write_float(T data) { typedef typename PrintType::Type PT; if(counter%numPerLine==0) s << indent; else s << " "; PT out_data = (PT) data; if (std::fpclassify(out_data) == FP_SUBNORMAL) { // truncate denormalized data to 0 to avoid Paraview segfaults on macOS out_data = 0; } const auto original_precision = std::cout.precision(); s << std::setprecision(std::numeric_limits::digits10) << out_data; std::cout.precision(original_precision); counter++; if (counter%numPerLine==0) s << "\n"; } std::ostream& s; int counter; int numPerLine; Indent indent; }; //! a streaming writer for data array tags, uses binary inline format class BinaryDataArrayWriter : public DataArrayWriter { public: //! make a new data array writer /** * \param theStream Stream to write to. * \param name Name of array to write. * \param ncomps Number of components of the array. * \param nitems Number of cells for cell data/Number of vertices for * point data. * \param indent_ Indentation to use. This is use as-is for the * header and trailer lines, but increase by one level * for the actual data. * \param prec_ The precision type with which to write the data. */ BinaryDataArrayWriter(std::ostream& theStream, std::string name, int ncomps, int nitems, const Indent& indent_, Precision prec_) : DataArrayWriter(prec_), s(theStream), b64(theStream), indent(indent_) { s << indent << "\n"; // write indentation for the data chunk s << indent+1; // store size, needs to be exactly 32 bit std::uint32_t size = ncomps*nitems*typeSize(prec_); b64.write(size); b64.flush(); } //! finish output; writes end tag ~BinaryDataArrayWriter () { b64.flush(); // append newline to written data s << "\n"; s << indent << "\n"; s.flush(); } private: //! write one double data element to output stream void writeFloat64 (double data) final { write_(data); } //! write one float data element to output stream void writeFloat32 (float data) final { write_(data); } //! write one int data element to output stream void writeInt32 (std::int32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt32 (std::uint32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt8 (std::uint8_t data) final { write_(data); } //! write one data element to output stream template void write_(T data) { b64.write(data); } std::ostream& s; Base64Stream b64; const Indent& indent; }; //! a streaming writer for data array tags, uses appended raw format class AppendedRawDataArrayWriter : public DataArrayWriter { public: //! make a new data array writer /** * \param s Stream to write to. * \param name Name of array to write. * \param ncomps Number of components of the array. * \param nitems Number of cells for cell data/Number of vertices for * point data. * \param offset Byte count variable: this is incremented by one for * each byte which has to written to the appended data * section later. * \param indent Indentation to use. This is uses as-is for the * header line. * \param prec_ The precision type with which to write the data. */ AppendedRawDataArrayWriter(std::ostream& s, std::string name, int ncomps, unsigned nitems, unsigned& offset, const Indent& indent, Precision prec_) : DataArrayWriter(prec_) { s << indent << "\n"; offset += 4; // header offset += ncomps*nitems*typeSize(prec_); } //! whether calls to write may be skipped bool writeIsNoop() const { return true; } private: //! write one data element to output stream (noop) void writeFloat64 (double) final {} void writeFloat32 (float) final {} void writeInt32 (std::int32_t) final {} void writeUInt32 (std::uint32_t) final {} void writeUInt8 (std::uint8_t) final {} }; //! a streaming writer for data array tags, uses appended base64 format class AppendedBase64DataArrayWriter : public DataArrayWriter { public: //! make a new data array writer /** * \param s Stream to write to. * \param name Name of array to write. * \param ncomps Number of components of the array. * \param nitems Number of cells for cell data/Number of vertices for * point data. * \param offset Byte count variable: this is incremented by one for * each base64 char which has to written to the * appended data section later. * \param indent Indentation to use. This is uses as-is for the * header line. * \param prec_ The precision type with which to write the data. */ AppendedBase64DataArrayWriter(std::ostream& s, std::string name, int ncomps, unsigned nitems, unsigned& offset, const Indent& indent, Precision prec_) : DataArrayWriter(prec_) { s << indent << "\n"; offset += 8; // header std::size_t bytes = ncomps*nitems*typeSize(prec_); offset += bytes/3*4; if(bytes%3 != 0) offset += 4; } //! whether calls to write may be skipped bool writeIsNoop() const { return true; } private: //! write one data element to output stream (noop) void writeFloat64 (double) final {} void writeFloat32 (float) final {} void writeInt32 (std::int32_t) final {} void writeUInt32 (std::uint32_t) final {} void writeUInt8 (std::uint8_t) final {} }; ////////////////////////////////////////////////////////////////////// // // Naked ArrayWriters for the appended section // //! a streaming writer for appended data array tags, uses base64 format class NakedBase64DataArrayWriter : public DataArrayWriter { public: //! make a new data array writer /** * \param theStream Stream to write to. * \param ncomps Number of components of the array. * \param nitems Number of cells for cell data/Number of vertices for * point data. * \param prec_ The precision type with which to write the data. */ NakedBase64DataArrayWriter(std::ostream& theStream, int ncomps, int nitems, Precision prec_) : DataArrayWriter(prec_), b64(theStream) { // store size std::uint32_t size = ncomps*nitems*typeSize(prec_); b64.write(size); b64.flush(); } private: //! write one double data element to output stream void writeFloat64 (double data) final { write_(data); } //! write one float data element to output stream void writeFloat32 (float data) final { write_(data); } //! write one int data element to output stream void writeInt32 (std::int32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt32 (std::uint32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt8 (std::uint8_t data) final { write_(data); } //! write one data element to output stream template void write_(T data) { b64.write(data); } Base64Stream b64; }; //! a streaming writer for appended data arrays, uses raw format class NakedRawDataArrayWriter : public DataArrayWriter { RawStream s; public: //! make a new data array writer /** * \param theStream Stream to write to. * \param ncomps Number of components of the array. * \param nitems Number of cells for cell data/Number of vertices for * point data. * \param prec_ The precision type with which to write the data. */ NakedRawDataArrayWriter(std::ostream& theStream, int ncomps, int nitems, Precision prec_) : DataArrayWriter(prec_), s(theStream) { s.write((unsigned int)(ncomps*nitems*typeSize(prec_))); } private: //! write one double data element to output stream void writeFloat64 (double data) final { write_(data); } //! write one float data element to output stream void writeFloat32 (float data) final { write_(data); } //! write one int data element to output stream void writeInt32 (std::int32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt32 (std::uint32_t data) final { write_(data); } //! write one unsigned int data element to output stream void writeUInt8 (std::uint8_t data) final { write_(data); } //! write one data element to output stream template void write_(T data) { s.write(data); } }; ////////////////////////////////////////////////////////////////////// // // Factory // //! a factory for DataArrayWriters /** * Some types of DataArrayWriters need to communicate data sauch as byte * counts between different instances which write to the same stream. * This factory will manage that data. */ class DataArrayWriterFactory { enum Phase { main, appended }; OutputType type; std::ostream& stream; unsigned offset; //! whether we are in the main or in the appended section writing phase Phase phase; public: //! create a DataArrayWriterFactory /** * \param type_ Type of DataArrayWriters to create * \param stream_ The stream that the DataArrayWriters will write to. * * Better avoid having multiple active factories on the same stream at * the same time. Having an inactive factory (one whose make() method * is not called anymore before destruction) around at the same time as * an active one should be OK however. */ inline DataArrayWriterFactory(OutputType type_, std::ostream& stream_) : type(type_), stream(stream_), offset(0), phase(main) { } //! signal start of the appended section /** * This method should be called after the main section has been written, * but before the appended section has been started. After this method * has been called, a call to make will produce DataArrayWriters * suitable for the appended section. The return value of this method * signals whether a appended section should be written at all: true * means write an appended section, false means don't write an appended * section. If an appended section is not needed, the method make() may * not be called after a call to this method. */ inline bool beginAppended() { phase = appended; switch(type) { case ascii : return false; case base64 : return false; case appendedraw : return true; case appendedbase64 : return true; } DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported " "OutputType " << type); } //! query encoding string for appended data const std::string& appendedEncoding() const { static const std::string rawString = "raw"; static const std::string base64String = "base64"; switch(type) { case ascii : case base64 : DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): No " "appended encoding for OutputType " << type); case appendedraw : return rawString; case appendedbase64 : return base64String; } DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): " "unsupported OutputType " << type); } //! create a DataArrayWriter /** * \tparam T Type of the data to write. * * \param name Name of the array to write. * \param ncomps Number of components of the vectors in to array. * \param nitems Number of vectors in the array. * \param indent Indentation to use. This is use as-is for the header * and trailer lines, but increase by one level for the * actual data. * \param prec the precision type of the output * * The should never be more than one DataArrayWriter on the same stream * around. The returned object should be freed with delete. */ DataArrayWriter* make(const std::string& name, unsigned ncomps, unsigned nitems, const Indent& indent, Precision prec) { switch(phase) { case main : switch(type) { case ascii : return new AsciiDataArrayWriter(stream, name, ncomps, indent, prec); case base64 : return new BinaryDataArrayWriter(stream, name, ncomps, nitems, indent, prec); case appendedraw : return new AppendedRawDataArrayWriter(stream, name, ncomps, nitems, offset, indent, prec); case appendedbase64 : return new AppendedBase64DataArrayWriter(stream, name, ncomps, nitems, offset, indent, prec); } break; case appended : switch(type) { case ascii : case base64 : break; // invalid in appended mode case appendedraw : return new NakedRawDataArrayWriter(stream, ncomps, nitems, prec); case appendedbase64 : return new NakedBase64DataArrayWriter(stream, ncomps, nitems, prec); } break; } DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported " "OutputType " << type << " in phase " << phase); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/function.hh000066400000000000000000000234541511655130300216410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_FUNCTION_HH #define DUNE_GRID_IO_FILE_VTK_FUNCTION_HH #include #include #include #include #include #include #include #include /** @file @author Peter Bastian, Christian Engwer @brief Functions for VTK output */ namespace Dune { //! \addtogroup VTK //! \{ ////////////////////////////////////////////////////////////////////// // // Base VTKFunction // /** \brief A base class for grid functions with any return type and dimension Trick : use double as return type */ template< class GridView > class VTKFunction { public: typedef typename GridView::ctype ctype; constexpr static int dim = GridView::dimension; typedef typename GridView::template Codim< 0 >::Entity Entity; //! return number of components (1 for scalar valued functions, 3 for //! vector valued function in 3D etc.) virtual int ncomps () const = 0; //! evaluate single component comp in the entity e at local coordinates xi /*! Evaluate the function in an entity at local coordinates. @param[in] comp number of component to be evaluated @param[in] e reference to grid entity of codimension 0 @param[in] xi point in local coordinates of the reference element of e \return value of the component */ virtual double evaluate (int comp, const Entity& e, const Dune::FieldVector& xi) const = 0; //! get name virtual std::string name () const = 0; //! get output precision for the field virtual VTK::Precision precision() const { return VTK::Precision::float32; } //! virtual destructor virtual ~VTKFunction () {} }; ////////////////////////////////////////////////////////////////////// // // P0VTKFunction // //! Take a vector and interpret it as cell data for the VTKWriter /** * This class turns a generic vector containing cell data into a * VTKFunction. The vector must allow read access to the data via * operator[]() and store the data in the order given by * MultipleCodimMultipleGeomTypeMapper with a layout class that allows only * elements. Also, it must support the method size(). * * While the number of components of the function is always 1, the vector * may represent a field with multiple components of which one may be * selected. * * \tparam GV Type of GridView the vector applies to. * \tparam V Type of vector. */ template class P0VTKFunction : public VTKFunction< GV > { //! Base class typedef VTKFunction< GV > Base; //! Mapper for elements typedef MultipleCodimMultipleGeomTypeMapper Mapper; //! store a reference to the vector const V& v; //! name of this function std::string s; //! number of components of the field stored in the vector int ncomps_; //! index of the component of the field in the vector this function is //! responsible for int mycomp_; //! precision with which to output the field VTK::Precision prec_; //! mapper used to map elements to indices Mapper mapper; public: typedef typename Base::Entity Entity; typedef typename Base::ctype ctype; using Base::dim; //! return number of components int ncomps () const override { return 1; } //! evaluate double evaluate (int, const Entity& e, const Dune::FieldVector&) const override { return v[mapper.index(e)*ncomps_+mycomp_]; } //! get name std::string name () const override { return s; } //! get output precision for the field VTK::Precision precision() const override { return prec_; } //! construct from a vector and a name /** * \param gv GridView to operate on (used to instantiate a * MultipleCodimMultipleGeomeTypeMapper, otherwise no * reference or copy is stored). Note that this must be the * GridView the vector applies to as well as the GridView * later used by the VTKWriter -- i.e. we do not implicitly * restrict or prolongate the data. * \param v_ Reference to the vector holding the data. The reference * is stored internally and must be valid for as long as * this functions evaluate method is used. * \param s_ Name of this function in the VTK file. * \param ncomps Number of components of the field represented by the * vector. * \param mycomp Number of the field component this function is * responsible for. * \param prec the precision with which to output the field */ P0VTKFunction(const GV &gv, const V &v_, const std::string &s_, int ncomps=1, int mycomp=0, VTK::Precision prec = VTK::Precision::float32) : v( v_ ), s( s_ ), ncomps_(ncomps), mycomp_(mycomp), prec_(prec), mapper( gv, mcmgElementLayout() ) { if (v.size()!=(unsigned int)(mapper.size()*ncomps_)) DUNE_THROW(IOError, "P0VTKFunction: size mismatch"); } //! destructor virtual ~P0VTKFunction() {} }; ////////////////////////////////////////////////////////////////////// // // P1VTKFunction // //! Take a vector and interpret it as point data for the VTKWriter /** * This class turns a generic vector containing point data into a * VTKFunction. The vector must allow read access to the data via * operator[]() and store the data in the order given by * MultipleCodimMultipleGeomTypeMapper with a layout class that allows only * vertices. Also, it must support the method size(). * * While the number of components of the function is always 1, the vector * may represent a field with multiple components of which one may be * selected. * * \tparam GV Type of GridView the vector applies to. * \tparam V Type of vector. */ template class P1VTKFunction : public VTKFunction< GV > { //! Base class typedef VTKFunction< GV > Base; //! Mapper for vertices typedef MultipleCodimMultipleGeomTypeMapper Mapper; //! store a reference to the vector const V& v; //! name of this function std::string s; //! number of components of the field stored in the vector int ncomps_; //! index of the component of the field in the vector this function is //! responsible for int mycomp_; //! precision with which to output the field VTK::Precision prec_; //! mapper used to map elements to indices Mapper mapper; public: typedef typename Base::Entity Entity; typedef typename Base::ctype ctype; using Base::dim; //! return number of components int ncomps () const override { return 1; } //! evaluate double evaluate ([[maybe_unused]] int comp, const Entity& e, const Dune::FieldVector& xi) const override { const unsigned int myDim = Entity::mydimension; const unsigned int nVertices = e.subEntities(dim); std::vector > cornerValues(nVertices); for (unsigned i=0; i interpolation(e.type(), cornerValues); return interpolation.global(xi); } //! get name std::string name () const override { return s; } //! get output precision for the field VTK::Precision precision() const override { return prec_; } //! construct from a vector and a name /** * \param gv GridView to operate on (used to instantiate a * MultipleCodimMultipleGeomTypeMapper, otherwise no * reference or copy is stored). Note that this must be the * GridView the vector applies to as well as the GridView * later used by the VTKWriter -- i.e. we do not implicitly * restrict or prolongate the data. * \param v_ Reference to the vector holding the data. The reference * is stored internally and must be valid for as long as * this functions evaluate method is used. * \param s_ Name of this function in the VTK file. * \param ncomps Number of components of the field represented by the * vector. * \param mycomp Number of the field component this function is * responsible for. * \param prec the precision with which to output the field */ P1VTKFunction(const GV& gv, const V &v_, const std::string &s_, int ncomps=1, int mycomp=0, VTK::Precision prec = VTK::Precision::float32) : v( v_ ), s( s_ ), ncomps_(ncomps), mycomp_(mycomp), prec_(prec), mapper( gv, mcmgVertexLayout() ) { if (v.size()!=(unsigned int)(mapper.size()*ncomps_)) DUNE_THROW(IOError,"P1VTKFunction: size mismatch"); } //! destructor virtual ~P1VTKFunction() {} }; //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_FUNCTION_HH dune-grid-2.11.0/dune/grid/io/file/vtk/functionwriter.hh000066400000000000000000000306431511655130300230740ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_FUNCTIONWRITER_HH #define DUNE_GRID_IO_FILE_VTK_FUNCTIONWRITER_HH #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! Base class for function writers template class FunctionWriterBase { typedef typename Cell_::Geometry::ctype DF; static const unsigned mydim = Cell_::mydimension; typedef ReferenceElements Refelems; public: typedef FieldVector Domain; typedef Cell_ Cell; //! return name virtual std::string name() const = 0; //! return number of components of the vector virtual unsigned ncomps() const = 0; //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) = 0; //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) = 0; //! write at the given position /** * This is the default dummy implementation. This method is not * abstract so derived classes don't have to override it if they don't * need it. */ virtual void write(const Cell& /* cell */, const Domain& /* xl */) { DUNE_THROW(NotImplemented, "FunctionWriterBase::write(const Cell&, " "const Domain&): Either the derived class " << typeid(*this).name() << " failed to implement this method " "or this method is not meant to be called on the derived " "class and was called in error."); } //! write at the given corner /** * This default method forwards the writing to write(const Cell&, const * Domain&). */ virtual void write(const Cell& cell, unsigned cornerIndex) { write(cell, Refelems::general(cell.type()).position(cornerIndex, mydim)); } //! signal end of writing virtual void endWrite() = 0; //! destructor virtual ~FunctionWriterBase() {} }; ////////////////////////////////////////////////////////////////////// // // A Generic Function writer for VTKFunctions // //! Base class for function writers template class VTKFunctionWriter : public FunctionWriterBase { typedef FunctionWriterBase Base; std::shared_ptr func; VTK::Precision precision_; std::shared_ptr arraywriter; public: VTKFunctionWriter(const std::shared_ptr& func_, VTK::Precision prec = VTK::Precision::float32) : func(func_), precision_(prec) { } //! return name virtual std::string name() const { return func->name(); } //! return number of components of the vector virtual unsigned ncomps() const { if(func->ncomps() == 2) return 3; else return func->ncomps(); } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), precision_); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter(name(), ncomps(), nitems, precision_)); return !arraywriter->writeIsNoop(); } //! write at the given position virtual void write(const typename Base::Cell& cell, const typename Base::Domain& xl) { for(int d = 0; d < func->ncomps(); ++d) arraywriter->write(func->evaluate(d, cell, xl)); for(unsigned d = func->ncomps(); d < ncomps(); ++d) arraywriter->write(0); } //! signal end of writing virtual void endWrite() { arraywriter.reset(); } }; ////////////////////////////////////////////////////////////////////// // // Writers for the grid information // //! writer for the Coordinates array template class CoordinatesWriter : public FunctionWriterBase { typedef FunctionWriterBase Base; VTK::Precision precision_; std::shared_ptr arraywriter; public: explicit CoordinatesWriter(VTK::Precision prec = VTK::Precision::float32) : precision_(prec) {} //! return name virtual std::string name() const { return "Coordinates"; } //! return number of components of the vector virtual unsigned ncomps() const { return 3; } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), precision_); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter(name(), ncomps(), nitems, precision_)); return !arraywriter->writeIsNoop(); } //! write at the given position virtual void write(const typename Base::Cell& cell, const typename Base::Domain& xl) { FieldVector xg = cell.geometry().global(xl); for(unsigned d = 0; d < 3 && d < Base::Cell::Geometry::coorddimension; ++d) arraywriter->write(xg[d]); for(unsigned d = Base::Cell::Geometry::coorddimension; d < 3; ++d) arraywriter->write(0); } //! signal end of writing virtual void endWrite() { arraywriter.reset(); } }; //! writer for the connectivity array in conforming mode template class ConformingConnectivityWriter : public FunctionWriterBase { typedef FunctionWriterBase Base; static const unsigned mydim = Base::Cell::mydimension; const IteratorFactory& factory; std::shared_ptr arraywriter; std::vector pointIndices; public: //! create a writer with the given iteratorfactory ConformingConnectivityWriter(const IteratorFactory& factory_) : factory(factory_) { } //! return name virtual std::string name() const { return "connectivity"; } //! return number of components of the vector virtual unsigned ncomps() const { return 1; } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), Precision::int32); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter(name(), ncomps(), nitems, Precision::int32)); if(arraywriter->writeIsNoop()) return false; //! write is meaningful, we need to build the data pointIndices.resize(factory.indexSet().size(mydim)); const typename IteratorFactory::PointIterator& pend = factory.endPoints(); typename IteratorFactory::PointIterator pit = factory.beginPoints(); unsigned counter = 0; while(pit != pend) { pointIndices[factory.indexSet().subIndex (pit->cell(), pit->duneIndex(), mydim)] = counter; ++counter; ++pit; } return true; } //! write at the given corner virtual void write(const typename Base::Cell& cell, unsigned cornerIndex) { // if pointIndices is empty, we're in writeIsNoop mode if(pointIndices.size() == 0) return; arraywriter->write(pointIndices[factory.indexSet().subIndex (cell, cornerIndex, mydim)]); } //! signal end of writing virtual void endWrite() { arraywriter.reset(); pointIndices.clear(); } }; //! writer for the connectivity array in nonconforming mode template class NonConformingConnectivityWriter : public FunctionWriterBase { std::shared_ptr arraywriter; unsigned counter; public: //! return name virtual std::string name() const { return "connectivity"; } //! return number of components of the vector virtual unsigned ncomps() const { return 1; } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), Precision::int32); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter(name(), ncomps(), nitems, Precision::int32)); counter = 0; return !arraywriter->writeIsNoop(); } //! write at the given corner virtual void write(const Cell& /* cell */, unsigned /* cornerIndex */) { arraywriter->write(counter); ++counter; } //! signal end of writing virtual void endWrite() { arraywriter.reset(); } }; //! writer for the offsets array template class OffsetsWriter : public FunctionWriterBase { typedef FunctionWriterBase Base; std::shared_ptr arraywriter; unsigned offset; public: //! return name virtual std::string name() const { return "offsets"; } //! return number of components of the vector virtual unsigned ncomps() const { return 1; } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), Precision::int32); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter(name(), ncomps(), nitems, Precision::int32)); offset = 0; return !arraywriter->writeIsNoop(); } //! write at the given position virtual void write(const Cell& cell, const typename Base::Domain&) { offset += cell.geometry().corners(); arraywriter->write(offset); } //! signal end of writing virtual void endWrite() { arraywriter.reset(); } }; //! writer for the types array template class TypesWriter : public FunctionWriterBase { typedef FunctionWriterBase Base; std::shared_ptr arraywriter; public: //! return name virtual std::string name() const { return "types"; } //! return number of components of the vector virtual unsigned ncomps() const { return 1; } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), Precision::uint8); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter ( name(), ncomps(), nitems, Precision::uint8)); return !arraywriter->writeIsNoop(); } //! write at the given position virtual void write(const Cell& cell, const typename Base::Domain&) { arraywriter->write(geometryType(cell.type())); } //! signal end of writing virtual void endWrite() { arraywriter.reset(); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_FUNCTIONWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/pointiterator.hh000066400000000000000000000106011511655130300227050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_POINTITERATOR_HH #define DUNE_GRID_IO_FILE_VTK_POINTITERATOR_HH #include #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! iterate over the points of some corner range /** * This iterator essentially filters the output from CornerIterator to * visit each point only once. * * \tparam CellIterator Type of the iterators over cells. The usual * codim0 EntityIterators should work here. * \tparam IS Type of the indexset. * * The IndexSet must provide methods and member types: *
    *
  • size(unsigned codimension) should return the number of vertices in * the indexset. The dimension of the cells will be passed as the * codimension parameter value. *
  • subIndex(const Cell& cell, unsigned subIndex, unsigned codimension) * should return the index of the point with local Dune index subIndex * in cell cell. The codimension parameter will again be the * dimension of the cell. *
  • IndexType should be the type of the indices returned by subIndex(). *
* The requirements are crafted in such a way that the indexsets provided * by the grid should fulfill them as long as the cells are codim=0 * Entities. */ template class PointIterator : public ForwardIteratorFacade < PointIterator, const Corner::value_type>::type>, const Corner::value_type>::type>&, typename std::iterator_traits::difference_type> { public: typedef VTK::Corner::value_type>::type> Corner; // reiterate the facades typedefs here typedef PointIterator DerivedType; typedef const Corner Value; typedef Value& Reference; typedef typename std::iterator_traits::difference_type DifferenceType; static const unsigned mydim = std::iterator_traits:: value_type::mydimension; private: typedef ForwardIteratorFacade Facade; CornerIterator cornerit; const IS* is; std::vector seen; public: Reference dereference() const { return *cornerit; } bool isDereferencable() const { return cornerit.isDereferencable(); } bool equals(const DerivedType& other) const { return cornerit == other.cornerit; } void increment() { for(++cornerit; isDereferencable(); ++cornerit) { typename IS::IndexType index = is->subIndex(cornerit->cell(), cornerit->duneIndex(), mydim); if(!seen[index]) { seen[index] = true; break; } } } //! construct a CornerIterator /** * \param cellit The begin iterator of the underlying range. * \param cellend The end iterator of the underlying range. * \param is_ A reference to the indexset to use. */ PointIterator(const CellIterator& cellit, const CellIterator& cellend, const IS& is_) : cornerit(cellit, cellend), is(&is_), seen(is->size(mydim), false) { } //! construct a CornerIterator /** * This constructs a passed-the-end iterator value. */ PointIterator(const CellIterator& cellend_) : cornerit(cellend_), is(0) { } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_POINTITERATOR_HH dune-grid-2.11.0/dune/grid/io/file/vtk/pvtuwriter.hh000066400000000000000000000164651511655130300222530ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_PVTUWRITER_HH #define DUNE_GRID_IO_FILE_VTK_PVTUWRITER_HH #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! Dump a .vtu/.vtp files contents to a stream /** * This will help generating a .vtu/.vtp file. Typical use is like this: \code { // create writer, writes begin tag PVTUWriter writer(std::cout, polyData); // start the main section writer.beginMain(); // dump cell data (optional) writer.beginCellData(); for(each cell data field) writer.addArray(field.name, field.ncomps, precision); writer.endCellData(); // dump point data (optional) writer.beginPointData(); for(each point data field) writer.addArray(field.name, field.ncomps, precision); writer.endPointData(); // dump point coordinates writer.beginPoints(); writer.addArray("Coordinates", 3, precision); writer.endPoints(); for(each serial piece) writer.addPiece(piece.filename); // finish main section writer.endMain(); // end scope so the destructor gets called and the closing tag is written } \endcode */ class PVTUWriter { std::ostream& stream; std::string fileType; Indent indent; public: //! create a PVTUWriter object /** * \param stream_ Stream to write to. * \param fileType_ Whether to write PolyData (1D) or UnstructuredGrid * (nD) format. * * Create object and write header. */ inline PVTUWriter(std::ostream& stream_, FileType fileType_) : stream(stream_) { switch(fileType_) { case polyData : fileType = "PPolyData"; break; case unstructuredGrid : fileType = "PUnstructuredGrid"; break; default : DUNE_THROW(IOError, "PVTUWriter: Unknown fileType: " << fileType_); } const std::string& byteOrder = getEndiannessString(); stream << indent << "\n"; stream << indent << "\n"; ++indent; } //! write footer inline ~PVTUWriter() { --indent; stream << indent << "\n" << std::flush; } //! start PointData section /** * \param scalars Name of field to which should be marked as default * scalars field. If this is the empty string, don't set * any default. * \param vectors Name of field to which should be marked as default * vectors field. If this is the empty string, don't set * any default. * * If there are no PointData fields, the call to this function may be * skipped, together with the corresponding call to endPointData(). */ inline void beginPointData(const std::string& scalars = "", const std::string& vectors = "") { stream << indent << "\n"; ++indent; } //! finish PointData section inline void endPointData() { --indent; stream << indent << "\n"; } //! start CellData section /** * \param scalars Name of field to which should be marked as default * scalars field. If this is the empty string, don't set * any default. * \param vectors Name of field to which should be marked as default * vectors field. If this is the empty string, don't set * any default. * * If there are no CellData fields, the call to this function may be * skipped, together with the corresponding call to endCellData(). */ inline void beginCellData(const std::string& scalars = "", const std::string& vectors = "") { stream << indent << "\n"; ++indent; } //! finish CellData section inline void endCellData() { --indent; stream << indent << "\n"; } //! start section for the point coordinates /** * Between the call to this method an the following call to the * endPoints(), there must be a single field written. The name must be * "Coordinates" and it must have 3 components. */ inline void beginPoints() { stream << indent << "\n"; ++indent; } //! finish section for the point coordinates inline void endPoints() { --indent; stream << indent << "\n"; } //! start the main PPolyData/PUnstructuredGrid section /** * \param ghostLevel Set the GhostLevel attribute * * Between the call to this method and to endMain(), there should be * calls to add the actual data: *
    *
  • (optional) beginCellData()/endCellData(), *
  • (optional) beginPointData()/endPointData(), *
  • beginPoints()/endPoints(), *
  • one or more calls to addPiece() *
*/ inline void beginMain(unsigned ghostLevel = 0) { stream << indent << "<" << fileType << " GhostLevel=\"" << ghostLevel << "\">\n"; ++indent; } //! finish the main PolyData/UnstructuredGrid section inline void endMain() { --indent; stream << indent << "\n"; } //! Add an array to the output file /** * \tparam T The datatype of the array. * \param name Name of the array. * \param ncomps Number of components in each vector of the array. * \param prec The output precision of the data array */ void addArray(const std::string& name, unsigned ncomps, Precision prec) { stream << indent << "\n"; } //! Add a serial piece to the output file inline void addPiece(const std::string& filename) { stream << indent << "\n"; } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_PVTUWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/skeletonfunction.hh000066400000000000000000000111251511655130300233760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_SKELETONFUNCTION_HH #define DUNE_GRID_IO_FILE_VTK_SKELETONFUNCTION_HH #include #include #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ /** @file @author Jö Fahlke @brief Functions for VTK output on the skeleton */ namespace VTK { ////////////////////////////////////////////////////////////////////// // // Prototype for VTKFunktions on the skeleton // template struct SkeletonFunctionTraits { typedef GV GridView; typedef typename GV::Intersection Cell; typedef typename GV::ctype DomainField; static const unsigned dimDomain = GV::dimension-1; typedef FieldVector Domain; typedef RF RangeField; typedef std::vector Range; }; //! A prototype for VTKFunctions on the skeleton template class SkeletonFunctionInterface { public: typedef SkeletonFunctionTraits Traits; //! get dimension of the Range unsigned dimRange() const; //! evaluate at local point xl in Cell c, store in result /** * \param c The cell (intersection) to evaluate in. * \param xl The local coordinate within the cell. * \param result Where to store the result. The vector is resized as * necessary, and is overwritten. */ void evaluate(const typename Traits::Cell& c, const typename Traits::Domain& xl, typename Traits::Range& result) const; }; //////////////////////////////////////////////////////////////////////// // // Class for writing SkeletonFunctions // //! function writer for skeleton functions /** * \tparam Func Function to write. Must be a model of * SkeletonFunctionInterface. */ template class SkeletonFunctionWriter : public FunctionWriterBase { typedef typename Func::Traits::RangeField RF; std::shared_ptr func; std::string name_; unsigned dimR; VTK::Precision precision_; std::shared_ptr arraywriter; public: SkeletonFunctionWriter(const std::shared_ptr& func_, const std::string& name, unsigned dimR_, VTK::Precision prec = VTK::Precision::float32) : func(func_), name_(name), dimR(dimR_), precision_(prec) { } SkeletonFunctionWriter(const std::shared_ptr& func_, const std::string& name, VTK::Precision prec = VTK::Precision::float32) : func(func_), name_(name), dimR(func->dimRange()), precision_(prec) { } //! return name virtual std::string name() const { return name_; } //! return number of components of the vector virtual unsigned ncomps() const { return dimR; } //! add this field to the given parallel writer virtual void addArray(PVTUWriter& writer) { writer.addArray(name(), ncomps(), precision_); } //! start writing with the given writer virtual bool beginWrite(VTUWriter& writer, std::size_t nitems) { arraywriter.reset(writer.makeArrayWriter(name(), ncomps(), nitems, precision_)); return !arraywriter->writeIsNoop(); } //! write at the given position virtual void write(const typename Func::Traits::Cell& cell, const typename Func::Traits::Domain& xl) { typename Func::Traits::Range result; func->evaluate(cell, xl, result); for(unsigned d = 0; d < result.size() && d < dimR; ++d) arraywriter->write(result[d]); for(unsigned d = result.size(); d < dimR; ++d) arraywriter->write(0); } //! signal end of writing virtual void endWrite() { arraywriter.reset(); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_SKELETONFUNCTION_HH dune-grid-2.11.0/dune/grid/io/file/vtk/streams.hh000066400000000000000000000046301511655130300214650ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_STREAMS_HH #define DUNE_GRID_IO_FILE_VTK_STREAMS_HH #include #include namespace Dune { //! class to base64 encode a stream of data class Base64Stream { std::ostream& s; b64chunk chunk; char obuf[4]; public: //! Construct a Base64Stream /** * \param s_ The stream the resulting base64-encoded text will be written * to. */ Base64Stream(std::ostream& s_) : s(s_) { // reset chunk chunk.reset(); } //! encode a data item /** * The result will be written to the stream, eventually. This method may * be called multiple times in a row. After this method has been called, * no one else may write to the underlying stream until flush() has been * called or this writer object has been destroyed. */ template void write(X & data) { char* p = reinterpret_cast(&data); for (size_t len = sizeof(X); len > 0; len--,p++) { chunk.put(*p); if (chunk.size == 3) { chunk.write(obuf); s.write(obuf,4); } } } //! flush the current unwritten data to the stream. /** * If the size of the received input is not a multiple of three bytes, an * end-marker will be written. * * Calling this function a second time without calling b64enc() or calling * it right after construction has no effect. */ void flush() { if (chunk.size > 0) { chunk.write(obuf); s.write(obuf,4); } } //! destroy the object /** * Calls flush() */ ~Base64Stream() { flush(); } }; //! write out data in binary class RawStream { public: //! make a new stream inline RawStream (std::ostream& theStream) : s(theStream) {} //! write data to stream template void write (T data) { char* p = reinterpret_cast(&data); s.write(p,sizeof(T)); } private: std::ostream& s; }; } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_STREAMS_HH dune-grid-2.11.0/dune/grid/io/file/vtk/subsamplingvtkwriter.hh000066400000000000000000000323011511655130300243110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_SUBSAMPLINGVTKWRITER_HH #define DUNE_SUBSAMPLINGVTKWRITER_HH #include #include #include #include #include #include #include /** @file @author Jö Fahlke @brief Provides subsampled file i/o for the visualization toolkit */ namespace Dune { /** * @brief Writer for the output of subsampled grid functions in the vtk format. * @ingroup VTK * * Writes arbitrary grid functions (living on cells or vertices of a grid) * to a file suitable for easy visualization with * The Visualization Toolkit * (VTK). In contrast to the regular VTKWriter, this Writer allows * subsampling of the elements via VirtualRefinement. The * SubSamplingVTKWriter always writes nonconforming data. */ template< class GridView > class SubsamplingVTKWriter : public VTKWriter { typedef VTKWriter Base; constexpr static int dim = GridView::dimension; constexpr static int dimw = GridView::dimensionworld; typedef typename GridView::Grid::ctype ctype; typedef typename GridView::template Codim< 0 >::Entity Entity; typedef VirtualRefinement Refinement; typedef typename Refinement::IndexVector IndexVector; typedef typename Refinement::ElementIterator SubElementIterator; typedef typename Refinement::VertexIterator SubVertexIterator; typedef typename Base::CellIterator CellIterator; typedef typename Base::FunctionIterator FunctionIterator; using Base::cellBegin; using Base::cellEnd; using Base::celldata; using Base::ncells; using Base::ncorners; using Base::nvertices; using Base::outputtype; using Base::vertexBegin; using Base::vertexEnd; using Base::vertexdata; public: /** * @brief Construct a SubsamplingVTKWriter working on a specific GridView. * * @param gridView The gridView the grid functions live * on. (E. g. a LevelGridView.) * @param intervals_ A wrapper for the number of refined intervals on one * axis as returned by either refinementIntervals() or * refinementLevels(). * @param coerceToSimplex_ Set this to true to always triangulate elements * into simplices, even where it's not necessary * (i.e. for hypercubes). * @param coordPrecision the precision in which to write out coordinates * * The datamode is always nonconforming. */ explicit SubsamplingVTKWriter (const GridView &gridView, Dune::RefinementIntervals intervals_, bool coerceToSimplex_ = false, VTK::Precision coordPrecision = VTK::Precision::float32) : Base(gridView, VTK::nonconforming, coordPrecision) , intervals(intervals_), coerceToSimplex(coerceToSimplex_) { if(intervals_.intervals() < 1) { DUNE_THROW(Dune::IOError,"SubsamplingVTKWriter: Refinement intervals must be larger than zero! (One interval means no subsampling)"); } } private: GeometryType subsampledGeometryType(GeometryType geometryType) { return (geometryType.isCube() && !coerceToSimplex ? geometryType : GeometryTypes::simplex(dim)); } template struct IteratorSelector {}; SubElementIterator refinementBegin(const Refinement& refinement, Dune::RefinementIntervals intervals, IteratorSelector) { return refinement.eBegin(intervals); } SubVertexIterator refinementBegin(const Refinement& refinement, Dune::RefinementIntervals intervals, IteratorSelector) { return refinement.vBegin(intervals); } SubElementIterator refinementEnd(const Refinement& refinement, Dune::RefinementIntervals intervals, IteratorSelector) { return refinement.eEnd(intervals); } SubVertexIterator refinementEnd(const Refinement& refinement, Dune::RefinementIntervals intervals, IteratorSelector) { return refinement.vEnd(intervals); } template void writeData(VTK::VTUWriter& writer, const Data& data, const Iterator begin, const Iterator end, int nentries, IteratorSelector sis) { for (auto it = data.begin(), iend = data.end(); it != iend; ++it) { const auto& f = *it; VTK::FieldInfo fieldInfo = f.fieldInfo(); std::size_t writecomps = fieldInfo.size(); switch (fieldInfo.type()) { case VTK::FieldInfo::Type::scalar: break; case VTK::FieldInfo::Type::vector: // vtk file format: a vector data always should have 3 comps (with // 3rd comp = 0 in 2D case) if (writecomps > 3) DUNE_THROW(IOError,"Cannot write VTK vectors with more than 3 components (components was " << writecomps << ")"); writecomps = 3; break; case VTK::FieldInfo::Type::tensor: DUNE_THROW(NotImplemented,"VTK output for tensors not implemented yet"); } std::shared_ptr p (writer.makeArrayWriter(f.name(), writecomps, nentries, fieldInfo.precision())); if(!p->writeIsNoop()) for (Iterator eit = begin; eit!=end; ++eit) { const Entity & e = *eit; f.bind(e); Refinement &refinement = buildRefinement(eit->type(), subsampledGeometryType(eit->type())); for(SubIterator sit = refinementBegin(refinement,intervals,sis), send = refinementEnd(refinement,intervals,sis); sit != send; ++sit) { f.write(sit.coords(),*p); // expand 2D-Vectors to 3D for VTK format for(unsigned j = f.fieldInfo().size(); j < writecomps; j++) p->write(0.0); } f.unbind(); } } } protected: //! count the vertices, cells and corners virtual void countEntities(int &nvertices_, int &ncells_, int &ncorners_); //! write cell data virtual void writeCellData(VTK::VTUWriter& writer); //! write vertex data virtual void writeVertexData(VTK::VTUWriter& writer); //! write the positions of vertices virtual void writeGridPoints(VTK::VTUWriter& writer); //! write the connectivity array virtual void writeGridCells(VTK::VTUWriter& writer); public: using Base::addVertexData; using Base::addCellData; private: // hide addVertexData -- adding raw data directly without a VTKFunction // currently does not make sense for subsampled meshes, as the higher order // information is missing. See FS#676. template void addVertexData (const V& v, const std::string &name, int ncomps=1); template void addCellData (const V& v, const std::string &name, int ncomps=1); Dune::RefinementIntervals intervals; bool coerceToSimplex; }; //! count the vertices, cells and corners template void SubsamplingVTKWriter::countEntities(int &nvertices_, int &ncells_, int &ncorners_) { nvertices_ = 0; ncells_ = 0; ncorners_ = 0; for (CellIterator it=this->cellBegin(); it!=cellEnd(); ++it) { Refinement &refinement = buildRefinement(it->type(), subsampledGeometryType(it->type())); ncells_ += refinement.nElements(intervals); nvertices_ += refinement.nVertices(intervals); ncorners_ += refinement.nElements(intervals) * refinement.eBegin(intervals).vertexIndices().size(); } } //! write cell data template void SubsamplingVTKWriter::writeCellData(VTK::VTUWriter& writer) { if(celldata.size() == 0) return; // Find the names of the first scalar and vector data fields. // These will be marked as the default fields (the ones that ParaView shows // when the file has just been opened). std::string defaultScalarField, defaultVectorField; std::tie(defaultScalarField, defaultVectorField) = this->getDataNames(celldata); writer.beginCellData(defaultScalarField, defaultVectorField); writeData(writer,celldata,cellBegin(),cellEnd(),ncells,IteratorSelector()); writer.endCellData(); } //! write vertex data template void SubsamplingVTKWriter::writeVertexData(VTK::VTUWriter& writer) { if(vertexdata.size() == 0) return; // Find the names of the first scalar and vector data fields. // These will be marked as the default fields (the ones that ParaView shows // when the file has just been opened). std::string defaultScalarField, defaultVectorField; std::tie(defaultScalarField, defaultVectorField) = this->getDataNames(vertexdata); writer.beginPointData(defaultScalarField, defaultVectorField); writeData(writer,vertexdata,cellBegin(),cellEnd(),nvertices,IteratorSelector()); writer.endPointData(); } //! write the positions of vertices template void SubsamplingVTKWriter::writeGridPoints(VTK::VTUWriter& writer) { writer.beginPoints(); std::shared_ptr p (writer.makeArrayWriter("Coordinates", 3, nvertices, this->coordPrecision())); if(!p->writeIsNoop()) for (CellIterator i=cellBegin(); i!=cellEnd(); ++i) { Refinement &refinement = buildRefinement(i->type(), subsampledGeometryType(i->type())); for(SubVertexIterator sit = refinement.vBegin(intervals), send = refinement.vEnd(intervals); sit != send; ++sit) { FieldVector coords = i->geometry().global(sit.coords()); for (int j=0; jwrite(coords[j]); for (int j=std::min(int(dimw),3); j<3; j++) p->write(0.0); } } // free the VTK::DataArrayWriter before touching the stream p.reset(); writer.endPoints(); } //! write the connectivity array template void SubsamplingVTKWriter::writeGridCells(VTK::VTUWriter& writer) { writer.beginCells(); // connectivity { std::shared_ptr p1 (writer.makeArrayWriter("connectivity", 1, ncorners, VTK::Precision::int32)); // The offset within the index numbering if(!p1->writeIsNoop()) { int offset = 0; for (CellIterator i=cellBegin(); i!=cellEnd(); ++i) { GeometryType coercedToType = subsampledGeometryType(i->type()); Refinement &refinement = buildRefinement(i->type(), coercedToType); for(SubElementIterator sit = refinement.eBegin(intervals), send = refinement.eEnd(intervals); sit != send; ++sit) { IndexVector indices = sit.vertexIndices(); for(unsigned int ii = 0; ii < indices.size(); ++ii) p1->write(offset+indices[VTK::renumber(coercedToType, ii)]); } offset += refinement.nVertices(intervals); } } } // offsets { std::shared_ptr p2 (writer.makeArrayWriter("offsets", 1, ncells, VTK::Precision::int32)); if(!p2->writeIsNoop()) { // The offset into the connectivity array int offset = 0; for (CellIterator i=cellBegin(); i!=cellEnd(); ++i) { Refinement &refinement = buildRefinement(i->type(), subsampledGeometryType(i->type())); unsigned int verticesPerCell = refinement.eBegin(intervals).vertexIndices().size(); for(int element = 0; element < refinement.nElements(intervals); ++element) { offset += verticesPerCell; p2->write(offset); } } } } // types if (dim>1) { std::shared_ptr p3 (writer.makeArrayWriter("types", 1, ncells, VTK::Precision::uint8)); if(!p3->writeIsNoop()) for (CellIterator it=cellBegin(); it!=cellEnd(); ++it) { GeometryType coerceTo = subsampledGeometryType(it->type()); Refinement &refinement = buildRefinement(it->type(), coerceTo); int vtktype = VTK::geometryType(coerceTo); for(int i = 0; i < refinement.nElements(intervals); ++i) p3->write(vtktype); } } writer.endCells(); } } #endif // DUNE_SUBSAMPLINGVTKWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/volumeiterators.hh000066400000000000000000000100601511655130300232450ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_VOLUMEITERATORS_HH #define DUNE_GRID_IO_FILE_VTK_VOLUMEITERATORS_HH #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { template class ConformingVolumeIteratorFactory { const GV& gv; typedef typename GV::IndexSet IndexSet; const IndexSet& indexSet() const { return gv.indexSet(); } friend class ConformingConnectivityWriter< ConformingVolumeIteratorFactory >; public: static const unsigned dimCell = GV::dimension; typedef typename GV::template Codim<0>::Entity Cell; typedef typename GV::template Codim<0>:: template Partition::Iterator CellIterator; typedef VTK::Corner Corner; typedef VTK::CornerIterator CornerIterator; typedef VTK::Corner Point; typedef VTK::PointIterator PointIterator; typedef ConformingConnectivityWriter > ConnectivityWriter; typedef typename GV::Communication Communication; explicit ConformingVolumeIteratorFactory(const GV& gv_) : gv(gv_) { } CellIterator beginCells() const { return gv.template begin<0, InteriorBorder_Partition>(); } CellIterator endCells() const { return gv.template end<0, InteriorBorder_Partition>(); } CornerIterator beginCorners() const { return CornerIterator(beginCells(), endCells()); } CornerIterator endCorners() const { return CornerIterator(endCells()); } PointIterator beginPoints() const { return PointIterator(beginCells(), endCells(), gv.indexSet()); } PointIterator endPoints() const { return PointIterator(endCells()); } ConnectivityWriter makeConnectivity() const { return ConnectivityWriter(*this); } const Communication& comm() const { return gv.comm(); } }; template class NonConformingVolumeIteratorFactory { const GV& gv; public: static const unsigned dimCell = GV::dimension; typedef typename GV::template Codim<0>::Entity Cell; typedef typename GV::template Codim<0>:: template Partition::Iterator CellIterator; typedef VTK::Corner Corner; typedef VTK::CornerIterator CornerIterator; typedef Corner Point; typedef CornerIterator PointIterator; typedef NonConformingConnectivityWriter ConnectivityWriter; typedef typename GV::Communication Communication; explicit NonConformingVolumeIteratorFactory(const GV& gv_) : gv(gv_) { } CellIterator beginCells() const { return gv.template begin<0, InteriorBorder_Partition>(); } CellIterator endCells() const { return gv.template end<0, InteriorBorder_Partition>(); } CornerIterator beginCorners() const { return CornerIterator(beginCells(), endCells()); } CornerIterator endCorners() const { return CornerIterator(endCells()); } PointIterator beginPoints() const { return beginCorners(); } PointIterator endPoints() const { return endCorners(); } ConnectivityWriter makeConnectivity() const { return ConnectivityWriter(); } const Communication& comm() const { return gv.comm(); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_VOLUMEITERATORS_HH dune-grid-2.11.0/dune/grid/io/file/vtk/volumewriter.hh000066400000000000000000000043671511655130300225620ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_VOLUMEWRITER_HH #define DUNE_GRID_IO_FILE_VTK_VOLUMEWRITER_HH #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { template class ConformingVolumeWriter : public ConformingVolumeIteratorFactory, public BasicWriter > { typedef ConformingVolumeIteratorFactory Factory; typedef BasicWriter Base; const GV& gv; public: typedef Dune::VTKFunction< GV > VTKFunction; typedef std::shared_ptr VTKFunctionPtr; ConformingVolumeWriter(const GV& gv_) : Factory(gv_), Base(static_cast(*this)), gv(gv_) { } using Base::addPointData; void addCellData(const VTKFunctionPtr& p) { Base::addCellData(std::shared_ptr (new VTKFunctionWriter(p))); } void addCellData(VTKFunction* p) { addCellData(VTKFunctionPtr(p)); } template void addCellData(const V &v, const std::string &name, int ncomps=1) { addCellData(new P0VTKFunction(gv, v, name, ncomps)); } void addVertexData(const VTKFunctionPtr& p) { addPointData(std::shared_ptr (new VTKFunctionWriter(p))); } void addVertexData(VTKFunction* p) { addVertexData(VTKFunctionPtr(p)); } template void addVertexData(const V &v, const std::string &name, int ncomps=1) { addVertexData(new P1VTKFunction(gv, v, name, ncomps)); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_VOLUMEWRITER_HH dune-grid-2.11.0/dune/grid/io/file/vtk/vtksequencewriter.hh000066400000000000000000000112641511655130300236020ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_VTKSEQUENCE_HH #define DUNE_VTKSEQUENCE_HH #include #include #include #include namespace Dune { /** * @brief Writer for the output of grid functions in the vtk format. * @ingroup VTK * * Writes arbitrary grid functions (living on cells or vertices of a grid) * to a file suitable for easy visualization with * The Visualization Toolkit (VTK). */ template< class GridView > class VTKSequenceWriter : public VTKSequenceWriterBase { public: /** \brief Constructor with a given VTKWriter or SubsamplingVTKWriter * * At each time step, the VTKSequenceWriter writes the grid and data currently attached to the vtkWriter object. * All calls to the addCellData and addVertexData methods of the VTKSequenceWriter class are forwarded to the * vtkWriter, but we propose that you call the corresponding methods on the vtkWriter directly. * * \param name Base name of the output files. This should not * contain any directory part and not filename * extensions. It will be used both for each processes * piece as well as the parallel collection file. */ VTKSequenceWriter ( std::shared_ptr > vtkWriter, const std::string& name ) : VTKSequenceWriterBase(vtkWriter, name, "", "", vtkWriter->gridView_.comm().rank(), vtkWriter->gridView_.comm().size()) {} /** \brief Constructor with a given VTKWriter or SubsamplingVTKWriter * * At each time step, the VTKSequenceWriter writes the grid and data currently attached to the vtkWriter object. * All calls to the addCellData and addVertexData methods of the VTKSequenceWriter class are forwarded to the * vtkWriter, but we propose that you call the corresponding methods on the vtkWriter directly. * * \param name Base name of the output files. This should not * contain any directory part and not filename * extensions. It will be used both for each processes * piece as well as the parallel collection file. * \param path Directory where to put the parallel collection * (.pvtu/.pvtp) files. If it is relative, it is taken * relative to the current directory. * \param extendpath Directory where to put the piece files (.vtu/.vtp) of * this process. If it is relative, it is taken * relative to the directory denoted by path. */ VTKSequenceWriter ( std::shared_ptr > vtkWriter, const std::string& name, const std::string& path, const std::string& extendpath ) : VTKSequenceWriterBase(vtkWriter, name, path, extendpath, vtkWriter->gridView_.comm().rank(), vtkWriter->gridView_.comm().size()) {} /** \brief Constructor creating its own VTKWriter object * * At each time step, the VTKSequenceWriter writes the grid and data currently attached to the vtkWriter object. * All calls to the addCellData and addVertexData methods of the VTKSequenceWriter class are forwarded to the * vtkWriter. */ explicit VTKSequenceWriter ( const GridView &gridView, const std::string& name, const std::string& path, const std::string& extendpath, VTK::DataMode dm = VTK::conforming ) : VTKSequenceWriterBase(std::make_shared >(gridView,dm), name,path,extendpath, gridView.comm().rank(), gridView.comm().size()) {} }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/vtk/vtksequencewriterbase.hh000066400000000000000000000137601511655130300244400ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_VTKSEQUENCEWRITERBASE_HH #define DUNE_GRID_IO_FILE_VTK_VTKSEQUENCEWRITERBASE_HH #include #include #include #include #include #include #include #include #include namespace Dune { /** \brief Base class to write pvd-files which contains a list of all collected vtk-files * * Derive from this class to write pvd-file suitable for easy visualization with * The Visualization Toolkit (VTK). * * \tparam GridView Grid view of the grid we are writing * */ template class VTKSequenceWriterBase { std::shared_ptr > vtkWriter_; std::vector timesteps_; std::string name_,path_,extendpath_; int rank_; int size_; public: /** \brief Set up the VTKSequenceWriterBase class * * \param vtkWriter Writer object used to write the individual time step data files * \param rank Process number in a multi-process setting * \param size Total number of processes */ explicit VTKSequenceWriterBase( std::shared_ptr > vtkWriter, const std::string& name, const std::string& path, const std::string& extendpath, int rank, int size) : vtkWriter_(vtkWriter), name_(name), path_(path), extendpath_(extendpath), rank_(rank), size_(size) {} /** * accessor for the underlying VTKWriter instance */ const std::shared_ptr< VTKWriter >& vtkWriter() const { return vtkWriter_; } /** \brief Adds a field of cell data to the VTK file */ void addCellData (const std::shared_ptr::VTKFunction> &p) { vtkWriter_->addCellData(p); } /** \brief Adds a field of cell data to the VTK file * \param v The container with the values of the grid function for each cell * \param name A name to identify the grid function * \param ncomps Number of components (default is 1) */ template void addCellData (const V &v, const std::string &name, int ncomps=1) { vtkWriter_->addCellData(v, name, ncomps); } /** \brief Adds a field of vertex data to the VTK file */ void addVertexData (const std::shared_ptr::VTKFunction> &p) { vtkWriter_->addVertexData(p); } /** \brief Adds a field of vertex data to the VTK file * \param v The container with the values of the grid function for each vertex * \param name A name to identify the grid function * \param ncomps Number of components (default is 1) */ template void addVertexData (const V &v, const std::string &name, int ncomps=1) { vtkWriter_->addVertexData(v, name, ncomps); } /** * \brief Writes VTK data for the given time, * \param time The time(step) for the data to be written. * \param type VTK output type. */ void write (double time, VTK::OutputType type = VTK::ascii) { /* remember current time step */ unsigned int count = timesteps_.size(); timesteps_.push_back(time); /* write VTK file */ if(size_==1) vtkWriter_->write(concatPaths(path_,seqName(count)),type); else vtkWriter_->pwrite(seqName(count), path_,extendpath_,type); /* write pvd file ... only on rank 0 */ if (rank_==0) { std::ofstream pvdFile; pvdFile.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); std::string pvdname = name_ + ".pvd"; pvdFile.open(pvdname.c_str()); pvdFile << " \n" << " \n" << " \n"; for (unsigned int i=0; i<=count; i++) { // filename std::string piecepath; std::string fullname; if(size_==1) { piecepath = path_; fullname = vtkWriter_->getSerialPieceName(seqName(i), piecepath); } else { piecepath = concatPaths(path_, extendpath_); fullname = vtkWriter_->getParallelHeaderName(seqName(i), piecepath, size_); } pvdFile << " \n"; } pvdFile << " \n" << " \n" << std::flush; pvdFile.close(); } } /** * \brief Clears all VTK data added to the VTK writer */ void clear() { vtkWriter_->clear(); } /** * \brief Retrieve the current list of time steps */ const std::vector& getTimeSteps() const { return timesteps_; } /** * \brief Set the current list of time steps * \note This makes it possible to serialize the sequence writers state. * Can be used to continue writing a VTK sequence after a restart of the program. */ void setTimeSteps(const std::vector& timesteps) { timesteps_ = timesteps; } private: // create sequence name std::string seqName(unsigned int count) const { std::stringstream n; n.fill('0'); n << name_ << "-" << std::setw(5) << count; return n.str(); } }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/vtk/vtkwriter.hh000066400000000000000000001563521511655130300220610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_VTKWRITER_HH #define DUNE_VTKWRITER_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** @file @author Peter Bastian, Christian Engwer @brief Provides file i/o for the visualization toolkit */ /** @todo put vtk io intro here ... details and examples regarding the VTK file format can be found here: http://www.earthmodels.org/software/vtk-and-paraview/vtk-file-formats */ namespace Dune { namespace Impl { // Check whether type F has a method 'bind' (see the dune-functions interface) template< class F, class E, class = void > struct IsBindable : std::false_type {}; template< class F, class E > struct IsBindable< F, E, std::void_t< decltype( std::declval< F & >().bind( std::declval< const E & >() ) ), decltype( std::declval< F & >().unbind() ) > > : std::true_type {}; // Check whether localFunction(F) can be called (see the dune-functions interface) template< class F, class = void > struct HasLocalFunction : std::false_type {}; template< class F > struct HasLocalFunction< F, std::void_t< decltype( localFunction( std::declval< F& >() ) ) > > : std::true_type {}; } // namespace Impl // Forward-declaration here, so the class can be friend of VTKWriter template class VTKSequenceWriterBase; template class VTKSequenceWriter; /** * @brief Writer for the output of grid functions in the vtk format. * @ingroup VTK * * Writes arbitrary grid functions (living on cells or vertices of a grid) * to a file suitable for easy visualization with * The Visualization Toolkit (VTK). */ template< class GridView > class VTKWriter { // VTKSequenceWriterBase needs getSerialPieceName // and getParallelHeaderName friend class VTKSequenceWriterBase; // VTKSequenceWriter needs the grid view, to get the MPI size and rank friend class VTKSequenceWriter; // extract types typedef typename GridView::Grid Grid; typedef typename GridView::ctype DT; constexpr static int n = GridView::dimension; constexpr static int w = GridView::dimensionworld; typedef typename GridView::template Codim< 0 >::Entity Cell; typedef typename GridView::template Codim< n >::Entity Vertex; typedef Cell Entity; typedef typename GridView::IndexSet IndexSet; static const PartitionIteratorType VTK_Partition = InteriorBorder_Partition; //static const PartitionIteratorType VTK_Partition = All_Partition; typedef typename GridView::template Codim< 0 > ::template Partition< VTK_Partition >::Iterator GridCellIterator; typedef typename GridView::template Codim< n > ::template Partition< VTK_Partition >::Iterator GridVertexIterator; typedef typename GridCellIterator::Reference EntityReference; typedef typename GridView::template Codim< 0 > ::Entity::Geometry::LocalCoordinate Coordinate; typedef MultipleCodimMultipleGeomTypeMapper< GridView > VertexMapper; // return true if entity should be skipped in Vertex and Corner iterator static bool skipEntity( const PartitionType entityType ) { switch( VTK_Partition ) { // for All_Partition no entity has to be skipped case All_Partition: return false; case InteriorBorder_Partition: return ( entityType != InteriorEntity ); default: DUNE_THROW(NotImplemented,"Add check for this partition type"); } return false ; } public: typedef Dune::VTKFunction< GridView > VTKFunction; protected: //! Type erasure wrapper for VTK data sets /** * This wrapper has value semantics */ class VTKLocalFunction { public: typedef VTK::DataArrayWriter Writer; //! Base class for polymorphic container of underlying data set struct FunctionWrapperBase { //! Bind data set to grid entity - must be called before evaluating (i.e. calling write()) virtual void bind(const Entity& e) = 0; //! Unbind data set from current grid entity - mostly here for performance and symmetry reasons virtual void unbind() = 0; //! Evaluate data set at local position pos inside the current entity and write result to w. /** * The function must write count scalar values as determined by the VTK::FieldInfo. */ virtual void write(const Coordinate& pos, Writer& w, std::size_t count) const = 0; virtual ~FunctionWrapperBase() {} }; //! Type erasure implementation for functions conforming to the dune-functions LocalFunction interface // DUNE_PRIVATE since _f has less visibility template struct DUNE_PRIVATE FunctionWrapper : public FunctionWrapperBase { using Function = typename std::decay::type; template FunctionWrapper(F_&& f) : _f(std::forward(f)) {} virtual void bind(const Entity& e) { _f.bind(e); } virtual void unbind() { _f.unbind(); } virtual void write(const Coordinate& pos, Writer& writer, std::size_t count) const { auto r = _f(pos); // we need to do different things here depending on whether r supports indexing into it or not. do_write(writer,r,count,IsIndexable()); } private: template void do_write(Writer& writer, const R& r, std::size_t count, std::true_type) const { for (std::size_t i = 0; i < count; ++i) writer.write(r[i]); } template void do_write(Writer& writer, const R& r, std::size_t count, std::false_type) const { assert(count == 1); writer.write(r); } Function _f; }; //! Type erasure implementation for C++ functions, i.e., functions that can be evaluated in global coordinates template struct GlobalFunctionWrapper : public FunctionWrapperBase { using Function = typename std::decay::type; template GlobalFunctionWrapper(F_&& f) : _f(std::forward(f)) , element_(nullptr) {} virtual void bind(const Entity& e) { element_ = &e; } virtual void unbind() { element_ = nullptr; } virtual void write(const Coordinate& pos, Writer& writer, std::size_t count) const { auto globalPos = element_->geometry().global(pos); auto r = _f(globalPos); if constexpr (IsIndexable()) { for (std::size_t i = 0; i < count; ++i) writer.write(r[i]); } else { assert(count == 1); writer.write(r); } } private: Function _f; const Entity* element_; }; //! Type erasure implementation for legacy VTKFunctions. struct VTKFunctionWrapper : public FunctionWrapperBase { VTKFunctionWrapper(const std::shared_ptr< const VTKFunction >& f) : _f(f) , _entity(nullptr) {} virtual void bind(const Entity& e) { _entity = &e; } virtual void unbind() { _entity = nullptr; } virtual void write(const Coordinate& pos, Writer& writer, std::size_t count) const { for (std::size_t i = 0; i < count; ++i) writer.write(_f->evaluate(i,*_entity,pos)); } private: std::shared_ptr< const VTKFunction > _f; const Entity* _entity; }; //! Construct a VTKLocalFunction for a dune-functions style LocalFunction template::value, int> = 0> VTKLocalFunction(F&& f, VTK::FieldInfo fieldInfo) : _f(std::make_unique >(std::forward(f))) , _fieldInfo(fieldInfo) {} //! Construct a VTKLocalFunction for a dune-functions GridViewFunction // That is, a function that you can create a LocalFunction for, and evaluate that in element coordinates template::value && Impl::HasLocalFunction::value, int> = 0> VTKLocalFunction(F&& f, VTK::FieldInfo fieldInfo) : _f(std::make_unique< FunctionWrapper< typename std::decay(f)))>::type > >(localFunction(std::forward(f)))) , _fieldInfo(fieldInfo) {} //! Construct a VTKLocalFunction for a C++ (global) function // That is, a function that can be evaluated in global coordinates of the domain template::value && not Impl::HasLocalFunction::value, int> = 0> VTKLocalFunction(F&& f, VTK::FieldInfo fieldInfo) : _f(std::make_unique< GlobalFunctionWrapper >(std::forward(f))) , _fieldInfo(fieldInfo) {} //! Construct a VTKLocalFunction for a legacy VTKFunction explicit VTKLocalFunction (const std::shared_ptr< const VTKFunction >& vtkFunctionPtr) : _f(std::make_unique(vtkFunctionPtr)) , _fieldInfo( vtkFunctionPtr->name(), (vtkFunctionPtr->ncomps() == 2 || vtkFunctionPtr->ncomps() == 3) ? VTK::FieldInfo::Type::vector : VTK::FieldInfo::Type::scalar, vtkFunctionPtr->ncomps(), vtkFunctionPtr->precision() ) {} //! Returns the name of the data set std::string name() const { return fieldInfo().name(); } //! Returns the VTK::FieldInfo for the data set const VTK::FieldInfo& fieldInfo() const { return _fieldInfo; } //! Bind the data set to grid entity e. void bind(const Entity& e) const { _f->bind(e); } //! Unbind the data set from the currently bound entity. void unbind() const { _f->unbind(); } //! Write the value of the data set at local coordinate @c pos to the @c writer. void write(const Coordinate& pos, Writer& writer) const { _f->write(pos,writer,fieldInfo().size()); } std::shared_ptr _f; VTK::FieldInfo _fieldInfo; }; typedef typename std::list::const_iterator FunctionIterator; //! Iterator over the grids elements /** * This class iterates over the gridview's elements. It is the same as * the gridview's Codim<0>::Iterator for the InteriorBorder_Partition, * except that it add a position() method. */ class CellIterator : public GridCellIterator { public: //! construct a CellIterator from the gridview's Iterator. CellIterator(const GridCellIterator & x) : GridCellIterator(x) {} //! get the position of the center of the element, in element-local //! coordinates const FieldVector position() const { return ReferenceElements::general((*this)->type()).position(0,0); } }; CellIterator cellBegin() const { return gridView_.template begin< 0, VTK_Partition >(); } CellIterator cellEnd() const { return gridView_.template end< 0, VTK_Partition >(); } //! Iterate over the grid's vertices /** * This class iterates over the elements, and within the elements over the * corners. If the data mode dm is nonconforming, each vertex is visited * once for each element where it is a corner (similar to CornerIterator). * If dm is conforming each vertex is visited only once globally, for the * first element where it is a corner. Contrary to CornerIterator, visit * the corners of a given element in Dune-ordering. * * Dereferencing the iterator yields the current entity, and the index of * the current corner within that entity is returned by the iterators * localindex() method. Another useful method on the iterator itself is * position() which returns the element-local position of the current * corner. */ class VertexIterator : public ForwardIteratorFacade { GridCellIterator git; GridCellIterator gend; VTK::DataMode datamode; // Index of the currently visited corner within the current element. // NOTE: this is in Dune-numbering, in contrast to CornerIterator. int cornerIndexDune; const VertexMapper & vertexmapper; std::vector visited; // in conforming mode, for each vertex id (as obtained by vertexmapper) // hold its number in the iteration order (VertexIterator) int offset; // hide operator -> void operator->(); protected: void basicIncrement () { if( git == gend ) return; ++cornerIndexDune; const int numCorners = git->subEntities(n); if( cornerIndexDune == numCorners ) { offset += numCorners; cornerIndexDune = 0; ++git; while( (git != gend) && skipEntity( git->partitionType() ) ) ++git; } } public: VertexIterator(const GridCellIterator & x, const GridCellIterator & end, const VTK::DataMode & dm, const VertexMapper & vm) : git(x), gend(end), datamode(dm), cornerIndexDune(0), vertexmapper(vm), visited(vm.size(), false), offset(0) { if (datamode == VTK::conforming && git != gend) visited[vertexmapper.subIndex(*git,cornerIndexDune,n)] = true; } void increment () { switch (datamode) { case VTK::conforming : while(visited[vertexmapper.subIndex(*git,cornerIndexDune,n)]) { basicIncrement(); if (git == gend) return; } visited[vertexmapper.subIndex(*git,cornerIndexDune,n)] = true; break; case VTK::nonconforming : basicIncrement(); break; } } bool equals (const VertexIterator & cit) const { return git == cit.git && cornerIndexDune == cit.cornerIndexDune && datamode == cit.datamode; } EntityReference dereference() const { return *git; } //! index of vertex within the entity, in Dune-numbering int localindex () const { return cornerIndexDune; } //! position of vertex inside the entity FieldVector position () const { return referenceElement(git->type()) .position(cornerIndexDune,n); } }; VertexIterator vertexBegin () const { return VertexIterator( gridView_.template begin< 0, VTK_Partition >(), gridView_.template end< 0, VTK_Partition >(), datamode, *vertexmapper ); } VertexIterator vertexEnd () const { return VertexIterator( gridView_.template end< 0, VTK_Partition >(), gridView_.template end< 0, VTK_Partition >(), datamode, *vertexmapper ); } //! Iterate over the elements' corners /** * This class iterates over the elements, and within the elements over the * corners. Each vertex in the grid can be a corner in multiple elements, * and is visited once for each element it is associated with. This class * differs from VertexIterator in that it visits the corners of a given * element in VTK-ordering, and that it always visits a given vertex once * for each element where that vertex is a corner in, independent of the * data mode dm. * * Dereferencing the iterator yields the current entity. Another useful * method on the iterator itself is id(), which returns the number of the * current corners associated vertex, in the numbering given by the * iteration order of VertexIterator. */ class CornerIterator : public ForwardIteratorFacade { GridCellIterator git; GridCellIterator gend; VTK::DataMode datamode; // Index of the currently visited corner within the current element. // NOTE: this is in VTK-numbering, in contrast to VertexIterator. int cornerIndexVTK; const VertexMapper & vertexmapper; // in conforming mode, for each vertex id (as obtained by vertexmapper) // hold its number in the iteration order of VertexIterator (*not* // CornerIterator) const std::vector & number; // holds the number of corners of all the elements we have seen so far, // excluding the current element int offset; // hide operator -> void operator->(); public: CornerIterator(const GridCellIterator & x, const GridCellIterator & end, const VTK::DataMode & dm, const VertexMapper & vm, const std::vector & num) : git(x), gend(end), datamode(dm), cornerIndexVTK(0), vertexmapper(vm), number(num), offset(0) {} void increment () { if( git == gend ) return; ++cornerIndexVTK; const int numCorners = git->subEntities(n); if( cornerIndexVTK == numCorners ) { offset += numCorners; cornerIndexVTK = 0; ++git; while( (git != gend) && skipEntity( git->partitionType() ) ) ++git; } } bool equals (const CornerIterator & cit) const { return git == cit.git && cornerIndexVTK == cit.cornerIndexVTK && datamode == cit.datamode; } EntityReference dereference() const { return *git; } //! Process-local consecutive zero-starting vertex id /** * This method returns the number of this corners associated vertex, in * the numbering given by the iteration order of VertexIterator. */ int id () const { switch (datamode) { case VTK::conforming : return number[vertexmapper.subIndex(*git,VTK::renumber(*git,cornerIndexVTK), n)]; case VTK::nonconforming : return offset + VTK::renumber(*git,cornerIndexVTK); default : DUNE_THROW(IOError,"VTKWriter: unsupported DataMode" << datamode); } } }; CornerIterator cornerBegin () const { return CornerIterator( gridView_.template begin< 0, VTK_Partition >(), gridView_.template end< 0, VTK_Partition >(), datamode, *vertexmapper, number ); } CornerIterator cornerEnd () const { return CornerIterator( gridView_.template end< 0, VTK_Partition >(), gridView_.template end< 0, VTK_Partition >(), datamode, *vertexmapper, number ); } public: /** * @brief Construct a VTKWriter working on a specific GridView. * * * @param gridView The gridView the grid functions live on. (E. g. a LevelGridView.) * @param dm The data mode. * @param coordPrecision the precision with which to write out the coordinates */ explicit VTKWriter ( const GridView &gridView, VTK::DataMode dm = VTK::conforming, VTK::Precision coordPrecision = VTK::Precision::float32) : gridView_( gridView ), datamode( dm ), coordPrec (coordPrecision), polyhedralCellsPresent_( checkForPolyhedralCells() ) { } /** * @brief Add a grid function that lives on the cells of the grid to the visualization. * @param p std::shared_ptr to the function to visualize */ void addCellData (const std::shared_ptr< const VTKFunction > & p) { celldata.push_back(VTKLocalFunction(p)); } /** * @brief Add a function by sampling it on the element centers * * \param f The function to be written to the file * * The object f can be one of several things. Depending on what it is exactly, * its object life-time is influenced in different ways: * - If f has the method bind(), then a copy of f is stored, regardless of whether f is an l- or r-value. * - If f can be localized by calling localFunction(f), then a copy of localFunction(f) is stored, * but f is never stored, regardless of whether f is an l- or r-value. * - If f supports neither bind() or localFunction(), then a copy of f is stored, * regardless if f is an l- or r-value. * * The previous paragraph actually refers to parts of the dune-functions interface, * and you may want to read up on that if you want to write functions to VTK. * * \deprecated f may also be a VTKFunction object, but you are strongly discouraged * from using VTKFunctions. */ template void addCellData(F&& f, VTK::FieldInfo vtkFieldInfo) { celldata.push_back(VTKLocalFunction(std::forward(f),vtkFieldInfo)); } /** * @brief Add a grid function (represented by container) that lives on the cells of * the grid to the visualization. * * The container has to have random access via operator[] (e.g. std::vector). The * value of the grid function for an arbitrary element * will be accessed by calling operator[] with the index (corresponding * to the index from the MGMC mapper on the grid view) of the element. * For vector valued data all components for an element are assumed to * be consecutive. * * @param v The container with the values of the grid function for each cell. * @param name A name to identify the grid function. * @param ncomps Number of components (default is 1). * \param prec The precision type with which to write the data. */ template void addCellData (const Container& v, const std::string &name, int ncomps = 1, VTK::Precision prec = VTK::Precision::float32) { typedef P0VTKFunction Function; for (int c=0; c1) compName << "[" << c << "]"; VTKFunction* p = new Function(gridView_, v, compName.str(), ncomps, c, prec); addCellData(std::shared_ptr< const VTKFunction >(p)); } } /** * @brief Add a grid function that lives on the vertices of the grid to the visualization. * @param p std::shared_ptr to the function to visualize */ void addVertexData (const std::shared_ptr< const VTKFunction > & p) { vertexdata.push_back(VTKLocalFunction(p)); } /** * @brief Add a function by sampling it on the grid vertices * * \param f The function to be written to the file * * The object f can be one of several things. Depending on what it is exactly, * its object life-time is influenced in different ways: * - If f has the method bind(), then a copy of f is stored, regardless of whether f is an l- or r-value. * - If f can be localized by calling localFunction(f), then a copy of localFunction(f) is stored, * but f is never stored, regardless of whether f is an l- or r-value. * - If f supports neither bind() or localFunction(), then a copy of f is stored, * regardless if f is an l- or r-value. * * The previous paragraph actually refers to parts of the dune-functions interface, * and you may want to read up on that if you want to write functions to VTK. * * \deprecated f may also be a VTKFunction object, but you are strongly discouraged * from using VTKFunctions. */ template void addVertexData(F&& f, VTK::FieldInfo vtkFieldInfo) { vertexdata.push_back(VTKLocalFunction(std::forward(f),vtkFieldInfo)); } /** * @brief Add a grid function (represented by container) that lives on the vertices of the * grid to the visualization output. * * The container has to have random access via operator[] (e.g. std::vector). The value * of the grid function for an arbitrary element * will be accessed by calling operator[] with the index (corresponding * to the index from the MGMC mapper on the grid view) of the vertex. * For vector valued data all components for a vertex are assumed to * be consecutive. * * @param v The container with the values of the grid function for each vertex. * @param name A name to identify the grid function. * @param ncomps Number of components (default is 1). * \param prec The precision type with which to write the data. */ template void addVertexData (const Container& v, const std::string &name, int ncomps=1, VTK::Precision prec = VTK::Precision::float32) { typedef P1VTKFunction Function; for (int c=0; c1) compName << "[" << c << "]"; VTKFunction* p = new Function(gridView_, v, compName.str(), ncomps, c, prec); addVertexData(std::shared_ptr< const VTKFunction >(p)); } } //! clear list of registered functions void clear () { celldata.clear(); vertexdata.clear(); } //! get the precision with which coordinates are written out VTK::Precision coordPrecision() const { return coordPrec; } //! destructor virtual ~VTKWriter () { this->clear(); } /** \brief write output (interface might change later) * * This method can be used in parallel as well as in serial programs. * For serial runs (commSize=1) it chooses other names without the * "s####-p####-" prefix for the .vtu/.vtp files and omits writing of the * .pvtu/pvtp file however. For parallel runs (commSize > 1) it is the * same as a call to pwrite() with name and path constructed from * a given filename possibly containing a path, and extendpath="". * * \param[in] name basic name to write (may not contain a path) * \param[in] type type of output (e.g,, ASCII) (optional) */ std::string write ( const std::string &name, VTK::OutputType type = VTK::ascii ) { return write( name, type, gridView_.comm().rank(), gridView_.comm().size() ); } /** \brief write output (interface might change later) * * "pwrite" means "path write" (i.e. write somewhere else than the current * directory). The "p" does not mean this method has a monopoly on * parallel writing, the regular write(const std::string &, * VTK::OutputType) method can do that just fine. * * \param name Base name of the output files. This should not * contain any directory part and not filename * extensions. It will be used both for each processes * piece as well as the parallel collection file. * \param path Directory where to put the parallel collection * (.pvtu/.pvtp) file. If it is relative, it is taken * relative to the current directory. * \param extendpath Directory where to put the piece file (.vtu/.vtp) of * this process. If it is relative, it is taken * relative to the directory denoted by path. * \param type How to encode the data in the file. * * \note Currently, extendpath may not be absolute unless path is * absolute, because that would require the value of the current * directory. * * \throw NotImplemented Extendpath is absolute but path is relative. * \throw IOError Failed to open a file. */ std::string pwrite ( const std::string & name, const std::string & path, const std::string & extendpath, VTK::OutputType type = VTK::ascii ) { return pwrite( name, path, extendpath, type, gridView_.comm().rank(), gridView_.comm().size() ); } protected: //! return name of a parallel piece file (or header name) /** * \param name Base name of the VTK output. This should be without * any directory parts and without a filename extension. * \param path Directory part of the resulting piece name. May be * empty, in which case the resulting name will not have a * directory part. If non-empty, may or may not have a * trailing '/'. If a trailing slash is missing, one is * appended implicitly. * \param commRank Rank of the process to generate a piece name for. if (-1) * then the header is created. * \param commSize Number of processes writing a parallel vtk output. */ std::string getParallelPieceName(const std::string& name, const std::string& path, int commRank, int commSize) const { std::ostringstream s; // write path first if(path.size() > 0) { s << path; if(path[path.size()-1] != '/') s << '/'; } std::string fileprefix; // check if a path was already added to name // and if yes find filename without path auto pos = name.rfind('/'); if( pos != std::string::npos ) { // extract filename without path fileprefix = name.substr( pos+1 ); // extract the path and added it before // the magic below is added std::string newpath = name.substr(0, pos); s << newpath; if(newpath[name.size()-1] != '/') s << '/'; } else { // if no path was found just copy the name fileprefix = name; } s << 's' << std::setw(4) << std::setfill('0') << commSize << '-'; const bool writeHeader = commRank < 0; if( ! writeHeader ) { s << 'p' << std::setw(4) << std::setfill('0') << commRank << '-'; } s << fileprefix << "."; // write p for header files if( writeHeader ) s << "p"; s << "vt"; if(GridView::dimension > 1) s << "u"; else s << "p"; return s.str(); } //! return name of a parallel header file /** * \param name Base name of the VTK output. This should be without * any directory parts and without a filename extension. * \param path Directory part of the resulting header name. May be * empty, in which case the resulting name will not have a * directory part. If non-empty, may or may not have a * trailing '/'. If a trailing slash is missing, one is * appended implicitly. * \param commSize Number of processes writing a parallel vtk output. */ std::string getParallelHeaderName(const std::string& name, const std::string& path, int commSize) const { return getParallelPieceName( name, path, -1, commSize ); } //! return name of a serial piece file /** * This is similar to getParallelPieceName, but skips the prefixes for * commSize ("s####-") and commRank ("p####-"). * * \param name Base name of the VTK output. This should be without * any directory parts and without a filename extension. * \param path Directory part of the resulting piece name. May be * empty, in which case the resulting name will not have a * directory part. If non-empty, may or may not have a * trailing '/'. If a trailing slash is missing, one is * appended implicitly. */ std::string getSerialPieceName(const std::string& name, const std::string& path) const { static const std::string extension = GridView::dimension == 1 ? ".vtp" : ".vtu"; return concatPaths(path, name+extension); } /** \brief write output (interface might change later) * * This method can be used in parallel as well as in serial programs. * For serial runs (commSize=1) it chooses other names without the * "s####-p####-" prefix for the .vtu/.vtp files and omits writing of the * .pvtu/pvtp file however. For parallel runs (commSize > 1) it is the * same as a call to pwrite() with name and path constructed from * a given filename possibly containing a path, and extendpath="". * * \param name Base name of the output files. This should not * contain any directory part and no filename extensions. * \param type How to encode the data in the file. * \param commRank Rank of the current process. * \param commSize Number of processes taking part in this write * operation. */ std::string write ( const std::string &name, VTK::OutputType type, const int commRank, const int commSize ) { // in the parallel case, just use pwrite, it has all the necessary // stuff, so we don't need to reimplement it here. if(commSize > 1) { std::string filename = name; std::string path = std::string(""); // check if a path was already added to name // and if yes find filename without path auto pos = name.rfind('/'); if( pos != std::string::npos ) { // extract filename without path filename = name.substr( pos+1 ); // extract the path and added it before // the magic below is added path = name.substr(0, pos); } return pwrite(filename, path, "", type, commRank, commSize); } // make data mode visible to private functions outputtype = type; // generate filename for process data std::string pieceName = getSerialPieceName(name, ""); // write process data std::ofstream file; file.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); // check if file can be opened try { file.open( pieceName.c_str(), std::ios::binary ); } catch(...) { std::cerr << "Filename: " << pieceName << " could not be opened" << std::endl; throw; } if (! file.is_open()) DUNE_THROW(IOError, "Could not write to piece file " << pieceName); writeDataFile( file ); file.close(); return pieceName; } //! write output; interface might change later /** * \param name Base name of the output files. This should not * contain any directory part and not filename * extensions. It will be used both for each processes * piece as well as the parallel collection file. * \param path Directory where to put the parallel collection * (.pvtu/.pvtp) file. If it is relative, it is taken * relative to the current directory. * \param extendpath Directory where to put the piece file (.vtu/.vtp) of * this process. If it is relative, it is taken * relative to the directory denoted by path. * \param ot How to encode the data in the file. * \param commRank Rank of the current process. * \param commSize Number of processes taking part in this write * operation. * * \note Currently, extendpath may not be absolute unless path is * absolute, because that would require the value of the current * directory. * * \throw NotImplemented Extendpath is absolute but path is relative. * \throw IOError Failed to open a file. */ std::string pwrite(const std::string& name, const std::string& path, const std::string& extendpath, VTK::OutputType ot, const int commRank, const int commSize ) { // make data mode visible to private functions outputtype=ot; // do some magic because paraview can only cope with relative paths to piece files std::ofstream file; file.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); std::string piecepath = concatPaths(path, extendpath); std::string relpiecepath = relativePath(path, piecepath); // write this processes .vtu/.vtp piece file std::string fullname = getParallelPieceName(name, piecepath, commRank, commSize); // check if file can be opened try { file.open(fullname.c_str(),std::ios::binary); } catch(...) { std::cerr << "Filename: " << fullname << " could not be opened" << std::endl; throw; } if (! file.is_open()) DUNE_THROW(IOError, "Could not write to piecefile file " << fullname); writeDataFile(file); file.close(); gridView_.comm().barrier(); // if we are rank 0, write .pvtu/.pvtp parallel header fullname = getParallelHeaderName(name, path, commSize); if( commRank ==0 ) { file.open(fullname.c_str()); if (! file.is_open()) DUNE_THROW(IOError, "Could not write to parallel file " << fullname); writeParallelHeader(file,name,relpiecepath, commSize ); file.close(); } gridView_.comm().barrier(); return fullname; } private: //! write header file in parallel case to stream /** * Writes a .pvtu/.pvtp file for a collection of concurrently written * .vtu/.vtp files. * * \param s Stream to write the file contents to. * \param piecename Base name of the pieces. Should not contain a * directory part or filename extension. * \param piecepath Directory part of the pieces. Since paraview does not * support absolute paths in parallel collection files, * this should be a path relative to the directory the * collection file resides in. A trailing '/' is * optional, and an empty value "" is equivalent to the * value "." except it will look nicer in the collection * file. * \param commSize Number of processes which are producing the VTK * output. */ void writeParallelHeader(std::ostream& s, const std::string& piecename, const std::string& piecepath, const int commSize) { VTK::FileType fileType = (n == 1) ? VTK::polyData : VTK::unstructuredGrid; VTK::PVTUWriter writer(s, fileType); writer.beginMain(); // PPointData { std::string scalars, vectors; std::tie(scalars,vectors) = getDataNames(vertexdata); writer.beginPointData(scalars, vectors); } for (auto it = vertexdata.begin(), end = vertexdata.end(); it != end; ++it) { unsigned writecomps = it->fieldInfo().size(); // for 2d vector fields should be written as 3d vector fields if(it->fieldInfo().type() == VTK::FieldInfo::Type::vector && writecomps == 2) writecomps = 3; writer.addArray(it->name(), writecomps, it->fieldInfo().precision()); } writer.endPointData(); // PCellData { std::string scalars, vectors; std::tie(scalars,vectors) = getDataNames(celldata); writer.beginCellData(scalars, vectors); } for (auto it = celldata.begin(), end = celldata.end(); it != end; ++it) { unsigned writecomps = it->fieldInfo().size(); // for 2d vector fields should be written as 3d vector fields if(it->fieldInfo().type() == VTK::FieldInfo::Type::vector && writecomps == 2) writecomps = 3; writer.addArray(it->name(), writecomps, it->fieldInfo().precision()); } writer.endCellData(); // PPoints writer.beginPoints(); writer.addArray("Coordinates", 3, coordPrec); writer.endPoints(); // Pieces for( int i = 0; i < commSize; ++i ) { const std::string& fullname = getParallelPieceName(piecename, piecepath, i, commSize); writer.addPiece(fullname); } writer.endMain(); } //! write data file to stream void writeDataFile (std::ostream& s) { VTK::FileType fileType = (n == 1) ? VTK::polyData : VTK::unstructuredGrid; VTK::VTUWriter writer(s, outputtype, fileType); // Grid characteristics vertexmapper = new VertexMapper( gridView_, mcmgVertexLayout() ); if (datamode == VTK::conforming) { number.resize(vertexmapper->size()); for (std::vector::size_type i=0; imap(), this iteration must be // in the order of Dune's numbering. const int subEntities = it->subEntities(n); for (int i=0; isubIndex(*it,i,n); if (number[alpha]<0) number[alpha] = nvertices_++; } else { nvertices_++; } } } } template std::tuple getDataNames(const T& data) const { std::string scalars = ""; for (auto it = data.begin(), end = data.end(); it != end; ++it) if (it->fieldInfo().type() == VTK::FieldInfo::Type::scalar) { scalars = it->name(); break; } std::string vectors = ""; for (auto it = data.begin(), end = data.end(); it != end; ++it) if (it->fieldInfo().type() == VTK::FieldInfo::Type::vector) { vectors = it->name(); break; } return std::make_tuple(scalars,vectors); } template void writeData(VTK::VTUWriter& writer, const Data& data, const Iterator begin, const Iterator end, int nentries) { for (auto it = data.begin(), iend = data.end(); it != iend; ++it) { const auto& f = *it; VTK::FieldInfo fieldInfo = f.fieldInfo(); std::size_t writecomps = fieldInfo.size(); switch (fieldInfo.type()) { case VTK::FieldInfo::Type::scalar: break; case VTK::FieldInfo::Type::vector: // vtk file format: a vector data always should have 3 comps (with // 3rd comp = 0 in 2D case) if (writecomps > 3) DUNE_THROW(IOError,"Cannot write VTK vectors with more than 3 components (components was " << writecomps << ")"); writecomps = 3; break; case VTK::FieldInfo::Type::tensor: DUNE_THROW(NotImplemented,"VTK output for tensors not implemented yet"); } std::shared_ptr p (writer.makeArrayWriter(f.name(), writecomps, nentries, fieldInfo.precision())); if(!p->writeIsNoop()) for (Iterator eit = begin; eit!=end; ++eit) { const Entity & e = *eit; f.bind(e); f.write(eit.position(),*p); f.unbind(); // vtk file format: a vector data always should have 3 comps // (with 3rd comp = 0 in 2D case) for (std::size_t j=fieldInfo.size(); j < writecomps; ++j) p->write(0.0); } } } //! write cell data virtual void writeCellData(VTK::VTUWriter& writer) { if(celldata.size() == 0) return; std::string scalars, vectors; std::tie(scalars,vectors) = getDataNames(celldata); writer.beginCellData(scalars, vectors); writeData(writer,celldata,cellBegin(),cellEnd(),ncells); writer.endCellData(); } //! write vertex data virtual void writeVertexData(VTK::VTUWriter& writer) { if(vertexdata.size() == 0) return; std::string scalars, vectors; std::tie(scalars,vectors) = getDataNames(vertexdata); writer.beginPointData(scalars, vectors); writeData(writer,vertexdata,vertexBegin(),vertexEnd(),nvertices); writer.endPointData(); } //! write the positions of vertices virtual void writeGridPoints(VTK::VTUWriter& writer) { writer.beginPoints(); std::shared_ptr p (writer.makeArrayWriter("Coordinates", 3, nvertices, coordPrec)); if(!p->writeIsNoop()) { VertexIterator vEnd = vertexEnd(); for (VertexIterator vit=vertexBegin(); vit!=vEnd; ++vit) { int dimw=w; for (int j=0; jwrite((*vit).geometry().corner(vit.localindex())[j]); for (int j=std::min(dimw,3); j<3; j++) p->write(0.0); } } // free the VTK::DataArrayWriter before touching the stream p.reset(); writer.endPoints(); } //! write the connectivity array virtual void writeGridCells(VTK::VTUWriter& writer) { writer.beginCells(); // connectivity { std::shared_ptr p1 (writer.makeArrayWriter("connectivity", 1, ncorners, VTK::Precision::int32)); if(!p1->writeIsNoop()) for (CornerIterator it=cornerBegin(); it!=cornerEnd(); ++it) p1->write(it.id()); } // offsets { std::shared_ptr p2 (writer.makeArrayWriter("offsets", 1, ncells, VTK::Precision::int32)); if(!p2->writeIsNoop()) { int offset = 0; for (CellIterator it=cellBegin(); it!=cellEnd(); ++it) { offset += it->subEntities(n); p2->write(offset); } } } // types if (n>1) { { std::shared_ptr p3 (writer.makeArrayWriter("types", 1, ncells, VTK::Precision::uint8)); if(!p3->writeIsNoop()) { for (CellIterator it=cellBegin(); it!=cellEnd(); ++it) { int vtktype = VTK::geometryType(it->type()); p3->write(vtktype); } } } // if polyhedron cells found also cell faces need to be written if( polyhedralCellsPresent_ ) { writeCellFaces( writer ); } } writer.endCells(); } protected: bool checkForPolyhedralCells() const { // check if polyhedron cells are present for( const auto& geomType : gridView_.indexSet().types( 0 ) ) { if( VTK::geometryType( geomType ) == VTK::polyhedron ) { if (Capabilities::hasEntity::v == false) DUNE_THROW(IOError, "VTKWriter: grid must support codim 1 entities to be able to write VTK polyhedral cells"); return true; } } return false; } //! write the connectivity array virtual void writeCellFaces(VTK::VTUWriter& writer) { if( ! faceVertices_ ) { faceVertices_.reset( new std::pair< std::vector, std::vector > () ); // fill face vertex structure fillFaceVertices( cornerBegin(), cornerEnd(), gridView_.indexSet(), faceVertices_->first, faceVertices_->second ); } std::vector< int >& faces = faceVertices_->first; std::vector< int >& faceOffsets = faceVertices_->second; assert( int(faceOffsets.size()) == ncells ); { std::shared_ptr p4 (writer.makeArrayWriter("faces", 1, faces.size(), VTK::Precision::int32)); if(!p4->writeIsNoop()) { for( const auto& face : faces ) p4->write( face ); } } { std::shared_ptr p5 (writer.makeArrayWriter("faceoffsets", 1, ncells, VTK::Precision::int32)); if(!p5->writeIsNoop()) { for( const auto& offset : faceOffsets ) p5->write( offset ); // clear face vertex structure faceVertices_.reset(); } } } template inline void fillFaceVertices( CornerIterator it, const CornerIterator end, const IndexSet& indexSet, std::vector& faces, std::vector& faceOffsets ) { if( n == 3 && it != end ) { // clear output arrays faces.clear(); faces.reserve( 15 * ncells ); faceOffsets.clear(); faceOffsets.reserve( ncells ); int offset = 0; Cell element = *it; int elIndex = indexSet.index( element ); std::vector< T > vertices; vertices.reserve( 30 ); for( ; it != end; ++it ) { const Cell& cell = *it ; const int cellIndex = indexSet.index( cell ) ; if( elIndex != cellIndex ) { fillFacesForElement( element, indexSet, vertices, offset, faces, faceOffsets ); vertices.clear(); element = cell ; elIndex = cellIndex ; } vertices.push_back( it.id() ); } // fill faces for last element fillFacesForElement( element, indexSet, vertices, offset, faces, faceOffsets ); } } template static void fillFacesForElement( const Entity& element, const IndexSet& indexSet, const std::vector& vertices, T& offset, std::vector& faces, std::vector& faceOffsets ) { const int dim = n; std::map< T, T > vxMap; // get number of local faces const int nVertices = element.subEntities( dim ); for( int vx = 0; vx < nVertices; ++ vx ) { const int vxIdx = indexSet.subIndex( element, vx, dim ); vxMap[ vxIdx ] = vertices[ vx ]; } // get number of local faces const int nFaces = element.subEntities( 1 ); // store number of faces for current element faces.push_back( nFaces ); ++offset; // extract each face as a set of vertex indices for( int fce = 0; fce < nFaces; ++ fce ) { if constexpr (Capabilities::hasEntity::v) { // obtain face const auto face = element.template subEntity< 1 > ( fce ); // get all vertex indices from current face const int nVxFace = face.subEntities( dim ); faces.push_back( nVxFace ); ++offset ; for( int i=0; i celldata; std::list vertexdata; // the grid GridView gridView_; // temporary grid information int ncells; int nvertices; int ncorners; private: VertexMapper* vertexmapper; // in conforming mode, for each vertex id (as obtained by vertexmapper) // hold its number in the iteration order (VertexIterator) std::vector number; VTK::DataMode datamode; VTK::Precision coordPrec; // true if polyhedral cells are present in the grid const bool polyhedralCellsPresent_; // pointer holding face vertex connectivity if needed std::shared_ptr< std::pair< std::vector, std::vector > > faceVertices_; protected: VTK::OutputType outputtype; }; } #endif dune-grid-2.11.0/dune/grid/io/file/vtk/vtuwriter.hh000066400000000000000000000316601511655130300220650ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_VTK_VTUWRITER_HH #define DUNE_GRID_IO_FILE_VTK_VTUWRITER_HH #include #include #include #include #include #include namespace Dune { //! \addtogroup VTK //! \{ namespace VTK { //! Dump a .vtu/.vtp files contents to a stream /** * This will help generating a .vtu/.vtp file. Typical use is like this: \code { // create writer, writes begin tag VTUWriter writer(std::cout, appendedraw, VTUWriter::polyData); // write the main header writer.beginMain(ncells, nvertices); dumpEverything(writer); writer.endMain(); // write the appended section, if required by the outputtype if(writer.beginAppended()) dumpEverything(writer); writer.endAppended(); // end scope so the destructor gets called and the closing tag is written } \endcode * The method dumpEverything() then looks something like this: * \code void dumpEverything(VTUWriter& writer) { // dump cell data (optional) writer.beginCellData(); for(each cell data field) { shared_ptr arraywriter (writer.makeArrayWriter(field.name, field.ncomps, ncells, precision)); // iterate over the points and write data for each } writer.endCellData(); // dump point data (optional) writer.beginPointData(); for(each point data field) { shared_ptr arraywriter (writer.makeArrayWriter(field.name, field.ncomps, npoints, precision)); // iterate over the points and write data for each } writer.endPointData(); // dump point coordinates writer.beginPoints(); { shared_ptr arraywriter (writer.makeArrayWriter("Coordinates", 3, npoints, precision)); // iterate over the points and write data for each } writer.endPoints(); // dump cells writer.beginCells(); { // connectivity shared_ptr arraywriter (writer.makeArrayWriter("connectivity", 1, ncorners, precision)); // iterate over the cells and write data for each } { // connectivity shared_ptr arraywriter (writer.makeArrayWriter("offsets", 1, ncells, precision)); // iterate over the cells and write data for each } if(fileType == unstructuredGrid) { // types shared_ptr arraywriter (writer.makeArrayWriter("types", 1, ncells, precision)); // iterate over the cells and write data for each } writer.endCells(); } \endcode */ class VTUWriter { public: std::ostream& stream; enum Phase { main, appended } phase; private: DataArrayWriterFactory factory; Indent indent; std::string fileType; std::string cellName; bool doAppended; public: //! create a VTUWriter object /** * \param stream_ Stream to write to. * \param outputType How to encode data. * \param fileType_ Whether to write PolyData (1D) or UnstructuredGrid * (nD) format. * * Create object and write header. */ inline VTUWriter(std::ostream& stream_, OutputType outputType, FileType fileType_) : stream(stream_), factory(outputType, stream) { switch(fileType_) { case polyData : fileType = "PolyData"; cellName = "Lines"; break; case unstructuredGrid : fileType = "UnstructuredGrid"; cellName = "Cells"; break; default : DUNE_THROW(IOError, "VTUWriter: Unknown fileType: " << fileType_); } const std::string& byteOrder = getEndiannessString(); stream << indent << "\n"; stream << indent << "\n"; ++indent; } //! write footer inline ~VTUWriter() { --indent; stream << indent << "\n" << std::flush; } //! start PointData section /** * \param scalars Name of field to which should be marked as default * scalars field. If this is the empty string, don't set * any default. * \param vectors Name of field to which should be marked as default * vectors field. If this is the empty string, don't set * any default. * * If there are no PointData fields, the call to this function may be * skipped, together with the corresponding call to endPointData(). */ inline void beginPointData(const std::string& scalars = "", const std::string& vectors = "") { switch(phase) { case main : stream << indent << "\n"; ++indent; break; case appended : break; } } //! finish PointData section inline void endPointData() { switch(phase) { case main : --indent; stream << indent << "\n"; break; case appended : break; } } //! start CellData section /** * \param scalars Name of field to which should be marked as default * scalars field. If this is the empty string, don't set * any default. * \param vectors Name of field to which should be marked as default * vectors field. If this is the empty string, don't set * any default. * * If there are no CellData fields, the call to this function may be * skipped, together with the corresponding call to endCellData(). */ inline void beginCellData(const std::string& scalars = "", const std::string& vectors = "") { switch(phase) { case main : stream << indent << "\n"; ++indent; break; case appended : break; } } //! finish CellData section inline void endCellData() { switch(phase) { case main : --indent; stream << indent << "\n"; break; case appended : break; } } //! start section for the point coordinates /** * Between the call to this method an the following call to the * endPoints(), there must be a single field written. The name must be * "Coordinates", it must have 3 components, and the number of items * must be the number of points. */ inline void beginPoints() { switch(phase) { case main : stream << indent << "\n"; ++indent; break; case appended : break; } } //! finish section for the point coordinates inline void endPoints() { switch(phase) { case main : --indent; stream << indent << "\n"; break; case appended : break; } } //! start section for the grid cells/PolyData lines /** * Between the call to this method an the following call to the * endCells(), there must be two or three fields written: *
    *
  • "connectivity" of type Int32 with 3 components, number of items * is the number of corners (that may be different from number of * vertices!) *
  • "offsets" of type Int32 with one component, number of items is * number of cells. *
  • for UnstructuredGrid, "types" of type UInt8 with one component, * number of items is number of cells. *
*/ inline void beginCells() { switch(phase) { case main : stream << indent << "<" << cellName << ">\n"; ++indent; break; case appended : break; } } //! start section for the grid cells/PolyData lines inline void endCells() { switch(phase) { case main : --indent; stream << indent << "\n"; break; case appended : break; } } //! start the main PolyData/UnstructuredGrid section /** * \param ncells Number of cells/lines. * \param npoints Number of points. * * Between the call to this method and to endMain(), there should be * calls to dump the actual data: *
    *
  • (optional) beginCellData()/endCellData(), *
  • (optional) beginPointData()/endPointData(), *
  • beginPoints()/endPoints(), *
  • beginCells()/endCells(), *
*/ inline void beginMain(unsigned ncells, unsigned npoints) { stream << indent << "<" << fileType << ">\n"; ++indent; stream << indent << "\n"; ++indent; phase = main; } //! finish the main PolyData/UnstructuredGrid section inline void endMain() { --indent; stream << indent << "
\n"; --indent; stream << indent << "\n"; } //! start the appended data section /** * \returns A value indicating whether the is an actual appended section * required. * * If this function returns true, an appended section is actually * required. In this case, between the call to this method and to * endAppended(), there should be literally the same calls (including * the same arguments) as between the calls to beginMain() and * endMain(). The only exception is, that if a DataArrayWriter in the * main section indicated that the calls to write could be skipped, this * is not necessarily true in the appended section also (you will have * to ask the DataArrayWriter again). * * If this function returns false, no appended section is required and a * call to endAppeded() should immediately follow the call to this * function. */ inline bool beginAppended() { doAppended = factory.beginAppended(); if(doAppended) { const std::string& encoding = factory.appendedEncoding(); stream << indent << "\n"; ++indent; // mark begin of data stream << indent << "_"; } phase = appended; return doAppended; } //! finish the appended data section inline void endAppended() { if(doAppended) { stream << "\n"; --indent; stream << indent << "\n"; } } //! acquire a DataArrayWriter /** * \tparam T Type of the data to write. * * \param name Name of the array to write. * \param ncomps Number of components of the vectors in the array. * \param nitems Number of vectors in the array (number of cells/number * of points/number of corners). * \param prec The precision type with which to write the data. * * There should never be more than one DataArrayWriter created by the * same VTUWriter around. The returned object should be freed with * delete. */ DataArrayWriter* makeArrayWriter(const std::string& name, unsigned ncomps, unsigned nitems, Precision prec) { return factory.make(name, ncomps, nitems, indent, prec); } }; } // namespace VTK //! \} group VTK } // namespace Dune #endif // DUNE_GRID_IO_FILE_VTK_VTUWRITER_HH dune-grid-2.11.0/dune/grid/modules.txt000066400000000000000000000064651511655130300175550ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil -*- // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /* This file determines the order how things appear in the doxygen documentation within the Grid group. It works like this: @defgroup commands appear only in this file here which is parsed before the other files (because it is mentioned first in the Doxyfile). Only @addtogroup is used in the code documentation. */ /** @defgroup GridInterface The Grid Interface @ingroup Grid @brief Interfaces needed when working with a \ref Grid "Dune::Grid" */ /** @defgroup GIRelatedTypes Related types and enumerations @ingroup GridInterface */ /** @defgroup GIGrid Grid Abstract Base Class @ingroup GridInterface */ /** @defgroup GIGridView GridView @ingroup GridInterface */ /** @defgroup GIEntity Entity @ingroup GridInterface */ /** @defgroup GIGeometry Geometry @ingroup GridInterface */ /** @defgroup GIEntityPointer EntityIterators @ingroup GridInterface */ /** @defgroup GIIntersectionIterator Intersections @ingroup GridInterface */ /** @defgroup GIIteration Iterating over grid entities and intersections @ingroup GridInterface */ /** @defgroup IndexIdSets IndexSet and IdSet @ingroup GridInterface */ /** @defgroup GICommunication Communication @ingroup GridInterface */ /** @defgroup GIMiscellaneous Miscellaneous @ingroup GridInterface */ /** @defgroup GICapabilities Capabilities @ingroup GridInterface */ /** @defgroup Mapper Mappers @ingroup Grid */ /** @defgroup GridImplementations Grid Implementations @ingroup Grid @brief A list of the different Implementations of the Dune Grid Interface */ /** \defgroup GeoGrid GeometryGrid \ingroup GridImplementations */ /** \defgroup IdentityGrid IdentityGrid \ingroup GridImplementations */ /** @defgroup OneDGrid OneDGrid @ingroup GridImplementations */ /** @defgroup UGGrid UGGrid @ingroup GridImplementations */ /** @defgroup YaspGrid YaspGrid @ingroup GridImplementations */ /** @defgroup AlbertaGrid AlbertaGrid @ingroup GridImplementations */ /** @defgroup IO I/O @ingroup Grid */ /** @defgroup GridFactory GridFactory @ingroup IO @brief An interface for the creation of macro grids, for use by grid file readers etc. */ /** @defgroup DuneGridFormatParser The Dune Grid Format (DGF) @ingroup IO */ /** @defgroup DGFGridParameter DGF grid parameter for different grids @ingroup DuneGridFormatParser */ /** @defgroup VTK Visualization ToolKit (VTK) @ingroup IO */ /** @defgroup Gnuplot Gnuplot @ingroup IO */ /** @defgroup Gmsh Gmsh grid format @ingroup IO */ /** @defgroup StarCD StarCD @ingroup IO */ /* @defgroup GridPart Grid Parts @ingroup Grid */ /** @defgroup GridDevel Grid Developer API @ingroup Grid @brief Interfaces needed to implement a new \ref Grid "Dune::Grid" For help implementing the geometries of your grid, have a look at \ref GenericGeometry from \ref dune-geometry. */ dune-grid-2.11.0/dune/grid/onedgrid.hh000066400000000000000000000335111511655130300174500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_HH #define DUNE_ONE_D_GRID_HH #include #include #include #include #include #include #include #include #include /** \file * \brief The OneDGrid class */ #include "onedgrid/onedgridlist.hh" #include "onedgrid/nulliteratorfactory.hh" #include "onedgrid/onedgridentity.hh" #include "onedgrid/onedgridentityseed.hh" #include "onedgrid/onedgridintersections.hh" #include "onedgrid/onedgridintersectioniterators.hh" #include "onedgrid/onedgridleafiterator.hh" #include "onedgrid/onedgridviews.hh" #include "onedgrid/onedgridleveliterator.hh" #include "onedgrid/onedgridhieriterator.hh" #include "onedgrid/onedgridindexsets.hh" namespace Dune { class OneDGrid; /** \brief The type used to for OneDGrid geometries If you ever want OneDGrid to use a different type for coordinates, you need to change the first argument of AxisAlignedCubeGeometry here. */ template using OneDGridGeometry = AxisAlignedCubeGeometry; struct OneDGridFamily { typedef GridTraits<1, // Grid dimension 1, // Dimension of the physical space Dune::OneDGrid, OneDGridGeometry, OneDGridEntity, OneDGridLevelIterator, OneDGridLeafIntersection, OneDGridLevelIntersection, OneDGridLeafIntersectionIterator, OneDGridLevelIntersectionIterator, OneDGridHierarchicIterator, OneDGridLeafIterator, OneDGridLevelIndexSet, OneDGridLeafIndexSet, OneDGridIdSet, unsigned int, OneDGridIdSet, unsigned int, Communication, OneDGridLevelGridViewTraits, OneDGridLeafGridViewTraits, OneDGridEntitySeed, OneDGridGeometry, unsigned int, std::array > Traits; }; //********************************************************************** // // --OneDGrid // //********************************************************************** /** \brief One-dimensional adaptive grid [ provides \ref Dune::Grid ] \ingroup GridImplementations \ingroup OneDGrid This implementation of the grid interface provides one-dimensional grids only. The OneDGrid can be nonuniform and provides local mesh refinement and coarsening. */ class OneDGrid : public GridDefaultImplementation <1, 1,typename OneDGridGeometry<0,1,OneDGrid>::ctype, OneDGridFamily> { // Grid and world dimension are hardwired in this grid constexpr static int dim = 1; constexpr static int dimworld = 1; template friend class OneDGridLevelIterator; friend class OneDGridHierarchicIterator; template friend class OneDGridEntity; friend class OneDGridHierarchicIterator; friend class OneDGridLeafIntersection; friend class OneDGridLevelIntersection; friend class OneDGridLeafIntersectionIterator; friend class OneDGridLevelIntersectionIterator; friend class OneDGridLevelIndexSet; friend class OneDGridLeafIndexSet; friend class OneDGridIdSet; template friend class OneDGridLeafIterator; friend class OneDGridLeafGridView; friend class OneDGridLevelGridView; template friend class GridFactory; template class EntityImp_> friend class Entity; /** \brief Default constructor for the GridFactory */ OneDGrid(); // ********************************************************** // The Interface Methods // ********************************************************** public: /** \brief The type used to store coordinates */ typedef typename OneDGridGeometry<0,1,OneDGrid>::ctype ctype; /** \brief GridFamily of OneDGrid */ typedef OneDGridFamily GridFamily; //Provides the standard grid types typedef OneDGridFamily::Traits Traits; /** \brief Constructor with an explicit set of coordinates */ OneDGrid(const std::vector& coords); /** \brief Constructor for a uniform grid */ OneDGrid(int numElements, const ctype& leftBoundary, const ctype& rightBoundary); //! Destructor ~OneDGrid(); /** \brief Return maximum level defined in this grid. Levels are numbered 0 ... maxlevel with 0 the coarsest level. */ int maxLevel() const {return entityImps_.size()-1;} /** \brief Create an Entity from an EntitySeed */ template static typename Traits::template Codim::Entity entity(const Seed& seed) { const int codim = Seed::codimension; return typename Traits::template Codim::Entity(OneDGridEntity(seed.impl().target())); } /** \brief Number of grid entities per level and codim */ int size (int level, int codim) const { switch (codim) { case 0: return elements(level).size(); case 1: return vertices(level).size(); default: return 0; } } //! number of leaf entities per codim in this process int size (int codim) const { return leafIndexSet().size(codim); } //! number of entities per level and geometry type in this process int size (int level, GeometryType type) const { // There is only one type for each codim return size(level,1-type.dim()); } //! number of leaf entities per geometry type in this process int size (GeometryType type) const { return leafIndexSet().size(type); } /** \brief Return the number of coarse grid boundary segments. For this grid implementation, the return value is always 2, because only connected domains are supported, and then the coarse grid boundary consists of two points. */ size_t numBoundarySegments() const { return 2; } /** \brief Get the set of global ids */ const Traits::GlobalIdSet& globalIdSet() const { return idSet_; } /** \brief Get the set of local ids */ const Traits::LocalIdSet& localIdSet() const { return idSet_; } /** \brief Get an index set for the given level */ const Traits::LevelIndexSet& levelIndexSet(int level) const { if (! levelIndexSets_[level]) { levelIndexSets_[level] = new OneDGridLevelIndexSet(*this, level); levelIndexSets_[level]->update(); } return * levelIndexSets_[level]; } /** \brief Get an index set for the leaf level */ const Traits::LeafIndexSet& leafIndexSet() const { return leafIndexSet_; } /** \brief Mark entity for refinement * * \param refCount if >0 mark for refinement, if <0 mark for coarsening * \param e Entity to the entity you want to mark * * \return True, if marking was successful */ bool mark(int refCount, const Traits::Codim<0>::Entity& e ); /** \brief return current adaptation marker of given entity \param e Entity to the entity you want to mark \return int current adaptation marker of entity pointer e */ int getMark(const Traits::Codim<0>::Entity& e ) const; //! Does nothing except return true if some element has been marked for refinement bool preAdapt(); //! Triggers the grid refinement process bool adapt(); /** \brief Adaptation post-processing: Reset all adaptation state flags */ void postAdapt(); // ********************************************************** // End of Interface Methods // ********************************************************** /** \brief The different forms of grid refinement supported by OneDGrid */ enum RefinementType { /** \brief New level consists only of the refined elements */ LOCAL, /** \brief New level consists of the refined elements and the unrefined ones, too */ COPY }; /** \brief Sets the type of grid refinement */ void setRefinementType(RefinementType type) { refinementType_ = type; } /** \brief Does one uniform refinement step * * \param refCount I don't know what this is good for. It doesn't * actually do anything. */ void globalRefine(int refCount); // dummy parallel functions const Communication &comm () const { return ccobj; } /** \brief Communicate data of level gridView */ template void communicate (DataHandle& /*handle*/, InterfaceType /*iftype*/, CommunicationDirection /*dir*/, int /*level*/) const { DUNE_THROW(Dune::NotImplemented, "communicate() for OneDGrid not implemented"); } /** \brief Communicate data of leaf gridView */ template void communicate (DataHandle& /*handle*/, InterfaceType /*iftype*/, CommunicationDirection /*dir*/) const { DUNE_THROW(Dune::NotImplemented, "communicate() for OneDGrid not implemented"); } private: /** \brief Get vertex lists directly -- makes the code more readable */ OneDGridList >& vertices(int level) { return std::get<0>(entityImps_[level]); } /** \brief Get vertex lists directly -- makes the code more readable */ const OneDGridList >& vertices(int level) const { return std::get<0>(entityImps_[level]); } /** \brief Get element lists directly -- makes the code more readable */ OneDGridList >& elements(int level) { return std::get<1>(entityImps_[level]); } /** \brief Get element lists directly -- makes the code more readable */ const OneDGridList >& elements(int level) const { return std::get<1>(entityImps_[level]); } Communication ccobj; /** \brief Update all indices and ids */ void setIndices(); /** \brief Produce an entity id that has not been used in this grid before. */ unsigned int getNextFreeId() { return freeIdCounter_++; } //! The type of grid refinement currently in use RefinementType refinementType_; OneDGridList >::iterator getLeftUpperVertex(const OneDEntityImp<1>* eIt); OneDGridList >::iterator getRightUpperVertex(const OneDEntityImp<1>* eIt); /** \brief Returns an iterator to the first element on the left of the input element which has sons. */ OneDGridList >::iterator getLeftNeighborWithSon(OneDGridList >::iterator eIt); // The vertices and elements of the grid hierarchy std::vector >, OneDGridList > > > entityImps_; // Our set of level indices mutable std::vector* > levelIndexSets_; OneDGridLeafIndexSet leafIndexSet_; OneDGridIdSet idSet_; // Every entity gets a unique id, unless it is a copy of an entity on a coarser level. // This is the counter that we use to create the unique id. unsigned int freeIdCounter_; /** Since a OneDGrid is one-dimensional and connected, there can only be two possible numberings of the boundary segments. Either the left one is '0' and the right one is '1' or the reverse. This flag stores which is the case. */ bool reversedBoundarySegmentNumbering_; }; // end Class OneDGrid namespace Capabilities { /** \struct hasBackupRestoreFacilities \ingroup OneDGrid */ /** \struct IsUnstructured \ingroup OneDGrid */ /** \brief OneDGrid has only one geometry type for codim 0 entities \ingroup OneDGrid */ template< > struct hasSingleGeometryType< OneDGrid > { static const bool v = true; static const unsigned int topologyId = GeometryTypes::cube(1).id(); }; /** \brief OneDGrid has entities for all codimension \ingroup OneDGrid */ template struct hasEntity< OneDGrid, cdim > { static const bool v = true; }; /** * \brief OneDGrid can iterate over all codimensions * \ingroup OneDGrid **/ template struct hasEntityIterator { static const bool v = true; }; /** \brief OneDGrid is levelwise conforming \ingroup OneDGrid */ template<> struct isLevelwiseConforming< OneDGrid > { static const bool v = true; }; /** \brief OneDGrid is leafwise conforming \ingroup OneDGrid */ template<> struct isLeafwiseConforming< OneDGrid > { static const bool v = true; }; } } // namespace Dune // Include the GridFactory specialization for OneDGrid, so everybody // who includes the grid also gets the factory. Since OneDGrid is // not a template class, it needs to be a complete type before // GridFactory can be defined. This is why the #include- // directive is at _the end_ of this file. #include #endif dune-grid-2.11.0/dune/grid/onedgrid/000077500000000000000000000000001511655130300171245ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/onedgrid/CMakeLists.txt000066400000000000000000000016011511655130300216620ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS nulliteratorfactory.hh onedgridentity.hh onedgridentityseed.hh onedgridfactory.hh onedgridhieriterator.hh onedgridindexsets.hh onedgridleafiterator.hh onedgridleveliterator.hh onedgridlist.hh onedgridintersections.hh onedgridintersectioniterators.hh onedgridviews.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/onedgrid/) # Some of the OnedGrid headers do not pass make headercheck, # and they don't need to necessarily. Remove this line when headers are fixed exclude_from_headercheck( onedgridleafiterator.hh onedgridleveliterator.hh onedgridhieriterator.hh ) target_sources(dunegrid PRIVATE onedgrid.cc onedgridfactory.cc nulliteratorfactory.cc) dune-grid-2.11.0/dune/grid/onedgrid/nulliteratorfactory.cc000066400000000000000000000007561511655130300235570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "nulliteratorfactory.hh" Dune::OneDGridList > Dune::OneDGridNullIteratorFactory<0>::emptyList_; Dune::OneDGridList > Dune::OneDGridNullIteratorFactory<1>::emptyList_; dune-grid-2.11.0/dune/grid/onedgrid/nulliteratorfactory.hh000066400000000000000000000017411511655130300235640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONEDGRID_NULL_ITERATORS_HH #define DUNE_ONEDGRID_NULL_ITERATORS_HH #include "onedgridlist.hh" namespace Dune { template class OneDEntityImp; template class OneDGridNullIteratorFactory {}; template <> class OneDGridNullIteratorFactory<0> { public: static OneDGridList >::iterator null() { return emptyList_.end(); } private: static OneDGridList > emptyList_; }; template <> class OneDGridNullIteratorFactory<1> { public: static OneDGridList >::iterator null() { return emptyList_.end(); } private: static OneDGridList > emptyList_; }; } #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgrid.cc000066400000000000000000000420131511655130300212260ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include "../onedgrid.hh" Dune::OneDGrid::OneDGrid() : refinementType_(LOCAL), leafIndexSet_(*this), idSet_(*this), freeIdCounter_(0), reversedBoundarySegmentNumbering_(false) {} Dune::OneDGrid::OneDGrid(int numElements, const ctype& leftBoundary, const ctype& rightBoundary) : refinementType_(LOCAL), leafIndexSet_(*this), idSet_(*this), freeIdCounter_(0), reversedBoundarySegmentNumbering_(false) { if (numElements<1) DUNE_THROW(GridError, "Nonpositive number of elements requested!"); if (leftBoundary >= rightBoundary) DUNE_THROW(GridError, "The left boundary coordinate has to be strictly less than the right boundary one!"); // Init grid hierarchy entityImps_.resize(1); // Init vertex set for (int i=0; i newVertex(0, newCoord); newVertex.id_ = getNextFreeId(); vertices(0).push_back(newVertex); } // Init element set OneDGridList >::iterator it = vertices(0).begin(); for (int i=0; i newElement(0, getNextFreeId(), false); newElement.vertex_[0] = it; it = it->succ_; newElement.vertex_[1] = it; elements(0).push_back(newElement); } setIndices(); } Dune::OneDGrid::OneDGrid(const std::vector& coords) : refinementType_(LOCAL), leafIndexSet_(*this), idSet_(*this), freeIdCounter_(0), reversedBoundarySegmentNumbering_(false) { if (coords.size()<2) DUNE_THROW(GridError, "You have to provide at least two coordinates!"); // Init grid hierarchy entityImps_.resize(1); // Init vertex set for (size_t i=0; i newVertex(0, coords[i], getNextFreeId()); vertices(0).push_back(newVertex); } // Init element set OneDGridList >::iterator it = vertices(0).begin(); for (size_t i=0; i newElement(0, getNextFreeId(), false); newElement.vertex_[0] = it; it = it->succ_; newElement.vertex_[1] = it; if (newElement.vertex_[0]->pos_ >= newElement.vertex_[1]->pos_) DUNE_THROW(GridError, "The coordinates have to be in ascending order!"); elements(0).push_back(newElement); } setIndices(); } Dune::OneDGrid::~OneDGrid() { // Delete all vertices for (unsigned int i=0; i >::iterator v = vertices(i).begin(); while (v) { OneDGridList >::iterator vSucc = v->succ_; vertices(i).erase(v); v = vSucc; } } // Delete all elements for (unsigned int i=0; i >::iterator e = elements(i).begin(); while (e) { OneDGridList >::iterator eSucc = e->succ_; elements(i).erase(e); e = eSucc; } } // Delete levelIndexSets for (unsigned int i=0; i >::iterator Dune::OneDGrid::getLeftUpperVertex(const OneDEntityImp<1>* eIt) { OneDGridList >::iterator l = eIt->pred_; if (!l) return 0; // return NULL if there is no geometrical left neighbor if (l->vertex_[1] != eIt->vertex_[0]) return 0; // return NULL if that neighbor doesn't have sons if (l->isLeaf()) return 0; // return the right vertex of the right son return l->sons_[1]->vertex_[1]; } Dune::OneDGridList >::iterator Dune::OneDGrid::getRightUpperVertex(const OneDEntityImp<1>* eIt) { OneDGridList >::iterator r = eIt->succ_; if (!r) return 0; // return NULL if there is no geometrical right neighbor if (r->vertex_[0]!=eIt->vertex_[1]) return 0; // return NULL if that neighbor doesn't have sons if (r->isLeaf()) return 0; // return the left vertex of the left son return r->sons_[0]->vertex_[0]; } Dune::OneDGridList >::iterator Dune::OneDGrid::getLeftNeighborWithSon(OneDGridList >::iterator eIt) { OneDGridList >::iterator l = eIt; do { l = l->pred_; } while (l && l->isLeaf()); return l; } bool Dune::OneDGrid::adapt() { // for the return value: true if the grid was changed bool refinedGrid = false; // remove elements that have been marked for coarsening. // If one son of an element is marked for coarsening, and the other one is not, // then the element is not removed. for (int i=1; i<=maxLevel(); i++) { for (auto eIt = elements(i).begin(); eIt!=elements(i).end(); ) { OneDGridList >::iterator leftElementToBeDeleted = eIt; OneDGridList >::iterator rightElementToBeDeleted = eIt->succ_; assert(eIt->succ_); OneDGridList >::iterator nextElement = eIt->succ_->succ_; if (leftElementToBeDeleted->markState_ == OneDEntityImp<1>::COARSEN && leftElementToBeDeleted->isLeaf() && rightElementToBeDeleted->markState_ == OneDEntityImp<1>::COARSEN && rightElementToBeDeleted->isLeaf()) { assert(rightElementToBeDeleted->isLeaf()); // Is the left vertex obsolete? if (leftElementToBeDeleted->pred_==NULL || leftElementToBeDeleted->pred_->vertex_[1] != leftElementToBeDeleted->vertex_[0]) { // If the left vertex has a father remove the reference to this vertex at this father assert(leftElementToBeDeleted->father_->vertex_[0]->son_ == leftElementToBeDeleted->vertex_[0]); leftElementToBeDeleted->father_->vertex_[0]->son_ = NULL; vertices(i).erase(leftElementToBeDeleted->vertex_[0]); } // Is the right vertex obsolete? if (rightElementToBeDeleted->succ_==NULL || rightElementToBeDeleted->succ_->vertex_[0] != rightElementToBeDeleted->vertex_[1]) { // If the left vertex has a father remove the reference to this vertex at this father assert(rightElementToBeDeleted->father_->vertex_[1]->son_ == rightElementToBeDeleted->vertex_[1]); rightElementToBeDeleted->father_->vertex_[1]->son_ = NULL; vertices(i).erase(rightElementToBeDeleted->vertex_[1]); } // Delete vertex between left and right element to be deleted assert(leftElementToBeDeleted->vertex_[1] == rightElementToBeDeleted->vertex_[0]); vertices(i).erase(leftElementToBeDeleted->vertex_[1]); // Remove references from the father element assert(rightElementToBeDeleted->father_->sons_[1] == rightElementToBeDeleted); leftElementToBeDeleted->father_->sons_[0] = NULL; rightElementToBeDeleted->father_->sons_[1] = NULL; // Paranoia: make sure the father is not marked for refinement rightElementToBeDeleted->father_->markState_ = OneDEntityImp<1>::DO_NOTHING; // Actually delete elements elements(i).erase(leftElementToBeDeleted); elements(i).erase(rightElementToBeDeleted); } // increment pointer eIt = nextElement; } } // ///////////////////////////////////////////////////////////////////////// // Check if one of the elements on the toplevel is marked for refinement // In that case add another level // ///////////////////////////////////////////////////////////////////////// bool toplevelRefinement = false; for (auto eIt = elements(maxLevel()).begin(); eIt != elements(maxLevel()).end(); eIt=eIt->succ_) if (eIt->markState_ == OneDEntityImp<1>::REFINE) { toplevelRefinement = true; break; } if (toplevelRefinement) { OneDGridList > newVertices; OneDGridList > newElements; entityImps_.push_back(std::tuple >, OneDGridList > >(newVertices, newElements)); } // ////////////////////////////// // refine all marked elements // ////////////////////////////// int oldMaxlevel = (toplevelRefinement) ? maxLevel()-1 : maxLevel(); for (int i=0; i<=oldMaxlevel; i++) { for (auto eIt = elements(i).begin(); eIt!=elements(i).end(); eIt = eIt->succ_) { if (eIt->markState_ == OneDEntityImp<1>::REFINE && eIt->isLeaf()) { OneDGridList >::iterator leftNeighbor = getLeftNeighborWithSon(eIt); // //////////////////////////////////////////////////////////// // Does the left vertex exist on the next-higher level? // //////////////////////////////////////////////////////////// OneDGridList >::iterator leftUpperVertex = getLeftUpperVertex(eIt); // If no create it if (leftUpperVertex==NULL) { OneDEntityImp<0> newLeftUpperVertex(i+1, eIt->vertex_[0]->pos_, eIt->vertex_[0]->id_); // Insert new vertex into vertex list leftUpperVertex = vertices(i+1).insert((leftNeighbor) ? leftNeighbor->sons_[1]->vertex_[1]->succ_ : vertices(i+1).begin(), newLeftUpperVertex); } eIt->vertex_[0]->son_ = leftUpperVertex; // ////////////////////////////////// // Create new center vertex // ////////////////////////////////// ctype p = 0.5*(eIt->vertex_[0]->pos_[0] + eIt->vertex_[1]->pos_[0]); OneDEntityImp<0> centerVertex(i+1, p, getNextFreeId()); OneDGridList >::iterator centerVertexIterator = vertices(i+1).insert(leftUpperVertex->succ_, centerVertex); // //////////////////////////////////////////////////////////// // Does the right vertex exist on the next-higher level? // If no create it // //////////////////////////////////////////////////////////// OneDGridList >::iterator rightUpperVertex = getRightUpperVertex(eIt); if (rightUpperVertex==NULL) { OneDEntityImp<0> newRightUpperVertex(i+1, eIt->vertex_[1]->pos_, eIt->vertex_[1]->id_); rightUpperVertex = vertices(i+1).insert(centerVertexIterator->succ_, newRightUpperVertex); } eIt->vertex_[1]->son_ = rightUpperVertex; // /////////////////////// // Create new elements // /////////////////////// OneDEntityImp<1> newElement0(i+1, getNextFreeId(), reversedBoundarySegmentNumbering_); newElement0.vertex_[0] = leftUpperVertex; newElement0.vertex_[1] = centerVertexIterator; newElement0.father_ = eIt; newElement0.isNew_ = true; OneDEntityImp<1> newElement1(i+1, getNextFreeId(), reversedBoundarySegmentNumbering_); newElement1.vertex_[0] = centerVertexIterator; newElement1.vertex_[1] = rightUpperVertex; newElement1.father_ = eIt; newElement1.isNew_ = true; // Insert new elements into element list if (leftNeighbor!=NULL) // leftNeighbor exists eIt->sons_[0] = elements(i+1).insert(leftNeighbor->sons_[1]->succ_, newElement0); else // leftNeighbor does not exist eIt->sons_[0] = elements(i+1).insert(elements(i+1).begin(), newElement0); eIt->sons_[1] = elements(i+1).insert(eIt->sons_[0]->succ_, newElement1); // The grid has been modified refinedGrid = true; } } } // delete uppermost level if it doesn't contain elements anymore if (std::get<1>(entityImps_.back()).size()==0) { assert(std::get<0>(entityImps_.back()).size()==0); entityImps_.pop_back(); } // If the refinement mode is 'COPY', fill the empty slots in the grid // by copying elements if (refinementType_ == COPY) { for (int i=0; isucc_) { if (eIt->isLeaf()) { OneDGridList >::iterator leftNeighbor = getLeftNeighborWithSon(eIt); // Does the left vertex exist on the next-higher level? // If no create it OneDGridList >::iterator leftUpperVertex = getLeftUpperVertex(eIt); if (leftUpperVertex==NULL) { OneDEntityImp<0> newLeftUpperVertex(i+1, eIt->vertex_[0]->pos_, eIt->vertex_[0]->id_); // Insert new vertex into vertex list leftUpperVertex = vertices(i+1).insert((leftNeighbor) ? leftNeighbor->sons_[1]->vertex_[1]->succ_ : vertices(i+1).begin(), newLeftUpperVertex); } eIt->vertex_[0]->son_ = leftUpperVertex; // Does the right vertex exist on the next-higher level? // If no create it OneDGridList >::iterator rightUpperVertex = getRightUpperVertex(eIt); if (rightUpperVertex==NULL) { OneDEntityImp<0> newRightUpperVertex(i+1, eIt->vertex_[1]->pos_, eIt->vertex_[1]->id_); // Insert new vertex into list rightUpperVertex = vertices(i+1).insert(leftUpperVertex->succ_, newRightUpperVertex); } eIt->vertex_[1]->son_ = rightUpperVertex; // ///////////////////////// // Create new element // ///////////////////////// OneDEntityImp<1> newElement(i+1, eIt->id_, reversedBoundarySegmentNumbering_); newElement.vertex_[0] = leftUpperVertex; newElement.vertex_[1] = rightUpperVertex; newElement.father_ = eIt; newElement.isNew_ = true; // Insert new elements into element list OneDGridList >::iterator newElementIterator; if (leftNeighbor!=NULL) // leftNeighbor exists newElementIterator = elements(i+1).insert(leftNeighbor->sons_[1]->succ_, newElement); else // leftNeighbor does not exist newElementIterator = elements(i+1).insert(elements(i+1).begin(), newElement); // Mark the new element as the sons of the refined element eIt->sons_[0] = eIt->sons_[1] = newElementIterator; } } } } // //////////////////////////////////// // renumber vertices and elements // //////////////////////////////////// setIndices(); return refinedGrid; } bool Dune::OneDGrid::preAdapt() { for (const auto& element : Dune::elements(leafGridView())) if (element.impl().target_->markState_ == OneDEntityImp<1>::COARSEN) return true; return false; } void Dune::OneDGrid::postAdapt() { for (int i=0; i<=maxLevel(); i++) { OneDGridList >::iterator eIt; for (eIt = elements(i).begin(); eIt!=elements(i).end(); eIt = eIt->succ_) { eIt->isNew_ = false ; eIt->markState_ = OneDEntityImp<1>::DO_NOTHING; } } } void Dune::OneDGrid::setIndices() { // Add space for new LevelIndexSets if the grid hierarchy got higher // They are not created until they are actually requested for (int i=levelIndexSets_.size(); i *) 0 ); // Delete old LevelIndexSets if the grid hierarchy got lower int excess = levelIndexSets_.size() - (maxLevel() + 1); for (int i=0; iupdate(); leafIndexSet_.update(); // IdSets don't need updating } void Dune::OneDGrid::globalRefine(int refCount) { for (int i=0; ipreAdapt(); adapt(); this->postAdapt(); } } bool Dune::OneDGrid::mark(int refCount, const Codim<0>::Entity & e ) { // don't mark non-leaf entities if( ! e.isLeaf() ) return false ; if (refCount < 0) { if (e.impl().target_->level_ == 0) return false; else { e.impl().target_->markState_ = OneDEntityImp<1>::COARSEN; return true; } } else if (refCount > 0) e.impl().target_->markState_ = OneDEntityImp<1>::REFINE; else e.impl().target_->markState_ = OneDEntityImp<1>::DO_NOTHING; return true; } int Dune::OneDGrid::getMark(const Codim<0>::Entity & e ) const { if(e.impl().target_->markState_ == OneDEntityImp<1>::COARSEN) return -1; else if(e.impl().target_->markState_ == OneDEntityImp<1>::REFINE) return 1; return 0; } dune-grid-2.11.0/dune/grid/onedgrid/onedgridentity.hh000066400000000000000000000402051511655130300224760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_ENTITY_HH #define DUNE_ONE_D_GRID_ENTITY_HH #include #include #include #include #include "nulliteratorfactory.hh" /** \file * \brief The OneDGridEntity class and its specializations */ namespace Dune { // forward declarations template class OneDGridLeafIntersectionIterator; template class OneDGridLevelIntersectionIterator; template class OneDGridLevelIterator; template class OneDGridHierarchicIterator; template class OneDEntityImp {}; /** \brief Specialization for vertices */ template <> class OneDEntityImp<0> { public: OneDEntityImp(int level, double pos) : pos_(pos), levelIndex_(0), leafIndex_(0), level_(level), son_(OneDGridNullIteratorFactory<0>::null()), pred_(OneDGridNullIteratorFactory<0>::null()), succ_(OneDGridNullIteratorFactory<0>::null()) {} OneDEntityImp(int level, const FieldVector& pos, unsigned int id) : pos_(pos), levelIndex_(0), leafIndex_(0), id_(id), level_(level), son_(OneDGridNullIteratorFactory<0>::null()), pred_(OneDGridNullIteratorFactory<0>::null()), succ_(OneDGridNullIteratorFactory<0>::null()) {} //private: bool isLeaf() const { return son_==OneDGridNullIteratorFactory<0>::null(); } FieldVector pos_; //! entity number unsigned int levelIndex_; unsigned int leafIndex_; unsigned int id_; //! level int level_; //! Son vertex on the next finer grid OneDEntityImp<0>* son_; //! OneDEntityImp<0>* pred_; OneDEntityImp<0>* succ_; }; /** \brief Specialization for elements */ template <> class OneDEntityImp<1> { public: /** \brief The different ways to mark an element for grid changes */ enum MarkState { DO_NOTHING , COARSEN , REFINE }; OneDEntityImp(int level, unsigned int id, bool reversedBoundarySegmentNumbering) : levelIndex_(0), leafIndex_(0), id_(id), level_(level), markState_(DO_NOTHING), isNew_(false), reversedBoundarySegmentNumbering_(reversedBoundarySegmentNumbering), pred_(OneDGridNullIteratorFactory<1>::null()), succ_(OneDGridNullIteratorFactory<1>::null()) { father_ = OneDGridNullIteratorFactory<1>::null(); sons_[0] = sons_[1] = OneDGridNullIteratorFactory<1>::null(); } bool isLeaf() const { assert( (sons_[0]==OneDGridNullIteratorFactory<1>::null() && sons_[1]==OneDGridNullIteratorFactory<1>::null()) || (sons_[0]!=OneDGridNullIteratorFactory<1>::null() && sons_[1]!=OneDGridNullIteratorFactory<1>::null()) ); return sons_[0]==OneDGridNullIteratorFactory<1>::null() && sons_[1]==OneDGridNullIteratorFactory<1>::null(); } std::array*, 2> sons_; OneDEntityImp<1>* father_; OneDEntityImp<0>* vertex_[2]; //! element number unsigned int levelIndex_; unsigned int leafIndex_; /** \brief Unique and persistent id for elements */ unsigned int id_; //! the level of the entity int level_; /** \brief Stores requests for refinement and coarsening */ MarkState markState_; /** \brief This flag is set by adapt() if this element has been newly created. */ bool isNew_; /** Since a OneDGrid is one-dimensional and connected, there can only be two possible numberings of the boundary segments. Either the left one is '0' and the right one is '1' or the reverse. This flag stores which is the case. It has the same value throughout the entire grid. This is a waste, because the Intersections class (which hands out the information), can access data here much easier than data in the central grid class. */ bool reversedBoundarySegmentNumbering_; /** \brief Predecessor in the doubly linked list of elements */ OneDEntityImp<1>* pred_; /** \brief Successor in the doubly linked list of elements */ OneDEntityImp<1>* succ_; }; // forward declarations template class OneDGridLevelIndexSet; template class OneDGridLeafIndexSet; template class OneDGridIdSet; //********************************************************************** // // --OneDGridEntity // --Entity // /** \brief The implementation of entities in a OneDGrid \ingroup OneDGrid A Grid is a container of grid entities. An entity is parametrized by the codimension. An entity of codimension c in dimension d is a d-c dimensional object. */ template class OneDGridEntity : public EntityDefaultImplementation { template friend class OneDGridLevelIterator; friend class OneDGrid; // IndexSets and IdSets need to access indices and ids friend class OneDGridLevelIndexSet; friend class OneDGridLeafIndexSet; friend class OneDGridIdSet; typedef typename GridImp::Traits::template Codim< cd >::GeometryImpl GeometryImpl; public: /** \brief The type of OneDGrid Entity seeds */ typedef typename GridImp::Traits::template Codim::EntitySeed EntitySeed; //! Default constructor OneDGridEntity() : target_(OneDGridNullIteratorFactory<0>::null()) {} explicit OneDGridEntity(OneDEntityImp<0>* target) : target_(target) {} typedef typename GridImp::template Codim::Geometry Geometry; bool equals(const OneDGridEntity& other) const { return target_ == other.target_; } //! level of this element int level () const {return target_->level_;} //! only interior entities PartitionType partitionType () const { return InteriorEntity; } private: unsigned int levelIndex() const {return target_->levelIndex_;} unsigned int leafIndex() const {return target_->leafIndex_;} unsigned int globalId() const {return target_->id_;} /** \brief Returns vertex level index, the arguments are ignored */ int subLevelIndex ([[maybe_unused]] int i, [[maybe_unused]] unsigned int codim) const { return target_->levelIndex_; } /** \brief Returns vertex leaf index, the arguments are ignored */ int subLeafIndex ([[maybe_unused]] int i, [[maybe_unused]] unsigned int codim) const { return target_->leafIndex_; } public: //! return the element type identifier (segment) GeometryType type () const {return GeometryTypes::vertex;} /** \brief Return the number of subentities of codimension codim. */ unsigned int subEntities (unsigned int codim) const { assert(codim==1); return 1; } //! geometry of this entity Geometry geometry () const { return Geometry(GeometryImpl(target_->pos_)); } /** \brief Get the seed corresponding to this entity */ EntitySeed seed () const { return EntitySeed( *this ); } void setToTarget(OneDEntityImp<0>* target) { target_ = target; } OneDEntityImp<0>* target_; }; //*********************** // // --OneDGridEntity // --0Entity // //*********************** /** \brief Specialization for codim-0-entities. * \ingroup OneDGrid * * This class embodies the topological parts of elements of the grid. * It has an extended interface compared to the general entity class. * For example, Entities of codimension 0 allow to visit all neighbors. * * OneDGrid only implements the case dim==dimworld==1 */ template class OneDGridEntity<0,dim, GridImp> : public EntityDefaultImplementation<0,dim,GridImp, OneDGridEntity> { friend class OneDGrid; template friend class OneDGridLevelIntersectionIterator; template friend class OneDGridLeafIntersectionIterator; friend class OneDGridHierarchicIterator ; friend class OneDGridLevelIterator <0,All_Partition,GridImp>; // IndexSets and IdSets need to access indices and ids friend class OneDGridLevelIndexSet; friend class OneDGridLeafIndexSet; friend class OneDGridIdSet; typedef typename GridImp::Traits::template Codim< 0 >::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim< 0 >::GeometryImpl LocalGeometryImpl; public: typedef typename GridImp::template Codim<0>::Geometry Geometry; typedef typename GridImp::template Codim<0>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::LevelIterator LevelIterator; typedef typename GridImp::LeafIntersectionIterator LeafIntersectionIterator; typedef typename GridImp::LevelIntersectionIterator LevelIntersectionIterator; typedef typename GridImp::HierarchicIterator HierarchicIterator; /** \brief The type of OneDGrid Entity seeds */ typedef typename GridImp::Traits::template Codim<0>::EntitySeed EntitySeed; template struct Codim { typedef typename GridImp::Traits::template Codim::Entity Entity; }; typedef typename GridImp::Traits::template Codim<0>::Entity Entity; //! Default Constructor OneDGridEntity () : target_( OneDGridNullIteratorFactory<1>::null() ) {} explicit OneDGridEntity (OneDEntityImp<1>* target) : target_( target ) {} bool equals(const OneDGridEntity& other) const { return target_ == other.target_; } //! Level of this element int level () const {return target_->level_;} //! only interior entities PartitionType partitionType () const { return InteriorEntity; } private: //! Level index is unique and consecutive per level and codim unsigned int levelIndex() const {return target_->levelIndex_;} unsigned int leafIndex() const {return target_->leafIndex_;} unsigned int globalId() const {return target_->id_;} public: //! Geometry of this entity Geometry geometry () const { return Geometry( GeometryImpl(target_->vertex_[0]->pos_, target_->vertex_[1]->pos_) ); } /** \brief Get the seed corresponding to this entity */ EntitySeed seed () const { return EntitySeed( *this ); } //! return the element type identifier (segment) GeometryType type () const {return GeometryTypes::line;} /** \brief Return the number of subentities of codimension codim. */ unsigned int subEntities (unsigned int codim) const { assert(codim==0 || codim==1); return (codim==0) ? 1 : 2; } private: /** \brief Return index of sub entity with codim = cc and local number i */ int subLevelIndex (int i,unsigned int codim) const { assert(i==0 || i==1); return (codim==0) ? target_->levelIndex_ : target_->vertex_[i]->levelIndex_; } /** \brief Return leaf index of sub entity with codim = cc and local number i */ int subLeafIndex (int i, unsigned int codim) const { assert(i==0 || i==1); return (codim==0) ? target_->leafIndex_ : target_->vertex_[i]->leafIndex_; } /** \brief Return leaf index of sub entity with codim = cc and local number i */ int subId (int i, unsigned int codim) const { assert(i==0 || i==1); return (codim==0) ? target_->id_ : target_->vertex_[i]->id_; } public: /** \brief Access to codim 0 subentities */ template typename std::enable_if< cc == 0, typename Codim<0>::Entity >::type subEntity (int i) const { assert(i==0); return typename Codim<0>::Entity(OneDGridEntity<0,dim,GridImp>(this->target_)); } /** \brief Access to codim 1 subentities */ template typename std::enable_if< cc == 1, typename Codim<1>::Entity >::type subEntity (int i) const { assert(i==0 || i==1); return typename Codim<1>::Entity(OneDGridEntity<1,dim,GridImp>(this->target_->vertex_[i])); } LeafIntersectionIterator ileafbegin () const { return OneDGridLeafIntersectionIterator(target_, (isLeaf()) ? 0 : 2); } LevelIntersectionIterator ilevelbegin () const { return OneDGridLevelIntersectionIterator(target_, 0); } LeafIntersectionIterator ileafend () const { return OneDGridLeafIntersectionIterator(target_); } LevelIntersectionIterator ilevelend () const { return OneDGridLevelIntersectionIterator(target_); } //! returns true if Entity has no children bool isLeaf () const { return (target_->sons_[0]==OneDGridNullIteratorFactory<1>::null()) && (target_->sons_[1]==OneDGridNullIteratorFactory<1>::null()); } //! Inter-level access to father element on coarser grid. //! Assumes that meshes are nested. Entity father () const { return Entity(OneDGridEntity(target_->father_)); } //! returns true if father entity exists bool hasFather () const { return (this->level()>0); } /*! Location of this element relative to the reference element of the father. This is sufficient to interpolate all dofs in conforming case. Nonconforming may require access to neighbors of father and computations with local coordinates. On the fly case is somewhat inefficient since dofs are visited several times. If we store interpolation matrices, this is tolerable. We assume that on-the-fly implementation of numerical algorithms is only done for simple discretizations. Assumes that meshes are nested. */ LocalGeometry geometryInFather () const { assert(target_->father_); assert(target_->father_->sons_[0] == target_ || target_->father_->sons_[1] == target_); if (target_->father_->sons_[0] == target_ && target_->father_->sons_[1] == target_) { // Copied element? return LocalGeometry(LocalGeometryImpl(FieldVector(0), FieldVector(1))); } else if (target_->father_->sons_[0] == target_) { // Left son? return LocalGeometry(LocalGeometryImpl(FieldVector(0), FieldVector(0.5))); } // Right son! return LocalGeometry(LocalGeometryImpl(FieldVector(0.5), FieldVector(1))); } /*! Inter-level access to son elements on higher levels<=maxlevel. This is provided for sparsely stored nested unstructured meshes. Returns iterator to first son. */ OneDGridHierarchicIterator hbegin (int maxlevel) const { OneDGridHierarchicIterator it(maxlevel); if (level()<=maxlevel) { // Load sons of old target onto the iterator stack if (!isLeaf()) { it.elemStack.push(target_->sons_[0]); it.elemStack.push(target_->sons_[1]); } } it.virtualEntity_.impl().setToTarget((it.elemStack.empty()) ? OneDGridNullIteratorFactory<1>::null() : it.elemStack.top()); return it; } //! Returns iterator to one past the last son HierarchicIterator hend (int maxlevel) const { return HierarchicIterator(maxlevel); } // *************************************************************** // Interface for Adaptation // *************************************************************** /** returns true, if entity might be coarsened during next adaptation cycle */ bool mightVanish () const { return target_->markState_ == OneDEntityImp<1> :: COARSEN; } /** returns true, if entity was refined during last adaptation cycle */ bool isNew () const { return target_->isNew_; } void setToTarget(OneDEntityImp<1>* target) { target_ = target; } OneDEntityImp<1>* target_; }; // end of OneDGridEntity codim = 0 } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridentityseed.hh000066400000000000000000000027041511655130300233410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_ENTITY_SEED_HH #define DUNE_ONE_D_GRID_ENTITY_SEED_HH #include "onedgridentity.hh" /** \file * \brief Implementation of EntitySeed for the OneDGrid grid manager */ namespace Dune { /** \brief Store a reference to an entity with a minimal memory footprint */ template class OneDGridEntitySeed { // grid dimension constexpr static int dim = GridImp::dimension; public: constexpr static int codimension = codim; //! default construct an invalid entity seed OneDGridEntitySeed () : target_(nullptr) {} //! construct entity seed from entity OneDGridEntitySeed (const OneDGridEntity& entity) : target_(entity.target_) {} //! check whether the EntitySeed refers to a valid Entity bool isValid() const { return target_ != nullptr; } /** \brief Access to the underlying OneDGrid data structure */ OneDEntityImp* target() const { return target_; } private: /** \brief Plain old pointer to the corresponding OneDGrid data structure */ OneDEntityImp* target_; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridfactory.cc000066400000000000000000000136041511655130300226220ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include namespace Dune { GridFactory:: GridFactory() : factoryOwnsGrid_(true), vertexIndex_(0) { grid_ = new OneDGrid; createBegin(); } GridFactory:: GridFactory(OneDGrid* grid) : factoryOwnsGrid_(false), vertexIndex_(0) { grid_ = grid; createBegin(); } GridFactory:: ~GridFactory() { if (grid_ && factoryOwnsGrid_) delete grid_; } void GridFactory:: insertVertex(const Dune::FieldVector::ctype,1>& pos) { vertexPositions_.insert(std::make_pair(pos, vertexIndex_++)); } void GridFactory:: insertElement(const GeometryType& type, const std::vector& vertices) { if (type.dim() != 1) DUNE_THROW(GridError, "You cannot insert a " << type << " into a OneDGrid!"); if (vertices.size() != 2) DUNE_THROW(GridError, "You cannot insert an element with " << vertices.size() << " vertices into a OneDGrid!"); elements_.push_back(std::array()); elements_.back()[0] = vertices[0]; elements_.back()[1] = vertices[1]; } void GridFactory:: insertBoundarySegment(const std::vector& vertices) { if (vertices.size() != 1) DUNE_THROW(GridError, "OneDGrid BoundarySegments must have exactly one vertex."); boundarySegments_.push_back(vertices[0]); } void GridFactory:: insertBoundarySegment(const std::vector& vertices, const std::shared_ptr > & /* boundarySegment */) { insertBoundarySegment(vertices); } bool GridFactory:: wasInserted(const typename OneDGrid::LeafIntersection& intersection) const { bool inserted(false); const auto vtx(intersection.geometry().center()[0]); for(const auto& idx : boundarySegments_) if(std::abs(vertexPositionsByIndex_[idx]-vtx)<1.e-12) { inserted=true; break; } return inserted; } unsigned int GridFactory:: insertionIndex(const typename OneDGrid::LeafIntersection& intersection) const { unsigned int insertionIdx(0); const auto vtx(intersection.geometry().center()[0]); for(const auto& idx : boundarySegments_) if(std::abs(vertexPositionsByIndex_[idx]-vtx)<1.e-12) break; else ++insertionIdx; return insertionIdx; } std::unique_ptr GridFactory:: createGrid() { // Prevent a crash when this method is called twice in a row // You never know who may do this... if (grid_==nullptr) return nullptr; // Assert that vertices are given assert (vertexPositions_.size() > 0); // Insert the vertices into the grid grid_->entityImps_.resize(1); for (const auto& vtx : vertexPositions_) { OneDEntityImp<0> newVertex(0, vtx.first, grid_->getNextFreeId()); newVertex.leafIndex_ = vtx.second; newVertex.levelIndex_ = vtx.second; grid_->vertices(0).push_back(newVertex); } // Fill the vector with the vertex positions accessible by index vertexPositionsByIndex_.resize(vertexPositions_.size()); for (const auto& vtx : vertexPositions_) vertexPositionsByIndex_[vtx.second] = vtx.first; // Set the numbering of the boundary segments if (boundarySegments_.size() > 2) DUNE_THROW(GridError, "You cannot provide more than two boundary segments to a OneDGrid (it must be connected)."); if (boundarySegments_.size() > 1 && vertexPositionsByIndex_[boundarySegments_[0]] > vertexPositions_.begin()->first[0]) grid_->reversedBoundarySegmentNumbering_ = true; // /////////////////////////////////////////////////////////////////// // Insert the elements into the grid // // This is a 1d grid and it has to be connected. Hence we actually // know where the elements are, even without being told explicitly. // The only thing of interest are the indices. // /////////////////////////////////////////////////////////////////// // First sort elements by increasing position. That is how they are expected in the grid data structure std::map, unsigned int> > elementsByPosition; for (std::size_t i=0; i(grid_->entityImps_[0]).begin(); auto eIt = elementsByPosition.begin(); // Looping over the vertices to get all elements assumes that the grid is connected for (size_t i=0; i newElement(0, grid_->getNextFreeId(), grid_->reversedBoundarySegmentNumbering_); newElement.vertex_[0] = it; it = it->succ_; newElement.vertex_[1] = it; newElement.levelIndex_ = eIt->second.second; newElement.leafIndex_ = eIt->second.second; grid_->elements(0).push_back(newElement); } // Create the index sets grid_->levelIndexSets_.resize(1); grid_->levelIndexSets_[0] = new OneDGridLevelIndexSet(*grid_, 0); grid_->levelIndexSets_[0]->setSizesAndTypes(vertexPositions_.size(), elements_.size()); grid_->leafIndexSet_.setSizesAndTypes(vertexPositions_.size(), elements_.size()); // Hand over the grid and delete the member pointer auto tmp = grid_; grid_ = nullptr; return std::unique_ptr(tmp); } void GridFactory:: createBegin() { vertexPositions_.clear(); } } // namespace Dune dune-grid-2.11.0/dune/grid/onedgrid/onedgridfactory.hh000066400000000000000000000101341511655130300226270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONEDGRID_FACTORY_HH #define DUNE_ONEDGRID_FACTORY_HH /** \file \brief The specialization of the generic GridFactory for OneDGrid \author Oliver Sander */ #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \brief Specialization of the generic GridFactory for OneDGrid */ template <> class GridFactory : public GridFactoryInterface { typedef GridFactoryInterface Base; /** \brief Type used by the grid for coordinates */ typedef OneDGrid::ctype ctype; public: // use default implementation from base class using Base::insertionIndex; /** \brief Default constructor */ GridFactory(); /** \brief Constructor for a given grid object If you already have your grid object constructed you can hand it over using this constructor. If you construct your factory class using this constructor the pointer handed over to you by the method createGrid() is the one you supplied here. */ GridFactory(OneDGrid* grid); /** \brief Destructor */ ~GridFactory(); /** \brief Insert a vertex into the coarse grid */ virtual void insertVertex(const FieldVector& pos); /** \brief Insert an element into the coarse grid \param type The GeometryType of the new element \param vertices The vertices of the new element, using the DUNE numbering */ virtual void insertElement(const GeometryType& type, const std::vector& vertices); /** \brief Insert a boundary segment (== a point). This influences the ordering of the boundary segments */ virtual void insertBoundarySegment(const std::vector& vertices); /** \brief Insert a boundary segment (== a point) and the boundary segment geometry * This influences the ordering of the boundary segments. The BoundarySegment object does not actually have any effect. */ virtual void insertBoundarySegment(const std::vector& vertices, const std::shared_ptr >& boundarySegment); /** \brief Return true if the intersection has been explicitly inserted into the factory */ virtual bool wasInserted(const typename OneDGrid::LeafIntersection& intersection) const; /** \brief Return the number of the intersection in the order of insertion into the factory */ virtual unsigned int insertionIndex(const typename OneDGrid::LeafIntersection& intersection) const; /** \brief Finalize grid creation and hand over the grid The receiver takes responsibility of the memory allocated for the grid */ virtual std::unique_ptr createGrid(); private: // Initialize the grid structure in UG void createBegin(); // Pointer to the grid being built OneDGrid* grid_; // True if the factory allocated the grid itself, false if the // grid was handed over from the outside bool factoryOwnsGrid_; /** \brief While inserting the elements this array records the vertices of the elements. */ std::vector > elements_; /** \brief Buffer the vertices until createGrid() is called */ std::map, unsigned int > vertexPositions_; /** \brief Counter that creates the vertex indices */ unsigned int vertexIndex_; /** \brief Store the explicitly given boundary segments until createGrid() is called */ std::vector boundarySegments_; /** \brief Store vertex positions sorted by index */ std::vector vertexPositionsByIndex_; }; } #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridhieriterator.hh000066400000000000000000000053701511655130300236670ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_HIERITERATOR_HH #define DUNE_ONE_D_GRID_HIERITERATOR_HH /** \file * \brief The OneDGridHierarchicIterator class */ #include namespace Dune { //********************************************************************** // // --OneDGridHierarchicIterator // --HierarchicIterator /** \brief Iterator over the descendants of an entity. * \ingroup OneDGrid Mesh entities of codimension 0 ("elements") allow to visit all entities of codimension 0 obtained through nested, hierarchic refinement of the entity. Iteration over this set of entities is provided by the HierarchicIterator, starting from a given entity. */ template class OneDGridHierarchicIterator { constexpr static int dim = GridImp::dimension; friend class OneDGridEntity<0,dim,GridImp>; // Stack entry typedef OneDGridList >::iterator StackEntry; public: typedef typename GridImp::template Codim<0>::Entity Entity; //! We iterating only over elements constexpr static int codimension = 0; //! Constructor OneDGridHierarchicIterator(int maxlevel) : maxlevel_(maxlevel), elemStack() {} //! prefix increment void increment() { if (elemStack.empty()) return; StackEntry old_target = elemStack.top(); elemStack.pop(); // Traverse the tree no deeper than maxlevel if (old_target->level_ < maxlevel_) { // Load sons of old target onto the iterator stack if (!old_target->isLeaf()) { elemStack.push(old_target->sons_[0]); // Add the second son only if it is different from the first one // i.e. the son is not just a copy of the father if (old_target->sons_[0] != old_target->sons_[1]) elemStack.push(old_target->sons_[1]); } } this->virtualEntity_.impl().setToTarget((elemStack.empty()) ? OneDGridNullIteratorFactory<1>::null() : elemStack.top()); } //! dereferencing const Entity& dereference() const {return virtualEntity_;} //! equality bool equals(const OneDGridHierarchicIterator& other) const { return virtualEntity_ == other.virtualEntity_; } private: //! The entity that the iterator is pointing to Entity virtualEntity_; //! max level to go down int maxlevel_; std::stack elemStack; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridindexsets.hh000066400000000000000000000211461511655130300231730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONEDGRID_INDEXSETS_HH #define DUNE_ONEDGRID_INDEXSETS_HH /** \file \brief The index and id sets for the OneDGrid class */ #include #include #include #include namespace Dune { template class OneDGridLevelIndexSet : public IndexSet,unsigned int,std::array > { public: /** \brief Constructor for a given level of a given grid */ OneDGridLevelIndexSet (const GridImp& grid, int level) : grid_(&grid), level_(level) {} //! get index of an entity template int index (const typename GridImp::Traits::template Codim::Entity& e) const { return e.impl().levelIndex(); } //! get index of subentity of an entity template unsigned int subIndex (const typename GridImp::Traits::template Codim::Entity& e, int i, unsigned int codim) const { return e.impl().subLevelIndex(i,codim); } //! get number of entities of given type and on this level std::size_t size (GeometryType type) const { return grid_->size(level_,type); } //! get number of entities of given codim, type and on this level std::size_t size (int codim) const { return grid_->size(level_,codim); } //! obtain all geometry types of entities in domain static constexpr std::array types (int codim) { return { GeometryTypes::cube(1-codim) }; } /** \brief Return true if e is contained in the index set. \warning This implementation takes O(n) time! It also assumes that e belongs to the correct grid. */ template bool contains (const EntityType& e) const { // If the entity isn't on the same level as this index set it cannot be contained in the index set if (e.level() != level_) return false; constexpr static int cd = EntityType::codimension; typedef typename GridImp::template Codim::template Partition::LevelIterator IteratorType; IteratorType iend = grid_->levelGridView(level_).template end(); for (IteratorType it = grid_->levelGridView(level_).template begin(); it != iend; ++it) { if (this->template index(*it) == this->template index(e)) return true; } return false; } /** \brief Sets the corresponding internal fields. Used by the GridFactory */ void setSizesAndTypes(unsigned int numVertices, unsigned int numElements) { numVertices_ = numVertices; numElements_ = numElements; } /** \todo Should be private */ void update() { // /////////////////////////////// // Init the element indices // /////////////////////////////// numElements_ = 0; OneDGridList >::const_iterator eIt; for (eIt = grid_->elements(level_).begin(); eIt != grid_->elements(level_).end(); eIt = eIt->succ_) /** \todo Remove this const cast */ const_cast*>(eIt)->levelIndex_ = numElements_++; // ////////////////////////////// // Init the vertex indices // ////////////////////////////// numVertices_ = 0; OneDGridList >::const_iterator vIt; for (vIt = grid_->vertices(level_).begin(); vIt != grid_->vertices(level_).end(); vIt = vIt->succ_) /** \todo Remove this const cast */ const_cast*>(vIt)->levelIndex_ = numVertices_++; // set the list of geometry types setSizesAndTypes(numVertices_, numElements_); } private: const GridImp* grid_; int level_; int numElements_; int numVertices_; }; template class OneDGridLeafIndexSet : public IndexSet,unsigned int,std::array > { public: //! constructor stores reference to a grid and level OneDGridLeafIndexSet (const GridImp& g) : grid_(g) {} //! get index of an entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template int index (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { return e.impl().leafIndex(); } //! get index of subentity of an entity template int subIndex (const typename std::remove_const::type::Traits::template Codim::Entity& e, int i, unsigned int codim) const { return e.impl().subLeafIndex(i,codim); } //! get number of entities of given codim, type on the leaf level std::size_t size (GeometryType type) const { if (type.isVertex()) { return numVertices_; } else if (type.isLine()) { return numElements_; } return 0; } //! get number of entities of given codim, type on the leaf level std::size_t size(int codim) const { if (codim==1) { return numVertices_; } else if (codim==0) { return numElements_; } return 0; } //! obtain all geometry types of entities in domain static constexpr std::array types (int codim) { return { GeometryTypes::cube(1-codim) }; } /** \brief Return true if e is contained in the index set. Warning: this implementation takes O(n) time! It also assumes that e belongs to the correct grid. */ template bool contains (const EntityType& e) const { constexpr static int cd = EntityType::codimension; for (const auto& entity : entities(grid_.leafGridView(), Codim())) { if (entity.level() == e.level() && this->template index(entity) == this->template index(e)) return true; } return false; } /** \brief Sets the corresponding internal fields. Used by the GridFactory */ void setSizesAndTypes(unsigned int numVertices, unsigned int numElements) { numVertices_ = numVertices; numElements_ = numElements; } /** \todo Should be private */ void update() { // /////////////////////////////// // Init the element indices // /////////////////////////////// numElements_ = 0; for (const auto& element : elements(grid_.leafGridView())) element.impl().target_->leafIndex_ = numElements_++; // ////////////////////////////// // Init the vertex indices // ////////////////////////////// numVertices_ = 0; for (int i=grid_.maxLevel(); i>=0; i--) { const OneDEntityImp<0>* vIt; for (vIt = grid_.vertices(i).begin(); vIt != grid_.vertices(i).end(); vIt = vIt->succ_) { /** \todo Remove the const casts */ if (vIt->isLeaf()) const_cast*>(vIt)->leafIndex_ = numVertices_++; else const_cast*>(vIt)->leafIndex_ = vIt->son_->leafIndex_; } } // set the list of geometry types setSizesAndTypes(numVertices_, numElements_); } private: const GridImp& grid_; int numElements_; int numVertices_; }; template class OneDGridIdSet : public IdSet,unsigned int> { public: //! define the type used for persistent indices typedef unsigned int IdType; //! constructor stores reference to a grid OneDGridIdSet (const GridImp& g) : grid_(g) {} //! get id of an entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template IdType id (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { return e.impl().globalId(); } //! get id of subentity IdType subId (const typename std::remove_const::type::Traits::template Codim<0>::Entity& e, int i, unsigned int codim) const { return e.impl().subId(i,codim); } private: const GridImp& grid_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridintersectioniterators.hh000066400000000000000000000064471511655130300256370ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_INTERSECTION_ITERATORS_HH #define DUNE_ONE_D_GRID_INTERSECTION_ITERATORS_HH /** \file * \brief The OneDGridLevelIntersectionIterator and OneDGridLeafIntersectionIterator classes */ #include namespace Dune { /** \brief The iterator over level intersections */ template class OneDGridLevelIntersectionIterator { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; friend class OneDGridEntity<0,dim,GridImp>; template friend class Dune::IntersectionIterator; OneDGridLevelIntersectionIterator() {} //! Constructor for a given grid entity and a given neighbor OneDGridLevelIntersectionIterator(OneDEntityImp<1>* center, int nb) : intersection_(OneDGridLevelIntersection(center,nb)) {} /** \brief Constructor creating the 'one-after-last'-iterator */ OneDGridLevelIntersectionIterator(OneDEntityImp<1>* center) : intersection_(OneDGridLevelIntersection(center)) {} public: typedef Dune::Intersection< GridImp, Dune::OneDGridLevelIntersection< GridImp > > Intersection; //! equality bool equals(const OneDGridLevelIntersectionIterator& other) const { return intersection_.impl().equals(other.intersection_.impl()); } //! prefix increment void increment() { intersection_.impl().neighbor_++; } //! \brief dereferencing const Intersection & dereference() const { return intersection_; } private: Intersection intersection_; }; /** \brief Iterator over OneDGrid leaf intersections */ template class OneDGridLeafIntersectionIterator { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; friend class OneDGridEntity<0,dim,GridImp>; template friend class Dune::IntersectionIterator; OneDGridLeafIntersectionIterator() {} //! Constructor for a given grid entity and a given neighbor OneDGridLeafIntersectionIterator(OneDEntityImp<1>* center, int nb) : intersection_(OneDGridLeafIntersection(center,nb)) {} /** \brief Constructor creating the 'one-after-last'-iterator */ OneDGridLeafIntersectionIterator(OneDEntityImp<1>* center) : intersection_(OneDGridLeafIntersection(center)) {} public: typedef Dune::Intersection< GridImp, Dune::OneDGridLeafIntersection< GridImp > > Intersection; //! equality bool equals(const OneDGridLeafIntersectionIterator& other) const { return intersection_.impl().equals(other.intersection_.impl()); } //! prefix increment void increment() { intersection_.impl().neighbor_++; } //! \brief dereferencing const Intersection & dereference() const { return intersection_; } private: Intersection intersection_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridintersections.hh000066400000000000000000000375021511655130300240610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_INTERSECTIONS_HH #define DUNE_ONE_D_GRID_INTERSECTIONS_HH /** \file * \brief The OneDGridLevelIntersection and OneDGridLeafIntersection classes */ #include namespace Dune { /** \brief Intersection between two neighboring elements on a level grid */ template class OneDGridLevelIntersection { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; // The corresponding iterator needs to access all members friend class OneDGridLevelIntersectionIterator; template friend class Intersection; OneDGridLevelIntersection() : center_(nullptr) , neighbor_(-1) // marker for invalid intersection {} //! Constructor for a given grid entity and a given neighbor OneDGridLevelIntersection(OneDEntityImp<1>* center, int nb) : center_(center), neighbor_(nb) {} /** \brief Constructor creating the 'one-after-last'-iterator */ OneDGridLevelIntersection(OneDEntityImp<1>* center) : center_(center), neighbor_(2) {} typedef typename GridImp::Traits::template Codim< 1 >::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim< 1 >::LocalGeometryImpl LocalGeometryImpl; public: typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::Entity Entity; //! equality bool equals(const OneDGridLevelIntersection& other) const { return (center_ == other.center_) && (neighbor_ == other.neighbor_); } OneDEntityImp<1>* target() const { const bool isValid = center_ && neighbor_>=0 && neighbor_<2; if (!isValid) return center_; else if (neighbor_==0) return center_->pred_; else return center_->succ_; } //! return true if intersection is with boundary. bool boundary () const { // Check whether we're on the left boundary if (neighbor_==0) { // If there's an element to the left we can't be on the boundary if (center_->pred_) return false; const OneDEntityImp<1>* ancestor = center_; while (ancestor->level_!=0) { // Check if we're the left son of our father if (ancestor != ancestor->father_->sons_[0]) return false; ancestor = ancestor->father_; } // We have reached level 0. If there is no element of the left // we're truly on the boundary return !ancestor->pred_; } // //////////////////////////////// // Same for the right boundary // //////////////////////////////// // If there's an element to the right we can't be on the boundary if (center_->succ_) return false; const OneDEntityImp<1>* ancestor = center_; while (ancestor->level_!=0) { // Check if we're the left son of our father if (ancestor != ancestor->father_->sons_[1]) return false; ancestor = ancestor->father_; } // We have reached level 0. If there is no element of the left // we're truly on the boundary return !ancestor->succ_; } //! return true if across the edge a neighbor on this level exists bool neighbor () const { assert(neighbor_ >= 0 && neighbor_ < 2); return (neighbor_==0) ? center_->pred_ && center_->pred_->vertex_[1] == center_->vertex_[0] : center_->succ_ && center_->succ_->vertex_[0] == center_->vertex_[1]; } //! return true if intersection is conform. bool conforming () const { return true; } //! return the Entity on the inside of this intersection //! (that is the Entity where we started this Iterator) Entity inside() const { return Entity(OneDGridEntity<0,dim,GridImp>(center_)); } //! return the Entity on the outside of this intersection //! (that is the neighboring Entity) Entity outside() const { assert(neighbor()); return Entity(OneDGridEntity<0,dim,GridImp>(target())); } //! return index of the boundary segment int boundarySegmentIndex () const { // It is hardwired here that the domain is connected, i.e., the boundary consists of two points return ((neighbor_==0 && center_->reversedBoundarySegmentNumbering_==false) || (neighbor_==1 && center_->reversedBoundarySegmentNumbering_==true)) ? 0 : 1; } //! Here returned element is in LOCAL coordinates of the element //! where iteration started. LocalGeometry geometryInInside () const { return LocalGeometry( LocalGeometryImpl( (indexInInside() == 0) ? 0 : 1 ) ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in LOCAL coordinates of neighbor LocalGeometry geometryInOutside () const { return LocalGeometry( LocalGeometryImpl( (indexInInside() == 0) ? 1 : 0 ) ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in GLOBAL coordinates of the element where iteration started. Geometry geometry () const { return Geometry( GeometryImpl( center_->vertex_[neighbor_]->pos_ ) ); } /** \brief obtain the type of reference element for this intersection */ GeometryType type () const { return GeometryTypes::vertex; } //! local index of codim 1 entity in self where intersection is contained in int indexInInside () const { return neighbor_; } //! local index of codim 1 entity in neighbor where intersection is contained int indexInOutside () const { // If numberInSelf is 0 then numberInNeighbor is 1 and vice versa return 1-neighbor_; } //! return outer normal FieldVector outerNormal ([[maybe_unused]] const FieldVector& local ) const { return centerUnitOuterNormal(); } //! Return outer normal scaled with the integration element FieldVector integrationOuterNormal ([[maybe_unused]] const FieldVector& local ) const { return centerUnitOuterNormal(); } //! return unit outer normal FieldVector unitOuterNormal ([[maybe_unused]] const FieldVector& local ) const { return centerUnitOuterNormal(); } //! return unit outer normal at center of intersection FieldVector centerUnitOuterNormal () const { return FieldVector(2 * neighbor_ - 1); } private: //********************************************************** // private methods //********************************************************** OneDEntityImp<1>* center_; /** \brief Count on which neighbor we are lookin' at. Can be only 0 or 1. */ int neighbor_; }; /** \brief Intersection between two neighboring elements on a leaf grid */ template class OneDGridLeafIntersection { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; // The corresponding iterator needs to access all members friend class OneDGridLeafIntersectionIterator; template friend class Intersection; OneDGridLeafIntersection() : center_(nullptr) , neighbor_(-1) // marker for invalid intersection {} //! Constructor for a given grid entity and a given neighbor OneDGridLeafIntersection(OneDEntityImp<1>* center, int nb) : center_(center), neighbor_(nb) {} /** \brief Constructor creating the 'one-after-last'-iterator */ OneDGridLeafIntersection(OneDEntityImp<1>* center) : center_(center), neighbor_(2) {} typedef typename GridImp::Traits::template Codim< 1 >::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim< 1 >::LocalGeometryImpl LocalGeometryImpl; public: typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::Entity Entity; //! equality bool equals(const OneDGridLeafIntersection& other) const { return (center_ == other.center_) && (neighbor_ == other.neighbor_); } OneDEntityImp<1>* target() const { const bool isValid = center_ && neighbor_>=0 && neighbor_<2; if (!isValid) return center_; if (neighbor_==0) { // Get left leaf neighbor if (center_->pred_ && center_->pred_->vertex_[1] == center_->vertex_[0]) { OneDEntityImp<1>* leftLeafNeighbor = center_->pred_; while (!leftLeafNeighbor->isLeaf()) { assert (leftLeafNeighbor->sons_[1] != NULL); leftLeafNeighbor = leftLeafNeighbor->sons_[1]; } return leftLeafNeighbor; } else { OneDEntityImp<1>* ancestor = center_; while (ancestor->father_) { ancestor = ancestor->father_; if (ancestor->pred_ && ancestor->pred_->vertex_[1] == ancestor->vertex_[0]) { assert(ancestor->pred_->isLeaf()); return ancestor->pred_; } } DUNE_THROW(GridError, "Programming error, apparently we're on the left boundary, neighbor_==2 should not occur!"); } } else { // Get right leaf neighbor if (center_->succ_ && center_->succ_->vertex_[0] == center_->vertex_[1]) { OneDEntityImp<1>* rightLeafNeighbor = center_->succ_; while (!rightLeafNeighbor->isLeaf()) { assert (rightLeafNeighbor->sons_[0] != NULL); rightLeafNeighbor = rightLeafNeighbor->sons_[0]; } return rightLeafNeighbor; } else { OneDEntityImp<1>* ancestor = center_; while (ancestor->father_) { ancestor = ancestor->father_; if (ancestor->succ_ && ancestor->succ_->vertex_[0] == ancestor->vertex_[1]) { assert(ancestor->succ_->isLeaf()); return ancestor->succ_; } } DUNE_THROW(GridError, "Programming error, apparently we're on the right boundary, neighbor_==3 should not occur!"); } } } //! return true if intersection is with boundary. bool boundary () const { // Check whether we're on the left boundary if (neighbor_==0) { // If there's an element to the left we can't be on the boundary if (center_->pred_) return false; const OneDEntityImp<1>* ancestor = center_; while (ancestor->level_!=0) { // Check if we're the left son of our father if (ancestor != ancestor->father_->sons_[0]) return false; ancestor = ancestor->father_; } // We have reached level 0. If there is no element of the left // we're truly on the boundary return !ancestor->pred_; } // //////////////////////////////// // Same for the right boundary // //////////////////////////////// // If there's an element to the right we can't be on the boundary if (center_->succ_) return false; const OneDEntityImp<1>* ancestor = center_; while (ancestor->level_!=0) { // Check if we're the left son of our father if (ancestor != ancestor->father_->sons_[1]) return false; ancestor = ancestor->father_; } // We have reached level 0. If there is no element of the left // we're truly on the boundary return !ancestor->succ_; } //! return true if across the edge an neighbor on this level exists bool neighbor () const { return !boundary(); } //! return true if intersection is conform. bool conforming () const { return true; } //! return Entity on the inside of this intersection //! (that is the Entity where we started this Iterator) Entity inside() const { return Entity(OneDGridEntity<0,dim,GridImp>(center_)); } //! return the Entity on the outside of this intersection //! (that is the neighboring Entity) Entity outside() const { return Entity(OneDGridEntity<0,dim,GridImp>(target())); } //! return index of the boundary segment int boundarySegmentIndex () const { // It is hardwired here that the domain is connected, i.e., the boundary consists of two points return ((neighbor_==0 && center_->reversedBoundarySegmentNumbering_==false) || (neighbor_==1 && center_->reversedBoundarySegmentNumbering_==true)) ? 0 : 1; } //! Here returned element is in LOCAL coordinates of the element //! where iteration started. LocalGeometry geometryInInside () const { return LocalGeometry( LocalGeometryImpl( (indexInInside() == 0) ? 0 : 1 ) ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in LOCAL coordinates of neighbor LocalGeometry geometryInOutside () const { return LocalGeometry( LocalGeometryImpl( (indexInInside() == 0) ? 1 : 0 ) ); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in GLOBAL coordinates of the element where iteration started. Geometry geometry () const { return Geometry( GeometryImpl( center_->vertex_[neighbor_%2]->pos_ ) ); } /** \brief obtain the type of reference element for this intersection */ GeometryType type () const { return GeometryTypes::vertex; } //! local index of codim 1 entity in self where intersection is contained in int indexInInside () const { return neighbor_ % 2; } //! local index of codim 1 entity in neighbor where intersection is contained int indexInOutside () const { // If numberInSelf is 0 then numberInNeighbor is 1 and vice versa return 1-(neighbor_ % 2); } //! return outer normal FieldVector outerNormal ([[maybe_unused]] const FieldVector& local) const { return centerUnitOuterNormal(); } //! Return outer normal scaled with the integration element FieldVector integrationOuterNormal ([[maybe_unused]] const FieldVector& local) const { return centerUnitOuterNormal(); } //! return unit outer normal FieldVector unitOuterNormal ([[maybe_unused]] const FieldVector& local) const { return centerUnitOuterNormal(); } //! return unit outer normal at center of intersection FieldVector centerUnitOuterNormal () const { return FieldVector(2 * neighbor_ - 1); } private: //********************************************************** // private methods //********************************************************** OneDEntityImp<1>* center_; /** \brief Count on which neighbor we are lookin' at 0,1 are the level neighbors, 2 and 3 are the leaf neighbors, if they differ from the level neighbors. */ int neighbor_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridleafiterator.hh000066400000000000000000000056161511655130300236520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_LEAFITERATOR_HH #define DUNE_ONE_D_GRID_LEAFITERATOR_HH /** \file * \brief The OneDGridLeafIterator class */ namespace Dune { /** \brief Iterator over all entities of a given codimension and level of a grid. * \ingroup OneDGrid */ template class OneDGridLeafIterator { constexpr static int dim = GridImp::dimension; friend class OneDGridEntity; public: typedef typename GridImp::template Codim::Entity Entity; constexpr static int codimension = codim; OneDGridLeafIterator(const GridImp& grid) : grid_(&grid) { /** \todo Can a make the fullRefineLevel work somehow? */ const int fullRefineLevel = 0; this->virtualEntity_.impl().setToTarget((OneDEntityImp<1-codim>*) std::get<1-codim>(grid_->entityImps_[fullRefineLevel]).begin()); if (!this->virtualEntity_.impl().target_->isLeaf()) increment(); } //! Constructor OneDGridLeafIterator() : grid_(nullptr) { this->virtualEntity_.impl().setToTarget(OneDGridNullIteratorFactory<1-codim>::null()); } //! prefix increment void increment() { // Increment until you find a leaf entity do { globalIncrement(); } while (this->virtualEntity_.impl().target_ && !this->virtualEntity_.impl().target_->isLeaf()); } //! dereferencing const Entity& dereference() const {return virtualEntity_;} //! equality bool equals(const OneDGridLeafIterator& other) const { return virtualEntity_ == other.virtualEntity_; } private: /** \brief This increment makes the iterator wander over all entities on all levels */ void globalIncrement() { // Backup current level because it may not be accessible anymore after // setting the pointer to the next entity. const int oldLevel = this->virtualEntity_.level(); // Increment on this level this->virtualEntity_.impl().setToTarget(this->virtualEntity_.impl().target_->succ_); // If beyond the end of this level set to first of next level if (!this->virtualEntity_.impl().target_ && oldLevel < grid_->maxLevel()) { this->virtualEntity_.impl().setToTarget(const_cast*>(std::get<1-codim>(grid_->entityImps_[oldLevel+1]).begin())); } } // ///////////////////////////////////// // Data members // ///////////////////////////////////// const GridImp* grid_ = nullptr; //! The entity that the iterator is pointing to Entity virtualEntity_ = {}; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridleveliterator.hh000066400000000000000000000035301511655130300240430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONE_D_GRID_LEVELITERATOR_HH #define DUNE_ONE_D_GRID_LEVELITERATOR_HH /** \file * \brief The OneDGridLevelIterator class */ #include namespace Dune { //********************************************************************** // // --OneDGridLevelIterator // --LevelIterator /** \brief Iterator over all entities of a given codimension and level of a grid. * \ingroup OneDGrid */ template class OneDGridLevelIterator { public: constexpr static int dim = GridImp::dimension; friend class OneDGrid; friend class OneDGridEntity; friend class OneDGridEntity<0,dim,GridImp>; friend class OneDGridLevelGridView; typedef typename GridImp::template Codim::Entity Entity; constexpr static int codimension = codim; protected: /** \brief Constructor from a given iterator */ OneDGridLevelIterator(OneDEntityImp* it) { virtualEntity_.impl().setToTarget(it); } public: //! prefix increment void increment() { this->virtualEntity_.impl().setToTarget(this->virtualEntity_.impl().target_->succ_); } //! dereferencing const Entity& dereference() const {return virtualEntity_;} //! equality bool equals(const OneDGridLevelIterator& other) const { return virtualEntity_ == other.virtualEntity_; } protected: //! The entity that the iterator is pointing to Entity virtualEntity_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridlist.hh000066400000000000000000000075071511655130300221450ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ONEDGRID_LIST_HH #define DUNE_ONEDGRID_LIST_HH #include namespace Dune { /** \file \brief A simple doubly-linked list needed in OneDGrid \todo I'd love to get rid of this and use std::list instead. Unfortunately, there are problems. I need to store pointers/iterators within one element which point to another element (e.g. the element father). */ template class OneDGridListIterator : public BidirectionalIteratorFacade,T> { public: bool equals(const OneDGridListIterator& other) const { return pointer_ == other.pointer_; } T& dereference() { return *pointer_; } void increment() { pointer_ = pointer_->succ_; } void decrement() { pointer_ = pointer_->pred_; } OneDGridListIterator() {} OneDGridListIterator(T* pointer) { pointer_ = pointer; } OneDGridListIterator operator=(T* pointer) { pointer_ = pointer; } operator T*() {return pointer_;} private: T* pointer_; }; template class OneDGridList { public: typedef T* iterator; typedef const T* const_iterator; OneDGridList() : numelements(0), begin_(0), rbegin_(0) {} int size() const {return numelements;} iterator push_back (const T& value) { T* i = rbegin(); // New list element by copy construction T* t = new T(value); // einfuegen if (begin_==0) { // insert in empty list begin_ = t; rbegin_ = t; } else { // insert after element i t->pred_ = i; t->succ_ = i->succ_; i->succ_ = t; if (t->succ_!=0) t->succ_->pred_ = t; // new tail? if (rbegin_==i) rbegin_ = t; } // adjust size, return iterator numelements = numelements+1; return t; } iterator insert (iterator i, const T& value) { // Insert before 'one-after-the-end' --> append to the list if (i==end()) return push_back(value); // New list element by copy construction T* t = new T(value); // insert if (begin_==0) { // insert in empty list begin_=t; rbegin_=t; } else { // insert before element i t->succ_ = i; t->pred_ = i->pred_; i->pred_ = t; if (t->pred_!=0) t->pred_->succ_ = t; // new head? if (begin_==i) begin_ = t; } // adjust size, return iterator numelements = numelements+1; return t; } void erase (iterator& i) { // test argument if (i==0) return; // handle pointers to predecessor and successor if (i->succ_!=0) i->succ_->pred_ = i->pred_; if (i->pred_!=0) i->pred_->succ_ = i->succ_; // head & tail if (begin_==i) begin_=i->succ_; if (rbegin_==i) rbegin_ = i->pred_; // adjust size numelements = numelements-1; // Actually delete the object delete(i); } iterator begin() { return begin_; } const_iterator begin() const { return begin_; } iterator end() { return NULL; } const_iterator end() const { return NULL; } iterator rbegin() { return rbegin_; } const_iterator rbegin() const { return rbegin_; } private: int numelements; T* begin_; T* rbegin_; }; // end class OneDGridList } // namespace Dune #endif dune-grid-2.11.0/dune/grid/onedgrid/onedgridviews.hh000066400000000000000000000277221511655130300223300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_ONEDGRID_ONEDGRIDVIEWS_HH #define DUNE_GRID_ONEDGRID_ONEDGRIDVIEWS_HH #include #include //- includes from dune-geometry #include //- includes from dune-grid #include #include #include #include namespace Dune { template< class GridImp > class OneDGridLevelGridView; template< class GridImp > class OneDGridLeafGridView; /** \brief Collect several types associated to OneDGrid LevelGridViews */ template< class GridImp> struct OneDGridLevelGridViewTraits { typedef OneDGridLevelGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid :: Traits :: LevelIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid :: Traits :: LevelIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid :: Traits :: LevelIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; template< int cd > struct Codim { typedef typename Grid :: Traits :: template Codim< cd > :: template Partition< All_Partition > :: LevelIterator Iterator; typedef typename Grid :: Traits :: template Codim< cd > :: Entity Entity; typedef typename Grid :: template Codim< cd > :: Geometry Geometry; typedef typename Grid :: template Codim< cd > :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template< PartitionIteratorType pit > struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid :: template Codim< cd > :: template Partition< pit > :: LevelIterator Iterator; }; }; constexpr static bool conforming = true; }; /** \brief Implementation class of LevelGridViews for OneDGrid */ template< class GridImp > class OneDGridLevelGridView { public: typedef OneDGridLevelGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Traits :: Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits :: template Codim {}; constexpr static bool conforming = Traits :: conforming; OneDGridLevelGridView ( const Grid &grid, int level ) : grid_( &grid ), level_( level ) {} /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { assert( grid_ ); return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return grid().levelIndexSet( level_ ); } /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming() const { return bool(conforming); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( level_, codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( level_, type ); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { return OneDGridLevelIterator(const_cast*>(std::get<1-cd>(grid_->entityImps_[level_]).begin())); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator begin () const { return OneDGridLevelIterator(const_cast*>(std::get<1-cd>(grid_->entityImps_[level_]).begin())); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return OneDGridLevelIterator(nullptr); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator end () const { return OneDGridLevelIterator(static_cast*>(nullptr)); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ilevelbegin(); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ilevelend(); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize([[maybe_unused]] int codim) const { return 0; } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize([[maybe_unused]] int codim) const { return 0; } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( [[maybe_unused]] CommDataHandleIF< DataHandleImp, DataType > &data, [[maybe_unused]] InterfaceType iftype, [[maybe_unused]] CommunicationDirection dir ) const {} private: const Grid *grid_; int level_; }; /** \brief Collect several types associated to OneDGrid LeafGridViews */ template< class GridImp> struct OneDGridLeafGridViewTraits { typedef OneDGridLeafGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid :: Traits :: LeafIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid :: Traits :: LeafIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid :: Traits :: LeafIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; template< int cd > struct Codim { typedef typename Grid :: Traits :: template Codim< cd > :: template Partition< All_Partition > :: LeafIterator Iterator; typedef typename Grid :: Traits :: template Codim< cd > :: Entity Entity; typedef typename Grid :: template Codim< cd > :: Geometry Geometry; typedef typename Grid :: template Codim< cd > :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid :: template Codim< cd > :: template Partition< pit > :: LeafIterator Iterator; }; }; constexpr static bool conforming = true; }; /** \brief Implementation class of LeafGridViews for UGGrid */ template< class GridImp > class OneDGridLeafGridView { public: typedef OneDGridLeafGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Traits :: Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits :: template Codim {}; constexpr static bool conforming = Traits :: conforming; public: OneDGridLeafGridView ( const Grid &grid ) : grid_( &grid ) {} /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { assert( grid_ ); return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return grid().leafIndexSet(); } /** \brief return true if current state of grid view represents a conforming grid */ bool isConforming() const { return bool(conforming); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( type ); } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { return OneDGridLeafIterator(*grid_); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator begin () const { return OneDGridLeafIterator(*grid_); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return OneDGridLeafIterator(); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator end () const { return OneDGridLeafIterator(); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ileafbegin(); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ileafend(); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize([[maybe_unused]] int codim) const { return 0; } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize([[maybe_unused]] int codim) const { return 0; } /** \brief Communicate data on this view -- does nothing because OneDGrid is purely sequential */ template< class DataHandleImp, class DataType > void communicate ( [[maybe_unused]] CommDataHandleIF< DataHandleImp, DataType > &data, [[maybe_unused]] InterfaceType iftype, [[maybe_unused]] CommunicationDirection dir ) const {} private: const Grid *grid_; }; } #endif dune-grid-2.11.0/dune/grid/test/000077500000000000000000000000001511655130300163105ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/test/CMakeLists.txt000066400000000000000000000076431511655130300210620ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(yasp) # Link all test targets in this directory against Dune::Grid link_libraries(Dune::Grid) dune_add_test(SOURCES test-concepts.cc) dune_add_test(SOURCES geometrygrid-coordfunction-copyconstructor.cc) dune_add_test(NAME test-geogrid-yaspgrid SOURCES test-geogrid.cc COMPILE_DEFINITIONS COORDFUNCTION=IdenticalCoordFunction CACHECOORDFUNCTION=0 DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\" GRIDTYPE=Dune::YaspGrid<2>) dune_add_test(NAME test-geogrid-uggrid SOURCES test-geogrid.cc COMPILE_DEFINITIONS COORDFUNCTION=IdenticalCoordFunction CACHECOORDFUNCTION=0 DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\" GRIDTYPE=Dune::UGGrid<2> CMAKE_GUARD dune-uggrid_FOUND) dune_add_test(SOURCES test-gridinfo.cc) dune_add_test(SOURCES test-identitygrid.cc) dune_add_test(SOURCES test-oned.cc) dune_add_test(SOURCES test-mcmg-geogrid.cc) dune_add_test(SOURCES testiteratorranges.cc) dune_add_test(SOURCES test-hierarchicsearch.cc) dune_add_test(SOURCES test-ug.cc COMPILE_DEFINITIONS DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\" CMAKE_GUARD dune-uggrid_FOUND) dune_add_test(SOURCES test-parallel-ug.cc CMAKE_GUARD dune-uggrid_FOUND MPI_RANKS 1 2 3 4 8 TIMEOUT 300) dune_add_test(SOURCES test-loadbalancing.cc CMAKE_GUARD dune-uggrid_FOUND) dune_add_test(SOURCES issue-53-uggrid-intersections.cc CMAKE_GUARD dune-uggrid_FOUND) # The alberta tests are only alibi-ported, until the grid and world dimension # are configuretime parameters and we can treat alberta just as any other grid manager # - buildsystemwise. PLEASE DON'T LOOK AT THIS IF YOU WANT TO KNOW HOW TO WRITE TESTS. if(Alberta_FOUND) foreach(WORLDDIM RANGE 1 3) foreach(GRIDDIM RANGE 1 ${WORLDDIM}) set(_test test-alberta-${GRIDDIM}-${WORLDDIM}) add_executable(${_test} EXCLUDE_FROM_ALL test-alberta.cc) add_dune_alberta_flags(${_test} WORLDDIM ${WORLDDIM}) target_compile_definitions(${_test} PUBLIC GRIDDIM=${GRIDDIM} DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\") dune_add_test(TARGET ${_test}) unset(_test) endforeach(GRIDDIM) endforeach(WORLDDIM) endif() # install the test tools as we want to support testing 3rdparty grids with installed dune-grid install(FILES basicunitcube.hh check-albertareader.hh checkadaptation.hh checkcomcorrectness.hh checkcommunicate.hh checkentitylifetime.hh checkentityseed.hh checkgeometry.hh checkgeometryinfather.hh checkgridfactory.hh checkidset.hh checkindexset.hh checkintersectionit.hh checkintersectionlifetime.hh checkiterators.hh checkjacobians.hh checkpartition.hh checktwists.hh functions.hh gridcheck.hh staticcheck.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/test) # clean up additional files during make clean. Unfortunately it is not possible with # cmake to use search patterns here. Automake wanted to clean the following files: # *.gcda *.gcno semantic.cache simplex-testgrid*.dgf.* cube-testgrid*.dgf.* dgfparser.log # add files to the list as they appear. set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "semantic.cache;dgfparser.log") dune-grid-2.11.0/dune/grid/test/basicunitcube.hh000066400000000000000000000116041511655130300214530ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef BASICUNITCUBE_HH #define BASICUNITCUBE_HH // StructuredGridFactory cannot replace BasicUnitCube when creating a projected unit cube in test-alberta.cc #include // declaration of a basic unit cube that uses the GridFactory template< int dim > struct BasicUnitCube; template<> struct BasicUnitCube< 1 > { template< class Grid > static void insertVertices ( Dune::GridFactory< Grid > &factory, const double left = 0.0, const double right = 1.0 ) { Dune::FieldVector pos; pos[0] = left; factory.insertVertex(pos); pos[ 0 ] = right; factory.insertVertex(pos); } template< class Grid > static void insertSimplices ( Dune::GridFactory< Grid > &factory ) { std::vector< unsigned int > cornerIDs( 2 ); cornerIDs[0] = 0; cornerIDs[1] = 1; factory.insertElement( Dune::GeometryTypes::simplex( 1 ), cornerIDs ); } template< class Grid > static void insertCubes ( Dune::GridFactory< Grid > &factory ) { std::vector< unsigned int > cornerIDs( 2 ); cornerIDs[0] = 0; cornerIDs[1] = 1; factory.insertElement( Dune::GeometryTypes::cube( 1 ), cornerIDs ); } }; // unit cube in two dimensions with 2 variants: triangle and rectangle elements template<> struct BasicUnitCube< 2 > { template< class Grid > static void insertVertices ( Dune::GridFactory< Grid > &factory, const double left = 0.0, const double right = 1.0 ) { Dune::FieldVector pos; pos[0] = right; pos[1] = left; factory.insertVertex(pos); /*@\label{uc:iv}@*/ pos[0] = left; pos[1] = left; factory.insertVertex(pos); pos[0] = right; pos[1] = right; factory.insertVertex(pos); pos[0] = left; pos[1] = right; factory.insertVertex(pos); } template< class Grid > static void insertSimplices ( Dune::GridFactory< Grid > &factory ) { std::vector< unsigned int > cornerIDs( 3 ); cornerIDs[0] = 0; cornerIDs[1] = 1; cornerIDs[2] = 2; factory.insertElement( Dune::GeometryTypes::simplex( 2 ), cornerIDs ); /*@\label{uc:ie}@*/ cornerIDs[0] = 2; cornerIDs[1] = 1; cornerIDs[2] = 3; factory.insertElement( Dune::GeometryTypes::simplex( 2 ), cornerIDs ); } template< class Grid > static void insertCubes ( Dune::GridFactory< Grid > &factory ) { std::vector< unsigned int > cornerIDs( 4 ); for( int i = 0; i < 4; ++i ) cornerIDs[ i ] = i; factory.insertElement( Dune::GeometryTypes::cube( 2 ), cornerIDs ); } }; // unit cube in 3 dimensions with two variants: tetraheda and hexahedra template<> struct BasicUnitCube< 3 > { template< class Grid > static void insertVertices ( Dune::GridFactory< Grid > &factory, const double left = 0.0, const double right = 1.0 ) { Dune::FieldVector< double, 3 > pos; pos[0] = right; pos[1] = left; pos[2] = left; factory.insertVertex(pos); pos[0] = left; pos[1] = left; pos[2] = left; factory.insertVertex(pos); pos[0] = right; pos[1] = right; pos[2] = left; factory.insertVertex(pos); pos[0] = left; pos[1] = right; pos[2] = left; factory.insertVertex(pos); pos[0] = right; pos[1] = left; pos[2] = right; factory.insertVertex(pos); pos[0] = left; pos[1] = left; pos[2] = right; factory.insertVertex(pos); pos[0] = right; pos[1] = right; pos[2] = right; factory.insertVertex(pos); pos[0] = left; pos[1] = right; pos[2] = right; factory.insertVertex(pos); } template< class Grid > static void insertSimplices ( Dune::GridFactory< Grid > &factory ) { std::vector< unsigned int > cornerIDs( 4 ); cornerIDs[0] = 0; cornerIDs[1] = 1; cornerIDs[2] = 2; cornerIDs[3] = 4; factory.insertElement( Dune::GeometryTypes::simplex( 3 ), cornerIDs ); cornerIDs[0] = 1; cornerIDs[1] = 3; cornerIDs[2] = 2; cornerIDs[3] = 7; factory.insertElement( Dune::GeometryTypes::simplex( 3 ), cornerIDs ); cornerIDs[0] = 1; cornerIDs[1] = 7; cornerIDs[2] = 2; cornerIDs[3] = 4; factory.insertElement( Dune::GeometryTypes::simplex( 3 ), cornerIDs ); cornerIDs[0] = 1; cornerIDs[1] = 7; cornerIDs[2] = 4; cornerIDs[3] = 5; factory.insertElement( Dune::GeometryTypes::simplex( 3 ), cornerIDs ); cornerIDs[0] = 4; cornerIDs[1] = 7; cornerIDs[2] = 2; cornerIDs[3] = 6; factory.insertElement( Dune::GeometryTypes::simplex( 3 ), cornerIDs ); } template< class Grid > static void insertCubes ( Dune::GridFactory< Grid > &factory ) { std::vector< unsigned int > cornerIDs( 8 ); for( int i = 0; i < 8; ++i ) cornerIDs[ i ] = i; factory.insertElement( Dune::GeometryTypes::cube( 3 ), cornerIDs ); } }; #endif /*BASICUNITCUBE_HH*/ dune-grid-2.11.0/dune/grid/test/check-albertareader.hh000066400000000000000000000024751511655130300225110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECK_ALBERTAREADER_HH #define DUNE_GRID_TEST_CHECK_ALBERTAREADER_HH #include // AlbertaReader needs ALBERTA 3.0 or newer // (otherwise just pass this check) #if HAVE_ALBERTA #include #include "gridcheck.hh" template< class Grid > void checkAlbertaReader () { std::cout << ">>> Checking AlbertaReader..." << std::endl; std::ostringstream filename; filename << DUNE_GRID_EXAMPLE_GRIDS_PATH << "amc/grid-" << Grid::dimension << "-" << Grid::dimensionworld << ".amc"; Dune::AlbertaReader< Grid > reader; Dune::GridFactory< Grid > factory; reader.readGrid( filename.str(), factory ); // create grid and just check the macro grid auto grid = factory.createGrid(); grid->globalRefine( 2 ); gridcheck( *grid ); } #else template< class Grid > void checkAlbertaReader () { std::cerr << "Warning: Skipping AlbertaReader check, " << "because ALBERTA is not available." << std::endl; } #endif // #if HAVE_ALBERTA #endif // DUNE_GRID_TEST_CHECK_ALBERTAREADER_HH dune-grid-2.11.0/dune/grid/test/checkadaptation.hh000066400000000000000000000223671511655130300217650ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKADAPTATION_HH #define DUNE_GRID_TEST_CHECKADAPTATION_HH #include #include #include #include /** \file \brief A test for the Adaptation interface */ template void markForAdaptation(GridType& grid, const int marker ) { using namespace Dune; // Loop over all levels except the lowest one for (int level = 0; level <= grid.maxLevel(); ++level) { typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; typedef typename ElementIterator :: Entity EntityType ; const ElementIterator eEndIt = grid.levelGridView(level).template end<0>(); for (ElementIterator it = grid.levelGridView(level).template begin<0>(); it != eEndIt; ++it ) { const EntityType& entity = *it ; // marking should only be possible on leaf entities const bool marked = grid.mark(marker, entity ); if( marker < 0 && entity.level() == 0 ) { if( marked ) { DUNE_THROW(InvalidStateException,"Macro entity was marked for coarsening"); } } else { if( ! entity.isLeaf() && marked == true ) { DUNE_THROW(InvalidStateException,"Non-leaf entity was marked"); } if( entity.isLeaf() && marked == false ) { DUNE_THROW(InvalidStateException,"Leaf entity could not be marked"); } } } } } template void checkHierarchy(const EntityType& entity) { using namespace Dune; if( ! entity.isLeaf() ) { // only leaf entities can vanish if( entity.mightVanish() ) { DUNE_THROW(InvalidStateException,"Non-leaf entity marked might vanish"); } const int level = entity.level() + 1 ; typedef typename EntityType :: HierarchicIterator HierarchicIterator; const HierarchicIterator end = entity.hend( level ); for(HierarchicIterator it = entity.hbegin( level ); it != end; ++it) { checkHierarchy( *it ); } } else { if( entity.level() == 0 ) { if( entity.mightVanish() ) DUNE_THROW(InvalidStateException,"entity.mightVanish() returns true for macro element"); } else { // on level 0 this should be false if( ! entity.mightVanish() ) { DUNE_THROW(InvalidStateException,"entity.mightVanish() returns wrong result"); } } } } template void checkAdaptRefinement(GridType& grid, const bool greenClosure = false ) { using namespace Dune; // skip empty grids if ( grid.levelGridView(0).template begin<0>() == grid.levelGridView(0).template end<0>() ) return; // some things are different for bisection grids const bool bisectionGrid = Capabilities::isLevelwiseConforming :: v == false && Capabilities::isLeafwiseConforming :: v == true ; for(int i=0; i<2; ++i) { const int oldMaxLevel = grid.maxLevel(); // mark all leaf entities for refinement markForAdaptation( grid , 1 ); bool markedCoarsen = grid.preAdapt(); if( markedCoarsen != greenClosure ) { DUNE_THROW(InvalidStateException,"grid.preAdapt() does not return correct information"); } bool refined = grid.adapt() ; if( ! refined ) { DUNE_THROW(InvalidStateException,"grid.adapt() returns wrong information"); } /// check new max level if( grid.maxLevel () <= oldMaxLevel ) { DUNE_THROW(InvalidStateException,"grid.maxLevel() wrong after refinement " << oldMaxLevel << " " << grid.maxLevel() ); } // Loop over all levels except the lowest one for (int level = 0 ; level <= grid.maxLevel(); ++level ) { typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; typedef typename ElementIterator :: Entity EntityType ; ElementIterator eEndIt = grid.levelGridView(level).template end<0>(); for (ElementIterator it = grid.levelGridView(level).template begin<0>(); it != eEndIt; ++ it) { const EntityType& entity = *it ; // this check fails on biscetion grids if( ! bisectionGrid ) { if( entity.isLeaf () != entity.isNew () ) { DUNE_THROW(InvalidStateException,"isNew information on entity gives wrong result"); } } else // at least all leafs have to be new { if( entity.isLeaf () && ! entity.isNew () ) { DUNE_THROW(InvalidStateException,"isNew information on entity gives wrong result"); } } } } grid.postAdapt(); // Loop over all levels except the lowest one for (int level = 0 ; level <= grid.maxLevel(); ++level ) { typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; ElementIterator eEndIt = grid.levelGridView(level).template end<0>(); for (ElementIterator it = grid.levelGridView(level).template begin<0>(); it != eEndIt; ++ it) { if( it->isNew () ) { DUNE_THROW(InvalidStateException,"After postAdapt() was called no entity is new, i.e., isNew() == false"); } } } } } template void checkAdaptation(GridType& grid, const bool greenClosure = false ) { using namespace Dune; // skip empty grids if (grid.levelGridView(0).template begin<0>() == grid.levelGridView(0).template end<0>()) return; // save start level const int startLevel = grid.maxLevel(); // save start grid size const int startSize = grid.size( 0 ); // some things are different for bisection grids const bool bisectionGrid = Capabilities::isLevelwiseConforming :: v == false && Capabilities::isLeafwiseConforming :: v == true ; /* run the refinement check */ checkAdaptRefinement(grid, greenClosure); /* run coarsening check */ int counter = 0; const int counterEstimate = (grid.maxLevel() - startLevel) * 10; // now the same with coarsening while ( grid.maxLevel() > startLevel ) { const int oldMaxLevel = grid.maxLevel(); // mark all leaf entities for coarsening markForAdaptation( grid , -1 ); bool markedCoarsen = grid.preAdapt(); if( markedCoarsen == false ) { DUNE_THROW(InvalidStateException,"grid.preAdapt() does not return correct information"); } // check mightVanish typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; ElementIterator eEndIt = grid.levelGridView(0).template end<0>(); for (ElementIterator it = grid.levelGridView(0).template begin<0>(); it != eEndIt; ++ it) { checkHierarchy( *it ); } // only marked for coarsening ==> refined = false bool refined = grid.adapt() ; if( refined ) { DUNE_THROW(InvalidStateException,"grid.adapt() returns wrong information"); } /// check new max level if( grid.maxLevel () >= oldMaxLevel ) { if( ! bisectionGrid ) DUNE_THROW(InvalidStateException,"grid.maxLevel() wrong after coarsening " << oldMaxLevel << " " << grid.maxLevel() ); } // Loop over all levels except the lowest one for (int level = 0 ; level <= grid.maxLevel(); ++level ) { typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; ElementIterator eEndIt = grid.levelGridView(level).template end<0>(); for (ElementIterator it = grid.levelGridView(level).template begin<0>(); it != eEndIt; ++ it) { if( it->isNew () ) { DUNE_THROW(InvalidStateException,"After postAdapt() was called no entity is new, i.e., isNew() == false"); } } } grid.postAdapt(); // Loop over all levels except the lowest one for (int level = 0 ; level <= grid.maxLevel(); ++level ) { typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; ElementIterator eEndIt = grid.levelGridView(level).template end<0>(); for (ElementIterator it = grid.levelGridView(level).template begin<0>(); it != eEndIt; ++ it) { if( it->isNew () ) { DUNE_THROW(InvalidStateException,"After postAdapt() was called no entity is new, i.e., isNew() == false"); } if( it->mightVanish() ) { DUNE_THROW(InvalidStateException,"After postAdapt() was called no entity might vanish, i.e., mightVanish() == false"); } } } ++counter; if( counter > counterEstimate ) DUNE_THROW(InvalidStateException,"Coarsening does not get back to startLevel"); } const int newSize = grid.size( 0 ); if( startSize != newSize ) { dwarn << "After coarsening a different number of elements is obtained! old = " << startSize << " new = " << newSize << std::endl; } if( startLevel != grid.maxLevel() ) { dwarn << "After coarsening a different maxLevel is obtained! old = " << startLevel << " new = " << grid.maxLevel() << std::endl; } } #endif dune-grid-2.11.0/dune/grid/test/checkcomcorrectness.hh000066400000000000000000000276511511655130300226730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKCOMMCORRECTNESS_HH #define DUNE_GRID_TEST_CHECKCOMMCORRECTNESS_HH #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { std::size_t hash_value(const PartitionType& pt) { return static_cast(pt); } } DUNE_DEFINE_HASH(DUNE_HASH_TEMPLATE_ARGS(),DUNE_HASH_TYPE(Dune::PartitionType)) namespace Dune { namespace GridCheck { struct SymmetryVerifyingDataHandle : public Dune::CommDataHandleIF { bool contains(int /* dim */, int codim) const { return codim == _codim; } bool fixedSize(int /* dim */, int /* codim */) const { return _fixed_size; } template std::size_t size(const E&) const { return _writes_per_cell; } template void gather(Buf& buf, const E&) const { for (std::size_t i = 0; i < _writes_per_cell; ++i) buf.write(std::size_t(42)); _writes += _writes_per_cell; } template void scatter(Buf& buf, const E&, std::size_t n) const { assert(_writes_per_cell == n); for (std::size_t i = 0; i < _writes_per_cell; ++i) { std::size_t tmp = 0; buf.read(tmp); assert(tmp == 42); } _reads += _writes_per_cell; } SymmetryVerifyingDataHandle(int codim, bool fixed_size, std::size_t writes_per_cell) : _codim(codim) , _fixed_size(fixed_size) , _writes_per_cell(writes_per_cell) , _reads(0) , _writes(0) {} const int _codim; const bool _fixed_size; const std::size_t _writes_per_cell; mutable std::size_t _reads; mutable std::size_t _writes; }; struct CodimLayout { bool operator()(Dune::GeometryType gt, int dim) const { return (static_cast< int >( gt.dim() ) == dim - _codim); } int _codim; }; template struct CommunicationTestDataHandle : public Dune::CommDataHandleIF, typename GV::template Codim<0>::Geometry::GlobalCoordinate> { using ctype = typename GV::ctype; bool contains([[maybe_unused]] int dim, int codim) const { return codim == _codim; } bool fixedSize([[maybe_unused]] int dim, [[maybe_unused]] int codim) const { return true; } template std::size_t size([[maybe_unused]] const E& e) const { return 1; } template void gather(Buf& buf, const E& e) const { assert(_allowed_writes.count(e.partitionType()) > 0); auto center = e.geometry().center(); buf.write(e.geometry().center()); if (_gv.comm().rank() == 0) std::cout << "Gathering from entity " << _mapper.index(e) << " at " << e.geometry().center() << std::endl; ++_writes[_mapper.index(e)]; center -= _coords[_mapper.index(e)]; assert(Dune::FloatCmp::eq(center.two_norm(),ctype(0))); } template void scatter(Buf& buf, const E& e, [[maybe_unused]] std::size_t n) const { assert(_allowed_reads.count(e.partitionType()) > 0); typename E::Geometry::GlobalCoordinate data; buf.read(data); ++_reads[_mapper.index(e)]; auto center = e.geometry().center(); data -= e.geometry().center(); assert(Dune::FloatCmp::eq(data.two_norm(),ctype(0))); center -= _coords[_mapper.index(e)]; assert(Dune::FloatCmp::eq(center.two_norm(),ctype(0))); } template void verify(Dune::Codim codim, Check check) { assert(codim == _codim); for (const auto& e : entities(_gv,codim)) { if (_gv.comm().rank() == 0) std::cout << "Entity of codim " << cd << " at " << e.geometry().center() << " with partition " << PartitionName(e.partitionType()) << " and " << _writes[_mapper.index(e)] << " / " << _reads[_mapper.index(e)] << " writes / reads" << std::endl; check( e.partitionType(), _allowed_writes.count(e.partitionType()) > 0, _allowed_reads.count(e.partitionType()) > 0, _writes[_mapper.index(e)], _reads[_mapper.index(e)] ); } } CommunicationTestDataHandle(GV gv, int codim, const std::unordered_set& allowed_writes, const std::unordered_set& allowed_reads, const std::vector::Geometry::GlobalCoordinate>& coords) : _gv(gv) , _codim(codim) , _mapper(gv, CodimLayout{_codim}) , _allowed_writes(allowed_writes) , _allowed_reads(allowed_reads) , _reads(_mapper.size(),0) , _writes(_mapper.size(),0) , _coords(coords) {} GV _gv; const int _codim; Dune::MultipleCodimMultipleGeomTypeMapper _mapper; const std::unordered_set _allowed_writes; const std::unordered_set _allowed_reads; mutable std::vector _reads; mutable std::vector _writes; const std::vector::Geometry::GlobalCoordinate>& _coords; }; template void check_communication_correctness_do(GV gv, Codim codim) { if (gv.grid().comm().rank() == 0) { std::cout << "Checking codim " << cd << std::endl; } std::unordered_map count; Dune::MultipleCodimMultipleGeomTypeMapper mapper(gv, CodimLayout{codim}); std::vector< typename GV::template Codim<0>::Geometry::GlobalCoordinate > coords(mapper.size()); // start by counting entities by partition type and storing entity positions for (const auto& e : entities(gv,codim)) { ++count[e.partitionType()]; coords[mapper.index(e)] = e.geometry().center(); } { SymmetryVerifyingDataHandle dh_forward(cd,false,3); gv.communicate(dh_forward,InteriorBorder_InteriorBorder_Interface,ForwardCommunication); SymmetryVerifyingDataHandle dh_backward(cd,true,3); gv.communicate(dh_backward,InteriorBorder_InteriorBorder_Interface,BackwardCommunication); if (count[BorderEntity] > 0) { assert(dh_forward._writes == dh_forward._reads); assert(dh_backward._writes == dh_backward._reads); assert(dh_forward._writes == dh_backward._writes); assert(dh_backward._writes == dh_backward._writes); } if (gv.grid().comm().size() == 2) { if (gv.comm().rank() == 0) std::cout << "MPI size == 2, checking writes (" << (dh_forward._writes / 3) << ") against count of border entities (" << count[BorderEntity] << ")" << std::endl; assert((dh_forward._writes / 3) == count[BorderEntity]); } } { SymmetryVerifyingDataHandle dh_forward(cd,true,7); gv.communicate(dh_forward,All_All_Interface,ForwardCommunication); SymmetryVerifyingDataHandle dh_backward(cd,false,7); gv.communicate(dh_backward,All_All_Interface,BackwardCommunication); if (count[BorderEntity] > 0) { assert(dh_forward._writes == dh_forward._reads); assert(dh_backward._writes == dh_backward._reads); assert(dh_forward._writes == dh_backward._writes); assert(dh_backward._writes == dh_backward._writes); } } using PTSet = std::unordered_set; { PTSet writers({InteriorEntity,BorderEntity}); PTSet readers({InteriorEntity,BorderEntity,OverlapEntity,FrontEntity,GhostEntity}); CommunicationTestDataHandle dh(gv,codim,writers,readers,coords); gv.communicate(dh,InteriorBorder_All_Interface,ForwardCommunication); } { PTSet writers({InteriorEntity,BorderEntity,OverlapEntity,FrontEntity,GhostEntity}); PTSet readers({InteriorEntity,BorderEntity}); CommunicationTestDataHandle dh(gv,codim,writers,readers,coords); gv.communicate(dh,InteriorBorder_All_Interface,BackwardCommunication); } { PTSet writers({InteriorEntity,BorderEntity}); PTSet readers({InteriorEntity,BorderEntity}); CommunicationTestDataHandle dh(gv,codim,writers,readers,coords); gv.communicate(dh,InteriorBorder_InteriorBorder_Interface,ForwardCommunication); dh.verify( codim, [](PartitionType partition, bool /* write_allowed */, bool /* read_allowed */, [[maybe_unused]] std::size_t writes, [[maybe_unused]] std::size_t reads) { if (partition == BorderEntity) { assert(writes > 0); assert(reads > 0); assert(writes == reads); } else { assert(writes == 0); assert(reads == 0); } }); } } // Need a forward declaration here template void check_communication_correctness_iter(GV gv, Codim codim); // Statically iterate over all codimensions template void check_communication_correctness_iter(GV, Codim, std::true_type, std::true_type) {} template void check_communication_correctness_iter(GV, Codim, std::false_type, std::true_type) {} template void check_communication_correctness_iter(GV gv, Codim codim, std::true_type, std::false_type) { check_communication_correctness_do(gv, codim); check_communication_correctness_iter (gv, Codim()); } template void check_communication_correctness_iter(GV gv, Codim codim, std::false_type, std::false_type) { check_communication_correctness_iter (gv, Codim()); } template void check_communication_correctness_iter(GV gv, Codim codim) { check_communication_correctness_iter (gv, codim, std::integral_constant::v>(), std::integral_constant()); } // Start with codim 0 template void check_communication_correctness(GV gv) { check_communication_correctness_iter (gv, Codim<0>()); } } // namespace GridCheck } // namespace Dune #endif dune-grid-2.11.0/dune/grid/test/checkcommunicate.hh000066400000000000000000000452011511655130300221350ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKCOMMUNICATE_HH #define DUNE_GRID_TEST_CHECKCOMMUNICATE_HH #include #include #include #include #include #include #include #include /* Communication Test for Parallel Grids * ------------------------------------- * * For a fixed codimension c and a fixed upwind direction u, the test works * as follows: * 1) In the center of all upwind codim c subentities of the interioir codim 0 * leaf entities a function is stored. Also a flag is set to 1. * The computation is also performed on the subentities of the physical * boundary. * -> For all leaf subentities of codim c the flag should be set to 1 * with the exception of the border subentities on the inflow * processor boundary and in the ghost elements - on these * subentities the flag is zero. * 2) Exchange both the data and the flags. * 3) Test if the flag for all leaf subentities of codim c is set to 1. * * Note: This test requires the normals on both sides of an intersection to * sum up to zero, i.e., there is exactly one tangent plane to the grid * in every point of the intersection (actually, the barycenter would be * sufficient). */ /***** The exchange is done using the ExampleDataHandle given below. Together with the function value and the flag the coordinates of all corners of the subenties are transmitted, giving the possibility for additional testing in the scatter/set methods. ******/ /*******************************************************************/ namespace { template< class Grid, int codim = Grid::dimension+1 > struct NextCodim { static const bool canCommunicate = Dune::Capabilities::canCommunicate< Grid, codim-1 >::v; static const int v = (canCommunicate ? codim-1 : NextCodim< Grid, codim-1 >::v); }; template< class Grid > struct NextCodim< Grid, 0 > { static const int v = -1; }; } template class ExampleDataHandle : public Dune::CommDataHandleIF< ExampleDataHandle< IndexSetImp, GlobalIdSetImp, DataVectorType >, typename DataVectorType::value_type > { const IndexSetImp & iset_; const GlobalIdSetImp & ids_; int cdim_; DataVectorType & data1_; DataVectorType & data2_; public: typedef typename DataVectorType :: value_type DataType; ExampleDataHandle(const IndexSetImp & iset, const GlobalIdSetImp & ids, int cdim, DataVectorType & d1, DataVectorType & d2) : iset_(iset), ids_(ids) , cdim_(cdim), data1_(d1) , data2_(d2) {} //! returns true if data for this codim should be communicated bool contains ([[maybe_unused]] int dim, int codim) const { return (codim==cdim_); } //! returns true if size per entity of given dim and codim is a constant bool fixedSize ([[maybe_unused]] int dim, [[maybe_unused]] int codim) const { // this problem is a fixed size problem, // but to simulate also non-fixed size problems // we set this to false, should work anyway return false; } /*! how many objects of type DataType have to be sent for a given entity Note: Only the sender side needs to know this size. */ template size_t size (EntityType& e) const { // flag+data+coordinates typedef typename EntityType::Geometry Geometry; return 2+e.geometry().corners() * Geometry::coorddimension; } //! pack data from user to message buffer template void gather (MessageBuffer& buff, const EntityType& e) const { int idx = iset_.index(e); //typename GlobalIdSetImp :: IdType id = ids_.id( e ); //buff.write( id ); buff.write(data2_[idx]); // flag buff.write(data1_[idx]); // data // all corner coordinates typedef typename EntityType::Geometry Geometry; const Geometry &geometry = e.geometry(); for( int i = 0; i < geometry.corners(); ++i ) { typedef Dune::FieldVector< typename Geometry::ctype, Geometry::coorddimension > Vector; const Vector corner = geometry.corner( i ); for( int j = 0; j < Geometry::coorddimension; ++j ) buff.write( corner[ j ] ); } } /*! unpack data from message buffer to user n is the number of objects sent by the sender */ template void scatter (MessageBuffer& buff, const EntityType& e, size_t n) { using std::sqrt; using Geometry = typename EntityType::Geometry; using ctype = typename Geometry::ctype; // define a tolerance for floating-point checks const ctype tolerance = sqrt(std::numeric_limits< ctype >::epsilon()); // as this problem is a fixed size problem we can check the sizes assert( n == size(e) ); // make sure that global id on all processors are the same // here compare the id of the entity that sended the data with my id //typename GlobalIdSetImp :: IdType id; //buff.read( id ); //typename GlobalIdSetImp :: IdType myId = ids_.id( e ); //std::cout << id << " id | my Id = " << myId << "\n"; //assert( id == myId ); // else do normal scatter int idx = iset_.index(e); DataType x=0.0; buff.read(x); // flag // for ghost entities x > 0 must be true assert( ( e.partitionType() == Dune::GhostEntity ) ? (x>=0.0) : 1); if (x>=0) { // only overwrite existing data if flag = 1, i.e., // the sending processor acctually computed the value data2_[idx] = x; x=0.; buff.read(x); // correct function value data1_[idx] = x; } else { x=0.; buff.read(x); } // test if the sending/receiving entities are geometrically the same const Geometry &geometry = e.geometry(); for( int i = 0; i < geometry.corners(); ++i ) { typedef Dune::FieldVector< ctype, Geometry::coorddimension > Vector; const Vector corner = geometry.corner( i ); for( int j = 0; j < Geometry::coorddimension; ++j ) { buff.read(x); if( std::abs( corner[ j ] - x ) > tolerance ) { std::cerr << "ERROR in scatter: Vertex <" << i << "," << j << ">: " << " this : (" << corner[ j ] << ")" << " other : (" << x << ")" << std::endl; } } } } }; /*******************************************************************/ /*******************************************************************/ template< class GridView, int cdim, class OutputStream > class CheckCommunication { typedef typename GridView :: Grid Grid; typedef typename GridView :: IndexSet IndexSet; typedef typename GridView :: IntersectionIterator IntersectionIterator; typedef typename IntersectionIterator :: Intersection Intersection; typedef typename GridView :: template Codim< 0 > :: Entity Entity; typedef typename GridView :: template Codim< 0 > :: Iterator Iterator; typedef typename GridView :: template Codim< cdim > :: Entity SubEntity; constexpr static int dimworld = Grid :: dimensionworld; constexpr static int dim = Grid :: dimension; typedef typename Grid :: ctype ctype; typedef Dune::FieldVector< ctype, dimworld > CoordinateVector; typedef std :: vector< ctype > ArrayType; CoordinateVector upwind_; OutputStream &sout_; const GridView &gridView_; const IndexSet &indexSet_; const int level_; // the function ctype f ( const CoordinateVector &x ) { CoordinateVector a( 1.0 ); a[0] = -0.5; return a*x+1.5; //+cos(x*x); } // compute the data on the upwind entities void project ( int dataSize, ArrayType &data, ArrayType &weight, int /* rank */ ) { // set initial data for(int i=0 ; i(); for( Iterator it = gridView_.template begin< 0 >(); it != end ; ++it ) { const Entity &entity = *it; if( cdim == 0 ) { CoordinateVector mid( 0.0 ); const int numVertices = entity.subEntities(dim); for( int i = 0; i < numVertices; ++i ) mid += entity.geometry().corner( i ); mid /= ctype( numVertices ); int index = indexSet_.index( entity ); data[ index ] = f( mid ); weight[ index ] = 1.0; } else { const IntersectionIterator nend = gridView_.iend( entity ); for( IntersectionIterator nit = gridView_.ibegin( entity ); nit != nend; ++nit ) { const Intersection &intersection = *nit; const typename Intersection::LocalGeometry &geoInSelf = intersection.geometryInInside(); auto faceRefElement = referenceElement( geoInSelf ); const Dune::FieldVector< ctype, dim-1 > &bary = faceRefElement.position( 0, 0 ); const CoordinateVector normal = intersection.integrationOuterNormal( bary ); ctype calc = normal * upwind_; // if testing level, then on non-conform grid also set values on // intersections that are not boundary, but has no level // neighbor const bool proceedAnyway = (level_ < 0 ? false : !intersection.neighbor()); if( (calc > -1e-8) || intersection.boundary() || proceedAnyway ) { auto insideRefElem = referenceElement( entity.geometry() ); const int indexInInside = intersection.indexInInside(); for( int i = 0; i < insideRefElem.size( indexInInside, 1, cdim ); ++i ) { const int e = insideRefElem.subEntity( indexInInside, 1, i, cdim ); const int idx = indexSet_.subIndex( entity, e, cdim ); CoordinateVector cmid( 0.0 ); SubEntity subE = entity.template subEntity< cdim >( e ); const int c = subE.geometry().corners(); for( int j = 0; j < c; ++j ) cmid += subE.geometry().corner( j ); cmid /= ctype( c ); data[ idx ] = f( cmid ); weight[ idx ] = 1.0; } // on non-conforming grids the neighbor entities might not // be the same as those on *it, therefore set data on neighbor // as well if( intersection.neighbor() ) { Entity neigh = intersection.outside(); assert( (level_ < 0) ? (neigh.isLeaf()) : 1); assert( (level_ < 0) ? 1 : (neigh.level() == level_) ); auto outsideRefElem = referenceElement( neigh.geometry() ); const int indexInOutside = intersection.indexInOutside(); for( int i = 0; i < outsideRefElem.size( indexInOutside, 1, cdim ); ++i ) { const int e = outsideRefElem.subEntity( indexInOutside, 1, i, cdim ); const int idx = indexSet_.subIndex( neigh, e, cdim ); CoordinateVector cmid( 0.0 ); SubEntity subE = neigh.template subEntity< cdim >( e ); const int c = subE.geometry().corners(); for( int j = 0; j < c; ++j ) cmid += subE.geometry().corner( j ); cmid /= ctype( c ); data[ idx ] = f( cmid ); weight[ idx ] = 1.0; } } } } } } } // test if all flags are 1 and return the // difference in the function values. // if testweight is true an error is printed for each // flag not equal to 1 ctype test ( int /* dataSize */, ArrayType &data, ArrayType &weight, bool testweight ) { const int rank = gridView_.comm().rank(); const int size = gridView_.comm().size(); // check whether there is an overlap or ghost region of // cells for the current grid view. if (size > 1 && cdim == 0 && gridView_.overlapSize(0) == 0 && gridView_.ghostSize(0) == 0) { sout_ << "<" << rank << "/test> Error in communication test."; sout_ << " overlapSize+ghostSize:" << gridView_.overlapSize(0) + gridView_.ghostSize(0) << " (should not be 0)"; sout_ << " communicator size is:" << size; sout_ << std :: endl; } //Variante MIT Geisterzellen //typedef typename IndexSet :: template Codim<0> :: template Partition :: Iterator IteratorType; ctype maxerr = 0.0; Iterator end = gridView_.template end< 0 >(); for( Iterator it = gridView_.template begin< 0 >(); it != end ; ++it ) { const Entity &entity = *it; CoordinateVector mid( 0.0 ); const int numVerticesDim = entity.subEntities(dim); for( int i = 0; i < numVerticesDim; ++i ) mid += entity.geometry().corner( i ); mid /= ctype(numVerticesDim); if( cdim == 0 ) { int index = indexSet_.index( entity ); ctype lerr = std::abs( f( mid ) - data[ index ] ); maxerr = std :: max( maxerr, lerr ); if( testweight && (weight[ index ] < 0) ) { sout_ << "<" << rank << "/test> Error in communication test."; sout_ << " weight:" << weight[ index ] << " (should be 0)"; sout_ << " value is : " << data[ index ]; sout_ << " index is: " << index; sout_ << " level:" << entity.level(); sout_ << std :: endl; } } else { const int numSubEntities = entity.subEntities(cdim); for( int i=0; i < numSubEntities; ++i ) { SubEntity subE = entity.template subEntity< cdim >( i ); const int index = indexSet_.index( subE ); CoordinateVector cmid( 0.0 ); const int numVertices = subE.geometry().corners(); for( int j = 0; j< numVertices; ++j ) cmid += subE.geometry().corner( j ); cmid /= ctype( numVertices ); ctype lerr = std::abs( f( cmid ) - data[ index ] ); maxerr = std::max( maxerr, lerr ); if( testweight && (weight[ index ] < 0) ) { sout_ << "<" << rank << "/test> Error in communication test."; sout_ << " weight:" << weight[ index ] << " should be zero!"; sout_ << " value is : " << data[ index ]; sout_ << " index is:" << index; sout_ << " level: " << entity.level() ; sout_ << std :: endl; for( int j = 0; j < numVertices; ) { auto refElem = referenceElement ( entity.geometry() ); const int vx = refElem.subEntity( i, cdim, j, dim ); sout_ << "index: " << indexSet_.subIndex( entity, vx, dim ) << " " << subE.geometry().corner( j ); (++j < numVertices ? sout_ << "/" : sout_ << std :: endl); } } } } } return maxerr; } // The main ''algorithm'' bool checkCommunication () { using std::sqrt; // define a tolerance for floating-point checks const ctype tolerance = sqrt(std::numeric_limits< ctype >::epsilon()); upwind_[ 0 ] = -0.1113; int myrank = gridView_.comm().rank(); if( myrank == 0 ) { std::cout << "TEST "; (level_ < 0 ? std :: cout << "Leaf" : std :: cout << "Level<" << level_ << ">"); std :: cout << " communication for codim " << cdim << std :: endl; } const int dataSize = indexSet_.size( cdim ); ArrayType data(dataSize, 0.0); ArrayType weight(dataSize, 0.0); project( dataSize, data, weight, myrank ); ctype preresult = test( dataSize, data, weight, false ); sout_ << "Test before Communication on <" << myrank << "> " << preresult << std :: endl; // Communicate typedef typename Grid :: Traits :: GlobalIdSet GlobalIdSet; ExampleDataHandle< IndexSet, GlobalIdSet, ArrayType > dh( indexSet_, gridView_.grid().globalIdSet(), cdim, data, weight ); // call communication of grid try { // call forward and backward communication auto obj1 = gridView_.communicate( dh, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication ); if( ! obj1.ready() ) obj1.wait(); // make sure backward communication does the same, this should change nothing auto obj2 = gridView_.communicate( dh, Dune::InteriorBorder_All_Interface, Dune::BackwardCommunication ); } catch( const Dune::NotImplemented &exception ) { if( myrank == 0 ) { sout_ << "Error: Communication for codimension " << cdim << " not implemented." << std :: endl; sout_ << " (" << exception << ")" << std :: endl; } return false; } ctype result = test( dataSize, data, weight, true ); sout_ << "Test after Communication on <" << myrank << "> " << result << std :: endl; return (std::abs(result) < tolerance); } public: CheckCommunication ( const GridView &gridView, OutputStream &sout, int level ) : upwind_( -1.0 ), sout_( sout ), gridView_( gridView ), indexSet_( gridView_.indexSet() ), level_( level ) { // if no overlap and ghost is available we skip the check const bool skipCheck = ( cdim == 0 ) ? (gridView_.overlapSize(0) == 0 && gridView_.ghostSize(0) == 0) : false ; if( skipCheck ) { std :: cerr << "Codim " << cdim << ": Test skipped because of empty set of overlap and ghosts!" << std :: endl; } else if ( ! checkCommunication() ) { std :: cerr << "Error in communication test for codim " << cdim << "!" << std :: endl; } // for automatic testing of all codims CheckCommunication< GridView, NextCodim< Grid, cdim >::v, OutputStream > test( gridView_, sout_, level_ ); } }; template< class GridView, class OutputStream > class CheckCommunication< GridView, -1, OutputStream > { public: CheckCommunication ( const GridView &, OutputStream &, int) {} }; template< class Grid, class OutputStream > void checkCommunication( const Grid &grid, int level, OutputStream &sout ) { if( level < 0 ) { typedef typename Grid::LeafGridView GridView; GridView gridView = grid.leafGridView(); CheckCommunication< GridView, NextCodim< Grid >::v, OutputStream > test( gridView, sout, level ); } else { typedef typename Grid::LevelGridView GridView; GridView gridView = grid.levelGridView( level ); CheckCommunication< GridView, NextCodim< Grid >::v, OutputStream > test( gridView, sout, level ); } } #endif // DUNE_GRID_TEST_CHECKCOMMUNICATE_HH dune-grid-2.11.0/dune/grid/test/checkentitylifetime.hh000066400000000000000000000123011511655130300226570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKENTITYLIFETIME_HH #define DUNE_GRID_TEST_CHECKENTITYLIFETIME_HH /** \file \brief Tests that make sure range-based entity iteration works correctly and that copied entities have the correct lifetime */ #include #include #include #include #include #include #include #if not defined(DUNE_ENTITY_LIFETIME_CHECK_ELEMENT_COUNT) #define DUNE_ENTITY_LIFETIME_CHECK_ELEMENT_COUNT 32 #endif template bool checkEntityLifetimeForCodim(GV gv, std::size_t check_element_count, Dune::Codim, std::true_type) { using namespace Dune; std::cout << "Lifetime / consistency check for entities, codim " << codim << std::endl; if (check_element_count > static_cast(gv.size(codim))) { std::cout << "WARNING! Requested check of first " << check_element_count << " entities, but grid view only contains " << gv.size(codim) << " entities" << std::endl; check_element_count = gv.size(codim); } auto& index_set = gv.indexSet(); auto& id_set = gv.grid().localIdSet(); std::vector indices; std::vector ids; std::vector::Entity> entity_list; std::vector::Entity::Geometry::GlobalCoordinate> coords; // store indices + ids + entities + coordinates { std::size_t i = 0; for (const auto& e : entities(gv,Dune::Codim())) { #if DUNE_GRID_HAVE_CONCEPTS static_assert(Dune::Concept::Entity>); #endif if (++i > check_element_count) break; indices.push_back(index_set.index(e)); ids.push_back(id_set.id(e)); entity_list.push_back(e); coords.push_back(e.geometry().corner(0)); } } // check for consistency for (std::size_t i = 0; i < check_element_count; ++i) { if (index_set.index(entity_list[i]) != indices[i]) DUNE_THROW( InvalidStateException, "ERROR! inconsistent index for entity " << i << " (" << index_set.index(entity_list[i]) << " != " << indices[i] << ")"); if (id_set.id(entity_list[i]) != ids[i]) DUNE_THROW( InvalidStateException, "ERROR! inconsistent id for entity " << i << " (" << id_set.id(entity_list[i]) << " != " << ids[i] << ")"); if ((entity_list[i].geometry().corner(0) - coords[i]).two_norm() > std::numeric_limits::epsilon()) DUNE_THROW( InvalidStateException, "ERROR! inconsistent corner(0) coordinate for entity " << i << " (" << entity_list[i].geometry().corner(0) << " != " << coords[i] << ")"); } #if DUNE_GRID_HAVE_CONCEPTS using Iterator = typename GV::template Codim::Iterator; static_assert(Dune::Concept::GridView); static_assert(Dune::Concept::IndexSet); static_assert(Dune::Concept::IdSet); static_assert(Dune::Concept::IdSet); static_assert(Dune::Concept::EntityIterator); static_assert(Dune::Concept::Grid); #endif return true; } template bool checkEntityLifetimeForCodim(GV, const std::size_t, Dune::Codim, std::false_type) { std::cout << "SKIPPING lifetime / consistency check for missing entities, codim " << codim << std::endl; return false; } namespace { // helper stuff for checking all codims template struct index_pack {}; //! TMP to build an index_pack containing the sequence 0,...,n-1. template struct index_pack_builder : public index_pack_builder {}; // end of recursion template struct index_pack_builder<0,i...> { typedef index_pack type; }; template typename index_pack_builder::type create_codims(GV) { return {}; } template void invoke(T&&...) {} template void do_check_entity_lifetime(GV gv, const std::size_t check_element_count, index_pack) { invoke( checkEntityLifetimeForCodim( gv, check_element_count, Dune::Codim(), std::integral_constant< bool, Dune::Capabilities::hasEntity::v && Dune::Capabilities::hasEntityIterator::v >() )... ); } } template void checkEntityLifetime(GV gv, const std::size_t check_element_count = 32) { do_check_entity_lifetime(gv,check_element_count,create_codims(gv)); } #endif // #ifndef DUNE_GRID_TEST_CHECKENTITYLIFETIME_HH dune-grid-2.11.0/dune/grid/test/checkentityseed.hh000066400000000000000000000133351511655130300220110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_CHECK_ENTITYSEED_HH #define DUNE_GRID_CHECK_ENTITYSEED_HH //- C++ includes #include #include #include //- dune-common includes #include //- dune-grid includes #include #include #include /** @file @author Christoph Gersbacher @brief Provides a check for EntitySeeds of all codimensions. */ namespace CheckEntitySeed // don't blur namespace Dune { // Capability hasEntitySeed // ------------------------ // allow for switching off the tests below by overloading this capability template< class Grid, int codim > struct hasEntitySeed { static const bool v = Dune::Capabilities::hasEntity< Grid, codim >::v; }; // Equals // ------ template< class T > struct Equals { typedef T Type; static bool apply ( const T &t1, const T &t2 ) { return ( t1 == t2 ); } }; // Template specialization for const // --------------------------------- template< class T > struct Equals< const T > : public Equals< T > { }; // Equals for Dune::Geometry // ------------------------------------------ template struct GeometryEquals { static bool apply ( const Geometry &t1, const Geometry &t2, const double eps = 1e-10 ) { //typedef typename Type::GlobalCoordinate GlobalCooridinate; // check geometry type if( t1.type() != t2.type() ) return false; // compare corners assert( t1.corners() == t2.corners() ); const int corners = t1.corners(); for( int i = 0; i < corners; ++i ) { if( (t1.corner( i ) - t2.corner( i )).two_norm() > eps ) return false; } return true; } }; // Check // ----- template< int codim, class GridView, bool check = hasEntitySeed< typename GridView::Grid, codim >::v > class Check; // Template specialization for hasEntitySeed< Grid, codim >::v = false // ------------------------------------------------------------------- template< int codim, class GridView > class Check< codim, GridView, false > { public: static void apply ( const GridView &, std::ostream & ) { }; }; // Template specialization for hasEntitySeed< Grid, codim >::v = true // ------------------------------------------------------------------ template< int codim, class GridView > class Check< codim, GridView, true > { public: // iterator type typedef typename GridView::template Codim< codim >::Iterator Iterator; // entity type typedef typename GridView::template Codim< codim >::Entity Entity; // geometry type typedef typename Entity::Geometry Geometry; // grid type typedef typename GridView::Grid Grid; // type of entity seed (not available on GridView) typedef typename Grid::template Codim< codim >::EntitySeed EntitySeed; // Check whether EntitySeed reports the correct codimension static_assert(EntitySeed::codimension==codim, "Codimension exported by EntitySeed is incorrect!"); static void apply ( const GridView &gridView, std::ostream &output ) { // get grid, as method entity() is missing on GridViews const Grid &grid = gridView.grid(); const Iterator end = gridView.template end< codim >(); for( Iterator it = gridView.template begin< codim >(); it != end; ++it ) { // get entity const Entity &entity = *it; EntitySeed seed = entity.seed(); // get entity from seed Entity entity2 = grid.entity( seed ); compare( entity, *it, output ); // test default constructor EntitySeed seed2; assert(! seed2.isValid()); // create copy of seed and compare again seed2 = seed; assert( seed2.isValid()); // we might like to check the assignment operator as well compare( entity2, grid.entity( seed2 ), output ); } } private: // compare two entities for equality static void compare ( const Entity &e1, const Entity &e2, std::ostream &output ) { // compare entities if( !Equals< Entity >::apply( e1, e2 ) ) output << "Warning: Entities do not coincide" << std::endl; // compare geometries const double eps = 1e-10; if( !GeometryEquals< Geometry >::apply( e1.geometry(), e2.geometry(), eps ) ) output << "Warning: Geometries do not coincide" << std::endl; } }; // IfHasEntitySeed // --------------- template< int codim > struct IfHasEntitySeed { template< class GridView > static void apply ( const GridView &gridView, std::ostream &output ) { if constexpr (Dune::Capabilities::hasEntityIterator::v) Check< codim, GridView >::apply( gridView, output ); } }; } // namespace CheckEntitySeed namespace Dune { /** \brief Check for EntitySeeds for all codimensions available in a grid implementation \param gridView Grid view for which EntitySeeds will be tested */ template< class VT > void checkEntitySeed ( const GridView< VT > &gridView, std::ostream &output = std::cerr ) { const int dimension = GridView< VT >::dimension; Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ CheckEntitySeed::IfHasEntitySeed< i >::apply( gridView, output ); } ); } } // namespace Dune #endif // #ifndef DUNE_GRID_CHECK_ENTITYSEED_HH dune-grid-2.11.0/dune/grid/test/checkgeometry.hh000066400000000000000000000133401511655130300214630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKGEOMETRY_HH #define DUNE_GRID_TEST_CHECKGEOMETRY_HH #include #include #include #include #include #include #include #include namespace Dune { template struct GeometryChecker; /** \param geometry The local geometry to be tested * \param type The type of the element that the local geometry is embedded in * \param geoName Helper string that will appear in the error message */ template< int mydim, int cdim, class Grid, template< int, int, class > class Imp > void checkLocalGeometry ( const Geometry< mydim, cdim, Grid, Imp > &geometry, GeometryType type, const std::string &geoName = "local geometry" ) { checkGeometry( geometry ); // check that corners are within the reference element of the given type assert( type.dim() == cdim ); // we can't get the reference element from the geometry here, because we need global coordinates auto refElement = referenceElement< typename Grid::ctype, cdim >( type ); const int numCorners = geometry.corners(); for( int i = 0; i < numCorners; ++i ) { if( !refElement.checkInside( geometry.corner( i ) ) ) { std::cerr << "Corner " << i << " of " << geoName << " not within reference element: " << geometry.corner( i ) << "." << std::endl; } } } template struct CheckSubEntityGeometry { template struct Operation { template static void apply(const Entity &entity) { std::integral_constant< bool, Dune::Capabilities::hasEntity::v > capVar; check(capVar,entity); } template static void checkGeometryStatic(const Geometry& geometry) { std::integral_constant< bool, Dune::Capabilities::hasGeometry::v > capVar; checkGeometry(capVar, geometry); } template static void checkGeometry(const std::true_type&,const Geometry& geometry) { Dune::checkGeometry(geometry); } template static void checkGeometry(const std::false_type&,const Geometry& /*geometry*/) {} template static void check(const std::true_type&, const Entity &entity) { for (unsigned int i=0; i(i); auto subGeo = subEn.geometry(); if( subEn.type() != subGeo.type() ) std::cerr << "Error: Entity and geometry report different geometry types on codimension " << codim << "." << std::endl; // Move from dynamic codim to static codim to // prevent checking non-existing geometries switch(codim+1) { case 0: { Operation<0> geometryChecker; geometryChecker.checkGeometryStatic(subGeo); break; } case 1: { Operation<1> geometryChecker; geometryChecker.checkGeometryStatic(subGeo); break; } case 2: { Operation<2> geometryChecker; geometryChecker.checkGeometryStatic(subGeo); break; } case 3: { Operation<3> geometryChecker; geometryChecker.checkGeometryStatic(subGeo); break; } default: break; } } } template static void check(const std::false_type&, const Entity &) {} }; }; template void checkGeometryLifetime (const GV &gridView) { typedef typename GV::ctype ctype; constexpr static int dim = GV::dimension; const FieldVector pos(0.2); auto it = gridView.template begin<0>(); const auto end = gridView.template end<0>(); // check that it != end otherwise the following is not valid if( it == end ) return ; #ifndef NDEBUG constexpr static int dimw = GV::dimensionworld; const FieldVector glob = it->geometry().global(pos); #endif const auto geomCopy = it->geometry(); checkGeometry ( geomCopy ); for( ; it != end; ++it ) { // due to register/memory differences we might have // errors < 1e-16 assert (std::abs((geomCopy.global(pos) - glob).one_norm()) < std::numeric_limits::epsilon()); } } template struct GeometryChecker { template using SubEntityGeometryChecker = typename CheckSubEntityGeometry::template Operation; template< class VT > void checkGeometry ( const GridView< VT > &gridView ) { const auto end = gridView.template end<0>(); auto it = gridView.template begin<0>(); for( ; it != end; ++it ) Hybrid::forEach(std::make_index_sequence::dimension+1>{},[&](auto i){SubEntityGeometryChecker::apply(*it);}); } }; } // namespace Dune #endif // #ifndef DUNE_GRID_TEST_CHECKGEOMETRY_HH dune-grid-2.11.0/dune/grid/test/checkgeometryinfather.hh000066400000000000000000000277521511655130300232200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKGEOMETRYINFATHER_HH #define DUNE_GRID_TEST_CHECKGEOMETRYINFATHER_HH #include #include "checkgeometry.hh" /** \file \brief A test for the Method Geometry::geometryInFather() */ /** \brief Test the Method Geometry::geometryInFather() This test works by comparing the output of geometryInFather with the vertex positions obtained by directly expressing the son vertex positions in local coordinates of the father. That should work for all grid implementations that realize truly nested grids. One exception is UGGrid with parametrized boundaries. */ template void checkGeometryInFather(const GridType& grid) { using namespace Dune; using std::sqrt; using ctype = typename GridType::ctype; // define a tolerance for floating-point checks const ctype tolerance = sqrt(std::numeric_limits< ctype >::epsilon()); // count the number of different vertices unsigned int differentVertexCoords = 0; typedef typename GridType::Traits::LocalIdSet IdSet; const IdSet &idSet = grid.localIdSet(); // We need at least two levels to do any checking if (grid.maxLevel()==0) { dwarn << "SKIPPING check geometryInFather(), because grid has only one level! \n"; return; } // Loop over all levels except the lowest one for (int level = 1; level <= grid.maxLevel(); ++level) { typedef typename GridType::template Codim<0>::LevelIterator ElementIterator; ElementIterator eIt = grid.levelGridView(level).template begin<0>(); ElementIterator eEndIt = grid.levelGridView(level).template end<0>(); for (; eIt!=eEndIt; ++eIt) { // check geometry checkGeometry( eIt->geometry() ); // check the father method if( eIt->hasFather() ) { typedef typename GridType::template Codim<0>::Entity Entity; Entity father = eIt->father(); // check geometry checkGeometry( father.geometry() ); while ( father.hasFather() ) { if( father.level() == 0 ) DUNE_THROW( GridError, "A level zero entity returns hasFather()=true." ); Entity grandPa = father.father(); typedef typename GridType :: Traits :: HierarchicIterator HierarchicIterator; const int mxl = grandPa.level() + 1; bool foundChild = false; const HierarchicIterator end = grandPa.hend( mxl ); for( HierarchicIterator sons = grandPa.hbegin( mxl ); sons != end; ++sons ) { // check geometry checkGeometry( sons->geometry() ); if( father != *sons ) { if( idSet.id( father ) == idSet.id( *sons ) ) DUNE_THROW( GridError, "Two different entities have the same id." ); } else foundChild = true; } if( !foundChild ) DUNE_THROW( GridError, "Cannot find child in its own father." ); father = grandPa; } } // hierarchy check { typedef typename GridType :: Traits :: HierarchicIterator HierarchicIterator; const int mxl = grid.maxLevel(); int countChildren = 0; HierarchicIterator end = eIt->hend(mxl); for(HierarchicIterator sons = eIt->hbegin(mxl); sons != end; ++sons) { ++countChildren; int count = sons->level(); if( sons->hasFather() ) { typedef typename GridType::template Codim<0>::Entity Entity; Entity father = sons->father(); --count; while ( father.hasFather() ) { father = father.father(); --count; } } assert( count == 0 ); } if( eIt->isLeaf () && countChildren > 0 ) DUNE_THROW(GridError, "leaf entity has children ==> entity is not leaf"); } if ( eIt->hasFather() ) { // Get geometry in father typedef typename GridType::template Codim<0>::Entity::Geometry Geometry; typedef typename GridType::template Codim<0>::Entity::LocalGeometry LocalGeometry; const LocalGeometry& geometryInFather = eIt->geometryInFather(); checkLocalGeometry( geometryInFather, eIt->father().type(), "geometryInFather" ); // ////////////////////////////////////////////////////// // Check for types and constants // ////////////////////////////////////////////////////// static_assert((std::is_same< typename Geometry::ctype, typename GridType::ctype>::value == true), "Geometry has wrong ctype"); static_assert((static_cast(Geometry::mydimension) == static_cast(GridType::dimension)), "Geometry has wrong mydimension"); static_assert((static_cast(Geometry::coorddimension) == static_cast(GridType::dimensionworld)), "Geometry has wrong coorddimension"); // /////////////////////////////////////////////////////// // Check the different methods // /////////////////////////////////////////////////////// if (geometryInFather.type() != eIt->type()) DUNE_THROW(GridError, "Type of geometry and geometryInFather differ!"); if (geometryInFather.corners() != eIt->geometry().corners()) DUNE_THROW(GridError, "entity and geometryInFather have different number of corners!"); // Compute the element center just to have an argument for the following methods auto refElement = referenceElement( geometryInFather ); typename LocalGeometry::GlobalCoordinate center = refElement.position(0,0); if (geometryInFather.integrationElement(center) <=0) DUNE_THROW(GridError, "nonpositive integration element found!"); // ///////////////////////////////////////////////////////////////////////////////////// // check global transformation of geometryInFather // ///////////////////////////////////////////////////////////////////////////////////// for( int j=0; j < eIt->geometry().corners(); ++j ) { // create a global vertex const typename Geometry::GlobalCoordinate cornerViaSon = eIt->geometry().corner(j); // map to child local const typename Geometry::LocalCoordinate cornerInSon = eIt->geometry().local(cornerViaSon); // map to father const typename Geometry::LocalCoordinate cornerInFather = geometryInFather.global(cornerInSon); // map father to global const typename Geometry::GlobalCoordinate cornerViaFather = eIt->father().geometry().global(cornerInFather); if( (cornerViaFather - cornerViaSon).infinity_norm() > tolerance ) { ++differentVertexCoords; std :: cout << "global transformation of geometryInFather yields different vertex position " << "(son: " << cornerViaSon << ", father: " << cornerViaFather << ")." << std :: endl; } } const typename Geometry::LocalCoordinate X(0.2); typename Geometry::LocalCoordinate x = X; typename GridType::template Codim<0>::Entity e(*eIt); while (e.level() != 0) { x = e.geometryInFather().global(x); e = e.father(); } if ((e.geometry().global(x)-eIt->geometry().global(X)).two_norm() > tolerance) { std::cerr << "Warning: mapping broken! " << e.geometry().global(x) << " vs. " << eIt->geometry().global(X) << "\tchild " << eIt->geometry().center() << "\tfather " << e.geometry().center() << "\tat " << x << "\tmaps to " << X << std::endl; } for( int j=0; j < eIt->geometry().corners(); ++j ) { // create a global vertex const typename Geometry::GlobalCoordinate cornerViaSon = eIt->geometry().corner(j); // map to child local const typename Geometry::LocalCoordinate cornerInSon = eIt->geometry().local(cornerViaSon); // map to father local const typename Geometry::LocalCoordinate cornerInFather = geometryInFather.global(cornerInSon); // map father to const typename Geometry::LocalCoordinate cornerFromGlobal = eIt->father().geometry().local(cornerViaSon); if( (cornerInFather - cornerFromGlobal).infinity_norm() > tolerance ) { ++differentVertexCoords; std :: cout << "geometryInFather().global() and yields different vertex position than father().geometry().local()" << "(from son: " << cornerInFather << ", from global: " << cornerFromGlobal << ")." << std :: endl; break; } } // ///////////////////////////////////////////////////////////////////////////////////// // check local transformation of geometryInFather // ///////////////////////////////////////////////////////////////////////////////////// for( int j=0; j < eIt->geometry().corners(); ++j ) { // create a global vertex const typename Geometry::GlobalCoordinate global = eIt->geometry().corner(j); // map to child local const typename Geometry::LocalCoordinate cornerInSon = eIt->geometry().local(global); // map global to father const typename Geometry::LocalCoordinate cornerInFather = eIt->father().geometry().local(global); // map from father to son const typename Geometry::LocalCoordinate cornerViaFather = geometryInFather.local(cornerInFather); if( (cornerViaFather - cornerInSon).infinity_norm() > tolerance ) { ++differentVertexCoords; std :: cout << "local transformation of geometryInFather yields different vertex position " << "(global: " << global << ", son: " << cornerInSon << ", father: " << cornerViaFather << ")." << std :: endl; } } /** \todo Missing jacobianInverse() */ /** \todo Missing checkInside() */ // ///////////////////////////////////////////////////////////////////////////////////// // Check whether the positions of the vertices of geometryInFather coincide // with the ones computed 'by hand'. This only works if the grids really are nested! // ///////////////////////////////////////////////////////////////////////////////////// for( int j=0; j < geometryInFather.corners(); ++j ) { const typename Geometry::GlobalCoordinate cornerViaFather = eIt->father().geometry().global( geometryInFather.corner( j ) ); const typename Geometry::GlobalCoordinate &cornerViaSon = eIt->geometry().corner( j ); if( (cornerViaFather - cornerViaSon).infinity_norm() > tolerance ) { ++differentVertexCoords; std :: cout << "geometryInFather yields different vertex position " << "(son: " << cornerViaSon << ", father: " << cornerViaFather << ")." << std :: endl; } } } } } if( differentVertexCoords > 0 ) { std :: cerr << "Warning: geometryInFather yields different vertex positions." << std :: endl; std :: cerr << " This behaviour may be correct if the grid is not" << " nested geometrically." << std :: endl; } } #endif // DUNE_GRID_TEST_CHECKGEOMETRYINFATHER_HH dune-grid-2.11.0/dune/grid/test/checkgridfactory.hh000066400000000000000000000101071511655130300221430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_GRID_TEST_CHECKGRIDFACTORY_HH #define DUNE_GRID_TEST_CHECKGRIDFACTORY_HH #include #include #include #include #include #include #include namespace Dune { // checkGridFactory // ---------------- template< class Grid, class Mesh, class Projection > void checkGridFactory ( const Mesh &mesh, Projection &&projection ) { GridFactory< Grid > factory; // create grid from mesh typedef FieldVector< typename Grid::ctype, Grid::dimensionworld > Vertex; mesh.addToGridFactory( factory, projection ); std::unique_ptr< Grid > gridptr( factory.createGrid() ); Grid &grid = *gridptr; // check insertion indices // check vertex insertion index for( const auto &vertex : vertices( grid.leafGridView() ) ) { std::size_t idx = factory.insertionIndex( vertex ); Vertex v = projection( mesh.vertices[ idx ] ); if( (v - vertex.geometry().center() ).two_norm() > 1e-8 ) DUNE_THROW( GridError, "GridFactory error, Vertex insertion Index wrong!" ); } // check element insertion index std::vector< unsigned int > indices; for( const auto &element : elements( grid.leafGridView() ) ) { std::size_t idx = factory.insertionIndex( element ); unsigned int numSubEntitites = element.subEntities( Grid::dimension ); if( numSubEntitites != mesh.elements[ idx ].second.size() ) DUNE_THROW( GridError, "GridFactory error, wrong number of subEntities inserted!" ); indices.clear(); for( unsigned int i = 0; i < numSubEntitites; ++i ) indices.push_back( factory.insertionIndex( element.template subEntity< Grid::dimension >( i ) ) ); if( !std::is_permutation( indices.begin(), indices.end(), mesh.elements[ idx ].second.begin() ) ) DUNE_THROW( GridError, "GridFactory error, Element insertion index wrong!" ); } // check boundary segment index typedef std::pair< unsigned int, std::vector< unsigned int > > BoundarySegementPair; std::vector< BoundarySegementPair > bndInsIndex; for( const auto &entity : elements( grid.leafGridView() ) ) { auto refelement = referenceElement< typename Grid::ctype, Grid::dimension >( entity.type() ); for( const auto &intersection : intersections( grid.leafGridView(), entity ) ) if( factory.wasInserted( intersection ) ) { std::vector< unsigned int > vertices; const int numSubEntitites = refelement.size( intersection.indexInInside(), 1, Grid::dimension ); for( int i = 0; i < numSubEntitites; ++i ) vertices.push_back( factory.insertionIndex( entity.template subEntity< Grid::dimension >( refelement.subEntity( intersection.indexInInside(), 1, i, Grid::dimension ) ) ) ); bndInsIndex.emplace_back( factory.insertionIndex( intersection ), vertices ); } } auto compare = [] ( const BoundarySegementPair &v, const BoundarySegementPair &w ) { return v.first == w.first; }; bndInsIndex.resize( std::distance( bndInsIndex.begin(), std::unique( bndInsIndex.begin(), bndInsIndex.end(), compare ) ) ); if( bndInsIndex.size() != mesh.boundaries.size() ) DUNE_THROW( GridError, "GridFactory error, wrong number of boundary segments inserted." ); for( const BoundarySegementPair &pair : bndInsIndex ) if( !std::is_permutation( pair.second.begin(), pair.second.end(), mesh.boundaries[ pair.first ].begin() ) ) DUNE_THROW( GridError, "GridFactory error, insertion index for boundary segment wrong." ); } template< class Grid, class Mesh > void checkGridFactory ( const Mesh &mesh ) { checkGridFactory< Grid >( mesh, [] ( const typename Mesh::Vertex &v ) { return v; } ); } } // namespace Dune #endif // #ifndef DUNE_GRID_TEST_CHECKGRIDFACTORY_HH dune-grid-2.11.0/dune/grid/test/checkidset.hh000066400000000000000000000107031511655130300207400ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKIDSET_HH #define DUNE_GRID_TEST_CHECKIDSET_HH #include #include #include #include #include #include /** @file @brief Unit tests for IdSet implementations */ namespace Dune { // Check the type used for ids template void checkIdType(const Grid& grid, const IdSet& idSet) { auto gridView = grid.leafGridView(); auto begin = gridView.template begin<0>(); // skip test for empty grids if( begin == gridView.template end<0>() ) return ; // Get some entity for testing auto entity = *begin; // The IdSet class exports a type IdSet, and this is the type actually // used for return values of the id class static_assert(std::is_same::value, "IdSet::IdType does not match the return value of idSet.id()"); static_assert(std::is_same::value, "IdSet::IdType does not match the return value of idSet.subId()"); // Get some id for testing auto id = idSet.id(entity); // Test for operator< if (id void checkInjectivity(const Grid& grid, const IdSet& idSet) { const int dim = Grid::dimension; using IdType = typename IdSet::IdType; using GlobalCoordinate = typename Grid::template Codim<0>::Geometry::GlobalCoordinate; std::map idContainer; // Loop over all entities of all codimensions on all grid levels for (int i=0; i<=grid.maxLevel(); ++i) { const auto gridView = grid.levelGridView(i); for (const auto& element: elements(gridView)) { // Loop over all faces of all codimensions Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( auto codim ) { if constexpr( Capabilities::hasEntity::v ) { for (size_t face=0; face(face); auto id = idSet.id(entity); // Has the same id already been used by a different entity? if (idContainer.find(id) != idContainer.end()) { // Yes. Then either we have seen the same entity before, or we are now // on the copy of an entity we have seen before. In either case we must // have the same entity center. // CAVEAT: This last reasoning does not hold if the grid uses parametrized // elements or parametrized boundaries. if (! FloatCmp::eq(entity.geometry().center(), idContainer[id], 1e-12 )) DUNE_THROW(GridError, "IdSet is not injective"); } else { idContainer[id] = entity.geometry().center(); } // While we are here: Do subEntity.id and subId return the same value? if (id != idSet.subId(element,face,codim)) DUNE_THROW(GridError, "subEntity.id and subId do not return the same value!"); } } }); } } } // Run all available tests for a given IdSet template void checkIdSet ( const Grid &grid, const IdSet& idSet) { checkIdType(grid,idSet); checkInjectivity(grid, idSet); } } // end namespace Dune #endif // DUNE_GRID_TEST_CHECKIDSET_HH dune-grid-2.11.0/dune/grid/test/checkindexset.hh000066400000000000000000000466671511655130300214750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKINDEXSET_HH #define DUNE_GRID_TEST_CHECKINDEXSET_HH #include #include #include #include #include #include #include #include #include #include #include /** @file @author Robert Kloefkorn @brief Provides a check of the grids index set. */ template< class Grid > struct EnableLevelIntersectionIteratorCheck { static const bool v = true; }; template< class Grid > struct EnableLevelIntersectionIteratorCheck< const Grid > { static const bool v = EnableLevelIntersectionIteratorCheck< Grid >::v; }; namespace Dune { // Check whether two FieldVectors are equal in the max norm template bool compareVec(const FieldVector & vx1 , const FieldVector & vx2 ) { const ctype eps = 1e5 * std::numeric_limits::epsilon(); return (vx1-vx2).infinity_norm() < eps; } /** \brief Check various features of codim-0 entities (elements) \param grid The grid we are testing \param en The grid element we are testing \param lset The corresponding level set \param sout The output stream that status (non-error) messages will go to \param setOfVerticesPerSubEntity A map that associates a vector of vertex indices to a subEntity \param subEntityPerSetOfVertices The reverse: a map that associates a subEntity to a vector of vertex indices \param vertexCoordsMap Map that associates vertex positions to indices (integers) */ template void checkSubEntity ( const GridType &, const Entity &en , const IndexSetType & lset, OutputStreamImp & sout , MapType1 & setOfVerticesPerSubEntity , MapType2 & subEntityPerSetOfVertices, const MapType3 & vertexCoordsMap ) { constexpr static int dim = GridType::dimension; const int dimworld = GridType::dimensionworld; typedef typename GridType::ctype coordType; const GeometryType type = en.type(); assert( type == en.geometry().type() ); if( type.isNone() ) return; auto refElem = referenceElement( en.geometry() ); // check whether the element has the number of codim-subentities mandated by the reference element if(int(en.subEntities(codim)) != refElem.size(0,0,codim)) { std::cerr << "entity index = " << lset.index(en) << ", type = " << type << std::endl << "codim = " << codim << std::endl << "subEntities(codim) = " << en.subEntities(codim) << std::endl << "refElem.size(codim) = " << refElem.size(0,0,codim) << std::endl; DUNE_THROW(GridError, "wrong number of subEntities of codim " << codim); } for( int subEntity = 0; subEntity < refElem.size( 0, 0, codim ); ++subEntity ) { // Number of vertices of the current subentity int numVertices = refElem.size( subEntity, codim, dim ); // every entity must have at least one vertex assert( numVertices > 0 ); // The local vertex numbers std::vector local (numVertices); for( int j = 0; j < numVertices; ++j ) local[ j ] = refElem.subEntity ( subEntity, codim, j, dim ); sout << numVertices << " vertices on subEntity< codim = " << codim << " >" << std::endl; sout << "check subentity [" << local[ 0 ]; for( int j = 1; j < numVertices; ++j ) sout << ", " << local[ j ]; sout << "]" << std::endl; // The global vertex numbers std::vector global(numVertices); for( int j = 0; j < numVertices; ++j ) global[ j ] = lset.subIndex( en, local[ j ], dim ); sout << "Found global numbers of entity [ "; for( int j = 0; j < numVertices; ++j ) sout << global[ j ] << " "; sout << "]" << std::endl; // Check whether we get the same index if we // -- ask for the subEntity itself and then its index // -- ask for the subIndex directly const auto& subE = en.template subEntity< codim >( subEntity ); if( lset.subIndex( en, subEntity, codim ) != lset.index( subE) ) { std::cerr << "Index for subEntity does not match." << std::endl; assert( lset.subIndex( en, subEntity, codim ) == lset.index( subE) ); } // Make a unique identifier for the subEntity. Since indices are unique only per GeometryType, // we need a (index,GeometryType)-pair. std::pair globalSubEntity( lset.index( subE ), subE.type() ); assert( globalSubEntity.first >= 0 ); sout << "local subentity " << subEntity << " consider subentity with global key (" << globalSubEntity.first << "," << globalSubEntity.second << ") on en = " << lset.index(en) << std::endl; if( subE.type() != subE.geometry().type() ) { std::cerr << "Geometry types for subEntity don't match." << std::endl; assert( subE.type() == subE.geometry().type() ); } // assert that all sub entities have the same level assert( subE.level() == en.level() ); // Loop over all vertices for( int j = 0; j < numVertices; ++j ) { // get entity pointer to subEntity vertex typedef typename GridType::template Codim< dim >::Entity VertexE; VertexE vxE = en.template subEntity< dim >( local[ j ] ); // Find the global coordinate of the vertex by its index if(vertexCoordsMap.find(global[j]) != vertexCoordsMap.end()) { // Check whether index and coordinate match FieldVector vxcheck ( vertexCoordsMap.find(global[j])->second ); FieldVector< coordType, dimworld > vx1 = vxE.geometry().corner( 0 ); if( ! compareVec( vxcheck, vx1 ) ) { std::cerr << "ERROR map global vertex [" << global[j] << "] vx " << vxcheck << " is not " << vx1 << "\n"; assert( compareVec( vxcheck, vx1 ) ); } } sout << "vx[" << global[j] << "] = " << subE.geometry().corner( j ) << "\n"; } sout << "sort vector of global vertex\n"; // sort vector of global vertex number for storage in map // the smallest entry is the first entry std::sort( global.begin(), global.end() ); // check whether vertex key is already stored in map if(subEntityPerSetOfVertices.find(global) == subEntityPerSetOfVertices.end()) { subEntityPerSetOfVertices[global] = globalSubEntity; } else { assert( globalSubEntity == subEntityPerSetOfVertices[global] ); } // check whether subEntity is already stored in map if(setOfVerticesPerSubEntity.find(globalSubEntity) == setOfVerticesPerSubEntity.end() ) { setOfVerticesPerSubEntity[globalSubEntity] = global; } else { std::vector globalcheck = setOfVerticesPerSubEntity[globalSubEntity]; if(! (global == globalcheck )) { std::cerr << "For subEntity key (" << globalSubEntity.first << "," << globalSubEntity.second << ") \n"; std::cerr << "Got "; for(int j=0 ; j void checkIndexSetForCodim ( const Grid &grid, const GridView &view, OutputStream &sout, bool levelIndex ) { constexpr static int dim = Grid :: dimension; constexpr static int dimworld = Grid :: dimensionworld; typedef typename Grid :: ctype coordType; //typedef typename GridView :: template Codim< 0 > :: Entity EntityCodim0Type; typedef typename GridView :: IndexSet IndexSetType; typedef typename GridView :: template Codim< codim > :: Iterator IteratorType; const IndexSetType &lset = view.indexSet(); sout <<"\n\nStart consistency check of index set \n\n"; // //////////////////////////////////////////////////////////////// // Check whether types() returns correct result // //////////////////////////////////////////////////////////////// std :: set< GeometryType > geometryTypes; const IteratorType endit = view.template end< codim >(); IteratorType it = view.template begin< codim >(); if (it == endit) return; for (; it!=endit; ++it) { // while we're here: check whether the GeometryTypes returned by the entity // and the Geometry match assert(it->type()==it->type()); geometryTypes.insert(it->type()); } const typename IndexSetType::Types types = lset.types( codim ); bool geomTypesError = false; // Check whether all entries in the official geometry types list are contained in our self-computed one for( auto itT = types.begin(); itT != types.end(); ++itT ) if( geometryTypes.find( *itT ) == geometryTypes.end() ) geomTypesError = true; // And vice versa for( std::set::iterator itG = geometryTypes.begin(); itG != geometryTypes.end(); ++itG ) { if( std::find( types.begin(), types.end(), *itG ) == types.end() ) geomTypesError = true; } if (geomTypesError) { std::cerr << "There is a mismatch in the list of geometry types of codim " << codim << "." << std::endl; std::cerr << "Geometry types present in the grid are:" << std::endl; for (std::set::iterator itG = geometryTypes.begin(); itG!=geometryTypes.end(); ++itG) std::cerr << " " << *itG << std::endl; std::cerr << std::endl << "but the method types() returned:" << std::endl; for( auto itT = types.begin(); itT != types.end(); ++itT ) std::cerr << " " << *itT << std::endl; DUNE_THROW(GridError, "!"); } //***************************************************************** // check size of index set int gridsize = 0; { using IteratorTypeV = typename GridView :: template Codim< codim > :: Iterator; int count = 0; const IteratorTypeV enditV = view.template end< codim >(); for( IteratorTypeV itV = view.template begin< codim >(); itV != enditV; ++itV ) ++count; int lsetsize = lset.size(codim); if( count != lsetsize) { derr << "WARNING: walk = "<< count << " entities | set = " << lsetsize << " for codim " << codim << std::endl; } gridsize = count; // lsetsize should be at least the size of iterated entities assert( count <= gridsize ); } { using IteratorTypeC = typename GridView :: template Codim< 0 > :: Iterator; using LocalIdSetType = typename Grid :: Traits :: LocalIdSet; using IdType = typename LocalIdSetType :: IdType; std::set< IdType > entityfound; const IteratorTypeC enditC = view.template end< 0 >(); auto itC = view.template begin< 0 >(); if( itC == enditC ) return; const auto &localIdSet = grid.localIdSet(); for( ; itC != enditC; ++itC ) { const auto &entity = *itC; if( !lset.contains( entity ) ) { std::cerr << "Error: IndexSet does not contain all entities." << std::endl; assert( false ); } const int subcount = entity.subEntities(codim); for( int i = 0; i < subcount; ++i ) { const auto id = localIdSet.id( entity.template subEntity< codim >( i ) ); entityfound.insert( id ); } } if( (size_t)gridsize != entityfound.size() ) { std::cerr << "Warning: gridsize = " << gridsize << " entities" << ", set of entities = " << entityfound.size() << " [codim " << codim << "]" << std::endl; } // gridsize should be at least the size of found entities //assert( gridsize <= (int) entityfound.size() ); } //****************************************************************** typedef std::pair < int , GeometryType > SubEntityKeyType; //typedef std::map < int , std::pair > subEntitymapType; std::map < SubEntityKeyType , std::vector > setOfVerticesPerSubEntity; std::map < std::vector , SubEntityKeyType > subEntityPerSetOfVertices; std::map < int , FieldVector > vertexCoordsMap; // setup vertex map , store vertex coords for vertex number { unsigned int count = 0; using VxIterator = typename GridView :: template Codim< dim > :: Iterator; const VxIterator endV = view.template end< dim >(); for( auto itV = view.template begin< dim >(); itV != endV; ++itV ) { ++count; // get coordinates of vertex FieldVector< coordType, dimworld > vx ( itV->geometry().corner( 0 ) ); // get index of vertex sout << "Vertex " << vx << "\n"; assert( lset.contains ( *itV ) ); int idx = lset.index( *itV ); sout << "Vertex " << idx << " = [" << vx << "]\n"; // if vertex not in map insert it if( vertexCoordsMap.find(idx) == vertexCoordsMap.end()) vertexCoordsMap[idx] = vx; } sout << "Found " << vertexCoordsMap.size() << " vertices for that index set!\n\n"; // check whether size of map equals all found vertices assert( vertexCoordsMap.size() == count ); // check whether size of vertices of set equals all found vertices sout << "Checking size of vertices " << count << " equals all found vertices " << (unsigned int)lset.size(Dune::GeometryTypes::vertex) << "\n"; // assertion goes wrong: // - for parallel grid since no iteration over ghost subentities // - if there are vertices with geometry type 'none' //assert( count == (unsigned int)lset.size(Dune::GeometryTypes::vertex) ); } { typedef typename GridView :: template Codim< 0 > :: Iterator Iterator; // choose the right reference element #ifndef NDEBUG const Iterator refend = view.template end< 0 >(); #endif Iterator refit = view.template begin< 0 >(); assert( refit != refend ); auto refElem = referenceElement( refit->geometry() ); // print dune reference element sout << "Dune reference element provides: \n"; for(int i = 0; i < refElem.size( codim ); ++i ) { sout << i << " subEntity ["; int s = refElem.size(i,codim,dim); for(int j=0; j :: Iterator; const Iterator enditC = view.template end< 0 >(); for( Iterator itC = view.template begin< 0 >(); itC != enditC; ++itC ) { // if (it->partitionType()==4) continue; sout << "****************************************\n"; sout << "Element = " << lset.index(*itC) << " on level " << itC->level () << "\n"; sout << "Vertices = ["; int svx = itC->subEntities(dim); // print all vertex numbers for( int i = 0; i < svx; ++i ) { const typename IndexSetType::IndexType idx = lset.subIndex( *itC, i, dim ); sout << idx << (i < svx-1 ? ", " : "]\n"); } // print all vertex coordinates sout << "Vertex Coords = ["; for( int i = 0; i < svx; ++i ) { // get entity pointer of sub entity codim=dim (Vertex) typedef typename GridView::template Codim< dim >::Entity VertexE; VertexE vxE = itC->template subEntity< dim >( i ); // get coordinates of entity pointer FieldVector< coordType, dimworld > vx( vxE.geometry().corner( 0 ) ); // output vertex coordinates sout << vx << (i < svx-1 ? ", " : "]\n"); const typename IndexSetType::IndexType vxidx = lset.subIndex( *itC, i, dim ); // the subIndex and the index for subEntity must be the same if( vxidx != lset.index( vxE ) ) { std::cerr << "Error: index( *subEntity< dim >( i ) ) != subIndex( entity, i, dim )" << std::endl; assert( vxidx == lset.index( vxE ) ); } // check whether the coordinates are the same assert(vertexCoordsMap.find(vxidx)!=vertexCoordsMap.end()); FieldVector vxcheck ( vertexCoordsMap[vxidx] ); if( !compareVec( vxcheck, vx ) ) { std::cerr << "Error: Inconsistent map of global vertex " << vxidx << ": " << vxcheck << " != " << vx << " (type = " << itC->partitionType() << ")" << std::endl; assert( compareVec( vxcheck, vx ) ); } } //////////////////////////////////////////////////////////// // check sub entities //////////////////////////////////////////////////////////// checkSubEntity< codim >( grid, *itC, lset, sout, setOfVerticesPerSubEntity, subEntityPerSetOfVertices, vertexCoordsMap ); // check neighbors if( codim == 1 ) { typedef typename GridView :: IntersectionIterator IntersectionIterator; if( !levelIndex || EnableLevelIntersectionIteratorCheck< typename GridView::Grid >::v ) { const IntersectionIterator endnit = view.iend( *itC ); for( IntersectionIterator nit = view.ibegin( *itC ); nit != endnit; ++nit ) { if( !nit->neighbor() ) continue; checkSubEntity< codim >( grid, nit->outside(), lset, sout, setOfVerticesPerSubEntity, subEntityPerSetOfVertices, vertexCoordsMap ); } } else { static int called = 0; if( called++ == 0 ) std::cerr << "Warning: Skipping index test using LevelIntersectionIterator." << std::endl; } } } } } template< class Grid, class GridView, class OutputStream > void checkIndexSet ( const Grid &grid, const GridView &view, OutputStream &sout, bool levelIndex = false ) { Hybrid::forEach( std::make_index_sequence< Grid :: dimension+1 >{}, [ & ]( auto codim ) { if constexpr (Capabilities :: hasEntityIterator< Grid, codim>::v) checkIndexSetForCodim< codim >( grid, view, sout, levelIndex ); else derr << "WARNING: Entities for codim " << int(codim) << " are not being tested!" << std::endl; }); } } // end namespace Dune #endif // DUNE_GRID_TEST_CHECKINDEXSET_HH dune-grid-2.11.0/dune/grid/test/checkintersectionit.hh000066400000000000000000000637531511655130300227100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKINTERSECTIONIT_HH #define DUNE_GRID_TEST_CHECKINTERSECTIONIT_HH #include #include #include #include #include "checkiterators.hh" #include "checkgeometry.hh" /** \file \brief Tests for the IntersectionIterator */ struct CheckIntersectionIteratorErrorState { unsigned int sumNormalsNonZero; CheckIntersectionIteratorErrorState () : sumNormalsNonZero( 0 ) {} }; template< class Grid > struct EnableIntersectionIteratorReverseCheck { static const bool v = true; }; // Check that normal and normal2 pointing in the same direction template< class ctype, int dimworld, class String > inline void checkParallel ( const Dune::FieldVector< ctype, dimworld > &normal, const Dune::FieldVector< ctype, dimworld > &refNormal, const String & name ) { using std::sqrt; if( (normal.two_norm()*refNormal.two_norm() - normal*refNormal) > sqrt(std::numeric_limits< ctype >::epsilon()) ) { std::cerr << "Error: " << name << " does not point in the direction of outer normal." << std::endl; std::cerr << " " << name << " = " << normal << ", outer normal = " << refNormal << std :: endl; assert( false ); } } // Check whether the normal is orthogonal to the intersection, i.e., // whether (J^-1 * n) = 0. Here J is the jacobian of the intersection // geometry (geometry) and n is a normal. template< class ctype, int dimworld, class JacobianInverseTransposed, class String > inline void checkJIn ( const Dune :: FieldVector< ctype, dimworld > &normal, const JacobianInverseTransposed &jit, const String & name ) { using std::sqrt; const int facedim = JacobianInverseTransposed::cols; Dune :: FieldVector< ctype, facedim > x( ctype( 0 ) ); jit.umtv( normal, x ); if (x.infinity_norm() > sqrt(std::numeric_limits< ctype >::epsilon())) { const Dune::FieldMatrix< ctype, dimworld, facedim > &mjit = jit; std :: cerr << "Error: (J^-1 * n) != 0." << std :: endl; std :: cerr << " " << name << " = " << normal << std :: endl; std :: cerr << " J^-1^T = \n" << mjit << std::endl; assert( false ); } } template< class GridView > void checkIntersectionAssignment ( const GridView &view, const typename GridView::template Codim< 0 >::Iterator &l ) { typedef typename GridView::template Codim< 0 >::Iterator Iterator; typedef typename GridView::IntersectionIterator IntersectionIterator; Iterator l1( l ); Iterator l2( l ); ++l2; if( l2 != view.template end< 0 >() ) { IntersectionIterator it1 = view.ibegin( *l1 ); IntersectionIterator it2 = view.ibegin( *l2 ); // verify prerequisites assert( l1 != l2 ); assert( it1 != it2 ); assert( it1->inside() == *l1 ); assert( it2->inside() == *l2 ); // check assignment it1 = it2; assert( it1 == it2 ); assert( it1->inside() == *l2 ); } } template< class Intersection > void checkIntersection ( const Intersection &intersection, bool isCartesian = false ) { using std::sqrt; typedef typename Intersection::ctype ctype; typedef typename Intersection::Entity Entity; typedef typename Intersection::LocalGeometry LocalGeometry; typedef typename Intersection::Geometry Geometry; [[maybe_unused]] const int dimension = Entity::dimension; const int mydimension = Intersection::mydimension; // check consistency of exported types static_assert((std::is_same< ctype, typename Entity::Geometry::ctype >::value), "Type Intersection::ctype differs from Intersection::Entity::ctype."); static_assert((std::is_same< ctype, typename LocalGeometry::ctype >::value), "Type Intersection::ctype differs from Intersection::LocalGeometry::ctype."); static_assert((std::is_same< ctype, typename Geometry::ctype >::value), "Type Intersection::ctype differs from Intersection::Geometry::ctype."); const ctype tolerance = sqrt(std::numeric_limits< ctype >::epsilon()); // cache some information on the intersection const int indexInInside = intersection.indexInInside(); // obtain inside entity, its geometry and reference element const Entity inside = intersection.inside(); const typename Entity::Geometry insideGeometry = inside.geometry(); auto refElement = referenceElement( insideGeometry ); // check that boundary id has positive value and that intersection is conforming if( intersection.boundary() ) { if( !intersection.conforming() && !intersection.neighbor() ) DUNE_THROW( Dune::GridError, "Boundary intersections must be conforming." ); } // check the geometry const Geometry geometry = intersection.geometry(); checkGeometry( geometry ); if( geometry.type() != intersection.type() ) { std::cerr << "Error: Reference geometry type for intersection and its global geometry differ." << std::endl; assert( false ); } // check the geometryInInside if( !inside.type().isNone() ) { const LocalGeometry geometryInInside = intersection.geometryInInside(); checkLocalGeometry( geometryInInside, inside.type(), "geometryInInside" ); if( geometryInInside.corners() != geometry.corners() ) DUNE_THROW( Dune::GridError, "Intersection's geometry is inconsistent with concatenation of inside entity's geometry and intersection's geometryInInside."); // create quadrature rule as a set of test points const Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre; const Dune::QuadratureRule< ctype, mydimension > &quadrature = Dune::QuadratureRules< ctype, mydimension >::rule( intersection.type(), 3, qt ); for( std::size_t i = 0; i < quadrature.size(); ++i ) { const Dune::FieldVector< ctype, mydimension > &pt = quadrature[ i ].position(); typename Geometry::GlobalCoordinate globalPos = geometry.global( pt ); typename Geometry::GlobalCoordinate localPos = insideGeometry.global( geometryInInside.global( pt ) ); if( (globalPos - localPos).infinity_norm() > tolerance ) { std::cerr << "Error: Intersection's geometry is inconsistent with concatenation of inside entity's geometry and intersection's geometryInInside." << std::endl; std::cerr << " inside()->geometry().global( intersection.geometryInInside().global( x ) ) != intersection.geometry().global( x )" << std::endl; std::cerr << " x = " << pt << std::endl; std::cerr << " intersection.geometry() = " << geometry.corner( 0 ); for( int i = 1; i < geometry.corners(); ++i ) std::cerr << " | " << geometry.corner( i ); std::cerr << std::endl; std::cerr << " intersection.geometryInInside() = " << geometryInInside.corner( 0 ); for( int i = 1; i < geometryInInside.corners(); ++i ) std::cerr << " | " << geometryInInside.corner( i ); std::cerr << std::endl; std::cerr << " inside()->geometry() = " << insideGeometry.corner( 0 ); for( int i = 1; i < insideGeometry.corners(); ++i ) std::cerr << " | " << insideGeometry.corner( i ); std::cerr << std::endl; assert( false ); } } } // check geometryInOutside if( intersection.neighbor() ) { const Entity outside = intersection.outside(); if( !outside.type().isNone() ) { const LocalGeometry geometryInOutside = intersection.geometryInOutside(); checkLocalGeometry( geometryInOutside, outside.type(), "geometryInOutside" ); if( geometryInOutside.corners() != geometry.corners() ) DUNE_THROW( Dune::GridError, "Intersection's geometry is inconsistent with concatenation of outside entity's geometry and intersection's geometryInOutside."); if( !intersection.boundary() ) { const typename Entity::Geometry outsideGeometry = outside.geometry(); // create quadrature rule as a set of test points const Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre; const Dune::QuadratureRule< ctype, mydimension > &quadrature = Dune::QuadratureRules< ctype, mydimension >::rule( intersection.type(), 3, qt ); for( std::size_t i = 0; i < quadrature.size(); ++i ) { const Dune::FieldVector< ctype, mydimension > &pt = quadrature[ i ].position(); typename Geometry::GlobalCoordinate globalPos = geometry.global( pt ); typename Geometry::GlobalCoordinate localPos = outsideGeometry.global( geometryInOutside.global( pt ) ); if( (globalPos - localPos).infinity_norm() > tolerance ) { std::cerr << "Error: Intersection's geometry is inconsistent with concatenation of outside entity's geometry and intersection's geometryInOutside." << std::endl; std::cerr << " outside()->geometry().global( intersection.geometryInOutside().global( x ) ) != intersection.geometry().global( x )" << std::endl; std::cerr << " x = " << pt << std::endl; std::cerr << " intersection.geometry() = " << geometry.corner( 0 ); for( int i = 1; i < geometry.corners(); ++i ) std::cerr << " | " << geometry.corner( i ); std::cerr << std::endl; std::cerr << " intersection.geometryInOutside() = " << geometryInOutside.corner( 0 ); for( int i = 1; i < geometryInOutside.corners(); ++i ) std::cerr << " | " << geometryInOutside.corner( i ); std::cerr << std::endl; std::cerr << " outside()->geometry() = " << outsideGeometry.corner( 0 ); for( int i = 1; i < outsideGeometry.corners(); ++i ) std::cerr << " | " << outsideGeometry.corner( i ); std::cerr << std::endl; assert( false ); } } } } } // check normal vectors if( !intersection.type().isNone() ) { // create quadrature rule as a set of test points const Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre; const Dune::QuadratureRule< ctype, mydimension > &quadrature = Dune::QuadratureRules< ctype, mydimension >::rule( intersection.type(), 3, qt ); for( std::size_t i = 0; i < quadrature.size(); ++i ) { const Dune::FieldVector< ctype, mydimension > &pt = quadrature[ i ].position(); const typename Geometry::JacobianInverseTransposed &jit = geometry.jacobianInverseTransposed( pt ); // independently calculate the integration outer normal for the inside entity typename Geometry::GlobalCoordinate refIntNormal; if( !inside.type().isNone() ) { const LocalGeometry geometryInInside = intersection.geometryInInside(); const typename LocalGeometry::GlobalCoordinate xInside = geometryInInside.global( pt ); const typename LocalGeometry::GlobalCoordinate &refNormal = refElement.integrationOuterNormal( indexInInside ); insideGeometry.jacobianInverseTransposed( xInside ).mv( refNormal, refIntNormal ); // note: refElement.template geometry< 1 >( indexInInside ) is affine, // hence we may use any point to obtain the integrationElement. refIntNormal *= insideGeometry.integrationElement( xInside ) * geometryInInside.integrationElement( pt ) / refElement.template geometry< 1 >( indexInInside ).integrationElement( pt ); } // check outer normal const typename Intersection::GlobalCoordinate normal = intersection.outerNormal( pt ); if( !inside.type().isNone() ) checkParallel( normal, refIntNormal, "outerNormal" ); // check normal vector is orthogonal to all vectors connecting the vertices // note: This only makes sense for non-curved faces. As there is no method // to check curvature, we only check this for affine surface. if( geometry.affine() ) { for( int c = 1; c < geometry.corners(); ++c ) { typename Geometry::GlobalCoordinate x = geometry.corner( c-1 ); x -= geometry.corner( c ); if( x*normal >= tolerance ) { std::cerr << "outerNormal not orthogonal to line between corner " << (c-1) << " and corner " << c << "." << std::endl; assert( false ); } } } // check consistency with JacobianInverseTransposed (J^-1 * n) = 0, // where J denotes the Jacobian of the intersection's geometry and n is a // normal. checkJIn( normal, jit, "outerNormal" ); // check integration outer normal const typename Intersection::GlobalCoordinate intNormal = intersection.integrationOuterNormal( pt ); const ctype det = geometry.integrationElement( pt ); if( std::abs( det - intNormal.two_norm() ) > tolerance ) { std::cerr << "Error: integrationOuterNormal yields wrong length." << std::endl; std::cerr << " |integrationOuterNormal| = " << intNormal.two_norm() << ", integrationElement = " << det << std::endl; assert( false ); } checkJIn( intNormal, jit, "integrationOuterNormal" ); if( !inside.type().isNone() ) { checkParallel( intNormal, refIntNormal, "integrationOuterNormal" ); if( (intNormal - refIntNormal).two_norm() > tolerance ) { std::cerr << "Error: Wrong integration outer normal (" << intNormal << ", should be " << refIntNormal << ")." << std::endl; std::cerr << " Intersection: " << geometry.corner( 0 ); for( int c = 1; c < geometry.corners(); ++c ) std::cerr << ", " << geometry.corner( c ); std::cerr << "." << std::endl; assert( false ); } } // check unit outer normal const typename Intersection::GlobalCoordinate unitNormal = intersection.unitOuterNormal( pt ); if( std::abs( ctype( 1 ) - unitNormal.two_norm() ) > tolerance ) { std::cerr << "Error: unitOuterNormal yields wrong length." << std::endl; std::cerr << " |unitOuterNormal| = " << unitNormal.two_norm() << std::endl; assert( false ); } checkJIn( unitNormal, jit, "unitOuterNormal" ); if( !inside.type().isNone() ) checkParallel( unitNormal, refIntNormal, "unitOuterNormal" ); // check normal for Cartesian grids if( isCartesian ) { if( !geometry.affine() ) DUNE_THROW( Dune::GridError, "Intersection's geometry is not affine, although isCartesian is true" ); // check that unit normal of Cartesian grid is given in a specific way typename Intersection::GlobalCoordinate normal( 0 ); normal[ indexInInside / 2 ] = 2 * (indexInInside % 2) - 1; if( (normal - unitNormal).infinity_norm() > tolerance ) DUNE_THROW( Dune::GridError, "Unit normal is not in Cartesian format, although isCartesian is true" ); } } // check center unit outer normal auto refFace = referenceElement( geometry ); if( (intersection.centerUnitOuterNormal() - intersection.unitOuterNormal( refFace.position( 0, 0 ) )).two_norm() > tolerance ) { std::cerr << "Error: centerUnitOuterNormal() does not match unitOuterNormal( " << refFace.position( 0, 0 ) << " )." << std::endl; std::cerr << " centerUnitOuterNormal = " << intersection.centerUnitOuterNormal() << ", unitOuterNormal( " << refFace.position( 0, 0 ) << " ) = " << intersection.unitOuterNormal( refFace.position( 0, 0 ) ) << std::endl; assert( false ); } } } /** \brief Test the IntersectionIterator */ template< class GridViewType, class ErrorState > void checkIntersectionIterator ( const GridViewType &view, const typename GridViewType::template Codim< 0 >::Iterator &eIt, ErrorState &errorState ) { using std::sqrt; typedef typename GridViewType::Grid GridType; typedef typename GridViewType::IntersectionIterator IntersectionIterator; typedef typename GridViewType::Intersection Intersection; typedef typename GridType::ctype ctype; typedef typename Intersection::Entity Entity; const bool isCartesian = Dune::Capabilities::isCartesian< GridType >::v; const bool checkOutside = EnableIntersectionIteratorReverseCheck< GridType >::v; // check consistency of exported types static_assert( (std::is_same< ctype, typename Intersection::ctype >::value), "Type GridView::Grid::ctype differs from GridView::Intersection::ctype." ); static_assert( (std::is_same< Intersection, typename IntersectionIterator::Intersection >::value), "Type GridView::Intersection differs from GridView::IntersectionIterator::Intersection." ); static_assert((static_cast(Intersection::dimensionworld) == static_cast(GridType::dimensionworld)),"IntersectionIterator has wrong dimensionworld"); // check default constructibility of intersections [[maybe_unused]] Intersection default_construct_intersection; // initialize variables for element checks bool hasBoundaryIntersection = false; typename Intersection::GlobalCoordinate sumNormal( ctype( 0 ) ); // check whether intersection iterator is a forward iterator NoopFunctor< Intersection > op; if( 0 != testForwardIterator( view.ibegin( *eIt ), view.iend( *eIt ), op ) ) DUNE_THROW( Dune::Exception, "IntersectionIterator does not fulfill the forward iterator concept" ); const IntersectionIterator iend = view.iend( *eIt ); for( IntersectionIterator iIt = view.ibegin( *eIt ); iIt != iend; ++iIt ) { const Intersection &intersection = *iIt; // perform intersection check checkIntersection( intersection, isCartesian ); // check correctness of inside entity if( *eIt != intersection.inside() ) { std::cerr << "Error: Intersection's inside entity does not equal the entity the intersection iterator was started on." << std::endl; assert( false ); } // check if conforming() method is compatible with static information on grid view if( GridViewType::conforming && !intersection.conforming() ) DUNE_THROW( Dune::GridError, "Non-conforming intersection found in a conforming grid view (static)." ); // check if conforming() method is compatible with dynamic information on grid view if( view.isConforming() && !intersection.conforming() ) DUNE_THROW( Dune::GridError, "Non-conforming intersection found in a conforming grid view (dynamic)." ); // check symmetry of 'has-intersection-with'-relation if( intersection.neighbor() && checkOutside ) { const Entity outside = intersection.outside(); bool insideFound = false; const IntersectionIterator oiend = view.iend( outside ); for( IntersectionIterator oiit = view.ibegin( outside ); oiit != oiend; ++oiit ) { if( !oiit->neighbor() || (oiit->outside() != intersection.inside()) ) continue; insideFound = true; if( oiit->indexInInside() != intersection.indexInOutside() ) { std::cerr << "Error: symmetric intersection found, but with incorrect numbering." << std::endl; std::cerr << " (from inside: indexInOutside = " << intersection.indexInOutside() << ", from outside: indexInInside = " << oiit->indexInInside() << ")." << std::endl; assert( false ); } if( oiit->indexInOutside() != intersection.indexInInside() ) { std::cerr << "Error: symmetric intersection found, but with incorrect numbering." << std::endl; std::cerr << " (from inside: indexInInside = " << intersection.indexInInside() << ", from outside: indexInOutside = " << oiit->indexInOutside() << ")." << std::endl; assert( false ); } if( oiit->boundary() != intersection.boundary() ) { std::cerr << "Error: symmetric intersection found, but with incorrect boundary flag." << std::endl; std::cerr << " (from inside: boundary = " << intersection.boundary() << ", from outside: boundary = " << oiit->boundary() << ")." << std::endl; assert( false ); } } if( !insideFound ) DUNE_THROW( Dune::GridError, "Could not find inside entity through intersection iterator on outside entity." ); } else if( !checkOutside ) { static bool called = false; if( !called ) { Dune::derr << "Warning: Skipping reverse intersection iterator check." << std::endl; called = true; } } // check consistency of conforming intersection if( intersection.conforming() && intersection.neighbor() && !intersection.boundary() ) { const Entity outside = intersection.outside(); const int indexInInside = intersection.indexInInside(); const int indexInOutside = intersection.indexInOutside(); const typename GridViewType::IndexSet &indexSet = view.indexSet(); if( indexSet.subIndex( *eIt, indexInInside, 1 ) != indexSet.subIndex( outside, indexInOutside, 1 ) ) { std::cerr << "Error: Index of conforming intersection differs when " << "obtained from inside and outside." << std::endl; std::cerr << " inside index = " << indexSet.subIndex( *eIt, indexInInside, 1 ) << ", outside index = " << indexSet.subIndex( outside, indexInOutside, 1 ) << std::endl; assert( false ); } const typename GridType::LocalIdSet &localIdSet = view.grid().localIdSet(); if( localIdSet.subId( *eIt, indexInInside, 1 ) != localIdSet.subId( outside, indexInOutside, 1 ) ) { std::cerr << "Error: Local id of conforming intersection differs when " << "obtained from inside and outside." << std::endl; std::cerr << " inside id = " << localIdSet.subId( *eIt, indexInInside, 1 ) << ", outside id = " << localIdSet.subId( outside, indexInOutside, 1 ) << std::endl; assert( false ); } const typename GridType::GlobalIdSet &globalIdSet = view.grid().globalIdSet(); if( globalIdSet.subId( *eIt, indexInInside, 1 ) != globalIdSet.subId( outside, indexInOutside, 1 ) ) { std::cerr << "Error: Global id of conforming intersection differs when " << "obtained from inside and outside." << std::endl; std::cerr << " inside id = " << globalIdSet.subId( *eIt, indexInInside, 1 ) << ", outside id = " << globalIdSet.subId( outside, indexInOutside, 1 ) << std::endl; assert( false ); } } // update variables for element checks if( intersection.boundary() ) hasBoundaryIntersection = true; const Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre; const Dune::QuadratureRule< ctype, Intersection::mydimension > &quadrature = Dune::QuadratureRules< ctype, Intersection::mydimension >::rule( intersection.type(), 3, qt ); for( std::size_t i = 0; i < quadrature.size(); ++i ) sumNormal.axpy( quadrature[ i ].weight(), intersection.integrationOuterNormal( quadrature[ i ].position() ) ); } // check implementation of hasBoundaryIntersections if( hasBoundaryIntersection != eIt->hasBoundaryIntersections() ) { if( !hasBoundaryIntersection ) { std::cerr << "Entity::hasBoundaryIntersections has a false positive." << std::endl; assert( false ); } else DUNE_THROW( Dune::GridError, "Entity::hasBoundaryIntersections has a false negative." ); } // check whether integral over the outer normals is zero // note: This is wrong on curved surfaces (take, e.g., the upper half sphere). // Therefore we only enforce this check on affine elements. // This might be also wrong for network grids where intersections maybe overlapping // Therefore we only enforce this check for dim==dimworld // note: The errorState variable will propagate the error as a warning for the cases // where this check is not enforced if( (sumNormal.two_norm() > sqrt(std::numeric_limits< ctype >::epsilon())) && (eIt->partitionType() != Dune::GhostEntity) ) { if( eIt->geometry().affine() && int(GridViewType::dimension) == int(GridViewType::dimensionworld)) DUNE_THROW( Dune::GridError, "Integral over outer normals on affine entity is nonzero: " << sumNormal ); ++errorState.sumNormalsNonZero; } // check assignment operator for IntersectionIterator checkIntersectionAssignment( view, eIt ); } /** \brief Test both IntersectionIterators */ template void checkViewIntersectionIterator(const GridViewType& view) { using namespace Dune; typedef typename GridViewType ::template Codim<0>::Iterator ElementIterator; ElementIterator eIt = view.template begin<0>(); ElementIterator eEndIt = view.template end<0>(); CheckIntersectionIteratorErrorState errorState; for (; eIt!=eEndIt; ++eIt) checkIntersectionIterator( view, eIt, errorState ); if( errorState.sumNormalsNonZero > 0 ) { std :: cerr << "Warning: Integral over outer normals is not always zero." << std :: endl; std :: cerr << " This behaviour may be correct for entities with" << " nonzero curvature, or in network grids." << std :: endl; } } template void checkIntersectionIterator(const GridType& grid, bool skipLevelIntersectionTest = false) { using namespace Dune; // Loop over all levels if(skipLevelIntersectionTest) { std::cerr<<"WARNING: skip test of LevelIntersectionIterator! \n"; } else { for (int i=0; i<=grid.maxLevel(); i++) checkViewIntersectionIterator(grid.levelGridView(i)); } // test leaf intersection iterator { checkViewIntersectionIterator(grid.leafGridView()); } } #endif // DUNE_GRID_TEST_CHECKINTERSECTIONIT_HH dune-grid-2.11.0/dune/grid/test/checkintersectionlifetime.hh000066400000000000000000000106121511655130300240540ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKINTERSECTIONLIFETIME_HH #define DUNE_GRID_TEST_CHECKINTERSECTIONLIFETIME_HH /** \file \brief Tests that make sure range-based intersection iteration works correctly and that copied intersections have the correct lifetime */ #include #include #include #include #include template void checkIntersectionLifetime(GV gv, std::size_t check_element_count = 32) { using namespace Dune; std::cout << "Intersection Lifetime / consistency check" << std::endl; if (check_element_count > static_cast(gv.size(0))) { std::cout << "WARNING! Requested check of intersections for first " << check_element_count << " elements, but grid view only contains " << gv.size(0) << " elements" << std::endl; check_element_count = gv.size(0); } auto& index_set = gv.indexSet(); std::vector > indices; std::vector::Entity> entity_list; std::vector > intersection_list; std::vector > coords; #if DUNE_GRID_HAVE_CONCEPTS using EntityIterator = decltype(gv.template begin<0>()); using IntersectionIterator = decltype(gv.ibegin(*std::declval())); static_assert(Dune::Concept::EntityIterator); static_assert(Dune::Concept::IntersectionIterator); static_assert(Dune::Concept::Entity())>>); static_assert(Dune::Concept::Intersection())>>); #endif // store indices + entities + intersections + coordinates { std::size_t i = 0; for (const auto& e : elements(gv)) { if (++i > check_element_count) break; entity_list.push_back(e); indices.push_back({}); intersection_list.push_back({}); coords.push_back({}); for (const auto& is : intersections(gv,e)) { #if DUNE_GRID_HAVE_CONCEPTS static_assert(Dune::Concept::Entity>); static_assert(Dune::Concept::Intersection>); #endif indices.back().push_back(is.indexInInside()); intersection_list.back().push_back(is); coords.back().push_back(is.geometry().corner(0)); } } } // check for consistency { std::size_t i = 0; for (const auto& e : elements(gv)) { if (i >= check_element_count) break; if (e != entity_list[i]) DUNE_THROW( InvalidStateException, "ERROR! Got different entity on second iteration for entity " << i << " (" << index_set.index(entity_list[i]) << " != " << index_set.index(e) << ")"); std::size_t j = 0; for (const auto& is : intersections(gv,e)) { if (indices[i][j] != is.indexInInside()) DUNE_THROW( InvalidStateException, "ERROR! inconsistent indexInInside() for intersection " << j << " of entity " << i << " (" << indices[i][j] << " != " << is.indexInInside() << ")"); if (intersection_list[i][j] != is) DUNE_THROW( InvalidStateException, "ERROR! inconsistent intersection equality for intersection " << j << " of entity " << i); if (entity_list[i] != is.inside()) DUNE_THROW( InvalidStateException, "ERROR! inconsistent inside() for intersection " << j << " of entity " << i); if (coords[i][j] != is.geometry().corner(0)) DUNE_THROW( InvalidStateException, "ERROR! inconsistent corner(0) coordinate for intersection " << j << " of entity " << i << " (" << coords[i][j] << " != " << is.geometry().corner(0) << ")"); ++j; } ++i; } } } #endif // #ifndef DUNE_GRID_TEST_CHECKENTITYLIFETIME_HH dune-grid-2.11.0/dune/grid/test/checkiterators.hh000066400000000000000000000071751511655130300216550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKITERATORS_HH #define DUNE_GRID_TEST_CHECKITERATORS_HH #include #include #include #include #include #include #include template class NoopFunctor { public: NoopFunctor() {} void operator()(const T& ){} }; // CheckCodimIterators // ------------------- template< class GridView, int codim, bool hasEntity = Dune::Capabilities::hasEntityIterator< typename GridView::Grid, codim >::v > struct CheckCodimIterators; template< class GridView, int codim > struct CheckCodimIterators< GridView, codim, false > { static void apply ( const GridView &gridView ) { std::cerr << "Warning: Not checking iterators for codimension " << codim << ", because the corresponding entities are not implemented." << std::endl; } }; template< class GridView, int codim > struct CheckCodimIterators< GridView, codim, true > { static void apply ( const GridView &gridView ); }; // CheckIterators // -------------- template< class GridView > class CheckIterators { template< int codim > struct CheckCodim; public: static void apply ( const GridView &gridView ) { std::cout << "Checking iterators for higher codimension..." << std::endl; Dune::Hybrid::forEach( std::make_index_sequence< GridView::dimension >{}, [ & ]( auto i ){ CheckCodim< i+1 >::apply( gridView ); } ); } }; // CheckIterators::CheckCodim // -------------------------- template< class GridView > template< int codim > struct CheckIterators< GridView >::CheckCodim { static void apply ( const GridView &gridView ) { return CheckCodimIterators< GridView, codim >::apply( gridView ); } }; // Implementation of CheckCodimIterators // ------------------------------------- template< class GridView, int codim > inline void CheckCodimIterators< GridView, codim, true > ::apply ( const GridView &gridView ) { typedef typename GridView::Grid::Traits::LocalIdSet::IdType IdType; const auto &idSet = gridView.grid().localIdSet(); std::map< IdType, int > count; const auto codimEnd = gridView.template end< codim >(); for( auto it = gridView.template begin< codim >(); it != codimEnd; ++it ) { ++count[ idSet.id( *it ) ]; } const auto elementEnd = gridView.template end< 0 >(); for( auto it = gridView.template begin< 0 >(); it != elementEnd; ++it ) { const auto &entity = *it; for( std::size_t i = 0; i < entity.subEntities(codim); ++i ) { IdType id = idSet.subId( entity, i, codim ); if( count[ id ] != 1 ) { std::cerr << "Error: Codim " << codim << " iterator" << " visited entity " << id << " " << count[ id ] << " times." << std::endl; assert( count[ id ] == 1 ); } } } // check forward iterator semantics typedef typename GridView::template Codim::Entity Entity; NoopFunctor op; if(0 != testForwardIterator(gridView.template begin(), gridView.template end(), op)) DUNE_THROW(Dune::Exception, "Iterator does not fulfill the forward iterator concept"); } template< class GridView > inline void checkIterators ( const GridView &gridView ) { CheckIterators< GridView >::apply( gridView ); } #endif // DUNE_GRID_TEST_CHECKITERATORS_HH dune-grid-2.11.0/dune/grid/test/checkjacobians.hh000066400000000000000000000171071511655130300215660ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKJACOBIANS_HH #define DUNE_GRID_TEST_CHECKJACOBIANS_HH #include #include #include #include #include /* Interface check for Jacobian related return types * ------------------------------------------------- * * The Dune grid interface allows for implementation-defined return types * of the Dune::Geometry member functions: * JacobianInverseTransposed &jacobianInverseTransposed ( const LocalCoordinate &local ); * JacobianTransposed &jacobianTransposed ( const LocalCoordinate &local ); * * The return types 'JacobianInverseTransposed', 'JacobianTransposed' * are expected to implement the following interface: \code struct Jacobian { // field type typedef ImplementationDefined field_type; // size type typedef ImplementationDefined size_type; // number of rows static const int rows = implementationDefined; // number of cols static const int cols = implementationDefined; // linear operations template< class X, class Y > void mv ( const X &x, Y &y ) const; template< class X, class Y > void mtv ( const X &x, Y &y ) const; template< class X, class Y > void umv ( const X &x, Y &y ) const; template< class X, class Y > void umtv ( const X &x, Y &y ) const; template< class X, class Y > void umhv ( const X &x, Y &y ) const; template< class X, class Y > void mmv ( const X &x, Y &y ) const; template< class X, class Y > void mmtv ( const X &x, Y &y ) const; template< class X, class Y > void mmhv ( const X &x, Y &y ) const; template< class X, class Y > void usmv ( const field_type &alpha, const X &x, Y &y ) const; template< class X, class Y > void usmtv ( const field_type &alpha, const X &x, Y &y ) const; template< class X, class Y > void usmhv ( const field_type &alpha, const X &x, Y &y ) const; // norms typename FieldTraits< field_type >::real_type frobenius_norm () const; typename FieldTraits< field_type >::real_type frobenius_norm2 () const; typename FieldTraits< field_type >::real_type infinity_norm () const; typename FieldTraits< field_type >::real_type infinity_norm_real () const; // cast to FieldMatrix operator FieldMatrix< field_type, rows, cols > () const; }; \endcode * * Note that a FieldMatrix itself is a valid return type. */ namespace Dune { namespace { // CheckJacobianInterface // ---------------------- template< class ctype, int dimRange, int dimDomain, class Jacobian, bool isFieldMatrix = std::is_same< Jacobian, FieldMatrix< ctype, dimRange, dimDomain > >::value > struct CheckJacobianInterface { // the interface check always holds if jacobian type is a FieldMatrix static void apply ( const Jacobian &jacobian ) {} }; template< class ctype, int dimRange, int dimDomain, class Jacobian > struct CheckJacobianInterface< ctype, dimRange, dimDomain, Jacobian, false > { // field type typedef typename Jacobian::field_type field_type; typedef typename FieldTraits< field_type >::real_type real_type; static_assert(( std::is_convertible::value && std::is_convertible::value ), "Field type not compatible with geometry's coordinate type"); // size type typedef typename Jacobian::size_type size_type; // number of rows static const int rows = Jacobian::rows; static_assert((rows == dimRange), "Number of rows and range dimension do not coincide"); // number of cols static const int cols = Jacobian::cols; static_assert((cols == dimDomain), "Number of columns and domain dimension do not coincide"); static void apply ( const Jacobian &jacobian ) { // call matrix-vector operations; methods must accept any dense // vector implementation { FieldVector< field_type, cols > x( field_type ( 0 ) ); FieldVector< field_type, rows > y( field_type( 0 ) ); callMappings( jacobian, x, y ); } { DynamicVector< field_type > x( cols, field_type( 0 ) ); DynamicVector< field_type > y( rows, field_type( 0 ) ); callMappings( jacobian, x, y ); } // call norms [[maybe_unused]] real_type frobenius_norm = jacobian.frobenius_norm(); [[maybe_unused]] real_type frobenius_norm2 = jacobian.frobenius_norm2(); [[maybe_unused]] real_type infinity_norm = jacobian.infinity_norm(); [[maybe_unused]] real_type infinity_norm_real = jacobian.infinity_norm_real(); // cast to FieldMatrix FieldMatrix< field_type, rows, cols > A( jacobian ); FieldMatrix< field_type, rows, cols > B; B = jacobian; // check consistency with matrix-vector multiplication assemble( jacobian, B ); A -= B; if( A.frobenius_norm() > std::numeric_limits< real_type >::epsilon() ) DUNE_THROW( MathError, "Cast to field matrix is inconsistent with matrix-vector multiplication" ); } private: // call matrix-vector multiplication methods template< class Domain, class Range > static void callMappings ( const Jacobian &jacobian, Domain &x, Range &y ) { field_type alpha( 1 ); jacobian.mv( x, y ); jacobian.mtv( y, x ); jacobian.umv( x, y ); jacobian.umtv( y, x ); jacobian.umhv( y, x ); jacobian.mmv( x, y ); jacobian.mmtv( y, x ); jacobian.mmhv( y, x ); jacobian.usmv( alpha, x, y ); jacobian.usmtv( alpha, y, x ); jacobian.usmhv( alpha, y, x ); } // use matrix-vector multiplication to assemble field matrix static void assemble ( const Jacobian &jacobian, FieldMatrix< field_type, rows, cols > &fieldMatrix ) { for( int j = 0; j < cols; ++j ) { // i-th standard basis vector FieldVector< field_type, cols > e( 0 ); e[ j ] = 1; // compute i-th row FieldVector< field_type, rows > x; jacobian.mv( e, x ); for( int i = 0; i < rows; ++i ) fieldMatrix[ i ][ j ] = x[ i ]; } } }; } // namespace // checkJacobians // -------------- template< class Geometry > void checkJacobians ( const Geometry &geometry ) { typedef typename Geometry::ctype ctype; const int mydimension = Geometry::mydimension; const int coorddimension = Geometry::coorddimension; const typename Geometry::LocalCoordinate local = geometry.local( geometry.center() ); // check jacobian inverse transposed typedef typename Geometry::JacobianInverseTransposed JacobianInverseTransposed; CheckJacobianInterface< ctype, coorddimension, mydimension, JacobianInverseTransposed > ::apply( geometry.jacobianInverseTransposed( local ) ); // check jacobian transposed typedef typename Geometry::JacobianTransposed JacobianTransposed; CheckJacobianInterface< ctype, mydimension, coorddimension, JacobianTransposed > ::apply( geometry.jacobianTransposed( local ) ); } } // namespace Dune #endif // #ifndef DUNE_GRID_TEST_CHECKJACOBIANS_HH dune-grid-2.11.0/dune/grid/test/checkpartition.hh000066400000000000000000000367431511655130300216550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKPARTITION_HH #define DUNE_GRID_TEST_CHECKPARTITION_HH #include #include #include #include #include #include #include #include #include #include #include template< Dune::PartitionIteratorType pitype > struct PartitionFilter; template<> struct PartitionFilter< Dune::Interior_Partition > { static bool contains ( const Dune::PartitionType partitionType ) { return (partitionType == Dune::InteriorEntity); } }; template<> struct PartitionFilter< Dune::InteriorBorder_Partition > { static bool contains ( const Dune::PartitionType partitionType ) { return (partitionType == Dune::InteriorEntity) || (partitionType == Dune::BorderEntity); } }; template<> struct PartitionFilter< Dune::Overlap_Partition > { static bool contains ( const Dune::PartitionType partitionType ) { return (partitionType != Dune::FrontEntity) && (partitionType != Dune::GhostEntity); } }; template<> struct PartitionFilter< Dune::OverlapFront_Partition > { static bool contains ( const Dune::PartitionType partitionType ) { return (partitionType != Dune::GhostEntity); } }; template<> struct PartitionFilter< Dune::All_Partition > { static bool contains ([[maybe_unused]] const Dune::PartitionType partitionType) { return true; } }; template<> struct PartitionFilter< Dune::Ghost_Partition > { static bool contains ( const Dune::PartitionType partitionType ) { return (partitionType == Dune::GhostEntity); } }; inline bool possibleSubPartitionType ( Dune::PartitionType ept, Dune::PartitionType pt ) { switch( ept ) { case Dune::InteriorEntity : return (pt == Dune::InteriorEntity) || (pt == Dune::BorderEntity); case Dune::OverlapEntity : return (pt == Dune::BorderEntity) || (pt == Dune::OverlapEntity) || (pt == Dune::FrontEntity); case Dune::GhostEntity : return (pt == Dune::BorderEntity) || (pt == Dune::FrontEntity) || (pt == Dune::GhostEntity); default : std::cerr << "Error: Codimension 0 entity cannot be of partition type " << ept << "." << std::endl; return false; } } template< class GridView, Dune::PartitionIteratorType pitype > class CheckPartitionType { template< int codim > struct CheckCodim; public: static void apply ( const GridView &gridView ) { std::cout << "Checking iterators for " << pitype << "..." << std::endl; Dune::Hybrid::forEach( std::make_index_sequence< GridView::dimension+1 >{}, [ & ]( auto i ){ CheckCodim< i >::apply( gridView ); } ); } }; template< class GridView, Dune::PartitionIteratorType pitype > template< int codim > struct CheckPartitionType< GridView, pitype >::CheckCodim { template< class IdSet > static void check ( const std::true_type &, const GridView &gridView, const IdSet &idSet ) { typedef typename GridView::template Codim< codim >::template Partition< pitype >::Iterator Iterator; typedef typename GridView::template Codim< 0 >::template Partition< Dune::All_Partition >::Iterator AllIterator; typedef std::map< typename IdSet::IdType, Dune::PartitionType > Map; typedef typename Map::iterator MapIterator; Map map; try { const Iterator end = gridView.template end< codim, pitype >(); for( Iterator it = gridView.template begin< codim, pitype >(); it != end; ++it ) { Dune::PartitionType pt = it->partitionType(); if( !PartitionFilter< pitype >::contains( pt ) ) { std::cerr << "Error: Codim " << codim << " iterator for the " << pitype << " visited entity " << idSet.id( *it ) << " with partition type " << pt << "." << std::endl; } map[ idSet.id( *it ) ] = pt; } const AllIterator allEnd = gridView.template end< 0, Dune::All_Partition >(); for( AllIterator it = gridView.template begin< 0, Dune::All_Partition >(); it != allEnd; ++it ) { Dune::PartitionType ept = it->partitionType(); const int subEntities = it->subEntities(codim); for( int i = 0; i < subEntities; ++i ) { Dune::PartitionType pt = it->template subEntity< codim >( i ).partitionType(); if( !possibleSubPartitionType( ept, pt ) ) { std::cerr << "Error: Codim " << codim << " entity " << idSet.subId( *it, i, codim ) << " with partition type " << pt << " is a subentity of entity " << idSet.id( *it ) << " with partition type " << ept << "." << std::endl; } const MapIterator mapIt = map.find( idSet.subId( *it, i, codim ) ); if( mapIt == map.end() ) { if( PartitionFilter< pitype >::contains( pt ) ) { std::cerr << "Error: Codim " << codim << " entity " << idSet.subId( *it, i, codim ) << " with partition type " << pt << " is not visited by codim " << codim << " iterator for the " << pitype << "." << std::endl; } } else { if( pt != mapIt->second ) { std::cerr << "Error: Codim " << codim << " entity " << idSet.subId( *it, i, codim ) << " with partition type " << pt << " reported partition type " << mapIt->second << " when accessed with the codim " << codim << " iterator for the " << pitype << "." << std::endl; } } } } } catch( const Dune::Exception &exception ) { std::cerr << "Error: Caught exception when testing partition iterator for the " << pitype << "(" << exception << ")." << std::endl; } } template< class IdSet > static void check (const std::false_type &, [[maybe_unused]] const GridView &gridView, [[maybe_unused]] const IdSet &idSet) {} static void apply ( const GridView &gridView ) { std::integral_constant< bool, Dune::Capabilities::hasEntity< typename GridView::Grid, codim >::v && Dune::Capabilities::hasEntityIterator< typename GridView::Grid, codim >::v > capabilityVariable; check( capabilityVariable, gridView, gridView.grid().localIdSet() ); } }; template< class GridView, Dune::InterfaceType iftype > class CheckPartitionDataHandle : public Dune::CommDataHandleIF< CheckPartitionDataHandle< GridView, iftype >, int > { static const int dimension = GridView::dimension; typedef typename GridView::Grid Grid; typedef typename Grid::LocalIdSet IdSet; typedef std::set< typename IdSet::IdType > CommSet; public: explicit CheckPartitionDataHandle ( const GridView &gridView ) : gridView_( gridView ), rank_( gridView_.comm().rank() ), idSet_( gridView_.grid().localIdSet() ), invalidDimension_( false ), invalidCodimension_( false ), invalidEntity_( false ), invalidSendEntity_( false ), invalidReceiveEntity_( false ), invalidSize_( false ), selfReceive_( false ), doubleInterior_( false ), interiorBorder_( false ) { Dune::Hybrid::forEach( std::make_index_sequence< dimension+1 >{}, [ & ]( auto i ){ contains_[ i ] = Dune::Capabilities::canCommunicate< Grid, i >::v; } ); } ~CheckPartitionDataHandle () { bool sendFailure = false; bool receiveFailure = false; typedef typename GridView::template Codim< 0 >::Iterator Iterator; typedef typename GridView::template Codim< 0 >::Entity Entity; const Iterator end = gridView_.template end< 0 >(); for( Iterator it = gridView_.template begin< 0 >(); it != end; ++it ) { const Entity entity = *it; if( entity.partitionType() == Dune::InteriorEntity ) continue; const bool wasSent = (sendSet_.find( idSet_.id( entity ) ) != sendSet_.end()); if( Dune::EntityCommHelper< iftype >::send( entity.partitionType() ) && !wasSent ) { std::cout << "[ " << rank_ << " ] Error: No data sent on non-interior entity " << grid().globalIdSet().id( entity ) << " of partition type " << entity.partitionType() << " contained in the send set." << std::endl; sendFailure = true; } const bool wasReceived = (receiveSet_.find( idSet_.id( entity ) ) != receiveSet_.end()); if( Dune::EntityCommHelper< iftype >::receive( entity.partitionType() ) && !wasReceived ) { std::cout << "[ " << rank_ << " ] Error: No data received on non-interior entity " << grid().globalIdSet().id( entity ) << " of partition type " << entity.partitionType() << " contained in the receive set." << std::endl; receiveFailure = true; } } if( invalidDimension_ ) std::cerr << "[ " << rank_ << " ] Error: Invalid dimension passed during communication." << std::endl; if( invalidCodimension_ ) std::cerr << "[ " << rank_ << " ] Error: Invalid codimension passed during communication." << std::endl; if( invalidEntity_ ) std::cerr << "[ " << rank_ << " ] Error: Uncontained entity passed during communication." << std::endl; if( invalidSendEntity_ ) std::cerr << "[ " << rank_ << " ] Error: Sent data on entity not contained in communication interface." << std::endl; if( invalidReceiveEntity_ ) std::cerr << "[ " << rank_ << " ] Error: Received data on entity not contained in communication interface." << std::endl; if( invalidSize_ ) std::cerr << "[ " << rank_ << " ] Error: Wrong size passed during communication." << std::endl; if( selfReceive_ ) std::cerr << "[ " << rank_ << " ] Warning: Received data from own process during communication." << std::endl; if( doubleInterior_ ) std::cerr << "[ " << rank_ << " ] Error: Received interior data on interior entity." << std::endl; if( interiorBorder_ ) std::cerr << "[ " << rank_ << " ] Error: Received interior data on border entity / border data on interior entity." << std::endl; if( sendFailure ) std::cerr << "[ " << rank_ << " ] Error: No data sent on a non-interior entity within the send set." << std::endl; if( receiveFailure ) std::cerr << "[ " << rank_ << " ] Error: No data received on a non-interior entity within the receive set." << std::endl; } bool contains ( const int dim, const int codim ) const { invalidDimension_ |= (dim != dimension); invalidCodimension_ |= ((codim < 0) || (codim > dimension)); return ((codim >= 0) && (codim <= dimension) ? contains_[ codim ] : false); } bool fixedSize ( const int dim, const int codim ) const { invalidDimension_ |= (dim != dimension); invalidCodimension_ |= ((codim < 0) || (codim > dimension)); return true; } template< class Entity > std::size_t size ([[maybe_unused]] const Entity &entity) const { static_assert( (Entity::dimension == dimension), "Entity has invalid dimension." ); static_assert( (Entity::codimension >= 0) || (Entity::codimension <= dimension), "Entity has invalid codimension." ); return (contains_[ Entity::codimension ] ? 2 : 0); } template< class Buffer, class Entity > void gather ( Buffer &buffer, const Entity &entity ) const { static_assert( (Entity::dimension == dimension), "Entity has invalid dimension." ); static_assert( (Entity::codimension >= 0) || (Entity::codimension <= dimension), "Entity has invalid codimension." ); invalidEntity_ |= !contains_[ Entity::codimension ]; invalidSendEntity_ |= !Dune::EntityCommHelper< iftype >::send( entity.partitionType() ); buffer.write( rank_ ); buffer.write( int( entity.partitionType() ) ); sendSet_.insert( idSet_.id( entity ) ); } template< class Buffer, class Entity > void scatter ( Buffer &buffer, const Entity &entity, std::size_t n ) { static_assert( (Entity::dimension == dimension), "Entity has invalid dimension." ); static_assert( (Entity::codimension >= 0) || (Entity::codimension <= dimension), "Entity has invalid codimension." ); invalidEntity_ |= !contains_[ Entity::codimension ]; invalidSize_ |= (n != size( entity )); invalidReceiveEntity_ |= !Dune::EntityCommHelper< iftype >::receive( entity.partitionType() ); int rank, partitionType; buffer.read( rank ); buffer.read( partitionType ); receiveSet_.insert( idSet_.id( entity ) ); selfReceive_ |= (rank == rank_); if( (partitionType == int( Dune::InteriorEntity )) && (entity.partitionType() == Dune::InteriorEntity) ) { std::cout << "[ " << rank_ << " ] Error: Receive interior data from process " << rank << " on interior entity " << grid().globalIdSet().id( entity ) << "." << std::endl; doubleInterior_ = true; } if( (partitionType == int( Dune::BorderEntity )) && (entity.partitionType() == Dune::InteriorEntity) ) { std::cout << "[ " << rank_ << " ] Error: Receive border data from process " << rank << " on interior entity " << grid().globalIdSet().id( entity ) << "." << std::endl; interiorBorder_ = true; } if( (partitionType == int( Dune::InteriorEntity )) && (entity.partitionType() == Dune::BorderEntity) ) { std::cout << "[ " << rank_ << " ] Error: Receive interior data from process " << rank << " on border entity " << grid().globalIdSet().id( entity ) << "." << std::endl; interiorBorder_ = true; } } static void apply ( const GridView &gridView ) { std::cout << "Checking communication for " << iftype << "..." << std::endl; CheckPartitionDataHandle handle( gridView ); auto commFuture = gridView.communicate( handle, iftype, Dune::ForwardCommunication ); if( ! commFuture.ready() ) commFuture.wait(); } const Grid &grid () const { return gridView_.grid(); } private: const GridView &gridView_; const int rank_; const IdSet &idSet_; std::bitset< dimension+1 > contains_; mutable CommSet sendSet_, receiveSet_; mutable bool invalidDimension_; mutable bool invalidCodimension_; mutable bool invalidEntity_; mutable bool invalidSendEntity_; bool invalidReceiveEntity_; bool invalidSize_; bool selfReceive_; bool doubleInterior_; bool interiorBorder_; }; template< class GridView > inline void checkPartitionType ( const GridView &gridView ) { CheckPartitionType< GridView, Dune::Interior_Partition >::apply( gridView ); CheckPartitionType< GridView, Dune::InteriorBorder_Partition >::apply( gridView ); CheckPartitionType< GridView, Dune::Overlap_Partition >::apply( gridView ); CheckPartitionType< GridView, Dune::OverlapFront_Partition >::apply( gridView ); CheckPartitionType< GridView, Dune::Ghost_Partition >::apply( gridView ); CheckPartitionDataHandle< GridView, Dune::InteriorBorder_InteriorBorder_Interface >::apply( gridView ); CheckPartitionDataHandle< GridView, Dune::InteriorBorder_All_Interface >::apply( gridView ); CheckPartitionDataHandle< GridView, Dune::Overlap_OverlapFront_Interface >::apply( gridView ); CheckPartitionDataHandle< GridView, Dune::Overlap_All_Interface >::apply( gridView ); CheckPartitionDataHandle< GridView, Dune::All_All_Interface >::apply( gridView ); } #endif // DUNE_GRID_TEST_CHECKPARTITION_HH dune-grid-2.11.0/dune/grid/test/checktwists.hh000066400000000000000000000143451511655130300211730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_CHECKTWISTS_HH #define DUNE_GRID_TEST_CHECKTWISTS_HH #include int applyTwist ( const int twist, const int i, const int numCorners ) { return (twist < 0 ? (2*numCorners + 1 - i + twist) : i + twist) % numCorners; } int inverseTwist ( const int twist, const int numCorners ) { return (twist <= 0 ? twist : numCorners - twist); } struct NoMapTwist { int operator() ( const int twist ) const { return twist; } }; template< class Intersection, class MapTwist > int checkTwistOnIntersection ( const Intersection &intersection, const MapTwist &mapTwist ) { const int dimension = Intersection::dimension; typedef typename Intersection::Entity Entity; typedef typename Entity::Geometry Geometry; typedef typename Geometry::ctype ctype; typedef typename Intersection::LocalGeometry LocalGeometry; typedef Dune::FieldVector< typename Geometry::ctype, Geometry::coorddimension > WorldVector; typedef Dune::FieldVector< typename LocalGeometry::ctype, LocalGeometry::coorddimension > LocalVector; if( !intersection.neighbor() || intersection.boundary() || !intersection.conforming() ) return 0; int errors = 0; const ctype tolerance = std::numeric_limits< ctype >::epsilon(); const int tIn = mapTwist( intersection.twistInInside() ); const int tOut = mapTwist( intersection.twistInOutside() ); const Entity entityIn = intersection.inside(); const Entity entityOut = intersection.outside(); const Geometry &geoIn = entityIn.geometry(); const Geometry &geoOut = entityOut.geometry(); const int nIn = intersection.indexInInside(); const int nOut = intersection.indexInOutside(); auto refIn = referenceElement( geoIn ); auto refOut = referenceElement( geoOut ); const int numCorners = refIn.size( nIn, 1, dimension ); assert( refOut.size( nOut, 1, dimension ) == numCorners ); for( int i = 0; i < numCorners; ++i ) { const int iIn = applyTwist( inverseTwist( tIn, numCorners ), i, numCorners ); const int iOut = applyTwist( inverseTwist( tOut, numCorners ), i, numCorners ); WorldVector xIn = geoIn.corner( refIn.subEntity( nIn, 1, iIn, dimension ) ); WorldVector xOut = geoOut.corner( refOut.subEntity( nOut, 1, iOut, dimension ) ); if( (xIn - xOut).two_norm() < tolerance ) continue; std::cout << "Error: corner( " << iIn << " ) = " << xIn << " != " << xOut << " = corner( " << iOut << " )." << std::endl; ++errors; } const LocalGeometry &lGeoIn = intersection.geometryInInside(); const LocalGeometry &lGeoOut = intersection.geometryInOutside(); bool twistInside = true ; bool twistOutside = true; for( int i = 0; i < numCorners; ++i ) { const int gi = i; const int iIn = applyTwist( inverseTwist( tIn, numCorners ), i, numCorners ); LocalVector xIn = refIn.position( refIn.subEntity( nIn, 1, iIn, dimension ), dimension ); if( (xIn - lGeoIn.corner( gi )).two_norm() >= tolerance ) { std::cout << "Error: twisted inside reference corner( " << iIn << " ) = " << xIn << " != " << lGeoIn.corner( gi ) << " = local corner( " << i << " )." << std::endl; twistInside = false ; ++errors; } const int iOut = applyTwist( inverseTwist( tOut, numCorners ), i, numCorners ); LocalVector xOut = refOut.position( refOut.subEntity( nOut, 1, iOut, dimension ), dimension ); if( (xOut - lGeoOut.corner( gi )).two_norm() >= tolerance ) { std::cout << "Error: twisted outside reference corner( " << iOut << " ) = " << xOut << " != " << lGeoOut.corner( gi ) << " = local corner( " << i << " )." << std::endl; twistOutside = false; ++errors; } } // calculate inside twist if( ! twistInside ) { for( int nTwist = numCorners-1; nTwist>= -numCorners; --nTwist ) { twistInside = true ; for( int i = 0; i < numCorners; ++i ) { const int gi = i; const int iIn = applyTwist( inverseTwist( nTwist, numCorners ), i, numCorners ); LocalVector xIn = refIn.position( refIn.subEntity( nIn, 1, iIn, dimension ), dimension ); if( (xIn - lGeoIn.corner( gi )).two_norm() >= tolerance ) { twistInside = false ; } } if( twistInside ) { std::cout << "\ninside " << nIn << "\n"; std::cout << "twist " << tIn << " should be replaced by " << nTwist << "\n"; break ; } } } // calculate outside twist if( ! twistOutside ) { for( int nTwist = numCorners-1; nTwist>=-numCorners; --nTwist ) { twistOutside = true ; for( int i = 0; i < numCorners; ++i ) { const int gi = i; const int iOut = applyTwist( inverseTwist( nTwist, numCorners ), i, numCorners ); LocalVector xOut = refOut.position( refOut.subEntity( nOut, 1, iOut, dimension ), dimension ); if( (xOut - lGeoOut.corner( gi )).two_norm() >= tolerance ) { twistOutside = false; } } if( twistOutside ) { std::cout << "\noutside " << nOut << " (inside = " << nIn << ")\n"; std::cout << "twist " << tOut << " should be replaced by " << nTwist << "\n"; break ; } } } return errors; } template< class GridView, class MapTwist > void checkTwists ( const GridView &gridView, const MapTwist &mapTwist ) { typedef typename GridView::template Codim< 0 >::Iterator Iterator; typedef typename GridView::IntersectionIterator IntersectionIterator; int errors = 0; const Iterator end = gridView.template end< 0 >(); for( Iterator it = gridView.template begin< 0 >(); it != end; ++it ) { const IntersectionIterator iend = gridView.iend( *it ); for( IntersectionIterator iit = gridView.ibegin( *it ); iit != iend; ++iit ) errors += checkTwistOnIntersection( iit->impl(), mapTwist ); } if( errors > 0 ) std::cerr << "Error: Intersection twists contain errors." << std::endl; } #endif // DUNE_GRID_TEST_CHECKTWISTS_HH dune-grid-2.11.0/dune/grid/test/functions.hh000066400000000000000000000050161511655130300206430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GEOGRID_TEST_FUNCTIONS_HH #define DUNE_GEOGRID_TEST_FUNCTIONS_HH #include #include #include namespace Dune { class Helix : public AnalyticalCoordFunction< double, 2, 3, Helix > { typedef Helix This; typedef AnalyticalCoordFunction< double, 2, 3, This > Base; public: typedef Base :: DomainVector DomainVector; typedef Base :: RangeVector RangeVector; void evaluate ( const DomainVector &x, RangeVector &y ) const { y[ 0 ] = (x[ 0 ] + 0.2) * cos( 2.0 * MathematicalConstants::pi() * x[ 1 ] ); y[ 1 ] = (x[ 0 ] + 0.2) * sin( 2.0 * MathematicalConstants::pi() * x[ 1 ] ); y[ 2 ] = x[ 1 ]; } }; class Circle : public AnalyticalCoordFunction< double, 2, 2, Circle > { typedef Circle This; typedef AnalyticalCoordFunction< double, 2, 2, This > Base; public: typedef Base :: DomainVector DomainVector; typedef Base :: RangeVector RangeVector; void evaluate ( const DomainVector &x, RangeVector &y ) const { y[ 0 ] = (x[ 0 ] + 0.2) * cos( 2.0 * MathematicalConstants::pi() * x[ 1 ] ); y[ 1 ] = (x[ 0 ] + 0.2) * sin( 2.0 * MathematicalConstants::pi() * x[ 1 ] ); } }; class ThickHelix : public AnalyticalCoordFunction< double, 3, 3, ThickHelix > { typedef ThickHelix This; typedef AnalyticalCoordFunction< double, 3, 3, This > Base; public: typedef Base :: DomainVector DomainVector; typedef Base :: RangeVector RangeVector; void evaluate ( const DomainVector &x, RangeVector &y ) const { double angle = x[1]-3.; if (std::abs(angle)<1.) { y[0] = x[0]+0.2; y[1] = angle; y[2] = x[2]; } else { double fac = 1.; if (angle>0) { y[1] = 1.; angle -= 1.; fac=3.; } else { y[1] = -1; angle += 1.; fac=5; } y[ 0 ] = (x[ 0 ] + 0.2) * cos( 2.0 * MathematicalConstants::pi() * angle ); y[ 1 ] += (x[ 0 ] + 0.2) * sin( 2.0 * MathematicalConstants::pi() * angle ); y[ 2 ] = x[ 2 ] + fac*std::abs(angle); } } }; } #endif dune-grid-2.11.0/dune/grid/test/geometrygrid-coordfunction-copyconstructor.cc000066400000000000000000000030051511655130300274460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception /* * Test that an implicit copy generator is available for classes derived from * - Dune::AnalyticalCoordFunction * - Dune::DiscreteCoordFunction * * See https://gitlab.dune-project.org/flyspray/FS/issues/1463 */ #include class Analytical : public Dune::AnalyticalCoordFunction { using Base = Dune::AnalyticalCoordFunction; Base::RangeVector offset_; public: Analytical(Base::RangeVector offset) : offset_(offset) { /* Nothing. */ } void evaluate(const Base::DomainVector& x, Base::RangeVector& y) const { y = x; y += offset_; } }; class Discrete : public Dune::DiscreteCoordFunction { using Base = Dune::DiscreteCoordFunction; Base::RangeVector offset_; public: Discrete(Base::RangeVector offset) : offset_(offset) { /* Nothing. */ } template void evaluate(const HostEntity& hostEntity, unsigned int corner, Base::RangeVector& y) const { y = hostEntity.geometry().corner(corner); y += offset_; } }; int main() { { Analytical a({1., 2., 3.}); Analytical b = a; [[maybe_unused]] Analytical c(b); } { Discrete a({1., 2., 3.}); Discrete b = a; [[maybe_unused]] Discrete c(b); } return 0; } dune-grid-2.11.0/dune/grid/test/gridcheck.hh000066400000000000000000001142411511655130300205570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_GRIDCHECK_HH #define DUNE_GRID_TEST_GRIDCHECK_HH /** \file \brief Implements a generic grid check \todo check return types */ #include #include #include #include #include #include #include #include #include #include #include #include #include "staticcheck.hh" #include "checkindexset.hh" #include "checkgeometry.hh" #include "checkentityseed.hh" #include "checkentitylifetime.hh" #include #include "checkintersectionlifetime.hh" #include // machine epsilon is multiplied by this factor static double factorEpsilon = 1.e8; class CheckError : public Dune::Exception {}; namespace Dune { // This flag can be used to disable the BoundarySegmentIndexCheck // Disabling this flag is important for meta grids like SubGrid and // MultiDomainGrid that cannot guarantee the usual boundary segment // index semantics // // By default, this test is on. template< class Grid > struct EnableBoundarySegmentIndexCheck : public std::true_type {}; template< class Grid > struct EnableBoundarySegmentIndexCheck< const Grid > : public EnableBoundarySegmentIndexCheck {}; } // check // Entity::geometry()[c] == Entity::entity.geometry()[0] // for codim=cd template struct subIndexCheck { template void checkEntitySeedRecovery([[maybe_unused]] const Grid& g, const E& e) { typedef typename Grid::template Codim< E::codimension >::EntitySeed EntitySeed; EntitySeed seed = e.seed(); E e1( e ); E e2 = g.entity( seed ); if( e1 != e2 ) DUNE_THROW( Dune::GridError, "EntitySeed recovery failed"); } subIndexCheck ( const Grid &g, const Entity &e ) { checkEntitySeedRecovery(g,e); // check subEntity range size if( subEntities(e, Dune::Codim{}).size() != e.subEntities(cd) ) { std::cerr << "Error: Number of subentities in range " << "does not match the number of subentities of the element." << std::endl; assert( false ); } // We use the both a range-based for loop and an index counter for testing purposes here. // In regular code you will often only need the subIndex in which case an index loop // is more convenient, or you only need the actual sub-entities in which // case the range-based for loop might be more readable. std::size_t subIndex = 0; for (const auto& se : subEntities(e, Dune::Codim{})) { auto se1 = se; auto se2 = se; se1 = se2; se1 = std::move(se2); // check construction of entities [[maybe_unused]] auto seCopy = se; assert( seCopy == se ); checkEntitySeedRecovery(g,se); // Check subentity counts against reference elements Dune::Hybrid::forEach(Dune::range(Dune::index_constant()), [&](auto ccd){ if (Dune::Capabilities::hasEntity::v && se.subEntities(cd+ccd) != referenceElement(se.type()).size(ccd)) { std::cerr << "Error: Number of subentities of codim " << ccd << " does not match reference element." << std::endl; std::cerr << " ... entity type: " << se.type() << std::endl; std::cerr << " ... expected: " << referenceElement(se.type()).size(ccd) << ", got: " << se.subEntities(cd+ccd) << std::endl; DUNE_THROW(Dune::GridError, "subEntities check failed"); } }); const typename Grid::LevelGridView &levelGridView = g.levelGridView(e.level()); if( !levelGridView.contains( se ) ) { std::cerr << "Error: Level grid view does not contain all subentities." << std::endl; assert( false ); } const typename Grid::LevelIndexSet &levelIndexSet = g.levelIndexSet( e.level() ); if( !levelIndexSet.contains( se ) ) { std::cerr << "Error: Level index set does not contain all subentities." << std::endl; assert( false ); } if( levelIndexSet.index( se ) != levelIndexSet.subIndex( e, subIndex, cd ) ) { int id_e = levelIndexSet.index( e ); int id_e_i = levelIndexSet.index( se ); int subid_e_i = levelIndexSet.subIndex( e, subIndex, cd ); std::cerr << "Error: levelIndexSet.index( *(e.template subEntity< cd >( subIndex ) ) ) " << "!= levelIndexSet.subIndex( e, subIndex, cd ) " << "[with cd=" << cd << ", subIndex=" << subIndex << "]" << std::endl; std::cerr << " ... index( e ) = " << id_e << std::endl; std::cerr << " ... index( e.subEntity< cd >( subIndex ) ) = " << id_e_i << std::endl; std::cerr << " ... subIndex( e, subIndex, cd ) = " << subid_e_i << std::endl; assert( false ); } ++subIndex; } subIndexCheck< cd-1, Grid, Entity, Dune::Capabilities::hasEntity< Grid, cd-1 >::v > sick( g, e ); } }; // end recursion of subIndexCheck template struct subIndexCheck<-1, Grid, Entity, doCheck> { subIndexCheck (const Grid & /* g */, const Entity & /* e */) { return; } }; // do nothing if doCheck==false template struct subIndexCheck { subIndexCheck (const Grid & g, const Entity & e) { subIndexCheck::v> sick(g,e); } }; template struct subIndexCheck<-1, Grid, Entity, false> { subIndexCheck (const Grid & , const Entity & ) { return; } }; // name says all template void zeroEntityConsistency (Grid &g) { typedef typename Grid::ctype ctype; const int dimGrid = Grid::dimension; // const int dimWorld = Grid::dimensionworld; typedef typename Grid::template Codim<0>::LevelIterator LevelIterator; typedef typename Grid::template Codim<0>::Geometry Geometry; typedef typename Grid::template Codim<0>::Entity Entity; const typename Grid::LevelIndexSet &levelIndexSet = g.levelIndexSet( g.maxLevel() ); const typename Grid::LeafIndexSet &leafIndexSet = g.leafIndexSet(); const typename Grid::LocalIdSet &localIdSet = g.localIdSet(); const typename Grid::GlobalIdSet &globalIdSet = g.globalIdSet(); LevelIterator it = g.levelGridView(g.maxLevel()).template begin<0>(); const LevelIterator endit = g.levelGridView(g.maxLevel()).template end<0>(); for (; it!=endit; ++it) { // check entity copy ctor Entity e( *it ) ; assert( e == *it ); Entity subEntity = it->template subEntity< 0 >( 0 ); // Entity::subEntity<0>(0) == Entity if( levelIndexSet.index( subEntity ) != levelIndexSet.index( *it ) ) { std::cerr << "Error: Level index for subEntity< 0 >( 0 ) differs." << std::endl; assert( false ); } if( leafIndexSet.index( subEntity ) != leafIndexSet.index( *it ) ) { std::cerr << "Error: Leaf index for subEntity< 0 >( 0 ) differs." << std::endl; assert( false ); } if( globalIdSet.id( subEntity ) != globalIdSet.id( *it ) ) { std::cerr << "Error: Global id for subEntity< 0 >( 0 ) differs." << std::endl; assert( false ); } if( localIdSet.id( subEntity ) != localIdSet.id( *it ) ) { std::cerr << "Error: Local id for subEntity< 0 >( 0 ) differs." << std::endl; assert( false ); } if( subEntity.level() != it->level() ) { std::cerr << "Error: Level for subEntity< 0 >( 0 ) differs." << std::endl; assert( false ); } // Entity::subEntities(dim) == Entity::geometry().corners(); // Entity::geometry()[c] == Entity::entity.geometry()[0]; const int numCorners = it->subEntities(dimGrid); if( numCorners != it->geometry().corners() ) { std::cerr << "Error: Entity::subEntities< dimGrid >() != Entity::geometry().corners()." << std::endl; assert( false ); } for( int c = 0; c < numCorners; ++c ) { typename Geometry::GlobalCoordinate c1( it->geometry().corner( c ) ); typename Geometry::GlobalCoordinate c2( it->template subEntity< dimGrid >( c ).geometry().corner( 0 ) ); if( (c2-c1).two_norm() > 10*std::numeric_limits< ctype >::epsilon() ) { std::cerr << "Error: | geometry.corner( c ) - subEntity< dimGrid >( c ) | = | " << c1 << " - " << c2 << " | = " << (c2-c1).two_norm() << " != 0 [with c = " << c << " ]" << std::endl; assert( false ); } } // check that corner coordinates are distinct const int corners= it->geometry().corners(); for (int c=0; cgeometry().corner( c ); const typename Geometry::GlobalCoordinate c2 = it->geometry().corner( d ); if( (c2-c1).two_norm() < 10 * std::numeric_limits::epsilon() ) DUNE_THROW( CheckError, "geometry.corner( " << c << " ) == geometry.corner( " << d << " )" ); } } // check hasSingleGeometryType capability const bool hasSingleGeomType = Dune :: Capabilities :: hasSingleGeometryType< Grid > :: v ; if( hasSingleGeomType ) { // check that geometry type generated from constant topo Id is the same as of the codim 0 entity const Dune::GeometryType constantType( Dune :: Capabilities :: hasSingleGeometryType< Grid > :: topologyId , dimGrid ); if( it->type() != constantType ) { DUNE_THROW(Dune::InvalidStateException,"it->type() " << it->type() << " differs from singleGeometryType " << constantType); } } const bool isCartesian = Dune :: Capabilities :: isCartesian< Grid > :: v ; // check geometry for Cartesian grids if( isCartesian ) { if( ! it->geometry().affine() ) DUNE_THROW( Dune::GridError, "Geometry is not affine, although isCartesian is true"); } subIndexCheck sick(g,*it); } } /* * search the LevelIterator for each IntersectionIterator */ template void assertNeighbor (Grid &g) { typedef typename Grid::LevelGridView GridView; typedef typename GridView::IntersectionIterator IntersectionIterator; typedef typename Grid::template Codim<0>::LevelIterator LevelIterator; [[maybe_unused]] constexpr static int dim = Grid::dimension; // [[maybe_unused]] typedef typename Grid::ctype ct; typedef typename Grid::GlobalIdSet GlobalIdSet; const GlobalIdSet & globalid = g.globalIdSet(); typedef typename Grid::template Codim< 0 >::Entity Entity; GridView gridView = g.levelGridView( 0 ); LevelIterator eit = g.levelGridView(0).template begin<0>(); const LevelIterator eend = g.levelGridView(0).template end<0>(); LevelIterator next = eit; if (next != eend) { ++next; if( !EnableLevelIntersectionIteratorCheck< Grid >::v ) { static int called = 0; if( called++ == 0 ) std::cerr << "Warning: Skipping level neighbor check." << std::endl; return; } // small check if LevelIntersectionIterators // from work reassigned Entity // after creation of LevelIterator on different level if (g.maxLevel()>0 && g.levelGridView(0).template begin<0>() != g.levelGridView(0).template end<0>() && g.levelGridView(1).template begin<0>() != g.levelGridView(1).template end<0>() ) { Entity e( *g.levelGridView(0).template begin<0>() ); e = *g.levelGridView(1).template begin<0>(); LevelIterator it = g.levelGridView(0).template begin<0>(); ++it; g.levelGridView(e.level()).ibegin(e); } // iterate over level for (; eit != eend; ++eit) { const Entity &entity = *eit; const bool isGhost = (entity.partitionType() == Dune::GhostEntity); // call global id [[maybe_unused]] const typename GlobalIdSet::IdType idG = globalid.id( entity ); const int numFaces = referenceElement(entity.type()).size(1); // flag vector for elements faces std::vector< bool > visited( numFaces, false ); // loop over intersections const IntersectionIterator endit = gridView.iend( entity ); IntersectionIterator it = gridView.ibegin( entity ); if( it == endit ) { // ALU has no intersection iterators on ghosts, so make this case non-fatal if( !isGhost ) { std::cerr << "Error: Entity without intersections encountered." << std::endl; assert( false ); } else std::cerr << "Warning: Ghost Entity without intersections encountered." << std :: endl; } // for all intersections for(; it != endit; ++it) { typedef typename IntersectionIterator::Intersection Intersection; const Intersection& is = *it; // check intersection copy ctor [[maybe_unused]] Intersection is2 = is; // numbering const int numberInSelf = is.indexInInside(); if( (numberInSelf < 0) || (numberInSelf >= numFaces) ) { std :: cout << "Error: Invalid numberInSelf: " << numberInSelf << " (should be between 0 and " << (numFaces-1) << ")" << std :: endl; assert( false ); } else { // mark face visited visited[ numberInSelf ] = true; } // index / id of boundary segment if( it->boundary() ) { [[maybe_unused]] const std::size_t bSI = it->boundarySegmentIndex(); } // check id assert( globalid.id(it->inside()) == globalid.id( entity ) ); // geometry if( !it->type().isNone() ) it->geometryInInside(); it->geometry(); // normal vectors typename IntersectionIterator::Intersection::LocalCoordinate v(0); using GlobalCoordinate = typename IntersectionIterator::Intersection::GlobalCoordinate; [[maybe_unused]] const GlobalCoordinate outerNormal = it->outerNormal(v); [[maybe_unused]] const GlobalCoordinate integrationOuterNormal = it->integrationOuterNormal(v); [[maybe_unused]] const GlobalCoordinate unitOuterNormal = it->unitOuterNormal(v); if( isGhost && !it->neighbor() ) { std::cerr << "Error: On ghosts, all intersections must have neighbors." << std::endl; assert( false ); } if( it->neighbor() ) { const Entity outside = it->outside(); if( isGhost && (outside.partitionType() == Dune::GhostEntity) ) { std::cerr << "Error: Intersections between ghosts shall not be returned." << std::endl; assert( false ); } // geometry if( !it->type().isNone() ) it->geometryInOutside(); // numbering const int indexInOutside = it->indexInOutside(); const int outNumFaces = referenceElement(outside.type()).size(1); if( (indexInOutside < 0) || (indexInOutside >= outNumFaces) ) { std :: cout << "Error: Invalid indexInOutside: " << indexInOutside << " (should be between 0 and " << (outNumFaces-1) << ")" << std :: endl; assert( false ); } // search neighbouring cell if( outside.partitionType() == Dune::InteriorEntity ) { assert( globalid.id( outside ) != globalid.id( entity ) ); const Dune::PartitionIteratorType pitype = Dune::InteriorBorder_Partition; typedef typename Grid::template Codim< 0 > ::template Partition< pitype >::LevelIterator LevelIteratorI; const int level = entity.level(); bool foundNeighbor = false; LevelIteratorI nit = g.levelGridView(level).template begin< 0, pitype >(); const LevelIteratorI nend = g.levelGridView(level).template end< 0, pitype > (); for( ; nit != nend; ++nit ) { if( nit->partitionType() != Dune::InteriorEntity ) { std::cerr << "Error: LevelIterator for InteriorBorder_Partition " << "stops on non-interior entity." << std :: endl; assert( false ); } if( *nit != outside ) assert( globalid.id( outside ) != globalid.id( *nit ) ); else foundNeighbor = true; } if( !foundNeighbor ) { std :: cerr << "Error: Interior neighbor returned by " << "LevelIntersectionIterator not found on that level." << std :: endl; assert( false ); } } } } // check that all faces were visited // note: This check is wrong on ghosts, where only intersections with // the domain are allowed. if( !isGhost ) { for(size_t i=0; i struct CheckMark { template static void check(GridType & grid, IteratorType & it) { // last marker is 0, so the grid is not changed after this check const int refCount[4] = {1,0,-1,0}; for(int k : refCount) { // mark entity bool marked = grid.mark( k , *it ); // if element was marked, check that the marker was set correctly if(marked) { // now getMark should return the mark we just set, otherwise error if( grid.getMark( *it ) < k ) DUNE_THROW(CheckError,"mark/getMark method not working correctly!"); } } } }; template struct CheckMark { template static void check(const GridType &, IteratorType & ) {} }; /* * Iterate over the grid und do some runtime checks */ template void iterate(Grid &g) { typedef typename Grid::template Codim<0>::LevelIterator LevelIterator; //[[maybe_unused]] typedef typename Grid::HierarchicIterator HierarchicIterator; typedef typename Grid::template Codim<0>::Geometry Geometry; int maxLevel = g.maxLevel(); LevelIterator it = g.levelGridView(maxLevel).template begin<0>(); const LevelIterator endit = g.levelGridView(maxLevel).template end<0>(); typename Geometry::LocalCoordinate origin(1); typename Geometry::LocalCoordinate result; for (; it != endit; ++it) { LevelIterator l1 = it; LevelIterator l2 = l1; ++l1; assert( (l2 == it) && (it == l2) ); assert( (l1 != it) && (it != l1) ); ++l2; assert( (l1 == l2) && (l2 == l1) ); const Geometry geo = it->geometry(); if( geo.type() != it->type() ) { std::cerr << "inconsistent geometry type: entity.type() = " << it->type() << ", geometry.type() = " << geo.type() << "." << std::endl; assert( false ); } if( !geo.type().isNone() ) { origin = referenceElement(geo).position(0,0); typename Geometry::LocalCoordinate origin2 = referenceElement( *it ).position(0,0); if( (origin - origin2 ).two_norm() > 1e-10 ) DUNE_THROW(CheckError, "referenceElement( entity ) != referenceElement( geo )"); result = geo.local( geo.global( origin ) ); typename Grid::ctype error = (result-origin).two_norm(); if(error >= factorEpsilon * std::numeric_limits::epsilon()) { DUNE_THROW(CheckError, "|| geom.local(geom.global(" << origin << ")) - origin || != 0 ( || " << result << " - origin || ) = " << error); }; [[maybe_unused]] const typename Geometry::ctype iE = geo.integrationElement( origin ); if((int)Geometry::coorddimension == (int)Geometry::mydimension) [[maybe_unused]] const typename Geometry::JacobianInverseTransposed jInvT = geo.jacobianInverseTransposed( origin ); } [[maybe_unused]] const int numCorners = geo.corners(); [[maybe_unused]] const typename Geometry::GlobalCoordinate cornerCoord = geo.corner( 0 ); } typedef typename Grid::template Codim<0>::LeafIterator LeafIterator; LeafIterator lit = g.leafGridView().template begin<0>(); const LeafIterator lend = g.leafGridView().template end<0>(); // if empty grid, do nothing if(lit == lend) return; for (; lit != lend; ++lit) { LeafIterator l1 = lit; LeafIterator l2 = l1; ++l1; assert(l2 == lit); assert(l1 != lit); ++l2; assert(l1 == l2); // leaf check if( !lit->isLeaf() ) DUNE_THROW(CheckError,"LeafIterator gives non-leaf entity!"); // check adaptation mark for leaf entity mark CheckMark::check(g,lit); if( !lit->type().isNone() ) { origin = referenceElement(lit->geometry()).position(0,0); result = lit->geometry().local(lit->geometry().global(origin)); typename Grid::ctype error = (result-origin).two_norm(); if(error >= factorEpsilon * std::numeric_limits::epsilon()) { DUNE_THROW(CheckError, "|| geom.local(geom.global(" << origin << ")) - origin || != 0 ( || " << result << " - origin || ) = " << error); } [[maybe_unused]] const typename Geometry::ctype iE = lit->geometry().integrationElement(origin); if((int)Geometry::coorddimension == (int)Geometry::mydimension) [[maybe_unused]] const typename Geometry::JacobianInverseTransposed jInvT = lit->geometry().jacobianInverseTransposed(origin); } [[maybe_unused]] const Dune::GeometryType geoType = lit->geometry().type(); [[maybe_unused]] const int numCorners = lit->geometry().corners(); [[maybe_unused]] const typename Geometry::GlobalCoordinate cornerCoord =lit->geometry().corner( 0 ); } } template void iteratorEquals (Grid &g) { typedef typename Grid::template Codim<0>::LevelIterator LevelIterator; typedef typename Grid::template Codim<0>::LeafIterator LeafIterator; typedef typename Grid::HierarchicIterator HierarchicIterator; typedef typename Grid::LeafGridView LeafGridView; typedef typename Grid::LevelGridView LevelGridView; typedef typename LeafGridView::IntersectionIterator LeafIntersectionIterator; typedef typename LevelGridView::IntersectionIterator LevelIntersectionIterator; LeafGridView leafGridView = g.leafGridView(); LevelGridView levelGridView = g.levelGridView(0); // assignment tests LevelIterator l1 = levelGridView.template begin<0>(); LevelIterator l2 = levelGridView.template begin<0>(); LeafIterator L1 = leafGridView.template begin<0>(); LeafIterator L2 = leafGridView.template begin<0>(); // if grid empty, leave if (l1 == levelGridView.template end<0>()) return; // check '==' consistency typedef typename Grid::template Codim<0>::Entity Entity; Entity a( *levelGridView.template begin<0,Dune::All_Partition>() ); Entity i( *levelGridView.template begin<0,Dune::InteriorBorder_Partition>() ); assert( (levelGridView.indexSet().index(a) != levelGridView.indexSet().index(i)) // index equal == (a != i) // entitypointer equal ); assert( (levelGridView.indexSet().index(a) == levelGridView.indexSet().index(i)) // index equal == (a == i) // entitypointer equal ); HierarchicIterator h1 = l1->hbegin(99); HierarchicIterator h2 = l2->hbegin(99); LeafIntersectionIterator i1 = leafGridView.ibegin( *l1 ); LeafIntersectionIterator i2 = leafGridView.ibegin( *l2 ); // assign l1 = l2; L1 = L2; h1 = h2; i1 = i2; // iterator comparisons assert(l1 == l2 && !(l1 != l2)); assert(L1 == L2 && !(L1 != L2)); assert(h1 == h2 && !(h1 != h2)); assert(i1 == i2 && !(i1 != i2)); // entity comparisons assert(*l1 == *l2 && !(*l1 != *l2)); assert(*L1 == *L2 && !(*L1 != *L2)); if (h1 != l1->hend(99)) assert(*h1 == *h2 && !(*h1 != *h2)); // intersection comparison if (i1 != leafGridView.iend(*l1)) assert(*i1 == *i2 && !(*i1 != *i2)); if( EnableLevelIntersectionIteratorCheck< Grid >::v ) { LevelIntersectionIterator li1 = levelGridView.ibegin( *l1 ); LevelIntersectionIterator li2 = levelGridView.ibegin( *l2 ); assert(li1 == li2 && !(li1 != li2)); if( !( li1 == li2 && !(li1 != li2) ) ) DUNE_THROW( Dune::GridError, "LevelIntersectionIterator check failed" ); if (li1 != levelGridView.iend(*l1)) { assert(*li1 == *li2 && !(*li1 != *li2)); if( ! ( *li1 == *li2 && !(*li1 != *li2) ) ) DUNE_THROW( Dune::GridError, "LevelIntersectionIterator dereferencing check failed" ); } } } template< class Grid, class Entity, class Intersection > void checkBoundarySegmentIndexProlongation ( const Grid &grid, const Entity &entity, const Intersection &intersection ) { typedef typename Entity::HierarchicIterator HierarchicIterator; typedef typename Entity::LocalGeometry GeometryInFather; typedef typename Grid::LevelGridView GridView; typedef typename GridView::IntersectionIterator IntersectionIterator; const typename Intersection::LocalGeometry &geoInInside = intersection.geometryInInside(); const GridView gridView = grid.levelGridView( entity.level()+1 ); const HierarchicIterator hend = entity.hend( entity.level()+1 ); for( HierarchicIterator hit = entity.hbegin( entity.level()+1 ); hit != hend; ++hit ) { GeometryInFather geoInFather = hit->geometryInFather(); auto refElement = referenceElement( geoInFather ); const IntersectionIterator iend = gridView.iend( *hit ); for( IntersectionIterator iit = gridView.ibegin( *hit ); iit != iend; ++iit ) { if( !iit->boundary() ) continue; const typename GeometryInFather::GlobalCoordinate x = geoInFather.global( refElement.position( iit->indexInInside(), 1 ) ); const typename GeometryInFather::GlobalCoordinate y = geoInInside.global( geoInInside.local( x ) ); if( (x-y).two_norm2() > 1e-10 ) continue; if( iit->boundarySegmentIndex() != intersection.boundarySegmentIndex() ) { std::cerr << "Error: Boundary segment index " << intersection.boundarySegmentIndex() << " not prolonged down (level " << entity.level() << " to " << hit->level() << ")." << std::endl; } if( !hit->isLeaf() ) checkBoundarySegmentIndexProlongation( grid, *hit, *iit ); } } } // check for consistency of hasFather(), father(), and father().level() template< class Grid > void checkFatherLevel ( Grid &grid ) { for(int level=0; level<=grid.maxLevel(); ++level) { typedef typename Grid::LevelGridView GridView; typedef typename GridView::template Codim<0>::Iterator Iterator; typedef typename Iterator::Entity Entity; GridView gv = grid.levelGridView(level); Iterator it = gv.template begin<0>(); Iterator end = gv.template end<0>(); for(; it!=end; ++it) { if (level==0) { if (it->hasFather()) { std::cerr << "Error: hasFather() is true for element " << gv.indexSet().index(*it) << " on level 0" << std::endl; assert(false); } } else { if (it->hasFather()) { // check level of father for newly created entitypointer { Entity f = it->father(); if (f.level() != level-1) { std::cerr << "Error! father().level()=" << f.level() << " for element on level " << level << std::endl; assert(false); } } // check level of father after reassignment { Entity f(*it); f = f.father(); if (f.level() != level-1) { std::cerr << "Error! father().level()=" << f.level() << " for element on level " << level << " with reassigned father pointer" << std::endl; assert(false); } } } } } } } template< class GridView > void checkBoundarySegmentIndex ( const GridView &gridView ) { typedef typename GridView::template Codim< 0 >::Iterator Iterator; typedef typename GridView::IntersectionIterator IntersectionIterator; size_t numBoundarySegments = gridView.grid().numBoundarySegments(); size_t countBoundarySegments = 0; bool error = false; const Iterator end = gridView.template end< 0 >(); for( Iterator it = gridView.template begin< 0 >(); it != end; ++it ) { if( !it->hasBoundaryIntersections() ) continue; const IntersectionIterator iend = gridView.iend( *it ); for( IntersectionIterator iit = gridView.ibegin( *it ); iit != iend; ++iit ) { if( iit->boundary() ) ++countBoundarySegments; } } if( countBoundarySegments != numBoundarySegments ) { std::cerr << "Error: Wrong number of boundary segments (reported: " << numBoundarySegments << ", counted: " << countBoundarySegments << ")." << std::endl; std::abort(); } std::vector< int > count( numBoundarySegments, 0 ); for( Iterator it = gridView.template begin< 0 >(); it != end; ++it ) { if( !it->hasBoundaryIntersections() ) continue; const IntersectionIterator iend = gridView.iend( *it ); for( IntersectionIterator iit = gridView.ibegin( *it ); iit != iend; ++iit ) { if( !iit->boundary() ) continue; const size_t index = iit->boundarySegmentIndex(); if( index >= numBoundarySegments ) { std::cerr << "Error: Boundary segment index out of bounds: (index: " << index << ", size: " << numBoundarySegments << ")." << std::endl; error = true; } else ++count[ index ]; if( !it->isLeaf() ) checkBoundarySegmentIndexProlongation( gridView.grid(), *it, *iit ); } } for( size_t i = 0; i < count.size(); ++i ) { if( count[ i ] == 0 ) { std::cerr << "Error: Boundary segment indices not consecutive (index " << i << " not used)." << std::endl; error = true; } else if( count[ i ] != 1 ) { std::cerr << "Error: Boundary segment index not unique within macro grid" << " (index " << i << " used " << count[ i ] << " times)." << std::endl; error = true; } } if (error) { std::string msg("Error encountered during checkBoundarySegmentIndex."); if( gridView.grid().comm().size() > 1 ) std::cerr << msg << std::endl; else DUNE_THROW(Dune::Exception, msg ); } } // Test whether the local-to-global map for codim 1 subentities is a bijective // mapping from the reference element onto the global element. // This is hard to test in general, but for elements that lie in an axis-parallel plane // we can just ignore one coordinate and check whether the determinant of the // Jacobian with respect to the other two coordinates is non-zero everywhere. As we // can't actually check "everywhere", test whether the determinant changes sign between // different quadrature points. As the determinant should be continuous, a sign flip // implies that the determinant is zero at some point. template = 0, std::enable_if_t::v, int> = 0> void checkCodim1Mapping(const Grid &g, Dune::PriorityTag<1>) { bool error = false; const auto& gv = g.leafGridView(); for (const auto& entity : Dune::elements(gv)) { for (unsigned int index = 0; index < entity.subEntities(1); ++index) { const auto& subEntity = entity.template subEntity<1>(index); const auto& subGeom = subEntity.geometry(); const auto numCorners = subGeom.corners(); std::bitset<3> equalCoords("111"); const auto& firstCornerCoords = subGeom.corner(0); for (int c = 1; c < numCorners; ++c) for (size_t i = 0; i < 3; ++i) equalCoords[i] = equalCoords[i] && Dune::FloatCmp::eq(subGeom.corner(c)[i], firstCornerCoords[i]); if (equalCoords.count() == 1) { size_t detPositive(0), detNegative(0), detZero(0), size(0); for (const auto& ip : Dune::QuadratureRules::rule(subEntity.type(),2)) { ++size; const Dune::FieldMatrix< typename Grid::ctype, 2, 3 > full_jacT( subGeom.jacobianTransposed( ip.position() ) ); Dune::FieldMatrix jacT(0); size_t k = 0; for (size_t j = 0; j < 3; ++j) { if (!equalCoords[j]) { for (size_t i = 0; i < 2; ++i) jacT[i][k] += full_jacT[i][j]; ++k; } } const auto det = jacT.determinant(); det > 0 ? ++detPositive : (det < 0 ? ++detNegative : ++detZero); } if (!(detPositive == size || detNegative == size)) { std::cerr << "Error: Local-to-global mapping for codim 1 subEntity " << index << " of element with index " << gv.indexSet().index(entity) << " is not invertible!" << std::endl; error = true; } } } } if (error) { std::string msg("Error encountered during checkCodim1Mapping!."); if( g.comm().size() > 1 ) std::cerr << msg << std::endl; else DUNE_THROW(Dune::Exception, msg ); } } template void checkConforming(const GridView& view) { view.isConforming(); } template void checkCodim1Mapping(const Grid &/*g*/, Dune::PriorityTag<0>) {} template void checkCodim1Mapping(const Grid &g) { checkCodim1Mapping(g, Dune::PriorityTag<4>{}); } template void gridcheck (Grid &g) { /* * first do the compile-test: this will not produce any code but * fails if an interface-component is missing */ GridInterface(); constexpr static int dim = Grid :: dimension; constexpr static int dimworld = Grid :: dimensionworld; typedef typename Grid :: ctype ctype; typedef typename Grid :: GridFamily GridFamily; /* * Check whether we have a nonzero number of entities in each view * in case the grid is non-empty */ if( g.size( 0 ) > 0 ) { for (int i=0; i<=dim; i++) { // if entities for a specific codimension are not available the size can be 0 if( g.size(i) > 0 ) { for (int j=0; j<=g.maxLevel(); j++) if (g.comm().size() == 1) assert(g.size(j,i)>0); else assert(g.size(j,i)>=0); // in parallel this could be zero (depends on definition of maxLevel() method in parallel) } } } #if DUNE_VERBOSE_TESTS // print infos Dune::gridinfo(g, "GridInfo"); for(int l=0; l >(); /* * now the runtime-tests */ const Grid & cg = g; iteratorEquals(g); iteratorEquals(cg); iterate(g); iterate(cg); zeroEntityConsistency(g); zeroEntityConsistency(cg); assertNeighbor(g); assertNeighbor(cg); checkFatherLevel(g); checkFatherLevel(cg); checkCodim1Mapping(g); // check conforming checkConforming( g.levelGridView( 0 ) ); checkConforming( g.leafGridView() ); // check geometries of macro level and leaf level Dune::GeometryChecker checker; checker.checkGeometry( g.levelGridView( 0 ) ); checker.checkGeometry( g.leafGridView() ); // check entity seeds Dune::checkEntitySeed( g.leafGridView(), std::cerr ); for( int level = 0; level <= g.maxLevel(); ++level ) Dune::checkEntitySeed( g.levelGridView( level ), std::cerr ); // note that for some grid this might fail // then un comment this test Dune :: checkIndexSet( g, g.leafGridView(), Dune :: dvverb ); for( int level = 0; level <= g.maxLevel(); ++level ) Dune :: checkIndexSet( g, g.levelGridView( level ), Dune :: dvverb, true ); // check id sets checkIdSet(g, g.localIdSet()); checkIdSet(g, g.globalIdSet()); // check at least if the subId method is there { typename Grid::Traits::template Codim<0>::LevelIterator it = g.levelGridView( g.maxLevel() ).template begin<0>(); typename Grid::Traits::template Codim<0>::LevelIterator end = g.levelGridView( g.maxLevel() ).template end<0>(); for (; it != end; ++it) { const typename Grid::GlobalIdSet::IdType idG = g.globalIdSet().subId(*it,0,dim); if(idG != g.globalIdSet().id(it->template subEntity(0))) { std::cerr << "Error: Inconsistent global subId for vertex 0 (id(subEntity)=" << g.globalIdSet().id(it->template subEntity(0)) << ", subId=" << g.globalIdSet().subId(*it,0,dim) << ") of cell " << g.globalIdSet().id(*it) << std::endl; assert(false); } } } if(Dune::EnableBoundarySegmentIndexCheck::value) { if( EnableLevelIntersectionIteratorCheck< Grid >::v ) checkBoundarySegmentIndex( g.levelGridView( 0 ) ); else if( g.maxLevel() == 0 ) checkBoundarySegmentIndex( g.leafGridView() ); else std::cout << "Warning: Skipping boundary segment index check (missing level intersection iterator)." << std::endl; } else std::cout << "Warning: Skipping boundary segment index check because it has been explicitly disabled." << std::endl; // check for range-based for iteration and correct entity / intersection lifetime checkEntityLifetime(g.levelGridView(g.maxLevel())); if (EnableLevelIntersectionIteratorCheck< Grid >::v) checkIntersectionLifetime(g.levelGridView(g.maxLevel())); checkEntityLifetime(g.leafGridView()); checkIntersectionLifetime(g.leafGridView()); } #endif // #ifndef DUNE_GRID_TEST_GRIDCHECK_HH dune-grid-2.11.0/dune/grid/test/issue-53-uggrid-intersections.cc000066400000000000000000000107011511655130300243410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /* * Check leaf intersection geometry on UGGrid. * * Reference: https://gitlab.dune-project.org/core/dune-grid/issues/53 */ #include #include #include #include #include #include #if HAVE_DUNE_ALUGRID # include #endif const double EPSILON = 1e-12; using Dune::TestSuite; template TestSuite testGrid(const Grid& grid, const std::string& name) { using std::sqrt; TestSuite test; // now iterate over intersections const auto& gv = leafGridView(grid); for (const auto& e : elements(gv)) { for (const auto& is : intersections(gv, e)) { if (is.boundary()) continue; // compute the edge lengths of the inner and outer element auto insideLength = sqrt(is.inside().geometry().volume()); auto outsideLength = sqrt(is.outside().geometry().volume()); // length of intersection auto intersectionLength = is.geometry().volume(); // intersection should not be longer than any full edge const bool check = intersectionLength < insideLength+EPSILON && intersectionLength < outsideLength+EPSILON; test.check(check) << "=== " << name << ": Intersection is longer than actual edge! ===\n" << " inside center: " << is.inside().geometry().center() << "\n" << " outside center: " << is.outside().geometry().center() << "\n" << " lengths: intersection: " << intersectionLength << " inside: " << insideLength << " outside: " << outsideLength << "\n"; } } // output mesh as VTK (uncomment if needed) // auto vtk = Dune::VTKWriter(gv); // vtk.write(s); return test; } template TestSuite testRefinement1(Grid& grid, const std::string& name) { const auto& gv = leafGridView(grid); // Make some pseudo-adaptive refinements for (int i = 0; i < 5; ++i) { for (auto e : elements(gv)) { if (gv.indexSet().subIndex(e,0,0) % 5 == 0) // mark some elements for refinement grid.mark(1, e); } grid.adapt(); grid.postAdapt(); } return testGrid(grid, name); } template TestSuite testRefinement2(Grid& grid, const std::string& name) { using Coordinate = typename Grid::template Codim<0>::Geometry::GlobalCoordinate; // List of list of elements to refine in each refinement cycle. // The elements are specified using their cell center. const std::vector< std::vector > refine = { {{0.5, 0.5}}, {{0.75, 0.25}}, {{0.875, 0.375}}, {{0.9375, 0.4375}, {0.875, 0.125}} }; const auto& gv = leafGridView(grid); for (const auto& xs : refine) { for (const auto& e : elements(gv)) { for (const auto& x : xs) { auto d = e.geometry().center() - x; if (d.two_norm() < EPSILON) grid.mark(1, e); } } grid.adapt(); grid.postAdapt(); } return testGrid(grid, name); } int main(int argc, char** argv) { Dune::MPIHelper::instance(argc, argv); TestSuite test; // test with UG { using GridType = Dune::UGGrid<2>; auto grid = Dune::StructuredGridFactory::createCubeGrid({0,0}, {1.0,1.0}, {16,16}); grid->setClosureType(GridType::ClosureType::NONE); test.subTest(testRefinement1(*grid, "UGGrid-1")); } { using GridType = Dune::UGGrid<2>; auto grid = Dune::StructuredGridFactory::createCubeGrid({0,0}, {2.0,1.0}, {2,1}); grid->setClosureType(GridType::ClosureType::NONE); test.subTest(testRefinement2(*grid, "UGGrid-2")); } // test with ALU #if HAVE_DUNE_ALUGRID { using GridType = Dune::ALUGrid<2,2, Dune::cube, Dune::nonconforming>; auto grid = Dune::StructuredGridFactory::createCubeGrid({0.0,0.0}, {1.0,1.0}, {16,16}); test.subTest(testRefinement1(*grid, "ALUGrid-1")); } { using GridType = Dune::ALUGrid<2,2, Dune::cube, Dune::nonconforming>; auto grid = Dune::StructuredGridFactory::createCubeGrid({0,0}, {2.0,1.0}, {2,1}); grid->setClosureType(GridType::ClosureType::NONE); test.subTest(testRefinement2(*grid, "ALUGrid-2")); } #endif return test.exit(); } dune-grid-2.11.0/dune/grid/test/staticcheck.hh000066400000000000000000000427471511655130300211340ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_STATICCHECK_HH #define DUNE_GRID_TEST_STATICCHECK_HH /** \file \brief Implements static grid checks \todo check return types */ #include #include #include #include #include #include #include template< class Geometry, int codim, int dim > struct GeometryInterface { static void check ( const Geometry &geo ) { static_assert( (Geometry::mydimension == dim-codim), "" ); using ctype [[maybe_unused]] = typename Geometry::ctype; [[maybe_unused]] const Dune::GeometryType geoType = geo.type(); [[maybe_unused]] const bool affinity = geo.affine(); [[maybe_unused]] const int numCorners = geo.corners(); [[maybe_unused]] const typename Geometry::GlobalCoordinate cornerCoord = geo.corner( 0 ); typename Geometry::LocalCoordinate v(0.0); [[maybe_unused]] const typename Geometry::GlobalCoordinate coord = geo.global(v); typename Geometry::GlobalCoordinate g(0.0); [[maybe_unused]] const typename Geometry::LocalCoordinate locCoord = geo.local(g); [[maybe_unused]] const ctype vol = geo.integrationElement(v); [[maybe_unused]] const typename Geometry::JacobianTransposed jT = geo.jacobianTransposed( v ); [[maybe_unused]] const typename Geometry::JacobianInverseTransposed jInvT = geo.jacobianInverseTransposed( v ); [[maybe_unused]] const typename Geometry::Jacobian j = geo.jacobian( v ); [[maybe_unused]] const typename Geometry::JacobianInverse iInv = geo.jacobianInverse( v ); } GeometryInterface () { c = check; } private: void (*c)( const Geometry & ); }; // --- compile-time check of entity-interface // tests that should work on entities of all codimensions template void DoEntityInterfaceCheck (Entity &e) { // exported types using Geometry [[maybe_unused]] = typename Entity::Geometry; using EntitySeed [[maybe_unused]] = typename Entity::EntitySeed; // methods on each entity [[maybe_unused]] const int lvl = e.level(); [[maybe_unused]] const Dune::PartitionType pT = e.partitionType(); [[maybe_unused]] const Geometry geo = e.geometry(); // check interface of attached element-interface GeometryInterface< typename Entity::Geometry, Entity::codimension, Entity::dimension >(); } // recursive check of codim-0-entity methods subEntities(), entity() template struct ZeroEntityMethodCheck { typedef typename Grid::template Codim<0>::Entity Entity; static void check(Entity &e) { // check types using HierarchicIterator [[maybe_unused]] = typename Entity::HierarchicIterator; [[maybe_unused]] const unsigned int subE = e.subEntities(cd); e.template subEntity(0); // recursively check on ZeroEntityMethodCheck::v >(); } ZeroEntityMethodCheck () { c = check; } void (*c)(Entity &e); }; // just the recursion if the grid does not know about this codim-entity template struct ZeroEntityMethodCheck { typedef typename Grid::template Codim<0>::Entity Entity; static void check(Entity &) { // check types using HierarchicIterator [[maybe_unused]] = typename Entity::HierarchicIterator; // recursively check on ZeroEntityMethodCheck::v >(); } ZeroEntityMethodCheck () { c = check; } void (*c)(Entity &e); }; // end recursive checking template struct ZeroEntityMethodCheck { typedef typename Grid::template Codim<0>::Entity Entity; static void check(Entity &e) { // check types using HierarchicIterator [[maybe_unused]] = typename Entity::HierarchicIterator; [[maybe_unused]] const unsigned int subE = e.subEntities(0); [[maybe_unused]] const Entity ent = e.template subEntity<0>(0); } ZeroEntityMethodCheck () { c = check; } void (*c)(Entity &e); }; // end recursive checking - same as true // ... codim 0 is always needed template struct ZeroEntityMethodCheck { typedef typename Grid::template Codim<0>::Entity Entity; static void check(Entity &e) { // check types using HierarchicIterator [[maybe_unused]] = typename Entity::HierarchicIterator; e.subEntities(0); e.template subEntity<0>(0); } ZeroEntityMethodCheck () { c = check; } void (*c)(Entity &e); }; // IntersectionIterator interface check template struct IntersectionIteratorInterface { constexpr static int dim = Grid::dimension; typedef typename Grid::ctype ct; static void check (IntersectionIterator &i) { // increment / equality / ... IntersectionIterator j = i; ++j; { [[maybe_unused]] bool tmp = (i == j); } { [[maybe_unused]] bool tmp = (i != j); } j = i; // state typedef typename IntersectionIterator::Intersection Intersection; using Entity = typename Grid::template Codim<0>::Entity; using Geometry = typename Grid::template Codim<1>::Geometry; using LocalGeometry = typename Grid::template Codim<1>::LocalGeometry; const Intersection &inter = *i; [[maybe_unused]] const bool isBoundary = inter.boundary(); [[maybe_unused]] const bool hasNeighbor = inter.neighbor(); [[maybe_unused]] const std::size_t bSI = inter.boundarySegmentIndex(); // neighbouring elements [[maybe_unused]] const Entity innerE = inter.inside(); if(inter.neighbor()) [[maybe_unused]] const Entity outerE = inter.outside(); // geometry [[maybe_unused]] const LocalGeometry locGeoInside = inter.geometryInInside(); if(inter.neighbor()) [[maybe_unused]] const LocalGeometry locGeoOutside = inter.geometryInOutside(); [[maybe_unused]] const Geometry geo = inter.geometry(); [[maybe_unused]] const int indexInside = inter.indexInInside(); if(inter.neighbor()) [[maybe_unused]] const int indexOutside = inter.indexInOutside(); typename Intersection::LocalCoordinate v(0); using GlobalCoordinate = typename Intersection::GlobalCoordinate; [[maybe_unused]] const GlobalCoordinate outerNormal = inter.outerNormal(v); [[maybe_unused]] const GlobalCoordinate integrationOuterNormal = inter.integrationOuterNormal(v); [[maybe_unused]] const GlobalCoordinate unitOuterNormal = inter.unitOuterNormal(v); } IntersectionIteratorInterface () { c = check; } private: void (*c)(IntersectionIterator&); }; // check codim-entity and pass on to codim + 1 template struct EntityInterface { typedef typename Grid::template Codim::Entity Entity; static void check ( const Entity &e ) { // consistent? static_assert( (Entity::codimension == codim), "" ); static_assert( (Entity::dimension == dim), "" ); // do the checking DoEntityInterfaceCheck(e); // recursively check sub-entities EntityInterface::v >(); } EntityInterface () { c = check; } private: void (*c)( const Entity & ); }; // just the recursion if the grid does not know about this codim-entity template struct EntityInterface { typedef typename Grid::template Codim::Entity Entity; static void check (Entity &) { // recursively check sub-entities EntityInterface::v >(); } EntityInterface () { c = check; } void (*c)(Entity&); }; // codim-0 entities have different interface template struct EntityInterface { typedef typename Grid::template Codim<0>::Entity Entity; static void check ( const Entity &e, bool checkLevelIter = true ) { // consistent? static_assert( (Entity::codimension == 0), "" ); static_assert( (Entity::dimension == dim), "" ); // do the common checking DoEntityInterfaceCheck(e); // special codim-0-entity methods which are parametrized by a codimension ZeroEntityMethodCheck ::v >(); // grid hierarchy if ( e.hasFather() ) { const Entity father = e.father(); father.hbegin(0); e.geometryInFather(); } // intersection iterator if (checkLevelIter) { // #if 0 // WARNING must be updated to new interface IntersectionIteratorInterface(); // #endif } // #if 0 // WARNING must be updated to new interface if(e.isLeaf()) IntersectionIteratorInterface(); // #endif // hierarchic iterator e.hbegin(0); e.hend(0); // adaption [[maybe_unused]] const bool isNew = e.isNew(); [[maybe_unused]] const bool mightVanish = e.mightVanish(); // recursively check sub-entities EntityInterface::v >(); } EntityInterface () { c = check; } private: void (*c)( const Entity &, bool ); }; // non existinng codim-0 entity template struct EntityInterface { typedef typename Grid::template Codim<0>::Entity Entity; static void check (Entity &/*e*/) { // recursively check sub-entities EntityInterface::v >(); } EntityInterface () { c = check; } void (*c)(Entity&); }; // end the recursion over entity-codimensions template struct EntityInterface { typedef typename Grid::template Codim::Entity Entity; // end recursion static void check ( const Entity &e ) { // consistent? static_assert( (Entity::codimension == dim), "" ); static_assert( (Entity::dimension == dim), "" ); // run common test DoEntityInterfaceCheck(e); } EntityInterface() { c = check; } void (*c)( const Entity & ); }; // end the recursion over entity-codimensions // ... codim dim entity does not exist template struct EntityInterface { typedef typename Grid::template Codim::Entity Entity; // end recursion static void check (Entity &/*e*/) {} EntityInterface() { c = check; } void (*c)(Entity&); }; template struct LeafInterface { static void check([[maybe_unused]] Grid &g) {} LeafInterface() { c = check; } void (*c)(Grid&); }; template< class GridView > struct GridViewInterface { static void check ( const GridView &gv ) { const int dimension = GridView::dimension; using Grid [[maybe_unused]] = typename GridView::Grid; using IndexSet [[maybe_unused]] = typename GridView::IndexSet; using Intersection [[maybe_unused]] = typename GridView::Intersection; using IntersectionIterator [[maybe_unused]] = typename GridView::IntersectionIterator; gv.grid(); [[maybe_unused]] const int elementsInGrid = gv.size( 0 ); [[maybe_unused]] const int cubesInGrid = gv.size( Dune::GeometryTypes::cube( GridView::dimension ) ); gv.template begin< 0 >(); gv.template end< 0 >(); // index set gv.indexSet(); using namespace Dune::Hybrid; forEach(std::make_integer_sequence< int, dimension+1 >(), [&](auto codim) { if constexpr (Dune::Capabilities::hasEntity::v) { typedef typename GridView::template Codim< codim >::Entity Entity; using Iterator [[maybe_unused]] = typename GridView::template Codim< codim >::Iterator; if( gv.template begin< 0 >() == gv.template end< 0 >() ) return; const Entity &entity = gv.template begin< 0 >()->template subEntity< codim >( 0 ); gv.indexSet().index( entity ); gv.indexSet().contains( entity ); try { using namespace Dune::Hybrid; forEach(std::make_integer_sequence< int, GridView::dimension+1 - codim>(), [&](auto subCodim) { gv.indexSet().subIndex( entity, 0, codim+subCodim); }); } catch( const Dune::NotImplemented& ) { // ignore Dune::NotImplemented for higher codimension if( codim == 0 ) throw; } gv.indexSet().types( codim ); } }); // intersections if( gv.template begin< 0 >() != gv.template end< 0 >() ) { gv.ibegin( *gv.template begin< 0 >() ); gv.iend( *gv.template begin< 0 >() ); } IntersectionIteratorInterface< Grid, IntersectionIterator >(); // parallel interface using GhostIterator [[maybe_unused]] = typename GridView::template Codim< 0 >::template Partition< Dune::Ghost_Partition >::Iterator; using Communication [[maybe_unused]] = typename GridView::Communication; gv.template begin< 0, Dune::Ghost_Partition >(); gv.template end< 0, Dune::Ghost_Partition >(); [[maybe_unused]] const bool overlapSize = gv.overlapSize( 0 ); [[maybe_unused]] const bool ghostSize = gv.ghostSize( 0 ); [[maybe_unused]] const Communication gcomm =gv.comm(); } GridViewInterface () : c( check ) {} void (*c)( const GridView & ); }; /** \brief Instantiate this class for a full static interface check */ template struct GridInterface { static void check (const Grid &g) { // check for exported types using LevelGridView [[maybe_unused]] = typename Grid::LevelGridView; using LeafGridView [[maybe_unused]] = typename Grid::LeafGridView; using ctype [[maybe_unused]] = typename Grid::ctype; // check for grid views g.levelGridView( 0 ); g.leafGridView(); levelGridView(g, 0); leafGridView(g); // check for member functions [[maybe_unused]] const int maxLvl = g.maxLevel(); // number of grid entities of a given codim on a given level [[maybe_unused]] const int numLevelEntities = g.size(0,0); // number of leaf entities per codim in this process [[maybe_unused]] const int numLeafEntities = g.size(0); // number of entities per level and geometry type in this process [[maybe_unused]] const int cubeLevelEntities = g.size(0, Dune::GeometryTypes::cube(Grid::dimension)); // number of leaf entities per geometry type in this process [[maybe_unused]] const int cubeLeafEntities = g.size(Dune::GeometryTypes::cube(Grid::dimension)); // check for iterator functions g.levelGridView(0).template begin<0>(); g.levelGridView(0).template end<0>(); LeafInterface< Grid >(); GridViewInterface< LevelGridView >(); GridViewInterface< LeafGridView >(); // Check for index sets using LevelIndexSet [[maybe_unused]] = typename Grid::LevelIndexSet; using LeafIndexSet [[maybe_unused]] = typename Grid::LeafIndexSet; using LocalIdSet [[maybe_unused]] = typename Grid::LocalIdSet; using GlobalIdSet [[maybe_unused]] = typename Grid::GlobalIdSet; g.levelIndexSet(0); if (g.levelGridView(0).template begin<0>() != g.levelGridView(0).template end<0>()) { // Instantiate all methods of LevelIndexSet g.levelIndexSet(0).index(*g.levelGridView(0).template begin<0>()); /** \todo Test for subindex is missing, because I don't know yet how to test for the existence of certain codims */ } g.levelIndexSet(0). size(Dune::GeometryTypes::simplex(Grid::dimension)); for( int codim = 0; codim < Grid::dimension; ++codim ) g.levelIndexSet( 0 ).types( codim ); /** \todo Test for subindex is missing, because I don't know yet how to test for the existence of certain codims */ g.leafIndexSet().size(Dune::GeometryTypes::simplex(Grid::dimension)); for( int codim = 0; codim < Grid::dimension; ++codim ) g.leafIndexSet().types( codim ); if ( g.levelGridView( 0 ).template begin< 0 >() != g.levelGridView( 0 ).template end< 0 >() ) { // Instantiate all methods of LocalIdSet /** \todo Test for subindex is missing, because I don't know yet how to test for the existence of certain codims */ [[maybe_unused]] const typename LocalIdSet::IdType idL = g.localIdSet().id( *g.levelGridView( 0 ).template begin< 0 >() ); // Instantiate all methods of GlobalIdSet /** \todo Test for subindex is missing, because I don't know yet how to test for the existence of certain codims */ [[maybe_unused]] const typename GlobalIdSet::IdType idG = g.globalIdSet().id( *g.levelGridView( 0 ).template begin< 0 >() ); } // recursively check entity-interface // ... we only allow grids with codim 0 entities static_assert((Dune::Capabilities::hasEntity::v),"Grid must have codim 0 entities"); static_assert((Dune::Capabilities::hasEntity::v),"Grid must have codim 0 entities"); EntityInterface< Grid, 0, Grid::dimension, Dune::Capabilities::hasEntity< Grid, 0 >::v >(); // !!! check for parallel grid? g.levelGridView(0).template begin<0, Dune::Ghost_Partition>(); g.levelGridView(0).template end<0, Dune::Ghost_Partition>(); } GridInterface() { c = check; } // member just to avoid "unused variable"-warning in constructor void (*c)(const Grid&); }; #endif // #ifndef DUNE_GRID_TEST_STATICCHECK_HH dune-grid-2.11.0/dune/grid/test/test-alberta.cc000066400000000000000000000147321511655130300212150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #ifndef GRIDDIM #define GRIDDIM ALBERTA_DIM #endif #include #include #include #include "../common/boundaryprojection.hh" #include "gridcheck.hh" #include "checkgeometryinfather.hh" #include "checkgeometry.hh" #include "checkintersectionit.hh" #include "checkcommunicate.hh" #include "checkiterators.hh" #include "checktwists.hh" #include "check-albertareader.hh" #include "checkadaptation.hh" #include "checkpartition.hh" #include "checkgridfactory.hh" #include template< int dim, int dimworld > struct EnableLevelIntersectionIteratorCheck< Dune::AlbertaGrid< dim, dimworld > > { static const bool v = false; }; template void markOne ( GridType & grid , int num , int ref ) { typedef typename GridType::template Codim<0> :: LeafIterator LeafIterator; int count = 0; const LeafIterator end = grid.template leafend< 0 >(); for( LeafIterator it = grid.template leafbegin< 0 >(); it != end ; ++it ) { if( num == count ) grid.mark( ref, *it ); ++count; } grid.preAdapt(); grid.adapt(); grid.postAdapt(); } template< class Grid, int dim > void addToGridFactory ( Dune::GridFactory< Grid > &factory, Dune::Dim< dim > ); template< class Grid > void addToGridFactory ( Dune::GridFactory< Grid > &factory, Dune::Dim< 1 > ) { Dune::TestGrids::unitLine.addToGridFactory( factory, [] ( const typename Dune::TestGrid< 1 >::Vertex &x ) { typename Dune::TestGrid< 1 >::Vertex y = x; y *= 2.0; y -= typename Dune::TestGrid< 1 >::Vertex( 1.0 ); return y; } ); } template< class Grid > void addToGridFactory ( Dune::GridFactory< Grid > &factory, Dune::Dim< 2 > ) { Dune::TestGrids::kuhn2d.addToGridFactory( factory, [] ( const typename Dune::TestGrid< 2 >::Vertex &x ) { typename Dune::TestGrid< 2 >::Vertex y = x; y *= 2.0; y -= typename Dune::TestGrid< 2 >::Vertex( 1.0 ); return y; } ); } template< class Grid > void addToGridFactory ( Dune::GridFactory< Grid > &factory, Dune::Dim< 3 > ) { Dune::TestGrids::kuhn3d.addToGridFactory( factory, [] ( const typename Dune::TestGrid< 3 >::Vertex &x ) { typename Dune::TestGrid< 3 >::Vertex y = x; y *= 2.0; y -= typename Dune::TestGrid< 3 >::Vertex( 1.0 ); return y; } ); } template< class Grid > void checkProjectedUnitCube () { typedef Dune::CircleBoundaryProjection< Grid::dimensionworld > Projection; std::cout << ">>> Checking projected unit cube..." << std::endl; Dune::GridFactory< Grid > gridFactory; addToGridFactory( gridFactory, Dune::Dim< Grid::dimensionworld > () ); gridFactory.insertBoundaryProjection( new Projection ); gridFactory.markLongestEdge(); auto grid = gridFactory.createGrid(); for( int i = 0; i < 2; ++i ) { grid->globalRefine( Grid::dimension ); gridcheck( *grid ); } } int main ( int argc, char **argv ) try { const int dim = GRIDDIM; typedef Dune::AlbertaGrid< dim > GridType; std::cout << "Testing " << GridType::typeName() << "..." << std::endl; #if ALBERTA_DIM == 2 && GRIDDIM == 2 std::cout << "Check GridFactory ..." <( Dune::TestGrids::kuhn2d ); #endif // #if ALBERTA_DIM == 2 && GRIDDIM == 2 #if ALBERTA_DIM == 3 && GRIDDIM == 3 std::cout << "Check GridFactory ..." <( Dune::TestGrids::kuhn3d ); #endif // #if ALBERTA_DIM == 3 && GRIDDIM == 3 std::string filename; if( argc <= 1 ) { checkAlbertaReader< GridType >(); #if ALBERTA_DIM == GRIDDIM if( dim < 3 ) checkProjectedUnitCube< GridType >(); #endif /* use grid-file appropriate for dimensions */ std::ostringstream sfilename; const int dimWorld = GridType::dimensionworld; sfilename << DUNE_GRID_EXAMPLE_GRIDS_PATH "dgf/simplex-testgrid-" << GridType::dimension << "-" << std::min( dimWorld, 3) << ".dgf"; filename = sfilename.str(); #if ALBERTA_DIM == 3 && GRIDDIM == 3 // FS#1234: The recursive bisection exhausts the execution stack using the other grid. filename = std::string(DUNE_GRID_EXAMPLE_GRIDS_PATH "dgf/grid3Y.dgf"); #endif } else filename = argv[ 1 ]; std::cout << std::endl << GridType::typeName() << " with grid file: " << filename << std::endl << std::endl; { factorEpsilon = 5e2; Dune::GridPtr gridPtr( filename ); GridType & grid = *gridPtr; // extra-environment to check destruction std::cout << ">>> Checking macro grid..." << std::endl; gridcheck(grid); // check macro grid // check grid adaptation interface checkAdaptation( grid ); checkPartitionType( grid.leafGridView() ); checkIterators( grid.leafGridView() ); checkIntersectionIterator(grid,true); checkTwists( grid.leafGridView(), NoMapTwist() ); for(int i=0; i<1; i++) { std::cout << ">>> Refining grid and checking again..." << std::endl; grid.globalRefine( 1 ); gridcheck(grid); checkIterators( grid.leafGridView() ); checkIntersectionIterator(grid,true); checkTwists( grid.leafGridView(), NoMapTwist() ); } // check dgf grid width half refinement const int stepsForHalf = Dune::DGFGridInfo< GridType >::refineStepsForHalf(); std::cout << ">>> Refining grid (" << stepsForHalf << " times) and checking again..." << std::endl; grid.globalRefine( stepsForHalf ); gridcheck(grid); checkIterators( grid.leafGridView() ); checkIntersectionIterator(grid,true); checkTwists( grid.leafGridView(), NoMapTwist() ); for(int i=0; i<2; i++) { std::cout << ">>> Refining one element and checking again..." << std::endl; markOne(grid,0,dim); gridcheck(grid); checkIterators( grid.leafGridView() ); } checkGeometryInFather(grid); checkIntersectionIterator(grid,true); checkTwists( grid.leafGridView(), NoMapTwist() ); checkCommunication(grid, -1, Dune::dvverb); }; return 0; } catch( const Dune::Exception &e ) { std::cerr << e << std::endl; return 1; } catch( ... ) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/test/test-concepts.cc000066400000000000000000000034141511655130300214140ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include // HAVE_DUNE_UGGRID #include #if DUNE_GRID_HAVE_CONCEPTS #include #include #include #include #if HAVE_ALBERTA #include #endif #if HAVE_DUNE_UGGRID #include #endif int main ( int argc, char **argv ) { Dune::MPIHelper::instance( argc, argv ); static_assert(Dune::Concept::Grid< Dune::OneDGrid >); static_assert(Dune::Concept::Grid< Dune::YaspGrid<1> >); static_assert(Dune::Concept::Grid< Dune::YaspGrid<2> >); static_assert(Dune::Concept::Grid< Dune::YaspGrid<3> >); #if HAVE_ALBERTA static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<1,1> >); static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<1,2> >); static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<1,3> >); static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<2,2> >); static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<2,3> >); static_assert(Dune::Concept::Grid< Dune::AlbertaGrid<3,3> >); #endif #if HAVE_DUNE_UGGRID static_assert(Dune::Concept::Grid< Dune::UGGrid<2> >); static_assert(Dune::Concept::Grid< Dune::UGGrid<3> >); #endif // check grid wrappers static_assert(Dune::Concept::Grid< Dune::GeometryGrid< Dune::YaspGrid<1> > >); static_assert(Dune::Concept::Grid< Dune::IdentityGrid< Dune::YaspGrid<1> > >); } #else // DUNE_GRID_HAVE_CONCEPTS int main() { return 77; } #endif // DUNE_GRID_HAVE_CONCEPTS dune-grid-2.11.0/dune/grid/test/test-geogrid.cc000066400000000000000000000212661511655130300212230ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifdef COORDFUNCTION #if defined __GNUC__ and not defined __clang__ and not defined __ICC #define GCCPOOL #endif #include #include #include #ifdef GCCPOOL #include #endif #include // HAVE_DUNE_UGGRID, GRIDTYPE #include #include #include #if HAVE_DUNE_UGGRID #include #include #endif #include #include #include #include "functions.hh" #include "gridcheck.hh" #include "checkcommunicate.hh" #include "checkgeometryinfather.hh" #include "checkintersectionit.hh" #include "checkiterators.hh" #include "checkpartition.hh" #include "checkgeometry.hh" namespace Dune { template< int dim, int dimworld > class AlbertaGrid; } template< int dim, int dimworld > struct EnableLevelIntersectionIteratorCheck< Dune::AlbertaGrid< dim, dimworld > > { static const bool v = false; }; template< class HostGrid, class CoordFunction > struct EnableLevelIntersectionIteratorCheck< Dune::GeometryGrid< HostGrid, CoordFunction > > { static const bool v = EnableLevelIntersectionIteratorCheck< HostGrid >::v; }; typedef Dune::COORDFUNCTION AnalyticalCoordFunction; typedef GRIDTYPE Grid; #if CACHECOORDFUNCTION typedef Dune::CachedCoordFunction< Grid, AnalyticalCoordFunction > CoordFunction; #else typedef AnalyticalCoordFunction CoordFunction; #endif typedef Dune::GeometryGrid< Grid, CoordFunction > GeometryGrid; typedef Dune::GeometryGrid< Grid, CoordFunction, Dune::PoolAllocator< char, 16384 > > GeometryGridWithPoolAllocator; #ifdef GCCPOOL typedef Dune::GeometryGrid< Grid, CoordFunction, __gnu_cxx::__pool_alloc > GeometryGridWithGCCPoolAllocator; #endif #ifdef HAVE_MPROTECT typedef Dune::GeometryGrid< Grid, CoordFunction, Dune::DebugAllocator > GeometryGridWithDebugAllocator; #endif template struct DeformationFunction : public Dune::DiscreteCoordFunction< double, HostGridView::dimension, DeformationFunction > { static const int dim = HostGridView::dimension; DeformationFunction(const HostGridView& gridView, const std::vector >& deformedPosition) : indexSet_(gridView.indexSet()), deformedPosition_(deformedPosition) {} /** \brief Evaluate the position at the corner of an entity * * \note This method needs to work for entities of all codimensions, * not just for elements! */ template void evaluate (const HostEntity& hostEntity, unsigned int corner, Dune::FieldVector &y ) const { auto idx = indexSet_.subIndex(hostEntity, corner,dim); y = deformedPosition_[idx]; } private: const typename HostGridView::IndexSet& indexSet_; const std::vector< Dune::FieldVector > deformedPosition_; }; template void test(const std::string& gridfile) { Dune::GridPtr< GeometryGridType > pgeogrid(gridfile); GeometryGridType &geogrid = *pgeogrid; geogrid.globalRefine( 1 ); geogrid.loadBalance(); std::cerr << "Checking grid..." << std::endl; gridcheck( geogrid ); std::cerr << "Checking geometry... " << std::endl; Dune::GeometryChecker< GeometryGridType > checker; checker.checkGeometry( geogrid.leafGridView() ); for( int i = 0; i <= geogrid.maxLevel(); ++i ) checker.checkGeometry( geogrid.levelGridView( i ) ); std::cerr << "Checking geometry in father..." << std::endl; checkGeometryInFather( geogrid ); std::cerr << "Checking intersections..." << std::endl; checkIntersectionIterator( geogrid, !EnableLevelIntersectionIteratorCheck< Grid >::v ); checkIterators( geogrid.leafGridView() ); for( int i = 0; i <= geogrid.maxLevel(); ++i ) checkIterators( geogrid.levelGridView( i ) ); checkPartitionType( geogrid.leafGridView() ); for( int i = 0; i <= geogrid.maxLevel(); ++i ) checkPartitionType( geogrid.levelGridView( i ) ); std::cerr << "Checking geometry lifetime..." << std::endl; checkGeometryLifetime( geogrid.leafGridView() ); std::cerr << "Checking communication..." << std::endl; checkCommunication( geogrid, -1, std::cout ); if( EnableLevelIntersectionIteratorCheck< Grid >::v ) { for( int i = 0; i <= geogrid.maxLevel(); ++i ) checkCommunication( geogrid, i, std::cout ); } } void testNestedGeometryGrid(const std::string& gridfile) { using NestedGeometryGrid = Dune::GeometryGrid< GeometryGrid, Dune::IdenticalCoordFunction< Grid::ctype, Grid::dimensionworld > >; using NestedGgLeafView = NestedGeometryGrid::LeafGridView; Dune::GridPtr< NestedGeometryGrid > pgeogrid(gridfile); NestedGeometryGrid &geogrid = *pgeogrid; geogrid.globalRefine( 1 ); // creating different variables for storing grid views NestedGgLeafView gv1 = geogrid.leafGridView(); std::shared_ptr pgv2; NestedGgLeafView gv3 = geogrid.leafGridView(); // use geometry grid views copy constructor and copy assignment operator { NestedGgLeafView tmpGv = geogrid.leafGridView(); // copying/assigning temporary grid view would be dangerous with default implementation of copy constructor or copy assignment operator from geomrtry grid view pgv2 = std::make_shared (tmpGv); gv3 = tmpGv; } // The following test would now be guaranteed to fail with the default implementation of geometry grid views copy constructor // assert(&(pgv2->indexSet().hostIndexSet()) == &(pgv2->impl().hostGridView().indexSet())) // but this would not compile since the member functions impl() and hostIndexSet() are protected/private. // So we do the following // get index sets and do some arbitrary test to check whether they work correctly auto const& is1 = gv1.indexSet(); auto const& is2 = pgv2->indexSet(); auto const& is3 = gv3.indexSet(); for(auto const& e : elements(gv1)) { bool idxCorrect = (is1.index(e)==is2.index(e)); idxCorrect &= (is1.index(e)==is3.index(e)); assert(idxCorrect); } } int main ( int argc, char **argv ) try { Dune::MPIHelper::instance( argc, argv ); std::string gridfile = DUNE_GRID_EXAMPLE_GRIDS_PATH "dgf/cube-2.dgf"; if(argc >= 2) { gridfile = argv[1]; } Dune::Timer watch; watch.reset(); test(gridfile); std::cout << "=== GeometryGrid took " << watch.elapsed() << " seconds\n"; watch.reset(); testNestedGeometryGrid(gridfile); std::cout << "=== NestedGeometryGrid took " << watch.elapsed() << " seconds\n"; // compile, but do not actually call, because it is not working yet if (false) { watch.reset(); test(gridfile); std::cout << "=== GeometryGridWithPoolAllocator took " << watch.elapsed() << " seconds\n"; } #ifdef GCCPOOL watch.reset(); test(gridfile); std::cout << "=== GeometryGridWithGCCPoolAllocator took " << watch.elapsed() << " seconds\n"; #endif watch.reset(); #ifdef HAVE_MPROTECT test(gridfile); std::cout << "=== GeometryGridWithDebugAllocator took " << watch.elapsed() << " seconds\n"; #endif // Check with a discrete coordinate function Dune::GridPtr< Grid > hostGridPtr(gridfile); auto& hostGrid = *hostGridPtr; const int dim = Grid::dimension; typedef Grid::LeafGridView HostGridView; const HostGridView& hostGridView = hostGrid.leafGridView(); std::vector > vertexPositions(hostGridView.size(dim)); for (const auto& vertex : vertices(hostGridView)) vertexPositions[hostGridView.indexSet().index(vertex)] = vertex.geometry().corner(0); typedef Dune::GeometryGrid > DiscretelyTransformedGrid; DeformationFunction discreteTransformation(hostGridView, vertexPositions); DiscretelyTransformedGrid discretelyTransformedGrid(hostGrid, discreteTransformation); gridcheck(discretelyTransformedGrid); return 0; } catch( const Dune::Exception &e ) { std::cerr << e << std::endl; return 1; } catch( const std::exception &e ) { std::cerr << e.what() << std::endl; return 1; } catch( ... ) { std::cerr << "Unknown exception raised." << std::endl; return 1; } #else #error "COORDFUNCTION not defined (e.g., Helix, Circle; see functions.hh)" #endif dune-grid-2.11.0/dune/grid/test/test-gridinfo.cc000066400000000000000000000015421511655130300213770ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include template bool test_gridinfo(const Grid& grid) { Dune::gridinfo(grid); for (int level = 0; level <= grid.maxLevel(); ++level) Dune::gridlevellist(grid, level, "gridlevellist"); Dune::gridleaflist(grid, "gridleaflist"); return true; } int main(int argc, char** argv) { Dune::MPIHelper::instance(argc, argv); { Dune::YaspGrid<2> grid({1., 1.}, {4, 4}); grid.globalRefine(2); test_gridinfo(grid); } { Dune::YaspGrid<3> grid({1., 1., 1.}, {4, 4, 4}); grid.globalRefine(2); test_gridinfo(grid); } return 0; } dune-grid-2.11.0/dune/grid/test/test-hierarchicsearch.cc000066400000000000000000000046351511655130300230730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include #include #include #include #include #include #include #include // UnitCube // -------- template< class Grid > class UnitCube; template< int dimension > class UnitCube< Dune::YaspGrid< dimension > > { public: typedef Dune::YaspGrid< dimension > Grid; static std::unique_ptr< Grid > create () { Dune::FieldVector< double, dimension > domain( 1. ); std::array< int, dimension > cells; cells.fill( 1 ); return std::make_unique< Grid >( domain, cells ); } }; // check // ----- template< class GridView > void check ( GridView gridView ) { typedef typename GridView::Grid Grid; typedef typename GridView::IndexSet IndexSet; typedef Dune::HierarchicSearch< Grid, IndexSet > HierarchicSearch; HierarchicSearch hsearch( gridView.grid(), gridView.indexSet() ); typedef typename GridView::template Codim< 0 >::Iterator Iterator; typedef typename Iterator::Entity Entity; const Iterator end = gridView.template end< 0 >(); for( Iterator it = gridView.template begin< 0 >(); it != end; ++it ) { const Entity &entity = *it; if( entity != hsearch.findEntity( entity.geometry().center() ) ) DUNE_THROW( Dune::GridError, "Could not retrieve element in hierarchic search" ); } } int main ( int argc, char **argv ) try { Dune::MPIHelper::instance( argc, argv ); // create grid const int dimension = 2; typedef Dune::YaspGrid< dimension > Grid; auto grid = UnitCube< Grid >::create(); // grid refinement int maxLevel = 4; if( argc > 1 ) maxLevel = std::atoi( argv[ 1 ] ); grid->globalRefine( maxLevel ); // check hierarchic search for( int level = 0; level < grid->maxLevel(); ++level ) check( grid->levelGridView( level ) ); check( grid->leafGridView() ); return 0; } catch( Dune::Exception &exception ) { std::cerr << exception << std::endl; return 1; } catch( std::exception &exception ) { std::cerr << exception.what() << std::endl; return 1; } catch( ... ) { std::cerr << "Unknown exception thrown" << std::endl; return 1; } dune-grid-2.11.0/dune/grid/test/test-identitygrid.cc000066400000000000000000000017161511655130300223000ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include "gridcheck.hh" #include "checkintersectionit.hh" using namespace Dune; // test IdentityGrid for given dimension template void testDim() { typedef YaspGrid GridType; std::array n; std::fill(n.begin(), n.end(), 1 << (5 - dim)); Dune::FieldVector extension(1.0); GridType grid(extension,n); grid.globalRefine(1); IdentityGrid identityGrid(grid); gridcheck(identityGrid); checkIntersectionIterator(identityGrid); } int main (int argc, char *argv[]) { Dune::MPIHelper::instance(argc, argv); testDim<1>(); testDim<2>(); testDim<3>(); return 0; } dune-grid-2.11.0/dune/grid/test/test-loadbalancing.cc000066400000000000000000000134151511655130300223560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include #include #include #include #include #include #if HAVE_PARMETIS #include # ifdef PARMETIS_MAJOR_VERSION # include # endif #endif using namespace Dune; template struct Ball { double radius; Dune::FieldVector center; Ball(const Dune::FieldVector& c, const double& r) : radius(r), center(c) {} double distanceTo(const Dune::FieldVector& other) const { return std::abs((center - other).two_norm() - radius); } }; // Write a set of default parameters into a ParameterTree. // The user can override all of these from the command line. ParameterTree defaultParameters(int dim) { ParameterTree result; if (dim==2) { result["n"] = "8 25"; result["lower"] = "0 0"; result["upper"] = "0.012 0.03"; //result["center"] = "0.012 0.01" result["center"] = "0.006 0.005"; //result["r"] = "0.004"; result["r"] = "0.002"; result["stepDisplacement"] = "0 0.001"; } else if (dim==3) { result["n"] = "8 2 2"; result["lower"] = "0 0 0"; result["upper"] = "0.012 0.03 0.012"; //result["center"] = "0.012 0.01 0.012" result["center"] = "0.006 0.005 0.006"; result["r"] = "0.002"; result["stepDisplacement"] = "0 0.001 0"; } result["epsilon"] = "0.0008"; result["levels"] = "2"; result["steps"] = "30"; return result; } // Define some constants and types const int dim = 2; typedef UGGrid GridType; typedef GridType::LeafGridView GV; int main(int argc, char** argv) { #if ! (HAVE_PARMETIS && defined(PARMETIS_MAJOR_VERSION)) // Skip test -- without ParMetis it doesn't do anything useful std::cerr << "This test requires ParMetis and will be skipped.\n" << "Note that the emulation layer provided by scotch is not sufficient.\n"; return 77; #else // Create MPIHelper instance MPIHelper& mpihelper = MPIHelper::instance(argc, argv); if (0 == mpihelper.rank()) std::cout << "Using " << mpihelper.size() << " Processes." << std::endl; ParameterTree parameterSet = defaultParameters(dim); // Create ug grid from structured grid const std::array n = parameterSet.get >("n"); const FieldVector lower = parameterSet.get >("lower"), upper = parameterSet.get >("upper"); std::shared_ptr grid = StructuredGridFactory::createSimplexGrid(lower, upper, n); const GV gv = grid->leafGridView(); // Create ball const FieldVector center = parameterSet.get >("center"); const double r = parameterSet.get("r"); Ball ball(center, r); // Refine const size_t steps = parameterSet.get("steps"); const FieldVector stepDisplacement = parameterSet.get >("stepDisplacement"); const double epsilon = parameterSet.get("epsilon"); const int levels = parameterSet.get("levels"); // Create initial partitioning using ParMETIS std::vector part(ParMetisGridPartitioner::partition(gv, mpihelper)); // Transfer partitioning from ParMETIS to our grid grid->loadBalance(part, 0); for (size_t s = 0; s < steps; ++s) { std::cout << "Step " << s << " on " << mpihelper.rank() << " ..." << std::endl; for (int k = 0; k < levels; ++k) { std::cout << " Refining level " << k << " on " << mpihelper.rank() << " ..." << std::endl; // select elements that are close to the sphere for grid refinement for (const auto& element : elements(gv, Partitions::interior)) { if (ball.distanceTo(element.geometry().center()) < epsilon) grid->mark(1, element); } // adapt grid grid->adapt(); // clean up markers grid->postAdapt(); } mpihelper.getCommunication().barrier(); // Repartition float itr = 1000; // ratio of inter-processor communication time compared to data redistribution time // high ~> minimize edge-cut and have smaller communication time during calculations // low ~> do not move elements around between processes too much and thous reduce communication time during redistribution part = ParMetisGridPartitioner::repartition(gv, mpihelper, itr); // Transfer partitioning from ParMETIS to our grid grid->loadBalance(part, 0); // Output grid const std::string baseOutName = "RefinedGrid_"; VTKWriter vtkWriter(gv); std::vector rankField(gv.size(0)); std::fill(rankField.begin(), rankField.end(), grid->comm().rank()); vtkWriter.addCellData(rankField,"rank"); vtkWriter.write(baseOutName+std::to_string(s)); // If this is not the last step, move sphere and coarsen grid if (s+1 < steps) { // Move sphere a little ball.center += stepDisplacement; // Coarsen everything for (int k = 0; k < levels; ++k) { std::cout << " Coarsening level " << k << " on " << mpihelper.rank() << " ..." << std::endl; for (const auto& element : elements(gv, Partitions::interior)) grid->mark(-1, element); // adapt grid grid->adapt(); // clean up markers grid->postAdapt(); } } } return 0; #endif // (HAVE_PARMETIS && defined(PARMETIS_MAJOR_VERSION)) } dune-grid-2.11.0/dune/grid/test/test-mcmg-geogrid.cc000066400000000000000000000040221511655130300221330ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 const int dim=2; using namespace Dune; template class DeformationFunction : public Dune :: DiscreteCoordFunction< double, dim, DeformationFunction > { typedef DeformationFunction This; typedef Dune :: DiscreteCoordFunction< double, dim, This > Base; public: DeformationFunction() {} void evaluate ( const typename GridView::template Codim::Entity& hostEntity, unsigned int corner, FieldVector &y ) const { y = hostEntity.geometry().corner(0); } void evaluate ( const typename GridView::template Codim<0>::Entity& hostEntity, unsigned int corner, FieldVector &y ) const { y = hostEntity.geometry().corner(corner); } void adapt() {} }; int main (int argc, char *argv[]) { Dune::MPIHelper::instance(argc, argv); // make simple structured grid typedef YaspGrid<2> GridType; std::array cells = {1,1}; FieldVector extend = {1,1}; GridType grid(extend,cells); // make deformed grid with identity deformation typedef DeformationFunction DeformationFunction; typedef GeometryGrid DeformedGridType; DeformationFunction deformation; DeformedGridType defGrid(grid,deformation); using GV = typename DeformedGridType::LeafGridView; MultipleCodimMultipleGeomTypeMapper mapper(defGrid.leafGridView(), mcmgElementLayout()); //grid.globalRefine(1); //defGrid.update(); mapper.update(defGrid.leafGridView()); } dune-grid-2.11.0/dune/grid/test/test-oned.cc000066400000000000000000000147371511655130300205350ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include "gridcheck.hh" #include "checkgeometryinfather.hh" #include "checkintersectionit.hh" #include "checkadaptation.hh" using namespace Dune; std::unique_ptr testFactory() { GridFactory factory; // Insert vertices std::vector > vertexPositions = {0.6, 1.0, 0.2, 0.0, 0.4, 0.3, 0.7}; for (auto&& pos : vertexPositions) factory.insertVertex(pos); // Insert elements factory.insertElement(GeometryTypes::line, {6,1}); factory.insertElement(GeometryTypes::line, {4,0}); factory.insertElement(GeometryTypes::line, {0,6}); factory.insertElement(GeometryTypes::line, {5,4}); factory.insertElement(GeometryTypes::line, {3,2}); factory.insertElement(GeometryTypes::line, {2,5}); // Insert boundary segments factory.insertBoundarySegment({1}); factory.insertBoundarySegment({3}); // Create the grid std::unique_ptr grid(factory.createGrid()); // ////////////////////////////////////////////////////////////// // Test whether the vertex numbering is in insertion order // ////////////////////////////////////////////////////////////// const OneDGrid::LevelGridView::IndexSet& levelIndexSet = grid->levelGridView(0).indexSet(); const OneDGrid::LeafGridView::IndexSet& leafIndexSet = grid->leafGridView().indexSet(); for (const auto& vertex : vertices(grid->levelGridView(0))) { auto idx = levelIndexSet.index(vertex); FieldVector p = vertex.geometry().corner(0); if ( (vertexPositions[idx] - p).two_norm() > 1e-6 ) DUNE_THROW(GridError, "Vertex with level index " << idx << " should have position " << vertexPositions[idx] << " but has position " << p << "."); // leaf index should be the same if (idx != leafIndexSet.index(vertex)) DUNE_THROW(GridError, "Newly created OneDGrids should have matching level- and leaf vertex indices."); } // ////////////////////////////////////////////////////////////// // Test whether the element numbering is in insertion order // ////////////////////////////////////////////////////////////// std::vector > elementCenters(6); // a priori knowledge: this is where the element centers should be elementCenters[0] = 0.85; elementCenters[1] = 0.5; elementCenters[2] = 0.65; elementCenters[3] = 0.35; elementCenters[4] = 0.1; elementCenters[5] = 0.25; for (const auto& element : elements(grid->levelGridView(0))) { auto idx = levelIndexSet.index(element); FieldVector p = element.geometry().center(); if ( (elementCenters[idx] - p).two_norm() > 1e-6 ) DUNE_THROW(GridError, "Element with index " << idx << " should have center " << elementCenters[idx] << " but has center " << p << "."); // leaf index should be the same if (idx != leafIndexSet.index(element)) DUNE_THROW(GridError, "Newly created OneDGrids should have matching level- and leaf element indices."); } // ///////////////////////////////////////////////////////////////////////// // Test whether the boundary segment numbering is in insertion order // ///////////////////////////////////////////////////////////////////////// typedef OneDGrid::LeafGridView GridView; const GridView gridView = grid->leafGridView(); for (const auto& element : elements(grid->levelGridView(0))) { for (const auto& intersection : intersections(gridView, element)) { if (intersection.boundary()) { if (intersection.boundarySegmentIndex()==0 && std::abs(intersection.geometry().corner(0)[0] - 1) > 1e-6) DUNE_THROW(GridError, "BoundarySegment with index 0 should have position 1," << " but has " << intersection.geometry().corner(0) << "."); if (intersection.boundarySegmentIndex()==1 && std::abs(intersection.geometry().corner(0)[0]) > 1e-6) DUNE_THROW(GridError, "BoundarySegment with index 1 should have position 0," << " but has " << intersection.geometry().corner(0) << "."); } } } // ////////////////////////////////////////////////////////////// // return the grid for further tests // ////////////////////////////////////////////////////////////// return grid; } void testOneDGrid(OneDGrid& grid) { // check macro grid gridcheck(grid); // create hybrid grid grid.mark(1, * grid.leafGridView().begin<0>()); grid.preAdapt(); grid.adapt(); grid.postAdapt(); checkIntersectionIterator(grid); // check the grid again gridcheck(grid); grid.globalRefine(1); gridcheck(grid); // check geometry lifetime checkGeometryLifetime( grid.leafGridView() ); // check the method geometryInFather() checkGeometryInFather(grid); // check the intersection iterator checkIntersectionIterator(grid); checkAdaptation( grid ); } int main () try { // Create a OneDGrid using the grid factory and test it std::unique_ptr factoryGrid(testFactory()); testOneDGrid(*factoryGrid); // Create a OneDGrid with an array of vertex coordinates and test it std::vector coords = {-1, -0.4, 0.1, 0.35, 0.38, 1}; Dune::OneDGrid coordsGrid(coords); testOneDGrid(coordsGrid); // Create a uniform OneDGrid and test it Dune::OneDGrid uniformGrid(7, // Number of elements -0.5, // Left boundary 2.3 // Right boundary ); testOneDGrid(uniformGrid); // Test a uniform grid with RefinementType set to COPY Dune::OneDGrid uniformGrid2(7, // Number of elements -0.5, // Left boundary 2.3 // Right boundary ); uniformGrid2.setRefinementType(OneDGrid::COPY); testOneDGrid(uniformGrid2); // everything okay return 0; } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/test/test-parallel-ug.cc000066400000000000000000000770761511655130300220220ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: // Test parallel interface if a parallel UG is used #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Dune; // A DataHandle class to exchange entries of a vector. template class DataExchange : public Dune::CommDataHandleIF, double> { public: //! export type of data for message buffer typedef double DataType; typedef std::vector > UserDataType; //! constructor DataExchange(const MapperT &mapper, std::bitset communicationCodims, std::vector& gatherCounter, std::vector& scatterCounter, UserDataType &userDataSend, UserDataType &userDataReceive) : mapper_(mapper), communicationCodims_(communicationCodims), gatherCounter_(gatherCounter), scatterCounter_(scatterCounter), userDataSend_(userDataSend), userDataReceive_(userDataReceive) {} //! returns true if data for this codim should be communicated bool contains (int dim, int codim) const { return communicationCodims_[codim]; } //! returns true if size per entity of given dim and codim is a constant bool fixedSize (int dim, int codim) const { return true; } /*! how many objects of type DataType have to be sent for a given entity Note: Only the sender side needs to know this size. */ template size_t size (EntityType& e) const { return 1; } //! pack data from user to message buffer template void gather(MessageBuffer& buff, const EntityType& e) const { DataType x = mapper_.index(e); gatherCounter_[mapper_.index(e)]++; userDataSend_[mapper_.index(e)][0] = x; dverb << "Process " << Dune::MPIHelper::getCommunication().rank()+1 << " sends for entity " << mapper_.index(e) << ": " << std::setprecision(20) << x << "\n"; buff.write(x); } /*! unpack data from message buffer to user n is the number of objects sent by the sender */ template void scatter(MessageBuffer& buff, const EntityType& e, size_t n) { DataType x; buff.read(x); userDataReceive_[mapper_.index(e)][0] = x; scatterCounter_[mapper_.index(e)]++; dverb << "Process " << Dune::MPIHelper::getCommunication().rank()+1 << " received for entity " << mapper_.index(e) << ": " << std::setprecision(20) << x << "\n"; } private: const MapperT &mapper_; const std::bitset communicationCodims_; std::vector &gatherCounter_; std::vector &scatterCounter_; UserDataType &userDataSend_; UserDataType &userDataReceive_; }; template void checkIntersections(const GridView &gv) { for (const auto& element : elements(gv)) { if (element.partitionType() == Dune::GhostEntity) continue; unsigned int n = 0; for (const auto& intersection : intersections(gv, element)) { intersection.boundary(); intersection.inside(); if (intersection.neighbor()) { intersection.outside(); } ++ n; } if (n != element.subEntities(1)) { DUNE_THROW(Dune::InvalidStateException, "Number of faces for non-ghost cell incorrect. Is " << n << " but should be " << element.subEntities(1)); } } } // some consistency tests for the mappers template void checkMappers(const GridView &gridView) { // make sure the number of entities is the same for // gridView.size() and iterating through the grid int numEntities = 0; for ([[maybe_unused]] const auto& entity : entities(gridView, Dune::Codim())) ++ numEntities; if (numEntities != gridView.size(codim)) { DUNE_THROW(InvalidStateException, gridView.comm().rank() + 1 << ": Number of codim " << codim << " entities is inconsistent (iterator: " << numEntities << " grid view: " << gridView.size(codim) << ")"); } typedef Dune::MultipleCodimMultipleGeomTypeMapper MapperType; MapperType mapper(gridView, mcmgLayout(Codim{})); // make sure no entity has two indices std::vector indices(numEntities, -100); for (const auto& entity : entities(gridView, Dune::Codim())) { int i = mapper.index(entity); if (i < 0 || i >= numEntities) { DUNE_THROW(InvalidStateException, gridView.comm().rank() + 1 << ": Mapper returns an invalid index for codim " << codim << " entities: " << i << " should be in range [0," << numEntities -1 << "]"); } if (indices[i] >= 0) { DUNE_THROW(InvalidStateException, gridView.comm().rank() + 1 << ": Mapper returns index " << i << " twice for codim " << codim << " entities."); } indices[i] = i; } } // specializations for non-implemented cases template struct checkMappersWrapper { static void check(const GridView &gv) { return checkMappers(gv); } }; // codim 3 entities for 2d grids template struct checkMappersWrapper<2, 3, GridView> { static void check(const GridView &gv) { } }; // codim 1 entities for 3d grids template struct checkMappersWrapper<3, 1, GridView> { static void check(const GridView &gv) { } }; // codim 2 entities for 3d grids template struct checkMappersWrapper<3, 2, GridView> { static void check(const GridView &gv) { } }; // codim 1 entities for 2d grids template struct checkMappersWrapper<2, 1, GridView> { static void check(const GridView &gv) { } }; template void testCommunication(const GridView &gridView, std::bitset communicationCodims, InterfaceType communicationInterface, CommunicationDirection communicationDirection, const std::set& sendingPartitions, const std::set& receivingPartitions) { const int dim = GridView::dimension; dverb << gridView.comm().rank() + 1 << ": Testing communication for the following codimensions " << communicationCodims << std::endl; typedef Dune::MultipleCodimMultipleGeomTypeMapper MapperType; auto mcmgLayout = [&communicationCodims](GeometryType gt, int dimgrid) { return communicationCodims[dim - gt.dim()]; }; MapperType mapper(gridView, mcmgLayout); // create the user data arrays using UserDataType = std::vector >; UserDataType userDataSend(mapper.size(), 0.0); UserDataType userDataReceive(mapper.size(), 0.0); // For each entity, count how many times 'gather' and 'scatter' have been called std::vector gatherCounter(mapper.size(), 0); std::vector scatterCounter(mapper.size(), 0); // write the partition type of each entity into the corresponding // result array for (const auto& element : elements(gridView)) { Hybrid::forEach(std::make_index_sequence< dim+1 >{}, [&](auto codim){ if (communicationCodims[codim]) { auto numberOfSubEntities = element.subEntities(codim); for (std::size_t k = 0; k < numberOfSubEntities; k++) { const auto entity(element.template subEntity(k)); if (entity.partitionType() == Dune::BorderEntity) { const auto geometry = element.geometry(); auto referenceElement = Dune::referenceElement(element.type()); const auto entityGlobal = geometry.global(referenceElement.position(k, codim)); dverb << gridView.comm().rank()+1 << ": border codim " << codim << " entity " << mapper.index(entity) << " (" << entityGlobal << ")" << std::endl; } } } }); } // initialize data handle (marks the nodes where some data was // send or received) DataExchange datahandle(mapper, communicationCodims, gatherCounter, scatterCounter, userDataSend, userDataReceive); // communicate the entities at the interior border to all other // processes gridView.communicate(datahandle, communicationInterface, communicationDirection); // write the partition type of each entity into the corresponding // result array for (const auto& element : elements(gridView)) { Hybrid::forEach(std::make_index_sequence< dim+1 >{}, [&](auto codim) { // TODO: Also check whether no communication happens when no communication // is requested. if (communicationCodims[codim]) { auto numberOfSubEntities = element.subEntities(codim); for (std::size_t k = 0; k < numberOfSubEntities; k++) { const auto entity(element.template subEntity(k)); auto partitionTypes = entity.impl().partitionTypes(); // Check whether 'gather' has been called the appropriate number of times std::size_t expectedNumberOfGatherCalls = 0; for (const auto& pType : partitionTypes) if (pType.first != gridView.comm().rank() && (sendingPartitions.find(entity.partitionType())!=sendingPartitions.end()) && (receivingPartitions.find(pType.second))!=receivingPartitions.end()) expectedNumberOfGatherCalls++; if (gatherCounter[mapper.index(entity)] != expectedNumberOfGatherCalls) { std::cerr << gridView.comm().rank() << ": UGGrid did not call 'gather' " << expectedNumberOfGatherCalls << " times, but " << gatherCounter[mapper.index(entity)] << " times on an entity!" << std::endl; std::cerr << gridView.comm().rank() << ": Problematic entity: codim = " << codim << ", partitionType = " << entity.partitionType() << ", center = " << entity.geometry().center() << std::endl; std::abort(); } // Check whether 'scatter' has been called the appropriate number of times std::size_t expectedNumberOfScatterCalls = 0; for (const auto& pType : partitionTypes) if (pType.first != gridView.comm().rank() && (receivingPartitions.find(entity.partitionType()) != receivingPartitions.end()) && (sendingPartitions.find(pType.second) != sendingPartitions.end())) expectedNumberOfScatterCalls++; if (scatterCounter[mapper.index(entity)] != expectedNumberOfScatterCalls) { std::cerr << gridView.comm().rank() << ": UGGrid did not call 'scatter' " << expectedNumberOfScatterCalls << " times, but " << scatterCounter[mapper.index(entity)] << " times on an entity!" << std::endl; std::cerr << gridView.comm().rank() << ": Problematic entity: codim = " << codim << ", partitionType = " << entity.partitionType() << ", center = " << entity.geometry().center() << std::endl; std::abort(); } } } }); } } template class LoadBalance { const static int dimension = Grid::dimension; using ctype = typename Grid::ctype; using Position = Dune::FieldVector; using GridView = typename Grid::LeafGridView; using IdSet = typename Grid::LocalIdSet; using Data = std::map; using Codims = std::bitset; class LBDataHandle : public Dune::CommDataHandleIF { public: typedef typename Data::mapped_type DataType; public: bool contains (int dim, int codim) const { assert(dim == dimension); return codims_.test(codim); } bool fixedSize (int dim, int codim) const { assert(dim == dimension); return true; } template size_t size (Entity& entity) const { return 1; } template void gather (MessageBuffer& buff, const Entity& entity) const { const auto& id = idSet_.id(entity); buff.write(data_.at(id)); } template void scatter (MessageBuffer& buff, const Entity& entity, size_t) { const auto& id = idSet_.id(entity); buff.read(data_[id]); } LBDataHandle (const IdSet& idSet, Data& data, const Codims& codims) : idSet_(idSet) , data_(data) , codims_(codims) {} private: const IdSet& idSet_; Data& data_; const Codims codims_; }; template static Codims toBitset(Codims codims = {}) { return codims; } template static Codims toBitset(Codims codims = {}) { return toBitset(codims.set(codim)); } template static void fillVector(const GridView&, Data&) {} template static void fillVector(const GridView& gv, Data& data) { const auto& idSet = gv.grid().localIdSet(); for (const auto& entity : entities(gv, Dune::Codim(), Dune::Partitions::interiorBorder)) { const auto& id = idSet.id(entity); // assign the position of the entity to the entry in the vector data[id] = entity.geometry().center(); } fillVector(gv, data); } template static bool checkVector(const GridView&, const Data&) { return true; } template static bool checkVector(const GridView& gv, const Data& data) { const auto& idSet = gv.grid().localIdSet(); for (const auto& entity : entities(gv, Dune::Codim(), Dune::Partitions::interiorBorder)) { const auto& id = idSet.id(entity); const auto& commPos = data.at(id); const auto& realPos = entity.geometry().center(); // compare the position with the balanced data for (int k = 0; k < dimension; k++) { if (Dune::FloatCmp::ne(commPos[k], realPos[k])) { DUNE_THROW(Dune::ParallelError, gv.comm().rank() << ": position " << realPos << " does not coincide with communicated data " << commPos); } } } return checkVector(gv, data); } public: template static void test(Grid& grid) { const Codims codims = toBitset(); const auto& gv = grid.leafGridView(); // define the vector containing the data to be balanced Data data; LBDataHandle dataHandle(grid.localIdSet(), data, codims); // fill the data vector fillVector(gv, data); // balance the grid and the data grid.loadBalance(dataHandle); // check for correctness checkVector(gv, data); dverb << gv.comm().rank() << ": load balancing with data was successful." << std::endl; } }; template std::shared_ptr setupGrid(bool simplexGrid, bool localRefinement, int refinementDim, bool refineUpperPart, int numCellsPerDim = 4) { const static int dim = Grid::dimension; StructuredGridFactory structuredGridFactory; Dune::FieldVector lowerLeft(0); Dune::FieldVector upperRight(1); std::array numElements; std::fill(numElements.begin(), numElements.end(), numCellsPerDim); if (simplexGrid) return structuredGridFactory.createSimplexGrid(lowerLeft, upperRight, numElements); else return structuredGridFactory.createCubeGrid(lowerLeft, upperRight, numElements); } template void testLoadBalance(bool simplexGrid, bool localRefinement, int refinementDim, bool refineUpperPart) { using Grid = UGGrid; auto grid = setupGrid(simplexGrid, localRefinement, refinementDim, refineUpperPart); LoadBalance::template test(*grid); // LoadBalance::template test(*grid); } template void testParallelUG(bool simplexGrid, bool localRefinement, int refinementDim, bool refineUpperPart) { std::cout << "Testing parallel UGGrid for " << dim << "D\n"; //////////////////////////////////////////////////////////// // Create uniform grid on rank 0 //////////////////////////////////////////////////////////// typedef UGGrid GridType; auto grid = setupGrid(simplexGrid, localRefinement, refinementDim, refineUpperPart); ////////////////////////////////////////////////////// // Distribute the grid ////////////////////////////////////////////////////// grid->loadBalance(); std::cout << "Process " << grid->comm().rank() + 1 << " has " << grid->size(0) << " elements and " << grid->size(dim) << " nodes.\n"; // make sure each process has some elements assert(grid->size(0) > 0); // make sure each process has some nodes assert(grid->size(dim) > 0); ////////////////////////////////////////////////////// // Test level and leaf mappers/gridViews ////////////////////////////////////////////////////// typedef typename GridType::LevelGridView LevelGV; typedef typename GridType::LeafGridView LeafGV; const LeafGV& leafGridView = grid->leafGridView(); const LevelGV& level0GridView = grid->levelGridView(0); dverb << "LevelGridView for level 0 has " << level0GridView.size(0) << " elements " << level0GridView.size(dim - 1) << " edges and " << level0GridView.size(dim) << " nodes.\n"; dverb << "LeafGridView has " << leafGridView.size(0) << " elements, " << leafGridView.size(dim - 1) << " edges and " << leafGridView.size(dim) << " nodes.\n"; // some consistency checks for the mappers and the intersections checkIntersections(level0GridView); checkMappersWrapper::check(level0GridView); checkMappersWrapper::check(level0GridView); checkMappersWrapper::check(level0GridView); checkMappersWrapper::check(level0GridView); checkIntersections(leafGridView); checkMappersWrapper::check(leafGridView); checkMappersWrapper::check(leafGridView); checkMappersWrapper::check(leafGridView); checkMappersWrapper::check(leafGridView); // Test communication std::map > sendingPartitions; sendingPartitions[InteriorBorder_InteriorBorder_Interface] = {InteriorEntity, BorderEntity}; sendingPartitions[InteriorBorder_All_Interface] = {InteriorEntity, BorderEntity}; sendingPartitions[Overlap_OverlapFront_Interface] = {OverlapEntity}; sendingPartitions[Overlap_All_Interface] = {OverlapEntity}; sendingPartitions[All_All_Interface] = {InteriorEntity, BorderEntity, OverlapEntity, FrontEntity, GhostEntity}; std::map > receivingPartitions; receivingPartitions[InteriorBorder_InteriorBorder_Interface] = {InteriorEntity, BorderEntity}; receivingPartitions[InteriorBorder_All_Interface] = {InteriorEntity, BorderEntity, OverlapEntity, FrontEntity, GhostEntity}; receivingPartitions[Overlap_OverlapFront_Interface] = {OverlapEntity, FrontEntity}; receivingPartitions[Overlap_All_Interface] = {InteriorEntity, BorderEntity, OverlapEntity, FrontEntity, GhostEntity}; receivingPartitions[All_All_Interface] = {InteriorEntity, BorderEntity, OverlapEntity, FrontEntity, GhostEntity}; // Test all communication interfaces for (auto&& communicationInterface : {InteriorBorder_InteriorBorder_Interface, InteriorBorder_All_Interface, Overlap_OverlapFront_Interface, Overlap_All_Interface, All_All_Interface}) { // The variable codimSet encodes a set of codimensions as a bitset. // We loop over all possible sets. for (std::size_t codimSet=0; codimSet<(1<<(dim+1)); codimSet++) { // TODO: Test BackwardCommunication, too! testCommunication(level0GridView, std::bitset(codimSet), communicationInterface, ForwardCommunication, sendingPartitions[communicationInterface], receivingPartitions[communicationInterface]); testCommunication(leafGridView, std::bitset(codimSet), communicationInterface, ForwardCommunication, sendingPartitions[communicationInterface], receivingPartitions[communicationInterface]); } } //////////////////////////////////////////////////// // Refine globally and test again //////////////////////////////////////////////////// if (!localRefinement) { grid->globalRefine(1); } else { // mark all elements with x-coordinate < 0.5 for refinement for (const auto& element : elements(grid->leafGridView())) { int nRefine = 1; bool refine; if (refineUpperPart) { refine = (element.geometry().center()[refinementDim] > 0.5); } else { refine = (element.geometry().center()[refinementDim] < 0.5); } if (refine) grid->mark(nRefine, element); } // adapt the grid grid->preAdapt(); grid->adapt(); grid->postAdapt(); } for (int i=0; i<=grid->maxLevel(); i++) { checkIntersections(grid->levelGridView(i)); checkMappersWrapper::check(grid->levelGridView(i)); checkMappersWrapper::check(grid->levelGridView(i)); checkMappersWrapper::check(grid->levelGridView(i)); checkMappersWrapper::check(grid->levelGridView(i)); } checkIntersections(grid->leafGridView()); checkMappersWrapper::check(grid->leafGridView()); checkMappersWrapper::check(grid->leafGridView()); checkMappersWrapper::check(grid->leafGridView()); checkMappersWrapper::check(grid->leafGridView()); // Test all communication interfaces for (auto&& communicationInterface : {InteriorBorder_InteriorBorder_Interface, InteriorBorder_All_Interface, Overlap_OverlapFront_Interface, Overlap_All_Interface, All_All_Interface}) { // The variable codimSet encodes a set of codimensions as a bitset. // We loop over all possible sets. for (std::size_t codimSet=0; codimSet<(1<<(dim+1)); codimSet++) { // TODO: Test BackwardCommunication, too! for (int i=0; i<=grid->maxLevel(); i++) testCommunication(grid->levelGridView(i), std::bitset(codimSet), communicationInterface, Dune::ForwardCommunication, sendingPartitions[communicationInterface], receivingPartitions[communicationInterface]); testCommunication(leafGridView, std::bitset(codimSet), communicationInterface, Dune::ForwardCommunication, sendingPartitions[communicationInterface], receivingPartitions[communicationInterface]); } } } template bool isViewWithinBounds(const GridView& gridView, const Dune::FieldVector& lowerLeft, const Dune::FieldVector& upperRight) { for (const auto& element : elements(gridView, Dune::Partitions::interior)) { const auto center = element.geometry().center(); for (int dimIdx = 0; dimIdx < int(GridView::dimensionworld); ++dimIdx) if (center[dimIdx] < lowerLeft[dimIdx] || center[dimIdx] > upperRight[dimIdx]) return false; } return true; } template = 0> void checkDefaultBisectionPartition(const GridView& gridView, int numProcs, int rank) { // check if all partitions exist (we don't care which processor has which partition) int part = -1; switch (numProcs){ case 1: if (isViewWithinBounds(gridView, {0,0}, {1,1})) part = 0; break; case 2: if (isViewWithinBounds(gridView, {0,0}, {0.5,1})) part = 0; if (isViewWithinBounds(gridView, {0.5,0}, {1,1})) part = 1; break; case 3: if (isViewWithinBounds(gridView, {0,0}, {1.0/3.0,1})) part = 0; if (isViewWithinBounds(gridView, {1.0/3.0,0}, {1,0.5})) part = 1; if (isViewWithinBounds(gridView, {1.0/3.0,0.5}, {1,1})) part = 2; break; case 4: if (isViewWithinBounds(gridView, {0,0}, {0.5,0.5})) part = 0; if (isViewWithinBounds(gridView, {0,0.5}, {0.5,1})) part = 1; if (isViewWithinBounds(gridView, {0.5,0}, {1,0.5})) part = 2; if (isViewWithinBounds(gridView, {0.5,0.5}, {1,1})) part = 3; break; case 8: if (isViewWithinBounds(gridView, {0,0}, {0.25,0.5})) part = 0; if (isViewWithinBounds(gridView, {0.25,0}, {0.5,0.5})) part = 1; if (isViewWithinBounds(gridView, {0.5,0}, {0.75,0.5})) part = 2; if (isViewWithinBounds(gridView, {0.75,0}, {1,0.5})) part = 3; if (isViewWithinBounds(gridView, {0,0.5}, {0.25,1})) part = 4; if (isViewWithinBounds(gridView, {0.25,0.5}, {0.5,1})) part = 5; if (isViewWithinBounds(gridView, {0.5,0.5}, {0.75,1})) part = 6; if (isViewWithinBounds(gridView, {0.75,0.5}, {1,1})) part = 7; break; default: DUNE_THROW(Dune::NotImplemented, "Test for number of processors: " << numProcs); } const auto sumPart = gridView.comm().sum(part); const auto n = numProcs-1; if (sumPart != (n*n + n)/2) DUNE_THROW(Dune::Exception, "Invalid partition!"); } template = 0> void checkDefaultBisectionPartition(const GridView& gridView, int numProcs, int rank) { int part = -1; switch (numProcs){ case 1: if (isViewWithinBounds(gridView, {0,0,0}, {1,1,1})) part = 0; break; case 2: if (isViewWithinBounds(gridView, {0,0,0}, {0.5,1,1})) part = 0; if (isViewWithinBounds(gridView, {0.5,0,0}, {1,1,1})) part = 1; break; case 3: if (isViewWithinBounds(gridView, {0,0,0}, {1.0/3.0,1,1})) part = 0; if (isViewWithinBounds(gridView, {1.0/3.0,0,0}, {1,0.5,1})) part = 1; if (isViewWithinBounds(gridView, {1.0/3.0,0.5,0}, {1,1,1})) part = 2; break; case 4: if (isViewWithinBounds(gridView, {0,0,0}, {0.5,0.5,1})) part = 0; if (isViewWithinBounds(gridView, {0,0.5,0}, {0.5,1,1})) part = 1; if (isViewWithinBounds(gridView, {0.5,0,0}, {1,0.5,1})) part = 2; if (isViewWithinBounds(gridView, {0.5,0.5,0}, {1,1,1})) part = 3; case 8: if (isViewWithinBounds(gridView, {0,0,0}, {0.5,0.5,0.5})) part = 0; if (isViewWithinBounds(gridView, {0,0.5,0}, {0.5,1,0.5})) part = 1; if (isViewWithinBounds(gridView, {0.5,0,0}, {1,0.5,0.5})) part = 2; if (isViewWithinBounds(gridView, {0.5,0.5,0}, {1,1,0.5})) part = 3; if (isViewWithinBounds(gridView, {0,0,0.5}, {0.5,0.5,1})) part = 4; if (isViewWithinBounds(gridView, {0,0.5,0.5}, {0.5,1,1})) part = 5; if (isViewWithinBounds(gridView, {0.5,0,0.5}, {1,0.5,1})) part = 6; if (isViewWithinBounds(gridView, {0.5,0.5,0.5}, {1,1,1})) part = 7; break; default: DUNE_THROW(Dune::NotImplemented, "Test for number of processors: " << numProcs); return; } const auto sumPart = gridView.comm().sum(part); const auto n = numProcs-1; if (sumPart != (n*n + n)/2) DUNE_THROW(Dune::Exception, "Invalid partition!"); } template void testDefaultLoadBalanceStructuredCube(const Dune::MPIHelper& mpiHelper) { if (mpiHelper.rank() == 0) std::cout << "Testing default load balancer for structured cube grid in " << dim << "D\n"; auto grid = setupGrid>(false, false, 0, false, mpiHelper.size()*2); grid->loadBalance(); grid->globalRefine(1); const auto& gridView = grid->leafGridView(); checkDefaultBisectionPartition(gridView, mpiHelper.size(), mpiHelper.rank()); } int main (int argc , char **argv) try { // initialize MPI, finalize is done automatically on exit auto &mpiHelper = Dune::MPIHelper::instance(argc, argv); #if !defined(ModelP) if (mpiHelper.size() > 1) { if (mpiHelper.rank() == 0) std::cout << "SKIPPED: test-parallel-ug requires a parallel version of dune-uggrid\n"; return 77; } #endif std::cout << "This is process " << mpiHelper.rank() + 1 << " of " << mpiHelper.size() << ", PID " << getpid() << " .\n"; /* * Test 2D and 3D grids, * on structured cube and simplex grids, * with global and local refinement. */ for (const bool simplexGrid : {false, true}) { for (const bool localRefinement : {false, true}) { for (const bool refineUpperPart : {false, true}) { for (const int refinementDim : {0,1}) { testParallelUG<2>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<2>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<2, 0>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<2, 2>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<2, 0, 2>(simplexGrid, localRefinement, refinementDim, refineUpperPart); } for (const int refinementDim : {0,1,2}) { testParallelUG<3>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<3>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<3, 0>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<3, 3>(simplexGrid, localRefinement, refinementDim, refineUpperPart); testLoadBalance<3, 0, 3>(simplexGrid, localRefinement, refinementDim, refineUpperPart); } } } } // test default bisection load balancer for case with known partition testDefaultLoadBalanceStructuredCube<2>(mpiHelper); testDefaultLoadBalanceStructuredCube<3>(mpiHelper); return 0; } catch (Dune::Exception& e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/test/test-ug.cc000066400000000000000000000340371511655130300202160ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include /* Instantiate UG-Grid and feed it to the generic gridcheck() */ #include #include #include #include "gridcheck.hh" #include "checkcommunicate.hh" #include "checkgeometryinfather.hh" #include "checkintersectionit.hh" #include "checkpartition.hh" using namespace Dune; class ArcOfCircle : public Dune::BoundarySegment<2> { public: ArcOfCircle(const Dune::FieldVector& center, double radius, double fromAngle, double toAngle) : center_(center), radius_(radius), fromAngle_(fromAngle), toAngle_(toAngle) {} Dune::FieldVector operator()(const Dune::FieldVector& local) const { double angle = fromAngle_ + local[0]*(toAngle_ - fromAngle_); Dune::FieldVector result = center_; result[0] += radius_ * std::cos(angle); result[1] += radius_ * std::sin(angle); return result; } Dune::FieldVector center_; double radius_; double fromAngle_; double toAngle_; }; void makeHalfCircleQuad(Dune::UGGrid<2>& grid, bool boundarySegments, bool parametrization) { Dune::GridFactory > factory(&grid); const double pi = Dune::MathematicalConstants::pi(); // ///////////////////////////// // Create boundary segments // ///////////////////////////// if (boundarySegments) { FieldVector center = {0,15}; if (parametrization) { factory.insertBoundarySegment({1,2}, std::make_shared(center, 15, pi, pi*4/3)); factory.insertBoundarySegment({2,3}, std::make_shared(center, 15, pi*4/3, pi*5/3)); factory.insertBoundarySegment({3,0}, std::make_shared(center, 15, pi*5/3, pi*2)); } else { factory.insertBoundarySegment({1,2}); factory.insertBoundarySegment({2,3}); factory.insertBoundarySegment({3,0}); } } // /////////////////////// // Insert vertices // /////////////////////// factory.insertVertex({15,15}); factory.insertVertex({-15,15}); factory.insertVertex({-7.5,2.00962}); factory.insertVertex({7.5,2.00962}); // ///////////////// // Insert elements // ///////////////// factory.insertElement(GeometryTypes::quadrilateral, {0,1,3,2}); // ////////////////////////////////////// // Finish initialization // ////////////////////////////////////// // The factory returns the grid object we have given it as a std::unique_ptr. // Release it, to keep the std::unique_ptr destructor from killing it at // the end of this very method. // Yes, that is a bit weird. But in particular the calling method tests whether // the GridFactory can reuse an existing UGGrid object, and I would like to keep // that for the time being. factory.createGrid().release(); } // compute boundary length of a given mesh double integrateBoundary(const Dune::UGGrid<2>& grid) { double len = 0.0; auto && gv = grid.leafGridView(); for (const auto& e : elements(gv)) { for (const auto& i : intersections(gv,e)) { if (i.boundary()) len += i.geometry().volume(); } } return len; } // test approximation to a curved boundary: refine, compare with the // exact length and check the expected 2nd order convergence rate void testGeometryApproximation(Dune::UGGrid<2>& grid, double exact, bool verbose = false) { double len = integrateBoundary(grid); if (verbose) std::cout << "boundary length: " << len << "\t" << exact << std::endl; double eoc = 0.0; for (unsigned int l = 0; l < 5; l++) { grid.globalRefine(1); double len_refined = integrateBoundary(grid); double err0 = std::abs(len-exact); double err = std::abs(len_refined-exact); eoc = std::log2(err0/err); // h0/h = 2 if (verbose) std::cout << "boundary length: " << len_refined << "\t" << exact << "\terr=" << err << "\teoc=" << eoc << std::endl; len = len_refined; } // we expect 2nd order convergence if (Dune::FloatCmp::ne(eoc,2.0,0.02)) DUNE_THROW(Dune::GridError, "Geometry approximation does not show expected 2nd order convergence"); } template void markOne ( GridType & grid , int num , int ref ) { int count = 0; for(const auto& element : elements(grid.leafGridView())) { if(num == count) grid.mark( ref, element ); count++; } grid.preAdapt(); grid.adapt(); grid.postAdapt(); } void generalTests(bool greenClosure) { // ////////////////////////////////////////////////////////// // Make some grids for testing // ////////////////////////////////////////////////////////// std::unique_ptr > grid2d(make2DHybridTestGrid >()); std::unique_ptr > grid3d(make3DHybridTestGrid >()); // Switch of the green closure, if requested if (!greenClosure) { grid2d->setClosureType(UGGrid<2>::NONE); grid3d->setClosureType(UGGrid<3>::NONE); } // check macro grid gridcheck(*grid2d); gridcheck(*grid3d); // check communication interface checkCommunication(*grid2d,-1,Dune::dvverb); checkCommunication(*grid3d,-1,Dune::dvverb); for(int l=0; l<=grid2d->maxLevel(); ++l) checkCommunication(*grid2d,l,Dune::dvverb); for(int l=0; l<=grid3d->maxLevel(); ++l) checkCommunication(*grid3d,l,Dune::dvverb); // create hybrid grid markOne(*grid2d,0,1) ; markOne(*grid3d,0,1) ; gridcheck(*grid2d); gridcheck(*grid3d); // check communication interface checkCommunication(*grid2d,-1,Dune::dvverb); checkCommunication(*grid3d,-1,Dune::dvverb); for(int l=0; l<=grid2d->maxLevel(); ++l) checkCommunication(*grid2d,l,Dune::dvverb); for(int l=0; l<=grid3d->maxLevel(); ++l) checkCommunication(*grid3d,l,Dune::dvverb); grid2d->globalRefine(1); grid3d->globalRefine(1); gridcheck(*grid2d); gridcheck(*grid3d); // check communication interface checkCommunication(*grid2d,-1,Dune::dvverb); checkCommunication(*grid3d,-1,Dune::dvverb); for(int l=0; l<=grid2d->maxLevel(); ++l) checkCommunication(*grid2d,l,Dune::dvverb); for(int l=0; l<=grid3d->maxLevel(); ++l) checkCommunication(*grid3d,l,Dune::dvverb); // check geometry lifetime checkGeometryLifetime( grid2d->leafGridView() ); checkGeometryLifetime( grid3d->leafGridView() ); // check the method geometryInFather() checkGeometryInFather(*grid2d); checkGeometryInFather(*grid3d); // check the intersection iterator checkIntersectionIterator(*grid2d); checkIntersectionIterator(*grid3d); // Check partition iterators checkPartitionType( grid2d->leafGridView() ); for( int i = 0; i <= grid2d->maxLevel(); ++i ) checkPartitionType( grid2d->levelGridView( i ) ); checkPartitionType( grid3d->leafGridView() ); for( int i = 0; i <= grid3d->maxLevel(); ++i ) checkPartitionType( grid3d->levelGridView( i ) ); } int main (int argc , char **argv) try { // use MPI helper to initialize MPI MPIHelper :: instance( argc, argv ); // //////////////////////////////////////////////////////////////////////// // Do the standard grid test for a 2d and a 3d UGGrid // //////////////////////////////////////////////////////////////////////// // Do the general tests for red/green refinement std::cout << "Testing UGGrid<2> and UGGrid<3> with red/green refinement" << std::endl; generalTests(true); // Do the general tests for nonconforming refinement std::cout << "Testing UGGrid<2> and UGGrid<3> with nonconforming refinement" << std::endl; generalTests(false); // //////////////////////////////////////////////////////////////////////////// // Test whether I can create a grid with explicit boundary segment ordering, // but not parametrization functions (only 2d, so far) // //////////////////////////////////////////////////////////////////////////// Dune::UGGrid<2> gridWithOrderedBoundarySegments; makeHalfCircleQuad(gridWithOrderedBoundarySegments, true, false); gridWithOrderedBoundarySegments.globalRefine(1); gridcheck(gridWithOrderedBoundarySegments); // //////////////////////////////////////////////////////////////////////// // Check whether geometryInFather returns equal results with and // without parametrized boundaries // //////////////////////////////////////////////////////////////////////// // Only the sequential UG can provide more than one 2d- or 3d-grid at once. // Therefore we do not perform the following test for parallel UGGrid. Dune::UGGrid<2> gridWithParametrization, gridWithoutParametrization; // make grids makeHalfCircleQuad(gridWithoutParametrization, false, false); makeHalfCircleQuad(gridWithParametrization, true, true); // make grids again just to check this is possible makeHalfCircleQuad(gridWithoutParametrization, false, false); makeHalfCircleQuad(gridWithParametrization, true, true); gridWithParametrization.globalRefine(1); gridWithoutParametrization.globalRefine(1); auto eIt = gridWithParametrization.levelGridView(1).begin<0>(); auto eWoIt = gridWithoutParametrization.levelGridView(1).begin<0>(); auto eEndIt = gridWithParametrization.levelGridView(1).end<0>(); for (; eIt!=eEndIt; ++eIt, ++eWoIt) { // The grids where constructed identically and they are traversed identically // Thus their respective output from geometryInFather should be the same for (int i=0; igeometry().corners(); i++) { Dune::FieldVector diff = eIt->geometryInFather().corner(i) - eWoIt->geometryInFather().corner(i); if ( diff.two_norm() > 1e-5 ) DUNE_THROW(Dune::GridError, "output of geometryInFather() depends on boundary parametrization!"); } } // //////////////////////////////////////////////////////////////////////// // Check refinement to boundary (exact circle geometry). // Upon refinement new vertices should be moved towards the exact geometry, // so that the boundary is better resolved // //////////////////////////////////////////////////////////////////////// { // geometry is a half circle with radius 15, so the exact length // of the boundary is $`R \cdot \pi + 2 R`$ double exact = (Dune::MathematicalConstants::pi() + 2.0) * 15.0; testGeometryApproximation(gridWithParametrization, exact); } // //////////////////////////////////////////////////////////////////////// // Check refinement to boundary (quadratic gmsh boundary) // upon refinement new vertices should be moved towards the exact geometry, // so that the boundary is better resolved // //////////////////////////////////////////////////////////////////////// { Dune::GridFactory> gridFactory; const std::string path(DUNE_GRID_EXAMPLE_GRIDS_PATH); const std::string inputName(path+"gmsh/circle2ndorder.msh"); std::cout << "Reading mesh file " << inputName << std::endl; auto reader = Dune::GmshReader>(inputName, gridFactory); auto gmshgrid = gridFactory.createGrid(); // 1/6 of a circle as 2nd order polynomial: /* the following python code can be used to compute the exact solution below: import sympy from sympy import * tau = sympy.symbols('τ') N = 6 # segments t = [0, pi/N, 2*pi/N] x = list(map(sin, t)) y = list(map(cos, t)) px = interpolate(list(zip(t,x)),tau) py = interpolate(list(zip(t,y)),tau) V = simplify(sqrt(diff(px,tau)**2+diff(py,tau)**2)) # det(J) len = N * integrate(V, (tau,0,t[-1])) print(simplify(len), " = ", len.evalf()) */ double exact = 6.27593206157460; testGeometryApproximation(*gmshgrid, exact); } // //////////////////////////////////////////////////////////////////////// // Check whether copies of elements have the same global ID // //////////////////////////////////////////////////////////////////////// { std::cout << "Testing if copies of elements have the same id." << std::endl; Dune::UGGrid<2> locallyRefinedGrid; locallyRefinedGrid.setRefinementType(Dune::UGGrid<2>::COPY); typedef Dune::UGGrid<2>::Codim<0>::LevelIterator ElementIterator; typedef Dune::UGGrid<2>::HierarchicIterator HierarchicIterator; typedef Dune::UGGrid<2>::Traits::GlobalIdSet GlobalIdSet; typedef Dune::UGGrid<2>::Traits::LocalIdSet LocalIdSet; // make grids makeHalfCircleQuad(locallyRefinedGrid, false, false); markOne(locallyRefinedGrid,0,1); markOne(locallyRefinedGrid,0,1); const GlobalIdSet& globalIdSet = locallyRefinedGrid.globalIdSet(); const LocalIdSet& localIdSet = locallyRefinedGrid.localIdSet(); for (int level=0; level(); ElementIterator eEnd = locallyRefinedGrid.levelGridView(level).end<0>(); for(; eIt!=eEnd; ++eIt) { int children = 0; GlobalIdSet::IdType globalChildId; LocalIdSet::IdType localChildId; HierarchicIterator hIt = eIt->hbegin(level+1); HierarchicIterator hEnd = eIt->hend(level+1); for( ; hIt!=hEnd; ++hIt) { globalChildId = globalIdSet.id<0>(*hIt); localChildId = localIdSet.id<0>(*hIt); ++children; } if (children != 1) continue; if (globalIdSet.id<0>(*eIt) != globalChildId) DUNE_THROW(Dune::GridError, "Copy of element has different globalId!"); if (localIdSet.id<0>(*eIt) != localChildId) DUNE_THROW(Dune::GridError, "Copy of element has different localId!"); } } } return 0; } catch (Dune::Exception& e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/test/testiteratorranges.cc000066400000000000000000000115021511655130300225470ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #define VERIFY(t,msg) do { if (!((t))) DUNE_THROW(Dune::Exception, "Check " #t " failed (" msg ")"); } while (false) template void checkRange(GV gv, int codim, R range, bool verify_less = false) { int count = 0; int indices = 0; for (auto& e : range) { VERIFY(codim == e.codimension,"wrong codimension"); ++count; indices += gv.indexSet().index(e); } if (verify_less) VERIFY(count <= gv.size(codim),"wrong number of elements for codim " << codim << " "); else VERIFY(count == gv.size(codim),"wrong number of elements for codim " << codim << " "); } // The grid *must* be refined at least once! template void check_ranges(const Grid& grid, OS&& os) { const int dim = Grid::dimension; auto gv = grid.leafGridView(); os << "Checking entity ranges with default PartitionSet... "; // check elements checkRange(gv,0,elements(gv)); // check facets checkRange(gv,1,facets(gv)); // check edges checkRange(gv,dim-1,edges(gv)); // check vertices checkRange(gv,dim,vertices(gv)); // check elements using codim checkRange(gv,0,entities(gv,Dune::Codim<0>())); // check facets using codim checkRange(gv,1,entities(gv,Dune::Codim<1>())); // check edges using dim checkRange(gv,dim-1,entities(gv,Dune::Dim<1>())); // check vertices using dim checkRange(gv,dim,entities(gv,Dune::Dim<0>())); os << "OK" << std::endl; os << "Checking entity ranges with non-default PartitionSet... "; // check versions with PartitionSet parameter checkRange(gv,0,elements(gv,Dune::Partitions::interiorBorder),true); checkRange(gv,1,facets(gv,Dune::Partitions::all),true); checkRange(gv,dim-1,edges(gv,Dune::Partitions::interior + Dune::Partitions::border),true); checkRange(gv,dim,vertices(gv,Dune::Partitions::interiorBorder + Dune::Partitions::overlap + Dune::Partitions::front),false); checkRange(gv,1,entities(gv,Dune::Codim<1>(),Dune::Partitions::interiorBorder),true); checkRange(gv,dim-1,entities(gv,Dune::Dim<1>(),Dune::Partitions::all - Dune::Partitions::ghost),true); os << "OK" << std::endl; os << "Checking hierarchic entity range... "; // check hierarchic entity range { int count = 0; int indices = 0; // we need a LevelGridView higher up in the hierarchy for this auto gv = grid.levelGridView(grid.maxLevel()-1); for (auto& e : descendantElements(*elements(gv).begin(),grid.maxLevel())) { ++count; indices += grid.levelGridView(e.level()).indexSet().index(e); } VERIFY(count == 1 << dim,"wrong number of descendant elements"); } os << "OK" << std::endl; os << "Checking intersection range... "; // check intersections { int count = 0; int indices = 0; for (auto& is : intersections(gv,*elements(gv).begin())) { ++count; indices += is.indexInInside(); } VERIFY(count == 2 * dim,"wrong number of intersections"); } os << "OK" << std::endl; } // little helper to only print output on rank 0 template struct Rank0Stream { Rank0Stream(S& s, C c) : _s(s) , _c(c) {} template Rank0Stream& operator<<(const T& t) { if (_c.rank() == 0) _s << t; return *this; } // needed for manipulators (std::endl etc.) Rank0Stream& operator<<(std::ostream& (*f)(std::ostream&)) { if (_c.rank() == 0) f(_s); return *this; } S& _s; C _c; }; template Rank0Stream rank0Stream(S& s, C c) { return {s,c}; } template void check_yasp_3d(OS&& os) { os << "Running tests on 3D YaspGrid..." << std::endl; const int dim = 3; Dune::FieldVector Len(1.0); std::array s; std::fill(s.begin(), s.end(), 8); std::bitset p; int overlap = 1; Dune::YaspGrid grid(Len,s,p,overlap); #if HAVE_MPI os << "Parallel run on " << grid.comm().size() << " processors" << std::endl; #else os << "Sequential run" << std::endl; #endif // refine once so that we can check the hierarchic iterator range grid.globalRefine(1); check_ranges(grid,os); } int main(int argc , char **argv) { try { // Initialize MPI, if present Dune::MPIHelper::instance(argc, argv); check_yasp_3d(rank0Stream(std::cout,Dune::MPIHelper::getCommunication())); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/000077500000000000000000000000001511655130300172645ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/test/yasp/CMakeLists.txt000066400000000000000000000032561511655130300220320ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # Link all test targets in this directory against Dune::Grid link_libraries(Dune::Grid) dune_add_test(NAME test-yaspgrid-backuprestore-equidistant SOURCES test-yaspgrid-backuprestore-equidistant.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(NAME test-yaspgrid-backuprestore-equidistantoffset SOURCES test-yaspgrid-backuprestore-equidistantoffset.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(NAME test-yaspgrid-backuprestore-tensor SOURCES test-yaspgrid-backuprestore-tensor.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(SOURCES test-yaspgrid-entityshifttable.cc) dune_add_test(SOURCES test-yaspgrid-partitioner.cc) dune_add_test(NAME test-yaspgrid-tensorgridfactory SOURCES test-yaspgrid-tensorgridfactory.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(NAME test-yaspgrid-yaspfactory-1d SOURCES test-yaspgrid-yaspfactory-1d.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(NAME test-yaspgrid-yaspfactory-2d SOURCES test-yaspgrid-yaspfactory-2d.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(NAME test-yaspgrid-yaspfactory-3d SOURCES test-yaspgrid-yaspfactory-3d.cc MPI_RANKS 1 2 TIMEOUT 666 ) dune_add_test(SOURCES test-yaspgrid-constructor.cc) dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-backuprestore-equidistant.cc000066400000000000000000000023761511655130300276010ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present const auto & mpiHelper = Dune::MPIHelper::instance(argc, argv); std::string testID = "backuprestore-equidistant-np" + std::to_string(mpiHelper.size()); // check the backup restore facility check_backuprestore(testID, YaspFactory<2,Dune::EquidistantCoordinates >::buildGrid()); // Test again with refinement check_backuprestore(testID + "-ref", YaspFactory<2,Dune::EquidistantCoordinates >::buildGrid(true, 1)); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-backuprestore-equidistantoffset.cc000066400000000000000000000024201511655130300307760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present const auto & mpiHelper = Dune::MPIHelper::instance(argc, argv); std::string testID = "backuprestore-equidistantoffset-np" + std::to_string(mpiHelper.size()); // check the backup restore facility check_backuprestore(testID, YaspFactory<2,Dune::EquidistantOffsetCoordinates >::buildGrid()); // Test again with refinement check_backuprestore(testID + "-ref", YaspFactory<2,Dune::EquidistantOffsetCoordinates >::buildGrid(true, 1)); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-backuprestore-tensor.cc000066400000000000000000000023751511655130300265600ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present const auto & mpiHelper = Dune::MPIHelper::instance(argc, argv); std::string testID = "backuprestore-tensor-np" + std::to_string(mpiHelper.size()); // check the backup restore facility check_backuprestore(testID, YaspFactory<2,Dune::TensorProductCoordinates >::buildGrid()); // Test again with refinement check_backuprestore(testID + "-ref", YaspFactory<2,Dune::TensorProductCoordinates >::buildGrid(true, 1)); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-constructor.cc000066400000000000000000000033151511655130300247570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include #include #include int main(int argc, char** argv) { using namespace Dune; MPIHelper::instance(argc, argv); using DVector = FieldVector; using FVector = FieldVector; std::bitset<2> p{0ULL}; { DVector x{1.0, 1.0}; std::array N{2, 2}; YaspGrid grid{x, N, p}; static_assert(std::is_same_v< decltype(grid), YaspGrid< 2, EquidistantCoordinates > >); } { FVector x{1.0f, 1.0f}; std::array N{2, 2}; YaspGrid grid{x, N}; static_assert(std::is_same_v< decltype(grid), YaspGrid< 2, EquidistantCoordinates > >); } { DVector x1{0.0, 0.0}, x2{1.0, 1.0}; std::array N{2, 2}; YaspGrid grid{x1, x2, N}; static_assert(std::is_same_v< decltype(grid), YaspGrid< 2, EquidistantOffsetCoordinates > >); } { FVector x1{0.0f, 0.0f}, x2{1.0f, 1.0f}; std::array N{2, 2}; YaspGrid grid{x1, x2, N}; static_assert(std::is_same_v< decltype(grid), YaspGrid< 2, EquidistantOffsetCoordinates > >); } { std::vector v{0.0, 1.0, 2.0}; std::array vs{v, v}; YaspGrid grid{vs}; static_assert(std::is_same_v< decltype(grid), YaspGrid< 2, TensorProductCoordinates > >); } { std::vector v{0.0f, 1.0f, 2.0f}; std::array vs{v, v}; YaspGrid grid{vs}; static_assert(std::is_same_v< decltype(grid), YaspGrid< 2, TensorProductCoordinates > >); } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-entityshifttable.cc000066400000000000000000000143431511655130300257570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include using Dune::TestSuite; template TestSuite testBinomialTable(std::vector const* reference = nullptr, bool dump = false) { TestSuite t; using Table = Dune::Yasp::BinomialTable; if (!reference) std::cerr << "W: No reference given!\n"; if (dump) std::cout << " std::vector reference{"; int i = 0; for (int d = 0; d <= n; ++d) { for (int c = 0; c <= d; ++c, ++i) { const auto value = Table::evaluate(d, c); if (reference) t.check(Table::evaluate(d, c) == reference->at(i)); if (dump) std::cout << value << ", "; } } if (dump) std::cout << "};\n"; return t; } template TestSuite testEntityShiftTable(std::vector const* reference = nullptr, bool dump = false) { TestSuite t; using Table = Dune::Yasp::EntityShiftTable; if (!reference) std::cerr << "W: No reference given!\n"; if (dump) std::cout << " std::vector reference{"; int i = 0; for (int codim = 0; codim <= dim; ++codim) { for (int j = 0; j < Dune::Yasp::subEnt(dim, codim); ++j, ++i) { const auto value = Table::evaluate(j, codim); t.check(value == F::evaluate(j, codim)); if (reference) t.check(value.to_ullong() == reference->at(i)); if (dump) std::cout << "0b" << value.to_string() << "ull, "; } } if (dump) std::cout << "};\n"; return t; } int main(int argc, char** /* argv */) { bool dump = false; if (argc > 1) dump = true; TestSuite t; { std::vector reference{1, 1, 1}; t.subTest(testBinomialTable<1>(&reference, dump)); } { std::vector reference{1, 1, 1, 1, 2, 1}; t.subTest(testBinomialTable<2>(&reference, dump)); } { std::vector reference{1, 1, 1, 1, 2, 1, 1, 3, 3, 1}; t.subTest(testBinomialTable<3>(&reference, dump)); } { std::vector reference{1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, 4, 6, 4, 1}; t.subTest(testBinomialTable<4>(&reference, dump)); } { std::vector reference{0b1ull, 0b0ull, 0b0ull}; t.subTest(testEntityShiftTable, 1>(&reference, dump)); } { std::vector reference{ 0b11ull, 0b10ull, 0b10ull, 0b01ull, 0b01ull, 0b00ull, 0b00ull, 0b00ull, 0b00ull }; t.subTest(testEntityShiftTable, 2>(&reference, dump)); } { std::vector reference{ 0b111ull, 0b110ull, 0b110ull, 0b101ull, 0b101ull, 0b011ull, 0b011ull, 0b100ull, 0b100ull, 0b100ull, 0b100ull, 0b010ull, 0b010ull, 0b001ull, 0b001ull, 0b010ull, 0b010ull, 0b001ull, 0b001ull, 0b000ull, 0b000ull, 0b000ull, 0b000ull, 0b000ull, 0b000ull, 0b000ull, 0b000ull }; t.subTest(testEntityShiftTable, 3>(&reference, dump)); } { std::vector reference{ 0b1111ull, 0b1110ull, 0b1110ull, 0b1101ull, 0b1101ull, 0b1011ull, 0b1011ull, 0b0111ull, 0b0111ull, 0b1100ull, 0b1100ull, 0b1100ull, 0b1100ull, 0b1010ull, 0b1010ull, 0b1001ull, 0b1001ull, 0b1010ull, 0b1010ull, 0b1001ull, 0b1001ull, 0b0110ull, 0b0110ull, 0b0101ull, 0b0101ull, 0b0011ull, 0b0011ull, 0b0110ull, 0b0110ull, 0b0101ull, 0b0101ull, 0b0011ull, 0b0011ull, 0b1000ull, 0b1000ull, 0b1000ull, 0b1000ull, 0b1000ull, 0b1000ull, 0b1000ull, 0b1000ull, 0b0100ull, 0b0100ull, 0b0100ull, 0b0100ull, 0b0010ull, 0b0010ull, 0b0001ull, 0b0001ull, 0b0010ull, 0b0010ull, 0b0001ull, 0b0001ull, 0b0100ull, 0b0100ull, 0b0100ull, 0b0100ull, 0b0010ull, 0b0010ull, 0b0001ull, 0b0001ull, 0b0010ull, 0b0010ull, 0b0001ull, 0b0001ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull, 0b0000ull }; t.subTest(testEntityShiftTable, 4>(&reference, dump)); } { std::vector reference{0b0ull, 0b0ull, 0b1ull}; t.subTest(testEntityShiftTable, 1>(&reference, dump)); } { std::vector reference{ 0b00ull, 0b00ull, 0b01ull, 0b00ull, 0b10ull, 0b00ull, 0b01ull, 0b10ull, 0b11ull }; t.subTest(testEntityShiftTable, 2>(&reference, dump)); } { std::vector reference{ 0b000ull, 0b000ull, 0b001ull, 0b000ull, 0b010ull, 0b000ull, 0b100ull, 0b000ull, 0b001ull, 0b010ull, 0b011ull, 0b000ull, 0b001ull, 0b000ull, 0b010ull, 0b100ull, 0b101ull, 0b100ull, 0b110ull, 0b000ull, 0b001ull, 0b010ull, 0b011ull, 0b100ull, 0b101ull, 0b110ull, 0b111ull }; t.subTest(testEntityShiftTable, 3>(&reference, dump)); } { std::vector reference{ 0b0000ull, 0b0000ull, 0b0001ull, 0b0000ull, 0b0010ull, 0b0000ull, 0b0100ull, 0b0000ull, 0b1000ull, 0b0000ull, 0b0001ull, 0b0010ull, 0b0011ull, 0b0000ull, 0b0001ull, 0b0000ull, 0b0010ull, 0b0100ull, 0b0101ull, 0b0100ull, 0b0110ull, 0b0000ull, 0b0001ull, 0b0000ull, 0b0010ull, 0b0000ull, 0b0100ull, 0b1000ull, 0b1001ull, 0b1000ull, 0b1010ull, 0b1000ull, 0b1100ull, 0b0000ull, 0b0001ull, 0b0010ull, 0b0011ull, 0b0100ull, 0b0101ull, 0b0110ull, 0b0111ull, 0b0000ull, 0b0001ull, 0b0010ull, 0b0011ull, 0b0000ull, 0b0001ull, 0b0000ull, 0b0010ull, 0b0100ull, 0b0101ull, 0b0100ull, 0b0110ull, 0b1000ull, 0b1001ull, 0b1010ull, 0b1011ull, 0b1000ull, 0b1001ull, 0b1000ull, 0b1010ull, 0b1100ull, 0b1101ull, 0b1100ull, 0b1110ull, 0b0000ull, 0b0001ull, 0b0010ull, 0b0011ull, 0b0100ull, 0b0101ull, 0b0110ull, 0b0111ull, 0b1000ull, 0b1001ull, 0b1010ull, 0b1011ull, 0b1100ull, 0b1101ull, 0b1110ull, 0b1111ull }; t.subTest(testEntityShiftTable, 4>(&reference, dump)); } return t.exit(); } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-partitioner.cc000066400000000000000000000074051511655130300247360ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright (c) DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 template void old_optimize_dims (int i, const std::array& size, int P, std::array& dims, std::array& trydims, double& opt) { if (i>0) // test all subdivisions recursively { for (int k=1; k<=P; k++) { if (P%k==0) { // P divisible by k trydims[i] = k; old_optimize_dims(i-1,size,P/k,dims,trydims,opt); } } } else { // found a possible combination trydims[0] = P; // check for optimality double m = -1.0; for (int k=0; k0.0001) mm*=3; if ( mm > m ) m = mm; } if (m void old_partition (const std::array& size, int P, std::array& dims, int = 0) { double opt=1E100; std::array trydims; old_optimize_dims(d-1,size,P,dims,trydims,opt); } template void run_test (const Dune::Yasp::Partitioning& partitioner, const std::array& size) { int maxP = d == 1 ? size[0] : d == 2 ? size[0]*size[1] : d == 3 ? size[0]*size[1]*size[2] : 0; int maxO = d == 1 ? size[0]/2 : d == 2 ? std::max({size[0], size[1]})/2 : d == 3 ? std::max({size[0], size[1], size[2]})/2 : 0; for (int o = 0; o <= maxO; ++o) { for (int p = 1; p <= maxP; ++p) { std::array dims; bool failed = false; try { partitioner.partition(size,p,dims,o); } catch(...) { failed = true; } if (!failed) { // Check that all successful computed dimensions are positive for (std::size_t i = 0; i < d; ++i) assert(dims[i] > 0); if (o == 0) { // Check that we get the same result as in the old implementation for overlap == 0 std::array old; old_partition(size,p,old); assert(dims == old); } } } // end p } // end o } template void test (const Partitioner& partitioner) { int maxS = 4; if constexpr (d == 1) { for (int s0 = 1; s0 <= maxS; ++s0) run_test<1>(partitioner,{s0}); } else if constexpr (d == 2) { for (int s0 = 1; s0 <= maxS; ++s0) for (int s1 = 1; s1 <= maxS; ++s1) run_test<2>(partitioner,{s0,s1}); } else if constexpr (d == 3) { for (int s0 = 1; s0 <= maxS; ++s0) for (int s1 = 1; s1 <= maxS; ++s1) for (int s2 = 1; s2 <= maxS; ++s2) run_test<3>(partitioner,{s0,s1,s2}); } } int main (int argc , char **argv) { // Initialize MPI, if present Dune::MPIHelper::instance(argc, argv); Dune::Yasp::DefaultPartitioning<1> p1; test<1>(p1); Dune::Yasp::DefaultPartitioning<2> p2; test<2>(p2); Dune::Yasp::DefaultPartitioning<3> p3; test<3>(p3); // Test construction of partitioners { Dune::Yasp::PowerDPartitioning<1> ylbp1; Dune::Yasp::PowerDPartitioning<2> ylbp2; Dune::Yasp::PowerDPartitioning<3> ylbp3; Dune::Yasp::FixedSizePartitioning<1> yfsp1(std::array{1}); Dune::Yasp::FixedSizePartitioning<2> yfsp2(std::array{1,1}); Dune::Yasp::FixedSizePartitioning<3> yfsp3(std::array{1,1,1}); } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-tensorgridfactory.cc000066400000000000000000000024231511655130300261410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present Dune::MPIHelper::instance(argc, argv); // check the factory class for tensorproduct grids Dune::TensorGridFactory > > factory; factory.setStart(0,-100.); factory.fillIntervals(0,10,20.); factory.fillRange(0, 5, 130.); factory.geometricFillIntervals(0, 5, 2.0); factory.geometricFillRange(1,10,100.,1.,false); factory.fillRange(1,10,200); factory.geometricFillRange(1,10,250.,1.,true); factory.fillUntil(1,50,1000.); factory.createGrid(); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-yaspfactory-1d.cc000066400000000000000000000034101511655130300252340ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present const auto & mpiHelper = Dune::MPIHelper::instance(argc, argv); std::string testID = "yaspfactory-1d-np" + std::to_string(mpiHelper.size()); check_yasp(testID + "equidistant", YaspFactory<1,Dune::EquidistantCoordinates >::buildGrid()); check_yasp(testID + "equidistantoffset", YaspFactory<1,Dune::EquidistantOffsetCoordinates >::buildGrid()); check_yasp(testID + "tensor", YaspFactory<1,Dune::TensorProductCoordinates >::buildGrid()); check_yasp(testID + "equidistant-generic-constructor", YaspFactory<1,Dune::EquidistantCoordinates >::buildGrid(true,0,false,true)); check_yasp(testID + "equidistantoffset-generic-constructor", YaspFactory<1,Dune::EquidistantOffsetCoordinates >::buildGrid(true,0,false,true)); check_yasp(testID + "tensor-generic-constructor", YaspFactory<1,Dune::TensorProductCoordinates >::buildGrid(true,0,false,true)); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-yaspfactory-2d.cc000066400000000000000000000054031511655130300252410ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present const auto &mpiHelper = Dune::MPIHelper::instance(argc, argv); std::string testID = "yaspfactory-2d-np" + std::to_string(mpiHelper.size()); check_yasp(testID + "equidistant", YaspFactory<2,Dune::EquidistantCoordinates >::buildGrid(true, 0)); check_yasp(testID + "equidistantoffset", YaspFactory<2,Dune::EquidistantOffsetCoordinates >::buildGrid(true, 0)); check_yasp(testID + "tensor", YaspFactory<2,Dune::TensorProductCoordinates >::buildGrid(true, 0)); // In 2D, also test refinement for (int refineOpt = 0; refineOpt <= 1; ++refineOpt) { std::string refTestID = testID + "-ref" + std::to_string(refineOpt); check_yasp(refTestID + "equidistant", YaspFactory<2,Dune::EquidistantCoordinates >::buildGrid(refineOpt == 1, 1)); check_yasp(refTestID + "equidistantoffset", YaspFactory<2,Dune::EquidistantOffsetCoordinates >::buildGrid(refineOpt == 1, 1)); check_yasp(refTestID + "tensor", YaspFactory<2,Dune::TensorProductCoordinates >::buildGrid(refineOpt == 1, 1)); } // Test the generic constructor check_yasp(testID + "equidistant-generic-constructor", YaspFactory<2,Dune::EquidistantCoordinates >::buildGrid(true,0,false,true)); check_yasp(testID + "equidistantoffset-generic-constructor", YaspFactory<2,Dune::EquidistantOffsetCoordinates >::buildGrid(true,0,false,true)); check_yasp(testID + "tensor-generic-constructor", YaspFactory<2,Dune::TensorProductCoordinates >::buildGrid(true,0,false,true)); // And periodicity // check_yasp(YaspFactory<2,Dune::EquidistantCoordinates >::buildGrid(true, 0, true)); // check_yasp(YaspFactory<2,Dune::EquidistantOffsetCoordinates >::buildGrid(true, 0, true)); // check_yasp(YaspFactory<2,Dune::TensorProductCoordinates >::buildGrid(true, 0, true)); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid-yaspfactory-3d.cc000066400000000000000000000034541511655130300252460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 "test-yaspgrid.hh" int main (int argc , char **argv) { try { // Initialize MPI, if present const auto & mpiHelper = Dune::MPIHelper::instance(argc, argv); std::string testID = "yaspfactory-3d-np" + std::to_string(mpiHelper.size()); check_yasp(testID + "equidistant", YaspFactory<3,Dune::EquidistantCoordinates >::buildGrid()); check_yasp(testID + "equidistantoffset", YaspFactory<3,Dune::EquidistantOffsetCoordinates >::buildGrid()); check_yasp(testID + "tensor", YaspFactory<3,Dune::TensorProductCoordinates >::buildGrid()); // Test the generic constructor check_yasp(testID + "equidistant-generic-constructor", YaspFactory<3,Dune::EquidistantCoordinates >::buildGrid(true,0,false,true)); check_yasp(testID + "equidistantoffset-generic-constructor", YaspFactory<3,Dune::EquidistantOffsetCoordinates >::buildGrid(true,0,false,true)); check_yasp(testID + "tensor-generic-constructor", YaspFactory<3,Dune::TensorProductCoordinates >::buildGrid(true,0,false,true)); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/test/yasp/test-yaspgrid.hh000066400000000000000000000167131511655130300224140ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_TEST_TEST_YASPGRID_HH #define DUNE_GRID_TEST_TEST_YASPGRID_HH #include #include #include #include #include #include #include #include #include #include #include #include template struct YaspFactory {}; template struct YaspFactory > { static Dune::YaspGrid* buildGrid( bool keepPhysicalOverlap = true, int refCount = 0, bool periodic = false, bool useGenericConstructor = false) { std::cout << " using equidistant coordinate container"; if (useGenericConstructor) std::cout << " with generic constructor"; std::cout << "!" << std::endl << std::endl; Dune::FieldVector len(1.0); std::array s; std::fill(s.begin(), s.end(), 4); s[0] = 8; std::bitset p(0); p[0] = periodic; int overlap = 1; Dune::YaspGrid* grid; if (useGenericConstructor) { Dune::EquidistantCoordinates coordinates(len,s); grid = new Dune::YaspGrid(coordinates,p,overlap); } else grid = new Dune::YaspGrid(len,s,p,overlap); grid->refineOptions (keepPhysicalOverlap); grid->globalRefine (refCount); return grid; } }; template struct YaspFactory > { static Dune::YaspGrid >* buildGrid( bool keepPhysicalOverlap = true, int refCount = 0, bool periodic = false, bool useGenericConstructor = false) { if (useGenericConstructor) std::cout << " using equidistant coordinate container with non-zero origin and generic constructor!" << std::endl << std::endl; else std::cout << " using equidistant coordinate container with non-zero origin!" << std::endl << std::endl; Dune::FieldVector lowerleft(-1.0); Dune::FieldVector upperright(1.0); std::array s; std::fill(s.begin(), s.end(), 4); s[0] = 8; std::bitset p(0); p[0] = periodic; int overlap = 1; Dune::YaspGrid >* grid; if (useGenericConstructor) { Dune::EquidistantOffsetCoordinates coordinates(lowerleft,upperright,s); grid = new Dune::YaspGrid >(coordinates,p,overlap); } else grid = new Dune::YaspGrid >(lowerleft,upperright,s,p,overlap); grid->refineOptions (keepPhysicalOverlap); grid->globalRefine (refCount); return grid; } }; template struct YaspFactory > { static Dune::YaspGrid >* buildGrid( bool keepPhysicalOverlap = true, int refCount = 0, bool periodic = false, bool useGenericConstructor = false) { if (useGenericConstructor) std::cout << " using tensorproduct coordinate container and generic constructor!" << std::endl << std::endl; else std::cout << " using tensorproduct coordinate container!" << std::endl << std::endl; std::bitset p(0); p[0] = periodic; int overlap = 1; std::array,dim> coords; coords[0].resize(9); coords[0][0] = -1.0; coords[0][1] = -0.5; coords[0][2] = -0.25; coords[0][3] = -0.125; coords[0][4] = 0.0; coords[0][5] = 0.125; coords[0][6] = 0.25; coords[0][7] = 0.5; coords[0][8] = 1.0; for (int i=1; i >* grid; if (useGenericConstructor) { std::array offset; std::fill(offset.begin(), offset.end(), 0); Dune::TensorProductCoordinates coordinates(coords,offset); grid = new Dune::YaspGrid >(coordinates,p,overlap); } else grid = new Dune::YaspGrid >(coords,p,overlap); grid->refineOptions (keepPhysicalOverlap); grid->globalRefine (refCount); return grid; } }; template void check_yasp(std::string testID, Dune::YaspGrid* grid) { std::cout << std::endl << "YaspGrid<" << dim << ">"; gridcheck(*grid); checkIterators ( grid->leafGridView() ); checkIterators ( grid->levelGridView(0) ); // check communication interface checkCommunication(*grid,-1,Dune::dvverb); for(int l=0; l<=grid->maxLevel(); ++l) checkCommunication(*grid,l,Dune::dvverb); // check communication correctness Dune::GridCheck::check_communication_correctness(grid->leafGridView()); // check geometry lifetime checkGeometryLifetime( grid->leafGridView() ); // check the method geometryInFather() checkGeometryInFather(*grid); // check the intersection iterator and the geometries it returns checkIntersectionIterator(*grid); // check grid adaptation interface checkAdaptRefinement(*grid); checkPartitionType( grid->leafGridView() ); std::ofstream file; std::ostringstream filename; filename << testID << "-output" <comm().rank(); file.open(filename.str()); file << *grid << std::endl; file.close(); delete grid; } template > void check_backuprestore(std::string testID, Dune::YaspGrid* grid) { typedef Dune::YaspGrid Grid; grid->globalRefine(2); Dune::BackupRestoreFacility::backup(*grid, testID+"-backup"); // avoid that processes that having nothing to backup try to restore // a grid that has not been backuped yet. grid->comm().barrier(); Grid* restored = Dune::BackupRestoreFacility::restore(testID+"-backup"); // write a backup of the restored file. this has to be identical to backup Dune::BackupRestoreFacility::backup(*restored, testID+"-copy"); if ((std::is_same >::value) || (grid->comm().rank() == 0)) { // check whether copy and backup are equal std::ostringstream s1,s2; s1 << testID << "-backup"; s2 << testID << "-copy"; if (std::is_same >::value) { s1 << grid->comm().rank(); s2 << grid->comm().rank(); } std::ifstream file1, file2; file1.open(s1.str()); file2.open(s2.str()); std::string token1, token2; while(!file1.eof() && !file2.eof()) { file1 >> token1; file2 >> token2; if (token1 != token2) DUNE_THROW(Dune::Exception, "Error in BackupRestoreFacility"); } } check_yasp(testID, restored); delete grid; } #endif dune-grid-2.11.0/dune/grid/uggrid.hh000066400000000000000000000677541511655130300171560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_HH #define DUNE_UGGRID_HH /** \file * \brief The UGGrid class */ #include #include #include #include #include #include // HAVE_DUNE_UGGRID #include #include #include #if HAVE_DUNE_UGGRID || DOXYGEN #ifdef ModelP #include #endif /* [Before reading the following: the macros UG_DIM_2 and UG_DIM_3 where named * _2 and _3, respectively, up until ug-3.12.0.] * * The following lines including the necessary UG headers are somewhat tricky. Here's what's happening: UG can support two- and three-dimensional grids. You choose by setting either UG_DIM_2 or UG_DIM_3 while compiling. This changes all sorts of stuff, in particular data structures in the headers. UG was never supposed to provide 2d and 3d grids at the same time. However, when compiling it as c++, the dimension-dependent parts are wrapped up cleanly in the namespaces UG::D2 and UG::D3, respectively. That way it is possible to link together the UG lib for 2d and the one for 3d. But we also need the headers twice! Once with UG_DIM_2 set and once with UG_DIM_3! So here we go:*/ // Set UG's space-dimension flag to 2d #define UG_DIM_2 // And include all necessary UG headers #include "uggrid/ugincludes.hh" #undef DUNE_UGINCLUDES_HH // Wrap a few large UG macros by functions before they get undef'ed away. // Here: The 2d-version of the macros #define UG_DIM 2 #include "uggrid/ugwrapper.hh" #undef UG_DIM // UG defines a whole load of preprocessor macros. ug_undefs.hh undefines // them all, so we don't get name clashes. #include "uggrid/ug_undefs.hh" #undef UG_DIM_2 /* Now we're done with 2d, and we can do the whole thing over again for 3d */ /* All macros set by UG have been unset. This includes the macros that ensure single inclusion of headers. We can thus include them again. However, we only want to include those headers again that contain dimension-dependent stuff. Therefore, we set a few single-inclusion defines manually before including ugincludes.hh again. */ #define UGTYPES_H #define __HEAPS__ #define __UGENV__ #define __DEVICESH__ #ifdef ModelP #define __PPIF__ #endif #define UG_DIM_3 #include "uggrid/ugincludes.hh" #undef DUNE_UGINCLUDES_HH // Wrap a few large UG macros by functions before they get undef'ed away. // This time it's the 3d-versions. #define UG_DIM 3 #include "uggrid/ugwrapper.hh" #undef UG_DIM // undef all macros defined by UG #include "uggrid/ug_undefs.hh" #undef UG_DIM_3 // The components of the UGGrid interface #include "uggrid/uggridgeometry.hh" #include "uggrid/uggridlocalgeometry.hh" #include "uggrid/uggridentity.hh" #include "uggrid/uggridentityseed.hh" #include "uggrid/uggridintersections.hh" #include "uggrid/uggridintersectioniterators.hh" #include "uggrid/uggridleveliterator.hh" #include "uggrid/uggridleafiterator.hh" #include "uggrid/uggridhieriterator.hh" #include "uggrid/uggridindexsets.hh" #include #ifdef ModelP #include "uggrid/ugmessagebuffer.hh" #include "uggrid/uglbgatherscatter.hh" #endif // Not needed here, but included for user convenience #include "uggrid/uggridfactory.hh" #ifdef ModelP template const Dune::UGGrid* Dune::UGMessageBuffer::grid_; template DataHandle *Dune::UGMessageBuffer::duneDataHandle_ = nullptr; template int Dune::UGMessageBuffer::level = -1; #endif // ModelP namespace Dune { #ifdef ModelP using UGCommunication = Communication; #else using UGCommunication = Communication; #endif template struct UGGridFamily { typedef GridTraits, UGGridGeometry, UGGridEntity, UGGridLevelIterator, UGGridLeafIntersection, UGGridLevelIntersection, UGGridLeafIntersectionIterator, UGGridLevelIntersectionIterator, UGGridHierarchicIterator, UGGridLeafIterator, UGGridLevelIndexSet< const UGGrid >, UGGridLeafIndexSet< const UGGrid >, UGGridIdSet< const UGGrid >, typename UG_NS::UG_ID_TYPE, UGGridIdSet< const UGGrid >, typename UG_NS::UG_ID_TYPE, UGCommunication, UGGridLevelGridViewTraits, UGGridLeafGridViewTraits, UGGridEntitySeed, UGGridLocalGeometry> Traits; }; //********************************************************************** // // --UGGrid // //********************************************************************** /** \brief Front-end for the grid manager of the finite element toolbox UG3 \ingroup GridImplementations This is the implementation of the grid interface using the UG3 grid management system. It is best described in this paper. To our knowledge, the original code is not available anymore, but the relevant parts have been forked into the %Dune module dune-uggrid, available from . UGGrid provides conforming grids in two and three space dimensions. The grids can be mixed, i.e. 2d grids can contain triangles and quadrilaterals and 3d grids can contain tetrahedra and hexahedra and also pyramids and prisms. The grid refinement rules are very flexible. Local adaptive red/green refinement is the default, but a special method in the UGGrid class allows you to directly access a number of anisotropic refinements rules. Last but not least, the UG grid manager is completely parallelized, and you can use boundaries parametrized by either analytical expressions or high-resolution piecewise linear surfaces. In your %Dune application, you can instantiate objects of the type UGGrid<2> or UGGrid<3>. You can have more than one, if you choose. It is even possible to have 2d and 3d grids at the same time, even though the original UG system never intended to support this! See the documentation for the factory class GridFactory > to learn how to create UGGrid objects. */ template class UGGrid : public GridDefaultImplementation > { typedef GridDefaultImplementation > Base; friend class UGGridGeometry<0,dim,const UGGrid >; friend class UGGridGeometry >; friend class UGGridGeometry<1,2,const UGGrid >; friend class UGGridGeometry<2,3,const UGGrid >; friend class UGGridEntity <0,dim,const UGGrid >; friend class UGGridEntity <1,dim,const UGGrid >; friend class UGGridEntity <2,dim,const UGGrid >; friend class UGGridEntity >; friend class UGGridHierarchicIterator >; friend class UGGridLeafIntersection >; friend class UGGridLevelIntersection >; friend class UGGridLeafIntersectionIterator >; friend class UGGridLevelIntersectionIterator >; friend class UGGridLevelIndexSet >; friend class UGGridLeafIndexSet >; friend class UGGridIdSet >; template friend class UGGridLeafGridView; template friend class UGGridLevelGridView; friend class GridFactory >; #ifdef ModelP friend class UGLBGatherScatter; #endif template friend class UGGridLeafIterator; template friend class UGGridLevelIterator; /** \brief UGGrid is only implemented for 2 and 3 dimension */ static_assert(dim==2 || dim==3, "Use UGGrid only for 2d and 3d!"); // The different instantiations are mutual friends so they can access // each others numOfUGGrids field friend class UGGrid<2>; friend class UGGrid<3>; //********************************************************** // The Interface Methods //********************************************************** public: //! type of the used GridFamily for this grid typedef UGGridFamily GridFamily; // the Traits typedef typename UGGridFamily::Traits Traits; //! The type used to store coordinates typedef UG::DOUBLE ctype; //! The type used for process ranks typedef unsigned int Rank; /** \brief Default constructor */ UGGrid(UGCommunication comm = {}); //! Destructor ~UGGrid() noexcept(false); //! Return maximum level defined in this grid. Levels are numbered //! 0 ... maxlevel with 0 the coarsest level. int maxLevel() const; /** \brief Create an Entity from an EntitySeed */ template typename Traits::template Codim::Entity entity(const Seed& seed) const { const int codim = Seed::codimension; return typename Traits::template Codim::Entity(UGGridEntity >(seed.impl().target(),this)); } /** \brief Number of grid entities per level and codim */ int size (int level, int codim) const; //! number of leaf entities per codim in this process int size (int codim) const { return leafIndexSet().size(codim); } //! number of entities per level and geometry type in this process int size (int level, GeometryType type) const { return this->levelIndexSet(level).size(type); } //! number of leaf entities per geometry type in this process int size (GeometryType type) const { return this->leafIndexSet().size(type); } /** \brief Return the number of boundary segments */ size_t numBoundarySegments() const { // The number is stored as a member of UGGrid upon grid creation. // The corresponding data structure is not exported by UG. (It is in ug/dom/std/std_internal.h) return numBoundarySegments_; } /** \brief Access to the GlobalIdSet */ const typename Traits::GlobalIdSet& globalIdSet() const { return idSet_; } /** \brief Access to the LocalIdSet */ const typename Traits::LocalIdSet& localIdSet() const { return idSet_; } /** \brief Access to the LevelIndexSets */ const typename Traits::LevelIndexSet& levelIndexSet(int level) const { if (level<0 || level>maxLevel()) DUNE_THROW(GridError, "levelIndexSet of nonexisting level " << level << " requested!"); return *levelIndexSets_[level]; } /** \brief Access to the LeafIndexSet */ const typename Traits::LeafIndexSet& leafIndexSet() const { return leafIndexSet_; } /** @name Grid Refinement Methods */ /*@{*/ /** \brief Mark element for refinement \param refCount
  • 1: mark for red refinement
  • -1: mark for coarsening
  • 0: delete a possible refinement mark
\param e Element to be marked \return
  • true, if element was marked
  • false, if nothing changed
*/ bool mark(int refCount, const typename Traits::template Codim<0>::Entity & e ); /** \brief Mark method accepting a UG refinement rule \param e element to be marked for refinement \param rule One of the UG refinement rules \param side If rule==UG::%D2::%BLUE (one quadrilateral is split into two rectangles) you can choose the orientation of the cut by setting side==0 or side==1 The available values for RefinementRule are: (see the RefinementRule enum in ug/gm/gm.h)

2D

- NO_REFINEMENT - COPY - RED - BLUE - COARSE - BISECTION_1 - BISECTION_2_Q - BISECTION_2_T1 - BISECTION_2_T2 - BISECTION_3

3D

- NO_REFINEMENT - COPY - RED - COARSE - TETRA_RED_HEX - PRISM_BISECT_1_2 - PRISM_QUADSECT - PRISM_BISECT_HEX0 - PRISM_BISECT_HEX1 - PRISM_BISECT_HEX2 - PRISM_ROTATE_LEFT - PRISM_ROTATE_RGHT - PRISM_QUADSECT_HEXPRI0 - PRISM_RED_HEX - PRISM_BISECT_0_1 - PRISM_BISECT_0_2 - PRISM_BISECT_0_3 - HEX_BISECT_0_1 - HEX_BISECT_0_2 - HEX_BISECT_0_3 - HEX_TRISECT_0 - HEX_TRISECT_5 - HEX_QUADSECT_0 - HEX_QUADSECT_1 - HEX_QUADSECT_2 - HEX_BISECT_HEXPRI0 - HEX_BISECT_HEXPRI1 */ bool mark(const typename Traits::template Codim<0>::Entity & e, typename UG_NS::RefinementRule rule, int side=0); /** \brief Query whether element is marked for refinement */ int getMark(const typename Traits::template Codim<0>::Entity& e) const; /** \brief returns true, if some elements might be coarsend during grid adaption, here always returns true */ bool preAdapt(); //! Triggers the grid refinement process bool adapt(); /** \brief Clean up refinement markers */ void postAdapt(); /*@}*/ /** \brief Distributes the grid and some data over the available nodes in a distributed machine \tparam DataHandle works like the data handle for the communicate methods. \return True, if grid has changed, false otherwise */ template bool loadBalance (DataHandle& dataHandle) { #ifdef ModelP // gather element data if (dataHandle.contains(dim, 0)) UGLBGatherScatter::template gather<0>(this->leafGridView(), dataHandle); // gather node data if (dataHandle.contains(dim,dim)) UGLBGatherScatter::template gather(this->leafGridView(), dataHandle); #endif // the load balancing step now also attaches // the data to the entities and distributes it loadBalance(); #ifdef ModelP // scatter element data if (dataHandle.contains(dim, 0)) UGLBGatherScatter::template scatter<0>(this->leafGridView(), dataHandle); // scatter node data if (dataHandle.contains(dim,dim)) UGLBGatherScatter::template scatter(this->leafGridView(), dataHandle); #endif return true; } /** \brief Distributes this grid over the available nodes in a distributed machine \bug The return value is always 'true' \param minlevel The coarsest grid level that gets distributed */ bool loadBalance(int minlevel=0); /** \brief Distribute this grid over a distributed machine * * \param[in] targetProcessors For each leaf element the rank of the process the element shall be sent to * \param[in] fromLevel The lowest level that gets redistributed (set to 0 when in doubt) * * This method allows to (re-)distribute the grid controlled by an external grid repartitioning library. * You need to get that library to assign a target rank to each interior element in the leaf grid. With this * information in a std::vector, call this method, and UG will do the actual repartitioning. * Each leaf element will be sent to the assigned target rank. For all other elements we look at * where there children are being sent to. The parent is then sent to where most of its children are * (Familienzusammenfuehrung). * * The size of the input array targetProcessors is expected to be equal to the number of elements in * the 'all'-partition, i.e., the number Interior elements plus the number of Ghost elements. * To get the array entry corresponding to an Interior element, a MultipleCodimMultipleGeomTypeMapper * with layout class MCMGElementLayout is used. Array entries corresponding to Ghost elements are ignored. * * In some cases you may also want to leave the lowest levels on one process, to have them all together * for multigrid coarse grid corrections. In that case, use the fromLevel parameter with a value other * than zero, to redistribute only elements above a certain level. * * The fromLevel argument is also needed to allow the compiler to distinguish this method from * the loadBalance method with a single template DataHandle argument. * * \note In theory you can assign a target rank to any element on any level, and UG will magically transfer * the element to that rank and make everything come out right. This is not supported by the UGGrid interface, * because I didn't see a use case for it. If you do need it please ask on the Dune mailing list. * * \return true */ bool loadBalance(const std::vector& targetProcessors, unsigned int fromLevel); /** \brief Distributes the grid over the processes of a parallel machine, and sends data along with it * * \param[in] targetProcessors For each leaf element the rank of the process the element shall be sent to * \param[in] fromLevel The lowest level that gets redistributed (set to 0 when in doubt) * \param[in,out] dataHandle A data handle object that does the gathering and scattering of data * \tparam DataHandle works like the data handle for the communicate methods. * * \return true */ template bool loadBalance (const std::vector& targetProcessors, unsigned int fromLevel, DataHandle& dataHandle) { #ifdef ModelP // gather element data if (dataHandle.contains(dim, 0)) UGLBGatherScatter::template gather<0>(this->leafGridView(), dataHandle); // gather node data if (dataHandle.contains(dim,dim)) UGLBGatherScatter::template gather(this->leafGridView(), dataHandle); #endif // the load balancing step now also attaches // the data to the entities and distributes it loadBalance(targetProcessors,fromLevel); #ifdef ModelP // scatter element data if (dataHandle.contains(dim, 0)) UGLBGatherScatter::template scatter<0>(this->leafGridView(), dataHandle); // scatter node data if (dataHandle.contains(dim,dim)) UGLBGatherScatter::template scatter(this->leafGridView(), dataHandle); #endif return true; } /** the communication */ const UGCommunication& comm () const { return ccobj_; } protected: #ifdef ModelP template void communicateUG_(const GridView& gv, int level, DataHandle &dataHandle, InterfaceType iftype, CommunicationDirection dir) const { // Translate the communication direction from Dune-Speak to UG-Speak const auto ugIfDir = (dir==ForwardCommunication) ? UG_NS::IF_FORWARD() : UG_NS::IF_BACKWARD(); // Set up the message buffer // No actual object is constructed, because the DDD_IFOneway method called below // needs *static* methods. Therefore, everything is currently routed // via static data members of the UGMessageBuffer class. using UGMsgBuf = UGMessageBuffer; UGMsgBuf::duneDataHandle_ = &dataHandle; UGMsgBuf::level = level; UGMsgBuf::grid_ = this; const std::vector::DDD_IF> ugIfs = findDDDInterfaces(iftype, codim); const auto bufSize = UGMsgBuf::ugBufferSize(gv); if (!bufSize) return; // we don't need to communicate if we don't have any data! for (auto&& dddInterface : ugIfs) UG_NS::DDD_IFOneway(multigrid_->dddContext(), dddInterface, ugIfDir, bufSize, &UGMsgBuf::ugGather_, &UGMsgBuf::ugScatter_); } /** \brief Translate Dune communication interface to UG communication interface */ std::vector::DDD_IF> findDDDInterfaces(InterfaceType iftype, int codim) const; #endif public: // ********************************************************** // End of Interface Methods // ********************************************************** /** \brief Rudimentary substitute for a hierarchic iterator on faces \param e, elementSide Grid face specified by an element and one of its sides \param maxl The finest level that should be traversed by the iterator \param[out] childElements For each subface: element index, elementSide, and level \param[out] childElementSides Indices for transformation because Dune numbers the faces of several elements differently than UG */ void getChildrenOfSubface(const typename Traits::template Codim<0>::Entity & e, int elementSide, int maxl, std::vector::Entity>& childElements, std::vector& childElementSides) const; /** \brief The different forms of grid refinement that UG supports */ enum RefinementType { /** \brief New level consists only of the refined elements and the closure*/ LOCAL, /** \brief New level consists of the refined elements and the unrefined ones, too */ COPY }; /** \brief Decide whether to add a green closure to locally refined grid sections or not */ enum ClosureType { /** \brief Standard red/green refinement */ GREEN, /** \brief No closure, results in nonconforming meshes */ NONE }; /** \brief Sets the type of grid refinement */ void setRefinementType(RefinementType type) { refinementType_ = type; } /** \brief Sets the type of grid refinement closure */ void setClosureType(ClosureType type) { closureType_ = type; } /** \brief Sets a vertex to a new position Changing a vertex' position changes its position on all grid levels!*/ void setPosition(const typename Traits::template Codim::Entity& e, const FieldVector& pos); /** \brief Does uniform refinement * * \param n Number of uniform refinement steps */ void globalRefine(int n); /** \brief Save entire grid hierarchy to disk Test implementation -- not working! */ void saveState(const std::string& filename) const; /** \brief Read entire grid hierarchy from disk Test implementation -- not working! */ void loadState(const std::string& filename); private: /** \brief UG multigrid, which contains the actual grid hierarchy structure */ typename UG_NS::MultiGrid* multigrid_; /** \brief The UG3 BoundaryValueProblem, a description of the domain boundary * * \todo The multigrid_ object also has pointer to this. I don't like this * redundancy, but I also don't quite know yet what to do about it. */ typename UG_NS::STD_BVP* bvp_; /** \brief The communication object. */ UGCommunication ccobj_; /** \brief Recomputes entity indices after the grid was changed \param setLevelZero If this is false, level indices of the level 0 are not touched \param nodePermutation Permutation array for the vertex level 0 indices. If this is NULL, the identity is used. */ void setIndices(bool setLevelZero, std::vector* nodePermutation); // Each UGGrid object has a unique name to identify it in the // UG environment structure std::string name_; // Our set of level indices std::vector > > > levelIndexSets_; UGGridLeafIndexSet > leafIndexSet_; // One id set implementation // Used for both the local and the global UGGrid id sets UGGridIdSet > idSet_; //! The type of grid refinement currently in use RefinementType refinementType_; //! The type of grid refinement closure currently in use ClosureType closureType_; /** \brief Number of UGGrids currently in use. * * This counts the number of UGGrids currently instantiated. All * constructors of UGGrid look at this variable. If it is zero, they * initialize UG before proceeding. Destructors use the same mechanism * to safely shut down UG after deleting the last UGGrid object. */ static int numOfUGGrids; /** \brief Remember whether some element has been marked for refinement ever since the last call to adapt(). This is here to implement the return value of adapt(). */ bool someElementHasBeenMarkedForRefinement_; /** \brief Remember whether some element has been marked for coarsening ever since the last call to adapt(). This is here to implement the return value of preAdapt(). */ bool someElementHasBeenMarkedForCoarsening_; /** \brief The classes implementing the geometry of the boundary segments, if requested */ std::vector > > boundarySegments_; /** \brief Overall number of coarse grid boundary segments. This includes the number of linear segments. Hence numBoundarySegments_ >= boundarySegments_.size() (greater than or equal) */ unsigned int numBoundarySegments_; }; // end Class UGGrid namespace Capabilities { /** \struct hasEntity \ingroup UGGrid */ /** \struct hasBackupRestoreFacilities \ingroup UGGrid */ /** \struct IsUnstructured \ingroup UGGrid */ /** \brief UGGrid has entities of all codimensions \ingroup UGGrid */ template struct hasEntity< UGGrid, codim> { static const bool v = true; }; /** * \brief Set default for hasEntityIterator to false * UGGrid can currently only iterate over elements and vertices * \ingroup UGGrid **/ template struct hasEntityIterator, codim> { static const bool v = false; }; /** * \brief UGGrid can iterate over codim=0 entities (elements) * \ingroup UGGrid **/ template struct hasEntityIterator, 0> { static const bool v = true; }; /** * \brief UGGrid can iterate over codim=dim entities (vertices) * \ingroup UGGrid **/ template struct hasEntityIterator, dim> { static const bool v = true; }; /** \brief UGGrid can communicate on entities of all (existing) codimensions * \ingroup UGGrid */ template struct canCommunicate, codim> { static const bool v = (codim>=0 && codim<=dim); }; /** \brief UGGrid is levelwise conforming \ingroup UGGrid */ template struct isLevelwiseConforming< UGGrid > { static const bool v = true; }; /** \brief UGGrid may not be leafwise conforming \ingroup UGGrid */ template struct isLeafwiseConforming< UGGrid > { static const bool v = false; }; /** \brief UGGrid is thread-safe for grid views \ingroup UGGrid */ template struct viewThreadSafe< UGGrid > { static const bool v = true; }; } } // namespace Dune #endif // HAVE_DUNE_UGGRID || DOXYGEN #endif // DUNE_UGGRID_HH dune-grid-2.11.0/dune/grid/uggrid/000077500000000000000000000000001511655130300166125ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/uggrid/CMakeLists.txt000066400000000000000000000027351511655130300213610ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception if(dune-uggrid_FOUND) target_sources(dunegrid PRIVATE uggridintersections.cc uggrid.cc uggridentity.cc boundaryextractor.cc boundaryextractor.hh uggridindexsets.cc uggridfactory.cc uggridgeometry.cc uggridhieriterator.cc) endif() exclude_all_but_from_headercheck( boundaryextractor.hh ug_undefs.hh) set(HEADERS uggridfactory.hh uggridentityseed.hh uggridentity.hh uggridgeometry.hh uggridlocalgeometry.hh uggridhieriterator.hh uggridleveliterator.hh uggridviews.hh ugincludes.hh uggridintersections.hh uggridintersectioniterators.hh uggridindexsets.hh uggridleafiterator.hh uggridrenumberer.hh ug_undefs.hh uglbgatherscatter.hh ugmessagebuffer.hh ugwrapper.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/uggrid) # tricks like undefAllMacros.pl don't have to be shipped, have they? # Oliver Sander: It depends. undefAllMacros.pl creates the file ug_undefs.hh # which contains an undef line for each macro encountered in the UG # headers which DUNE includes. This should be redone every time UG # changes, and currently I do it and then check in the new ug_undefs.hh. # An alternative would be to have the DUNE-build system call undefAllMacros # for the UG it is configured with. Then it needed to be shipped.") dune-grid-2.11.0/dune/grid/uggrid/boundaryextractor.cc000066400000000000000000000141621511655130300227040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include // for the exceptions #include "boundaryextractor.hh" namespace Dune { void BoundaryExtractor::detectBoundarySegments(const std::vector& elementTypes, const std::vector& elementVertices, std::set >& boundarySegments) { // The vertices that form the edges of a triangle -- in UG numbering static const int triIdx[][2] = { {0,1},{1,2},{2,0} }; // The vertices that form the edges of a quadrilateral -- in UG numbering static const int quadIdx[][2] = { {0,1},{1,2},{2,3},{3,0} }; boundarySegments.clear(); unsigned int currentBase = 0; for (size_t i=0; i v; if (verticesPerElement==3) { v[0] = elementVertices[currentBase+triIdx[k][0]]; v[1] = elementVertices[currentBase+triIdx[k][1]]; } else { v[0] = elementVertices[currentBase+quadIdx[k][0]]; v[1] = elementVertices[currentBase+quadIdx[k][1]]; } // Check if new face exists already in the list // (then it is no boundary face) std::pair >::iterator,bool> status = boundarySegments.insert(v); if (!status.second) // Not inserted because already existing boundarySegments.erase(status.first); } currentBase += verticesPerElement; } } void BoundaryExtractor::detectBoundarySegments(const std::vector& elementTypes, const std::vector& elementVertices, std::set >& boundarySegments) { int numElements = elementTypes.size(); // The vertices that form the faces of a tetrahedron -- in UG numbering // Double numbers mean the face is actually a triangle static const int tetraIdx[][4] = { {1,3,2,2},{0,2,3,3},{0,3,1,1},{0,1,2,2} }; // The vertices that form the faces of a pyramid -- in UG numbering static const int pyramidIdx[][4] = { {0,1,2,3},{0,4,1,1},{1,4,2,2},{3,2,4,4},{0,3,4,4} }; // The vertices that form the faces of a prism -- in UG numbering static const int prismIdx[][4] = { {0,1,2,2},{0,3,4,1},{1,4,5,2},{0,2,5,3},{3,5,4,4} }; // The vertices that form the faces of a hexahedron -- in UG numbering static const int hexaIdx[][4] = { {0,4,5,1},{1,5,6,2},{2,6,7,3},{3,7,4,0},{4,7,6,5},{1,2,3,0} }; // Number of faces for tetrahedra, pyramids, prisms, hexahedra // The zeros are just fill-in. static const int numFaces[9] = {0,0,0,0,4,5,5,0,6}; boundarySegments.clear(); // An index into the list of element vertices pointing to the current element int currentElement = 0; for (int i=0; i v; switch (elementTypes[i]) { case 4 : // tetrahedron for (int j=0; j<4; j++) v[j] = elementVertices[currentElement+tetraIdx[k][j]]; break; case 5 : // pyramid for (int j=0; j<4; j++) v[j] = elementVertices[currentElement+pyramidIdx[k][j]]; break; case 6 : // prism for (int j=0; j<4; j++) v[j] = elementVertices[currentElement+prismIdx[k][j]]; break; case 8 : // hexahedron for (int j=0; j<4; j++) v[j] = elementVertices[currentElement+hexaIdx[k][j]]; break; default : DUNE_THROW(Exception, "Can't handle elements with " << elementTypes[i] << " vertices!"); } // Check whether the faces is degenerated to a triangle if (v[2]==v[3]) v[3] = -1; // Find out if the element face has already been encountered. Then it is not a boundary face. std::pair >::iterator,bool> status = boundarySegments.insert(v); if (!status.second) { // Not inserted because already existing boundarySegments.erase(status.first); } } currentElement += elementTypes[i]; } } template int BoundaryExtractor::detectBoundaryNodes(const std::set >& boundarySegments, int noOfNodes, std::vector& isBoundaryNode) { isBoundaryNode.resize(noOfNodes); int UGNodeIdxCounter = 0; for (int i=0; i(const std::set >& boundarySegments, int noOfNodes, std::vector& isBoundaryNode); template int BoundaryExtractor::detectBoundaryNodes<3>(const std::set >& boundarySegments, int noOfNodes, std::vector& isBoundaryNode); } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/boundaryextractor.hh000066400000000000000000000115041511655130300227130ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_BOUNDARY_EXTRACTOR_HH #define DUNE_BOUNDARY_EXTRACTOR_HH /** \file \brief Contains helper classes for the creation of UGGrid objects \author Oliver Sander */ #include #include #include #include namespace Dune { /** \brief Boundary segments that can be compared This general implementation is empty. Only specializations for dim==2 and dim==3 exist. */ template class UGGridBoundarySegment {}; /** \brief Specialization of the boundary segment class for 2d */ template <> class UGGridBoundarySegment<2> : public std::array { public: /** \brief Always returns 2 */ int numVertices() const { return 2; } /** \brief Compare the vertex lists modulo permutation */ bool operator<(const UGGridBoundarySegment<2>& other) const { array sorted1, sorted2; // //////////////////////////////////////////////////////////////////////////// // Sort the two arrays to get rid of cyclic permutations in mirror symmetry // //////////////////////////////////////////////////////////////////////////// if ((*this)[0] < (*this)[1]) sorted1 = (*this); else { sorted1[0] = (*this)[1]; sorted1[1] = (*this)[0]; } if (other[0] < other[1]) sorted2 = other; else { sorted2[0] = other[1]; sorted2[1] = other[0]; } // //////////////////////////////////////////////////////////////////////////// // Compare the two sorted arrays // //////////////////////////////////////////////////////////////////////////// return sorted1 < sorted2; } }; /** \brief Specialization of the boundary segment class for 2d */ template <> class UGGridBoundarySegment<3> : public std::array { public: /** \brief 3 or 4 */ int numVertices() const { return ((*this)[3]==-1) ? 3 : 4; } /** \brief Compare the vertex lists modulo permutation */ bool operator<(const UGGridBoundarySegment<3>& other) const { UGGridBoundarySegment<3> sorted1 = (*this); UGGridBoundarySegment<3> sorted2 = other; if (numVertices()other.numVertices()) return false; // //////////////////////////////////////////////////////////////////////////// // Sort the two arrays to get rid of cyclic permutations and mirror symmetry // //////////////////////////////////////////////////////////////////////////// // bubble sort: sort and compare together until the first nonmatching digits are found for (int i=numVertices()-1; i>=0; i--) { for (int j=0; j sorted1[j+1]) std::swap(sorted1[j], sorted1[j+1]); if (sorted2[j] > sorted2[j+1]) std::swap(sorted2[j], sorted2[j+1]); } // if (sorted1[i]sorted2[i]) return false; } // The sorted arrays are identical return false; } }; //! Output operator for array inline std::ostream& operator<< (std::ostream& s, const UGGridBoundarySegment<2>& v) { return s << "[" << v[0] << ", " << v[1] << "]"; } inline std::ostream& operator<< (std::ostream& s, const UGGridBoundarySegment<3>& v) { s << "[" << v[0] << ", " << v[1] << ", " << v[2]; if (v[3]!=-1) // quadrilateral s << ", " << v[3]; return s << "]"; } /** \brief Extracts the boundary faces and nodes from a set grid given as a set of elements */ class BoundaryExtractor { typedef std::set >::iterator SetIterator2d; typedef std::set >::iterator SetIterator3d; public: static void detectBoundarySegments(const std::vector& elementTypes, const std::vector& elementVertices, std::set >& boundarySegments); static void detectBoundarySegments(const std::vector& elementTypes, const std::vector& elementVertices, std::set >& boundarySegments); template static int detectBoundaryNodes(const std::set >& boundarySegments, int noOfNodes, std::vector& isBoundaryNode); }; } #endif dune-grid-2.11.0/dune/grid/uggrid/ug_undefs.hh000066400000000000000000000541751511655130300211260ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \brief Contains #undefs for all preprocessor macros * defined by UG. * * This file is created automatically by the perl script undefAllMacros.pl. */ #undef ADDPATTERN #undef ADDPATTERN_LEN #undef ADDPATTERN_SHIFT #undef __ALGEBRA__ #undef __ANISOTROPIC__ #undef AREA_OF_ELEMENT #undef AREA_OF_ELEMENT_2D #undef AREA_OF_ELEMENT_3D #undef AREA_OF_ELEMENT_BND #undef AREA_OF_HEXAHEDRON #undef AREA_OF_PRISM #undef AREA_OF_PYRAMID #undef AREA_OF_QUADRILATERAL #undef AREA_OF_REF #undef AREA_OF_REF_2D #undef AREA_OF_REF_BND #undef AREA_OF_TETRAHEDRON #undef AREA_OF_TRIANGLE #undef ASSERT #undef ATTR #undef ATTR_TO_GLEVEL #undef AUXEDGE #undef AUXEDGE_LEN #undef AUXEDGE_SHIFT #undef BHM_OK #undef BITWISE_TYPE #undef BLOCK_NOT_DEFINED #undef BND_SIZE_TAG #undef Broadcast #undef BVPD_CONFIG #undef BVPD_CONVEX #undef BVPD_MIDPOINT #undef BVPD_NAME #undef BVPD_NCOEFFF #undef BVPD_NPARTS #undef BVPD_NSUBDOM #undef BVPD_NUSERF #undef BVPD_RADIUS #undef BVPD_S2P #undef BVPD_S2P_PTR #undef CANNOT_INIT_PROBLEM #undef CAT #undef CAT3 #undef CE_FREE #undef CE_INIT #undef CE_INIT_UNUSED #undef CE_LOCKED #undef CENTERNODE #undef CENTER_NODE_INDEX #undef CENTER_NODE_INDEX_TAG #undef CENTERTYPE #undef CE_USED #undef CEXTRA #undef CEXTRA_LEN #undef CEXTRA_SHIFT #undef C_FRONTEND #undef CHECK #undef CLASS_OF_RULE #undef CLEAR_FLAG #undef CMATRIX0 #undef CMATRIX1 #undef COARSEN #undef COARSEN_LEN #undef COARSEN_SHIFT #undef CONCAT #undef CONCAT_AUX #undef CONTEXT #undef ControlWord #undef COOBJ #undef COORDINATE_TO_KEY #undef COPY_SC_TO_SH #undef CORNER #undef CORNER_COORDINATES #undef CORNER_COORDINATES_HEXAHEDRON #undef CORNER_COORDINATES_PRISM #undef CORNER_COORDINATES_PYRAMID #undef CORNER_COORDINATES_QUADRILATERAL #undef CORNER_COORDINATES_TETRAHEDRON #undef CORNER_COORDINATES_TRIANGLE #undef CORNER_OF_EDGE #undef CORNER_OF_EDGE_PTR #undef CORNER_OF_EDGE_REF #undef CORNER_OF_EDGE_TAG #undef CORNER_OF_OPPEDGE #undef CORNER_OF_OPPEDGE_REF #undef CORNER_OF_OPPEDGE_TAG #undef CORNER_OF_SIDE #undef CORNER_OF_SIDE_INV #undef CORNER_OF_SIDE_INV_REF #undef CORNER_OF_SIDE_INV_TAG #undef CORNER_OF_SIDE_PTR #undef CORNER_OF_SIDE_REF #undef CORNER_OF_SIDE_TAG #undef CORNER_OPP_TO_SIDE #undef CORNER_OPP_TO_SIDE_REF #undef CORNER_OPP_TO_SIDE_TAG #undef CORNERS_OF_BND_SEG #undef CORNERS_OF_EDGE #undef CORNERS_OF_ELEM #undef CORNERS_OF_REF #undef CORNERS_OF_SIDE #undef CORNERS_OF_SIDE_REF #undef CORNERS_OF_SIDE_TAG #undef CORNERS_OF_TAG #undef CORNERTYPE #undef COUNTELEMENT #undef COUNTNODE #undef COUNTVECTOR #undef COUNTVERTEX #undef CP_EUKLIDNORM #undef CP_LIMCOMB #undef CPP_FRONTEND #undef CP_SCALARPRODUCT #undef CP_SUBTRACT #undef CTRL #undef CTRL2 #undef CURRENTLEVEL #undef CVECT #undef __CW__ #undef CW_FREE #undef CW_INIT #undef CW_INIT_UNUSED #undef CW_READ #undef CW_READ_STATIC #undef CW_USED #undef CW_WRITE #undef CW_WRITE_STATIC #undef __DDD__ #undef DDD_ATTR_NULL #undef DDD_DOMAIN_DATA #undef DDD_EXTRA_DATA #undef DDD_GID_TO_INT #undef DDD_IdentifyBegin #undef DDD_IdentifyEnd #undef DDD_IdentifyNumber #undef DDD_IFAOneway #undef DDD_InfoAttr #undef DDD_InfoGlobalId #undef DDD_InfoPriority #undef DDD_InfoType #undef DDD_OBJ #undef DDD_PRIO_ENV #undef DDD_PRIO_NULL #undef DDD_PrioritySet #undef DDD_PROC_NULL #undef DDDTYPE #undef DDD_TYPE_BY_HANDLER #undef DDD_TYPE_NULL #undef DDD_VERSION #undef __DEBUG__ #undef _DEBUG_CW_ #undef DEBUG_MODE #undef DEBUG_TIME #undef DEBUG_TIME_MAX #undef DEC_NO_OF_ELEM #undef DECNOOFNODE #undef DECOUPLED #undef DECOUPLED_LEN #undef DECOUPLED_SHIFT #undef DEL_VECTOR #undef DIAGMATRIXTYPE #undef DIM #undef DIMENSION_H #undef DIM_OF_BND #undef DIRSEP #undef DMTP #undef __DOMAIN__ #undef DOM_EVAL_SD_UNKNOWN #undef DOM_LOC_X #undef DOM_LOC_Y #undef DOM_PARAM_OFFSET #undef DOWNGRID #undef EATTR #undef EBUILDCON #undef EBUILDCON_LEN #undef EBUILDCON_SHIFT #undef ECLASS #undef ECLASS_LEN #undef ECLASS_SHIFT #undef EDATA #undef EDDATA #undef EDGENEW #undef EDGENEW_LEN #undef EDGENEW_SHIFT #undef EDGE_OF_CORNER #undef EDGE_OF_CORNER_REF #undef EDGE_OF_CORNER_TAG #undef EDGE_OFFSET #undef EDGE_OF_SIDE #undef EDGE_OF_SIDE_REF #undef EDGE_OF_SIDE_TAG #undef EDGE_OF_TWO_SIDES #undef EDGE_OF_TWO_SIDES_REF #undef EDGE_OF_TWO_SIDES_TAG #undef EDGE_ON_BND #undef EDGES_OF_CORNER #undef EDGES_OF_CORNER_REF #undef EDGES_OF_CORNER_TAG #undef EDGES_OF_ELEM #undef EDGES_OF_REF #undef EDGES_OF_SIDE #undef EDGES_OF_SIDE_REF #undef EDGES_OF_SIDE_TAG #undef EDGES_OF_TAG #undef EDGE_WITH_CORNERS #undef EDGE_WITH_CORNERS_REF #undef EDGE_WITH_CORNERS_TAG #undef EDID_FFMT #undef EDID_FFMTE #undef EDID_FFMTX #undef EDID_FMT #undef EDID_FMTE #undef EDID_FMTX #undef EDID_PRT #undef EDID_PRTE #undef EDID_PRTX #undef EDSUBDOM #undef EDSUBDOM_LEN #undef EDSUBDOM_SHIFT #undef EDVECTOR #undef EFATHER #undef EGHOST #undef EGHOSTPRIO #undef EGID #undef EHGHOST #undef EHGHOSTPRIO #undef EIDCNT #undef EID_FFMT #undef EID_FFMTE #undef EID_FFMTX #undef EID_FMT #undef EID_FMTE #undef EID_FMTX #undef EID_PRT #undef EID_PRTE #undef EID_PRTX #undef ELEM_BNDS #undef ELEMENTFMT #undef ELEMENT_OFFSET #undef ELEMENT_PTR #undef __ELEMENTS__ #undef EMASTER #undef EMASTERPRIO #undef ENCOPIES #undef ENDDEBUG #undef ENDPAR #undef END_UGDIM_NAMESPACE #undef END_UG_NAMESPACE #undef ENVDIR_DOWN #undef ENVITEM_DOWN #undef ENVITEM_LOCKED #undef ENVITEM_NAME #undef ENVITEM_TYPE #undef EPRIO #undef EPROCLIST #undef EPROCPRIO #undef ETA #undef EVECTOR #undef EVEN #undef EVGHOST #undef EVGHOSTPRIO #undef EVHGHOST #undef EVHGHOSTPRIO #undef __EVM__ #undef __EXCHANGE_CONNECTIONS__ #undef EX_MAT #undef FALSE #undef FATHER_SIDE_OFFSET #undef FINE_GRID_DOF #undef FINE_GRID_DOF_LEN #undef FINE_GRID_DOF_SHIFT #undef FIRSTELEMENT #undef FIRSTELEMSIDE #undef FIRSTNODE #undef FIRSTPART_OF_LIST #undef FIRSTVECTOR #undef FIRSTVERTEX #undef FLAG #undef FLAG_OFFSET #undef FMT_CONN_DEPTH_MAX #undef FMT_CONN_DEPTH_PTR #undef FMT_CONN_DEPTH_TP #undef FMT_MAX_PART #undef FMT_MAX_TYPE #undef FMT_N2T #undef FMT_NB_DEPTH #undef FMT_PO2T #undef FMT_SET_N2T #undef FMT_S_IMAT_TP #undef FMT_S_MATPTR #undef FMT_S_MAT_TP #undef FMT_S_VEC_TP #undef FMT_T2N #undef FMT_T2O #undef FMT_T2P #undef FMT_TYPE_IN_PART #undef FMT_TYPE_USES_OBJ #undef FMT_USES_OBJ #undef FMT_VTYPE_NAME #undef FORMAT #undef FROM_VTNAME #undef FULLREFINELEVEL #undef FULL_REFRULE #undef FULL_REFRULE_0_5 #undef FULL_REFRULE_1_3 #undef FULL_REFRULE_2_4 #undef GATTR #undef GBYTE #undef GENERAL_CW #undef GENERAL_OFFSET #undef GEN_MGUD #undef GEN_MGUD_ADR #undef GetAllSons #undef GETGID #undef GET_MATRIX #undef GetMemoryForObject #undef GetTmpMem #undef GFORMAT #undef GHOST #undef GHOSTPRIO #undef GID #undef GLEVEL #undef __GM__ #undef GREENCLASS #undef GRID_ATTR #undef GRID_OFFSET #undef GRID_ON_LEVEL #undef GRID_STATUS_OFFSET #undef GSTATUS #undef HAS_DDDHDR #undef HDR #undef HDRELEMENT #undef HDRNODE #undef HDRVECTOR #undef HDRVERTEX #undef HEAPFAULT #undef __HEAPS__ #undef HGHOST #undef HGHOSTPRIO #undef HiWrd #undef ID #undef IDENT_ONLY_NEW #undef ID_FFMT #undef ID_FFMTE #undef ID_FFMTX #undef ID_FMT #undef ID_FMTE #undef ID_FMTX #undef ID_PRT #undef ID_PRTE #undef ID_PRTX #undef IFDEBUG #undef INC_NO_OF_ELEM #undef INCNOOFNODE #undef INIT #undef __INITUG__ #undef INNER_BOUNDARY #undef INNER_SIDE #undef INNER_SIZE_TAG #undef INVERSE_TRANSFORMATION #undef IS_ENVDIR #undef ISNaN #undef IS_REFINED #undef KBYTE #undef KEEP_VECTOR #undef LASTELEMENT #undef LASTNODE #undef LASTPART_OF_LIST #undef LASTVECTOR #undef LASTVERTEX #undef LCVECT #undef LDATA #undef LEAFELEM #undef LELEM #undef LEVEL #undef LEVEL_LEN #undef LEVEL_SHIFT #undef LINK #undef LINK0 #undef LINK1 #undef LINK_OFFSET #undef LINKX #undef LIOBJ #undef LISTPART2PRIO #undef LISTPART_FIRSTELEMENT #undef LISTPART_FIRSTNODE #undef LISTPART_FIRSTVECTOR #undef LISTPART_FIRSTVERTEX #undef LISTPART_LASTELEMENT #undef LISTPART_LASTNODE #undef LISTPART_LASTVECTOR #undef LISTPART_LASTVERTEX #undef LOCAL_COORD_OF_ELEM #undef LOCAL_COORD_OF_REF #undef LOCAL_COORD_OF_TAG #undef LOCAL_TO_GLOBAL #undef LOCAL_TO_GLOBAL_2D #undef LOCAL_TO_GLOBAL_3D #undef LOCAL_TO_GLOBAL_BND #undef LOCAL_TO_GLOBAL_HEXAHEDRON #undef LOCAL_TO_GLOBAL_PRISM #undef LOCAL_TO_GLOBAL_PYRAMID #undef LOCAL_TO_GLOBAL_QUADRILATERAL #undef LOCAL_TO_GLOBAL_TETRAHEDRON #undef LOCAL_TO_GLOBAL_TRIANGLE #undef LOFFSET #undef LOFFSET_LEN #undef LOFFSET_SHIFT #undef LoWrd #undef M2_DET #undef M2_INVERT #undef M2_TIMES_V2 #undef M3_DET #undef M3_INVERT #undef M3_TIMES_V3 #undef MACTIVE #undef MACTIVE_LEN #undef MACTIVE_SHIFT #undef MADJ #undef MAPPED_BND_OBJT_TAG #undef MAPPED_INNER_OBJT_TAG #undef MARK #undef MARK2PAT #undef MARK2PATTERN #undef MARK2RULE #undef MARK2RULEADR #undef MARKCLASS #undef MARKCLASS_LEN #undef MARKCLASS_SHIFT #undef MARKCOUNT #undef MARKED #undef MARK_LEN #undef MARK_OF_RULE #undef MARK_SHIFT #undef MARK_STACK_SIZE #undef MarkTmpMem #undef MASTER #undef MASTERPRIO #undef MATELEM #undef MATRIX_OFFSET #undef MATRIXTYPE #undef MAX #undef MAXCONNECTIONS #undef MAX_CONTROL_ENTRIES #undef MAX_CONTROL_WORDS #undef MAX_CORNERS_OF_EDGE #undef MAX_CORNERS_OF_ELEM #undef MAX_CORNERS_OF_ELEM_2D #undef MAX_CORNERS_OF_ELEM_3D #undef MAX_CORNERS_OF_ELEM_DIM #undef MAX_CORNERS_OF_SIDE #undef MAXDDDTYPES #undef MAXDOMPARTS #undef MAX_EDGES_OF_CORNER #undef MAX_EDGES_OF_ELEM #undef MAX_EDGES_OF_ELEM_2D #undef MAX_EDGES_OF_ELEM_3D #undef MAX_EDGES_OF_ELEM_DIM #undef MAX_EDGES_OF_SIDE #undef MAX_ELEM_VECTORS #undef MAXLEVEL #undef MAXMATRICES #undef MAXNBLOCKS #undef MAX_NDOF #undef MAX_NDOF_MOD_32 #undef MAX_NEW_CORNERS #undef MAX_NEW_CORNERS_2D #undef MAX_NEW_CORNERS_3D #undef MAX_NEW_CORNERS_DIM #undef MAX_NEW_EDGES #undef MAX_NEW_EDGES_2D #undef MAX_NEW_EDGES_3D #undef MAX_NEW_EDGES_DIM #undef MAXOBJECTS #undef MAX_PAR_DIST #undef MAX_PATH_DEPTH #undef MAX_REFINED_CORNERS_DIM #undef MAX_RULES #undef MAX_SIDE_NODES #undef MAX_SIDES_OF_EDGE #undef MAX_SIDES_OF_ELEM #undef MAX_SIDES_OF_ELEM_2D #undef MAX_SIDES_OF_ELEM_3D #undef MAX_SIDES_OF_ELEM_DIM #undef MAX_SIDES_TOUCHING #undef MAX_SON_EDGES #undef MAX_SONS_2D #undef MAX_SONS_3D #undef MAX_SONS_DIM #undef MAXVECTORS #undef MAXVOBJECTS #undef MAXVTNAMES #undef MBYTE #undef MD2_TIMES_V2 #undef MDEC #undef MDEST #undef MDESTINDEX #undef MDESTTYPE #undef MDESTTYPE_LEN #undef MDESTTYPE_SHIFT #undef MDIAG #undef MDIAG_LEN #undef MDIAG_SHIFT #undef M_DIM_INVERT #undef MDOWN #undef MDOWN_LEN #undef MDOWN_SHIFT #undef MGBNDSEGDESC #undef MG_BVP #undef MG_BVPD #undef MG_COARSE_FIXED #undef MG_FILENAME #undef MGFORMAT #undef MGHEAP #undef MG_MAGIC_COOKIE #undef MG_MARK_KEY #undef MGNAME #undef MGNOOFCORNERS #undef MG_NPROPERTY #undef MG_SAVED #undef MGSTATUS #undef MG_USER_HEAP #undef MGVERTEX #undef MIDNODE #undef MIDTYPE #undef MIN #undef MINC #undef MIN_HEAP_SIZE #undef __MISC__ #undef MLOWER #undef MLOWER_LEN #undef MLOWER_SHIFT #undef MM2_TIMES_V2 #undef MMYCON #undef MNEW #undef MNEW_LEN #undef MNEW_SHIFT #undef MNEXT #undef MODIFIED #undef MODIFIED_LEN #undef MODIFIED_SHIFT #undef MOFFSET #undef MOFFSET_LEN #undef MOFFSET_SHIFT #undef MOVE #undef MOVED #undef MOVED_LEN #undef MOVED_SHIFT #undef MOVE_LEN #undef MOVE_SHIFT #undef MROOT #undef MROOTTYPE #undef MROOTTYPE_LEN #undef MROOTTYPE_SHIFT #undef MSIZE_LEN #undef MSIZEMAX #undef MSIZE_SHIFT #undef MSTRONG #undef MT2_TIMES_V2 #undef MT3_TIMES_V3 #undef MTP #undef MT_TIMES_V_DIM #undef MTYPE #undef MULTIGRID_STATUS_OFFSET #undef MUP #undef MUP_LEN #undef MUPPER #undef MUPPER_LEN #undef MUPPER_SHIFT #undef MUP_SHIFT #undef MUSED #undef MVALUE #undef MVALUEPTR #undef MYEDGE #undef MYMG #undef MYVERTEX #undef NAMELENSTR #undef NBELEM #undef NBNODE #undef NC #undef NCLASS #undef NCLASS_LEN #undef NCLASS_SHIFT #undef NCOPIES #undef NDATA #undef NDATA_DEF_IN_MG #undef NE #undef NELIST_DEF_IN_MG #undef NEW_DEFECT #undef NEW_DEFECT_LEN #undef NEW_DEFECT_SHIFT #undef NEW_EDIDENT #undef NEW_EDIDENT_LEN #undef NEWEL #undef NEWEL_LEN #undef NEWEL_SHIFT #undef NEW_NIDENT #undef NEW_NIDENT_LEN #undef NEXT #undef NEXT_ENVITEM #undef NEXTSIDE #undef NEXTSIDEHEX #undef NEXTSIDEMASK #undef NEXTSIDEMASKHEX #undef NFATHER #undef NFATHEREDGE #undef NIDCNT #undef NIMAT #undef NN #undef NNCLASS #undef NNCLASS_LEN #undef NNCLASS_SHIFT #undef NN_PRIO #undef NO #undef NO_CENTER_NODE #undef NOCLASS #undef NODE_ELEMENT_LIST #undef NODEFMT #undef NO_DELETE_OVERLAP2 #undef NO_DELETE_OVERLAP2_LEN #undef NODE_OFFSET #undef NODE_OF_RULE #undef NODEORD #undef NODEORD_LEN #undef NODEORD_SHIFT #undef NO_MSGID #undef NO_OF_ELEM #undef NO_OF_ELEM_LEN #undef NO_OF_ELEM_MAX #undef NO_OF_ELEM_SHIFT #undef NOOFNODE #undef NOOFNODE_LEN #undef NOOFNODEMAX #undef NOOFNODE_SHIFT #undef NOTUSED #undef NOVTYPE #undef NPROP #undef NPROP_LEN #undef NPROP_SHIFT #undef NS #undef NS_DIM_PREFIX #undef NSONS #undef NSONS_LEN #undef NSONS_OF_RULE #undef NSONS_SHIFT #undef NS_PREFIX #undef NSUBDOM #undef NSUBDOM_LEN #undef NSUBDOM_SHIFT #undef NT #undef NT_PRIO #undef NTYPE #undef NTYPE_LEN #undef NTYPE_SHIFT #undef NU #undef NV #undef NVEC #undef NVEC_PRIO #undef NVECTOR #undef NV_PRIO #undef OBJ_LEN #undef OBJ_SHIFT #undef OBJT #undef OBJT_MAX #undef OFF #undef OFFSET_IN_MGUD #undef ON #undef ONEDGE #undef ONEDGE_LEN #undef ONEDGE_SHIFT #undef ONNBSIDE #undef ONNBSIDE_LEN #undef ONNBSIDE_SHIFT #undef ONSIDE #undef ONSIDE_LEN #undef ONSIDE_SHIFT #undef OPPOSITE_EDGE #undef OPPOSITE_EDGE_REF #undef OPPOSITE_EDGE_TAG #undef OUT_OF_RANGE #undef __OVERLAP2__ #undef PAR #undef __PARALLEL_H__ #undef __PARGM_H__ #undef PARHDR #undef PARHDRE #undef PARHDRV #undef PARTITION #undef PATHDEPTH #undef PATHDEPTHMASK #undef PATHDEPTHSHIFT #undef PAT_OF_RULE #undef PATTERN #undef PATTERN2MARK #undef PATTERN2RULE #undef PATTERN_LEN #undef PATTERN_OF_RULE #undef PATTERN_SHIFT #undef PFIRSTELEMENT #undef PFIRSTNODE #undef PFIRSTVECTOR #undef PFIRSTVERTEX #undef PFMT #undef PI #undef PLASTELEMENT #undef PLASTNODE #undef PLASTVECTOR #undef PLASTVERTEX #undef POW #undef POW2 #undef __PPIF__ #undef PPIF_FAILURE #undef PPIF_SUCCESS #undef PPREDVC #undef PREDE #undef PREDMAX #undef PREDN #undef PREDNEW0 #undef PREDNEW1 #undef PREDNEW2 #undef PREDV #undef PREDVC #undef PREV_ENVITEM #undef PrintDebug #undef PRINTDEBUG #undef PRINTDEBUG_EXT #undef PRINT_LIST #undef PRIO #undef PRIO2INDEX #undef PRIO2LISTPART #undef PRIOCOUNTELEMENT #undef PRIOCOUNTNODE #undef PRIOCOUNTVECTOR #undef PRIOCOUNTVERTEX #undef PRIO_FIRSTELEMENT #undef PRIO_FIRSTNODE #undef PRIO_FIRSTVECTOR #undef PRIO_FIRSTVERTEX #undef PRIO_LASTELEMENT #undef PRIO_LASTNODE #undef PRIO_LASTVECTOR #undef PRIO_LASTVERTEX #undef PROCLIST #undef PROCPRIO #undef PROP #undef PROPERTY_OFFSET #undef PROP_LEN #undef PROP_SHIFT #undef PutFreeObject #undef READ_FLAG #undef REAL #undef REDCLASS #undef REF2TAG #undef REFINE #undef __REFINE__ #undef REFINECLASS #undef REFINECLASS_LEN #undef REFINECLASS_SHIFT #undef REFINE_ELEMENT_LIST #undef REFINE_GRID_LIST #undef REFINEINFO #undef REFINE_LEN #undef REFINE_MULTIGRID_LIST #undef REFINE_SHIFT #undef REFINESTEP #undef ReleaseTmpMem #undef REP_ERR_ENCOUNTERED #undef REP_ERR_INC #undef REP_ERR_MAX #undef REP_ERR_RESET #undef REP_ERR_RETURN #undef REP_ERR_RETURN_PTR #undef RESETGSTATUS #undef RESETMGSTATUS #undef RETURN #undef REVERSE #undef RINFO_MAX #undef ROOT_DIR #undef RULE2MARK #undef RULE2PAT #undef RULE2PATTERN #undef __RULEMANAGER__ #undef SETADDPATTERN #undef SETAUXEDGE #undef SET_BNDS #undef SET_CENTERNODE #undef SETCEXTRA #undef SETCOARSEN #undef SET_CORNER #undef SETCUSED #undef SETDECOUPLED #undef SETEBUILDCON #undef SETECLASS #undef SETEDGENEW #undef SETEDSUBDOM #undef SET_EFATHER #undef SETEPRIO #undef SETEPRIOX #undef SET_EVECTOR #undef SETFINE_GRID_DOF #undef SET_FLAG #undef SETGLOBALGSTATUS #undef SetHiWrd #undef SET_LELEM #undef SETLEVEL #undef SETLOFFSET #undef SetLoWrd #undef SETMACTIVE #undef SETMARK #undef SETMARKCLASS #undef SETMARKCOUNT #undef SETMDESTTYPE #undef SETMDIAG #undef SETMDOWN #undef SETMLOWER #undef SETMNEW #undef SETMODIFIED #undef SETMOFFSET #undef SETMOVE #undef SETMOVED #undef SETMROOTTYPE #undef SETMSIZE #undef SETMUP #undef SETMUPPER #undef SETMUSED #undef SET_NBELEM #undef SETNCLASS #undef SETNEW_DEFECT #undef SETNEW_EDIDENT #undef SETNEWEL #undef SETNEW_NIDENT #undef SETNEXTSIDE #undef SETNFATHER #undef SETNFATHEREDGE #undef SETNNCLASS #undef SETNO_DELETE_OVERLAP2 #undef SETNODEORD #undef SET_NO_OF_ELEM #undef SETNOOFNODE #undef SETNPROP #undef SETNSONS #undef SETNSUBDOM #undef SETNTYPE #undef SETOBJT #undef SETONEDGE #undef SETONNBSIDE #undef SETONSIDE #undef SETPATHDEPTH #undef SETPATTERN #undef SETPREDMAX #undef SETPREDNEW0 #undef SETPREDNEW1 #undef SETPREDNEW2 #undef SETPRIO #undef SETPRIOX #undef SETPROP #undef SETREAL #undef SETREFINE #undef SETREFINECLASS #undef SETREFINESTEP #undef SETSIDEPATTERN #undef SET_SON #undef SETSUBDOMAIN #undef SET_SVECTOR #undef SETTAG #undef SETTHEFLAG #undef SETUPDATE_GREEN #undef SETUSED #undef SETVACTIVE #undef SETVBUILDCON #undef SETVCCOARSE #undef SETVCCUT #undef SETVCFLAG #undef SETVCLASS #undef SETVCOUNT #undef SETVCUSED #undef SETVDATATYPE #undef SETVDOWN #undef SETVECTORSIDE #undef SETVNCLASS #undef SETVNEW #undef SETVOTYPE #undef SETVPART #undef SETVTYPE #undef SETVUP #undef SETVXPRIO #undef SETVXPRIOX #undef SETXFERMATX #undef SETXFERVECTOR #undef SFIRSTNODE #undef SFIRSTVECTOR #undef SFIRSTVERTEX #undef __SHAPES__ #undef SIDE_ON_BND #undef SIDE_OPP_TO_CORNER #undef SIDE_OPP_TO_CORNER_REF #undef SIDE_OPP_TO_CORNER_TAG #undef SIDEPATTERN #undef SIDEPATTERN_LEN #undef SIDEPATTERN_SHIFT #undef SIDES_OF_ELEM #undef SIDES_OF_REF #undef SIDES_OF_TAG #undef SIDETYPE #undef SIDE_WITH_EDGE #undef SIDE_WITH_EDGE_REF #undef SIDE_WITH_EDGE_TAG #undef SIGNIFICANT_DIGITS #undef SIZE_UNKNOWN #undef SON #undef SON_CORNER #undef SON_CORNER_OF_RULE #undef SON_NB #undef SON_NB_OF_RULE #undef SONNODE #undef SONNODE_OF_NODE_OF_RULE #undef SON_OF_NODE_OF_RULE #undef SON_OF_RULE #undef SON_PATH #undef SON_PATH_OF_RULE #undef SONS_OF_ELEM #undef SONS_OF_TAG #undef SON_TAG #undef SON_TAG_OF_RULE #undef SQRT #undef START #undef START_UGDIM_NAMESPACE #undef START_UG_NAMESPACE #undef StaticControlWord #undef StaticControlWordMask #undef STAT_OUT #undef __STD_DOMAIN__ #undef STR #undef SUBDOMAIN #undef SUBDOMAIN_LEN #undef SUBDOMAIN_SHIFT #undef SUCCE #undef SUCCN #undef SUCCV #undef SUCCVC #undef SVECTOR #undef SWAP #undef SWITCHCLASS #undef TAG #undef TAG_LEN #undef TAG_OF_RULE #undef TAGS #undef TAG_SHIFT #undef TET_COPY #undef TET_RED #undef TET_RED_0_5 #undef TET_RED_1_3 #undef TET_RED_2_4 #undef TET_RED_HEX #undef THEFLAG #undef THEFLAG_LEN #undef THEFLAG_SHIFT #undef __THREEDIM__ #undef TOPLEVEL #undef TOPNODE #undef TO_VTNAME #undef TRANSFORMATION #undef TRANSFORMATION_2D #undef TRANSFORMATION_3D #undef TRANSFORMATION_BND #undef TRANSFORMATION_OF_HEXAHEDRON #undef TRANSFORMATION_OF_PRISM #undef TRANSFORMATION_OF_PYRAMID #undef TRANSFORMATION_OF_QUADRILATERAL #undef TRANSFORMATION_OF_TETRAHEDRON #undef TRANSFORMATION_OF_TRIANGLE #undef TRUE #undef __TWODIM__ #undef __UGENV__ #undef UG_GlobalMaxDOUBLE #undef UG_GlobalMaxINT #undef UG_GlobalMaxNDOUBLE #undef UG_GlobalMaxNINT #undef UG_GlobalMinDOUBLE #undef UG_GlobalMinINT #undef UG_GlobalMinNDOUBLE #undef UG_GlobalMinNINT #undef UG_GlobalSumDOUBLE #undef UG_GlobalSumINT #undef UG_GlobalSumNDOUBLE #undef UG_GlobalSumNINT #undef __UGM__ #undef UG_MSIZE #undef UG_NAMESPACE_H #undef UGTYPE #undef UGTYPES_H #undef UNLINK #undef UPDATE_GREEN #undef UPDATE_GREEN_LEN #undef UPDATE_GREEN_SHIFT #undef UPGRID #undef USED #undef USED_LEN #undef USED_SHIFT #undef USING_UGDIM_NAMESPACE #undef USING_UG_NAMESPACE #undef USING_UG_NAMESPACES #undef V1_COPY #undef V2_ADD #undef V2_CLEAR #undef V2_COPY #undef V2_EUKLIDNORM #undef V2_EUKLIDNORM_OF_DIFF #undef V2_ISEQUAL #undef V2_LINCOMB #undef V2_SCALAR_PRODUCT #undef V2_SCALE #undef V2_SCAL_PROD #undef V2_SUBTRACT #undef V2_VECTOR_PRODUCT #undef V3_ADD #undef V3_CLEAR #undef V3_COPY #undef V3_EUKLIDNORM #undef V3_EUKLIDNORM_OF_DIFF #undef V3_ISEQUAL #undef V3_LINCOMB #undef V3_SCALAR_PRODUCT #undef V3_SCALE #undef V3_SCAL_PROD #undef V3_SUBTRACT #undef V3_VECTOR_PRODUCT #undef VACTIVE #undef VACTIVE_LEN #undef VACTIVE_SHIFT #undef V_BDIM_COPY #undef V_BNDP #undef VBUILDCON #undef VCCOARSE #undef VCCOARSE_LEN #undef VCCOARSE_SHIFT #undef VCCUT #undef VCCUT_LEN #undef VCCUT_SHIFT #undef VCFLAG #undef VCLASS #undef VCLASS_LEN #undef VCLASS_SHIFT #undef VCOUNT #undef VCOUNT_LEN #undef VCOUNT_SHIFT #undef VCUSED #undef VDATA #undef VDATATYPE #undef VDATATYPE_LEN #undef VDATATYPE_SHIFT #undef V_DIM_ADD #undef V_DIM_CLEAR #undef V_DIM_COPY #undef V_DIM_EUKLIDNORM #undef V_DIM_EUKLIDNORM_OF_DIFF #undef V_DIM_ISEQUAL #undef V_DIM_LINCOMB #undef V_DIM_SCALAR_PRODUCT #undef V_DIM_SCALE #undef V_DIM_SCAL_PROD #undef V_DIM_SUBTRACT #undef VDOWN #undef VEC_DEF_IN_OBJ_OF_GRID #undef VEC_DEF_IN_OBJ_OF_MG #undef VECTORFMT #undef VECTOR_OFFSET #undef VECTORSIDE #undef VECTORSIDE_LEN #undef VECTORSIDE_SHIFT #undef VERTEXFMT #undef VERTEX_OFFSET #undef VFATHER #undef VGHOST #undef VGHOSTPRIO #undef VGID #undef VHGHOST #undef VHGHOSTPRIO #undef VIDCNT #undef VID_FFMT #undef VID_FFMTE #undef VID_FFMTX #undef VID_FMT #undef VID_FMTE #undef VID_FMTX #undef VID_PRT #undef VID_PRTE #undef VID_PRTX #undef V_IN_DATATYPE #undef VINDEX #undef VINDEX_FFMT #undef VINDEX_FFMTE #undef VINDEX_FFMTX #undef VINDEX_FMT #undef VINDEX_FMTE #undef VINDEX_FMTX #undef VINDEX_PRT #undef VINDEX_PRTE #undef VINDEX_PRTX #undef VMYEDGE #undef VMYELEMENT #undef VMYNODE #undef VNCLASS #undef VNCLASS_LEN #undef VNCLASS_SHIFT #undef VNEW #undef VNEW_LEN #undef VNEW_SHIFT #undef VOBJECT #undef VOID_NBELEM #undef VOTYPE #undef VOTYPE_LEN #undef VOTYPE_SHIFT #undef VPART #undef VPART_LEN #undef VPART_SHIFT #undef VSTART #undef VTYPE #undef VTYPE_LEN #undef VTYPE_SHIFT #undef VUP #undef VVALUE #undef VVALUEPTR #undef VXATTR #undef VXGHOST #undef VXGID #undef VXHGHOST #undef VXMASTER #undef VXNCOPIES #undef VXPRIO #undef VXPROCLIST #undef VXPROCPRIO #undef VXVGHOST #undef VXVHGHOST #undef _X_ #undef XC #undef XCAT #undef XCAT3 #undef XFERCOPY #undef XFERCOPYX #undef XFERDELETE #undef XFERECOPY #undef XFERECOPYX #undef XFEREDELETE #undef XFERMATX #undef XFERMATX_LEN #undef XFERMATX_SHIFT #undef XFERVECTOR #undef XFERVECTOR_LEN #undef XFERVECTOR_SHIFT #undef XFERVXCOPY #undef XFERVXCOPYX #undef XFERVXDELETE #undef XI #undef XSTR #undef __XXL_MSIZE__ #undef _Y_ #undef YC #undef YELLOWCLASS #undef YES #undef _Z_ #undef ZC dune-grid-2.11.0/dune/grid/uggrid/uggrid.cc000066400000000000000000000516751511655130300204200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 /** \todo Remove the following two includes once getAllSubfaces... is gone */ #include #include #include #include namespace Dune { //*********************************************************************** // // --UGGrid // --Grid // //*********************************************************************** template<> int UGGrid<2>::numOfUGGrids = 0; template<> int UGGrid<3>::numOfUGGrids = 0; template UGGrid < dim >::UGGrid(UGCommunication comm) : multigrid_(nullptr), ccobj_(comm), leafIndexSet_(*this), idSet_(*this), refinementType_(LOCAL), closureType_(GREEN), someElementHasBeenMarkedForRefinement_(false), someElementHasBeenMarkedForCoarsening_(false), numBoundarySegments_(0) { // If no UGGrid object exists yet start up UG for 2d and 3d if ( (UGGrid<2>::numOfUGGrids+UGGrid<3>::numOfUGGrids)==0) { /* Why do we start UG for 2d and 3d? Why not just the one for the grid dimension * that we actually need? The reason is a certain error condition that you get * when using 2d and 3d UGGrids together. This was FlySpray task 887. * * UG has an internal directory-tree-like structure for storing different types of * miscellaneous data. It is called the 'environment heap'. The method InitUg * creates a directory 'BVP' there, which holds, among other things, a 'problem name' * (a string) for each existing grid. When you call InitUg twice (i.e., once for 2d * and once for 3d), the second call will not notice that a directory 'BVP' already exists. * This is possible because these directories have a name and a 'type', (an integer * of which I have not really understood what you need it for), and the new 'BVP' directory * has a different type. The new one will appear in the list before the old one. * However, some methods that look for entries in the environment heap only look for the name, * and hence only find the first 'BVP' entry, which only contains the information about * the second grid. Surprisingly, this doesn't appear to be a problem, at least the dune-grid * unit test for UG successfully tests a 2d and a 3d grid side by side. However when trying * to delete grids the method DisposeMultiGrid tries to remove a grid's information from the * BVP directory. However the information of the first grid is in the second BVP directory, * which is effectively hidden by the first one. DisposeMultiGrid doesn't find the * grid information and reports an error. * * If both calls to InitUg are directly in a row, then all information will be stored * in the first instance of 'BVP', and there is no error. */ int argc = 1; char* arg = strdup("dune.exe"); char** argv = &arg; if (UG_NS<2>::InitUg(&argc, &argv)) DUNE_THROW(GridError, "UG" << dim << "d::InitUg() returned an error code!"); if (UG_NS<3>::InitUg(&argc, &argv)) DUNE_THROW(GridError, "UG" << dim << "d::InitUg() returned an error code!"); free(arg); } // Create unique problem name std::stringstream numberAsAscii; numberAsAscii << numOfUGGrids; name_ = "DuneUGGrid_" + std::string((dim==2) ? "2" : "3") + std::string("d_") + numberAsAscii.str(); std::string problemName = name_ + "_Problem"; bvp_ = new typename UG_NS::STD_BVP; numOfUGGrids++; dverb << "UGGrid<" << dim << "> with name " << name_ << " created!" << std::endl; } template < int dim > UGGrid < dim >::~UGGrid() noexcept(false) { // Delete the UG multigrid if there is one (== createEnd() has been called) // DisposeMultiGrid cleans up the BVP as well. if (multigrid_) { // Set UG's currBVP variable to the BVP corresponding to this // grid. This is necessary if we have more than one UGGrid in use. // DisposeMultiGrid will crash if we don't do this UG_NS::Set_Current_BVP(multigrid_->theBVP); if (UG_NS::DisposeMultiGrid(multigrid_) != 0) DUNE_THROW(GridError, "UG" << dim << "d::DisposeMultiGrid returned error code!"); } numOfUGGrids--; // Shut down UG if this was the last existing UGGrid object. // Since we started both 2d and 3d versions of UG even if we don't need both, // we have to shut them down both, too. if (UGGrid<2>::numOfUGGrids + UGGrid<3>::numOfUGGrids == 0) { UG_NS<2>::ExitUg(); UG_NS<3>::ExitUg(); } } template < int dim > int UGGrid < dim >::maxLevel() const { if (!multigrid_) DUNE_THROW(GridError, "The grid has not been properly initialized!"); return multigrid_->topLevel; } template < int dim > int UGGrid < dim >::size (int level, int codim) const { return levelIndexSet(level).size(codim); } template < int dim > bool UGGrid < dim >::mark(int refCount, const typename Traits::template Codim<0>::Entity& e ) { typename UG_NS::Element* target = e.impl().target_; // No refinement requested if (refCount==0) { if (UG_NS::MarkForRefinement(target, UG_NS::NO_REFINEMENT, // unset 0) // Irrelevant if refinement rule is not BLUE ) DUNE_THROW(GridError, "UG" << dim << "d::MarkForRefinement returned error code!"); return true; } // Check whether element can be marked for refinement if (!EstimateHere(target)) return false; if (refCount==1) { if (UG_NS::MarkForRefinement(target, UG_NS::RED, // red refinement rule 0) // Irrelevant if refinement rule is not BLUE ) DUNE_THROW(GridError, "UG" << dim << "d::MarkForRefinement returned error code!"); someElementHasBeenMarkedForRefinement_ = true; return true; } else if (refCount==-1) { if (UG_NS::MarkForRefinement(target, UG_NS::COARSE, // coarsen the element 0) // Irrelevant if refinement rule is not BLUE ) DUNE_THROW(GridError, "UG" << dim << "d::MarkForRefinement returned error code!"); someElementHasBeenMarkedForCoarsening_ = true; return true; } else DUNE_THROW(GridError, "UGGrid only supports refCount values -1, 0, and 1 for mark()!"); } template < int dim > bool UGGrid < dim >::mark(const typename Traits::template Codim<0>::Entity& e, typename UG_NS::RefinementRule rule, int side) { typename UG_NS::Element* target = e.impl().target_; if (!UG_NS::isLeaf(target)) return false; someElementHasBeenMarkedForRefinement_ = true; return UG_NS::MarkForRefinement(target, rule, side); } template int UGGrid::getMark(const typename Traits::template Codim<0>::Entity& e) const { typename UG_NS::Element* target = e.impl().target_; // Return -1 if element is marked for coarsening if (UG_NS::ReadCW(target,UG_NS::COARSEN_CE)) return -1; // If the element is not regular, it's mark is actually stored on its regular target = ELEMENT_TO_MARK(target); // Return 0 if element is not marked at all if (UG_NS::ReadCW(target,UG_NS::MARK_CE)==UG_NS::NO_REFINEMENT) return 0; // Else return 1 return 1; } template bool UGGrid ::preAdapt() { if( closureType_ == GREEN ) { // when conforming refinement is enabled // green closure has to be removed although not // marked for coarsening return someElementHasBeenMarkedForCoarsening_ || someElementHasBeenMarkedForRefinement_ ; } else { // in non-conforming meshes only elements marked for coarsening // will be coarsened (hopefully) return someElementHasBeenMarkedForCoarsening_; } } template < int dim > bool UGGrid < dim >::adapt() { assert(multigrid_); // Set UG's currBVP variable to the BVP corresponding to this // grid. This is necessary if we have more than one UGGrid in use. UG_NS::Set_Current_BVP(multigrid_->theBVP); int mode = UG_NS::GM_REFINE_TRULY_LOCAL; if (refinementType_==COPY) mode = mode | UG_NS::GM_COPY_ALL; if (closureType_==NONE) mode = mode | UG_NS::GM_REFINE_NOT_CLOSED; // I don't really know what this means int seq = UG_NS::GM_REFINE_PARALLEL; // Skip test whether we have enough memory available int mgtest = UG_NS::GM_REFINE_NOHEAPTEST; int rv = AdaptMultiGrid(multigrid_,mode,seq,mgtest); if (rv!=0) DUNE_THROW(GridError, "UG::adapt() returned with error code " << rv); // Renumber everything setIndices(false, nullptr); // Return true iff the grid hierarchy changed //return !(bool)multigrid_->status; // grid has changed if at least one element was marked for refinement return someElementHasBeenMarkedForRefinement_; } template void UGGrid ::postAdapt() { for (int i=0; i<=maxLevel(); i++) for (const auto& element : elements(this->levelGridView(i))) UG_NS::WriteCW(element.impl().target_, UG_NS::NEWEL_CE, 0); // reset marker flags someElementHasBeenMarkedForRefinement_ = false; someElementHasBeenMarkedForCoarsening_ = false; } template < int dim > void UGGrid < dim >::globalRefine(int n) { for (int i=0; ileafGridView())) mark(1, element); this->preAdapt(); adapt(); } this->postAdapt(); } template void UGGrid::getChildrenOfSubface(const typename Traits::template Codim<0>::Entity & e, int elementSide, int maxl, std::vector::Entity>& childElements, std::vector& childElementSides) const { typedef std::pair::Element*,int> ListEntryType; std::list list; // ////////////////////////////////////////////////////////////////////// // Change the input face number from Dune numbering to UG numbering // ////////////////////////////////////////////////////////////////////// elementSide = UGGridRenumberer::facesDUNEtoUG(elementSide, e.type()); // /////////////// // init list // /////////////// if (!e.isLeaf() // Get_Sons_of_ElementSide returns GM_FATAL when called for a leaf !?! && e.level() < maxl) { typename UG_NS::Element* theElement = e.impl().target_; list.emplace_back(theElement, elementSide); } // ////////////////////////////////////////////////// // Traverse and collect all children of the side // ////////////////////////////////////////////////// for (const auto& f : list) { typename UG_NS::Element* theElement = f.first; int side = f.second; UG::INT Sons_of_Side = 0; typename UG_NS::Element* SonList[UG_NS::MAX_SONS]; UG::INT SonSides[UG_NS::MAX_SONS]; if (UG_NS::myLevel(theElement) < maxl) { int rv = Get_Sons_of_ElementSide(theElement, side, // Input element side number &Sons_of_Side, // Number of topological sons of the element side SonList, // Output elements SonSides, // Output element side numbers true, true); if (rv != 0) DUNE_THROW(GridError, "Get_Sons_of_ElementSide returned with error value " << rv); for (int i=0; i::Entity Entity; childElements.push_back( Entity( UGGridEntity< 0, dim, const UGGrid< dim > >( f.first, this ) ) ); int side = f.second; // Dune numbers the faces of several elements differently than UG. // The following switch does the transformation childElementSides[i] = UGGridRenumberer::facesUGtoDUNE(side, childElements[i].type()); ++i; } } template < int dim > bool UGGrid < dim >::loadBalance(int minlevel) { // Do nothing if we are on a single process if (comm().size()==1) return true; std::stringstream levelarg; levelarg << minlevel; UG_NS::lbs(levelarg.str().c_str(), multigrid_); // Renumber everything. // Note: this must not be called when on a single process, because it renumbers the zero-level // elements and vertices. setIndices(true, nullptr); return true; } template < int dim > bool UGGrid < dim >::loadBalance(const std::vector& targetProcessors, unsigned int fromLevel) { // Do nothing if we are on a single process if (comm().size()==1) return true; #ifdef ModelP // The Partition field only exists if ModelP is set if (int(targetProcessors.size()) != this->leafGridView().size(0)) DUNE_THROW(Exception, "targetProcessors argument does not have the correct size"); // Get unique consecutive index across different element types typedef MultipleCodimMultipleGeomTypeMapper ElementMapper; ElementMapper elementMapper(this->leafGridView(), mcmgElementLayout()); // Loop over all elements of all level, in decreasing level number. // If the element is a leaf, take its target rank from the input targetProcessors array. // If it is not, assign it to the processor most of its children are assigned to. for (int i=maxLevel(); i>=0; i--) { for (const auto& element : elements(this->levelGridView(i), Partitions::interior)) { if (element.isLeaf()) { int targetRank = targetProcessors[elementMapper.index(element)]; // sanity check if (targetRank >= comm().size()) DUNE_THROW(GridError, "Requesting target processor " << targetRank << ", but only " << comm().size() << " processors are available."); UG_NS::Partition(element.impl().target_) = targetRank; } else { std::map rank; Rank mostFrequentRank = 0; // which rank occurred most often? unsigned int mostFrequentCount = 0; // how often did it occur? // Loop over all children and collect the ranks they are assigned to for (const auto& child : descendantElements(element, element.level() + 1)) { auto childRank = UG_NS::Partition(child.impl().target_); if (rank.find(childRank) == rank.end()) rank[childRank] = 1; else rank[childRank]++; if (rank[childRank] > mostFrequentCount) { mostFrequentRank = childRank; mostFrequentCount = rank[childRank]; } } // Assign rank that occurred most often UG_NS::Partition(element.impl().target_) = mostFrequentRank; } } } #endif int errCode = UG_NS::TransferGridFromLevel(multigrid_, fromLevel); if (errCode) DUNE_THROW(GridError, "UG" << dim << "d::TransferGridFromLevel returned error code " << errCode); // Renumber everything. // Note: this must not be called when on a single process, because it renumbers the zero-level // elements and vertices. setIndices(true, nullptr); return true; } #ifdef ModelP template std::vector::DDD_IF> UGGrid::findDDDInterfaces(InterfaceType iftype, int codim) const { std::vector::DDD_IF> dddIfaces; // UGGrid does not have overlap or front entities if (iftype == Overlap_OverlapFront_Interface || iftype == Overlap_All_Interface) return dddIfaces; if (codim == 0) { switch (iftype) { case InteriorBorder_InteriorBorder_Interface : // do not communicate anything: Elements cannot be in // the interior of two processes at the same time break; case InteriorBorder_All_Interface : dddIfaces.push_back(UG_NS::ElementVHIF(multigrid_->dddContext())); break; case All_All_Interface : dddIfaces.push_back(UG_NS::ElementSymmVHIF(multigrid_->dddContext())); break; default : DUNE_THROW(GridError, "Element communication not supported for " "interfaces of type " << iftype); } } else if (codim == dim) { switch (iftype) { case InteriorBorder_InteriorBorder_Interface : dddIfaces.push_back(UG_NS::BorderNodeSymmIF(multigrid_->dddContext())); break; case InteriorBorder_All_Interface : dddIfaces.push_back(UG_NS::NodeInteriorBorderAllIF(multigrid_->dddContext())); break; case All_All_Interface : dddIfaces.push_back(UG_NS::NodeAllIF(multigrid_->dddContext())); break; default : DUNE_THROW(GridError, "Node communication not supported for " "interfaces of type " << iftype); } } else if (codim == dim-1) { switch (iftype) { case InteriorBorder_InteriorBorder_Interface : dddIfaces.push_back(UG_NS::BorderEdgeSymmIF(multigrid_->dddContext())); break; case InteriorBorder_All_Interface : dddIfaces.push_back(UG_NS::EdgeVHIF(multigrid_->dddContext())); break; case All_All_Interface : dddIfaces.push_back(UG_NS::EdgeSymmVHIF(multigrid_->dddContext())); break; default : DUNE_THROW(GridError, "Edge communication not supported for " "interfaces of type " << iftype); } } else if (codim == 1) { switch (iftype) { case InteriorBorder_InteriorBorder_Interface : dddIfaces.push_back(UG_NS::BorderVectorSymmIF(multigrid_->dddContext())); break; case InteriorBorder_All_Interface : dddIfaces.push_back(UG_NS::FacetInteriorBorderAllIF(multigrid_->dddContext())); break; case All_All_Interface : dddIfaces.push_back(UG_NS::FacetAllAllIF(multigrid_->dddContext())); break; default : DUNE_THROW(GridError, "Face communication not supported for " "interfaces of type " << iftype); } } else { DUNE_THROW(GridError, "Communication codimension must be between 0 and " << dim << "!"); } return dddIfaces; } #endif // ModelP template < int dim > void UGGrid < dim >::setPosition(const typename Traits::template Codim::Entity& e, const FieldVector& pos) { typename UG_NS::Node* target = e.impl().target_; for (int i=0; imyvertex->iv.x[i] = pos[i]; } template void UGGrid::saveState(const std::string& filename) const { DUNE_THROW(NotImplemented, "Writing complete UGGrid hierarchies is not implemented yet."); } template void UGGrid::loadState(const std::string& filename) { DUNE_THROW(NotImplemented, "Loading complete UGGrid hierarchies is not implemented yet."); } template < int dim > void UGGrid < dim >::setIndices(bool setLevelZero, std::vector* nodePermutation) { // Create new level index sets if necessary for (int i=levelIndexSets_.size(); i<=maxLevel(); i++) levelIndexSets_.push_back(std::make_shared > >()); // Update the zero level LevelIndexSet. It is updated only once, at the time // of creation of the coarse grid. After that it is not touched anymore. if (setLevelZero) levelIndexSets_[0]->update(*this, 0, nodePermutation); // Update the remaining level index sets for (int i=1; i<=maxLevel(); i++) if (levelIndexSets_[i]) levelIndexSets_[i]->update(*this, i); leafIndexSet_.update(nodePermutation); // id sets don't need updating } // ///////////////////////////////////////////////////////////////////////////////// // Explicit instantiation of the dimensions that are actually supported by UG. // g++-4.0 wants them to be _after_ the method implementations. // ///////////////////////////////////////////////////////////////////////////////// template class UGGrid<2>; template class UGGrid<3>; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridentity.cc000066400000000000000000000336631511655130300216520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include namespace Dune { //************************************************************************* // // --UGGridEntity // --Entity // //************************************************************************* // // codim > 0 // //********************************************************************* template< int codim, int dim, class GridImp> GeometryType UGGridEntity::type() const { static_assert(codim!=0, "The code for codim==0 is in the corresponding class specialization"); // Vertex if (dim-codim == 0) return GeometryTypes::vertex; // Edge if (dim-codim == 1) return GeometryTypes::line; if constexpr (codim==1 && dim==3) { // retrieve an element that this facet is a side of, and retrieve the side number typename UG_NS::Element* center; unsigned int side; UG_NS::GetElementAndSideFromSideVector(target_, center, side); switch (UG_NS::Tag(center)) { case UG::D3::TETRAHEDRON : return GeometryTypes::triangle; case UG::D3::PYRAMID : return (side==0 ? GeometryTypes::quadrilateral : GeometryTypes::triangle); case UG::D3::PRISM : return (side==0 or side==4 ? GeometryTypes::triangle : GeometryTypes::quadrilateral); case UG::D3::HEXAHEDRON : return GeometryTypes::quadrilateral; default : DUNE_THROW(GridError, "UGGridEntity::type(): Unknown type " << UG_NS::Tag(center) << " found!"); } } // The remaining cases are handled in specializations } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Specializations for codim == 0 // //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// template< int dim, class GridImp> bool UGGridEntity < 0, dim ,GridImp >::isNew () const { return UG_NS::ReadCW(target_, UG_NS::NEWEL_CE); } template< int dim, class GridImp> bool UGGridEntity < 0, dim ,GridImp >::mightVanish () const { if ((!isRegular()) || (UG_NS::ReadCW(target_, UG_NS::COARSEN_CE))) return true; // maybe it isn't marked, but a sibling is if(hasFather()) { typename UG_NS::Element* father_ = UG_NS::EFather(target_); typename UG_NS::Element* sons_[UG_NS::MAX_SONS]; UG_NS::GetSons(father_,sons_); for (int i = 0; i < UG_NS::MAX_SONS; ++i) { if (sons_[i] == nullptr) // last son visited break; if (!UG_NS::isRegular(sons_[i]) || UG_NS::ReadCW(sons_[i], UG_NS::COARSEN_CE)) return true; } } // neither the element nor a sibling is marked return false; } template template typename GridImp::template Codim::Entity UGGridEntity<0,dim,GridImp>::subEntity ( int i ) const { assert(i>=0 && i < int(subEntities(cc))); typename UG_NS::template Entity::T* subEntity; if (cc==dim) subEntity = reinterpret_cast::template Entity::T*>( UG_NS::Corner(target_,UGGridRenumberer::verticesDUNEtoUG(i, this->type())) ); else if (cc==dim - 1) subEntity = reinterpret_cast::template Entity::T*>( UG_NS::ElementEdge(target_,UGGridRenumberer::edgesDUNEtoUG(i, this->type())) ); else if (cc==0) subEntity = reinterpret_cast::template Entity::T*>( target_ ); else if (dim==3 and cc==1) subEntity = reinterpret_cast::template Entity::T*>( UG_NS::SideVector(target_,UGGridRenumberer::facesDUNEtoUG(i, this->type())) ); else DUNE_THROW(GridError, "subEntity for nonexisting codimension requested!" ); return typename GridImp::template Codim::Entity(UGGridEntity((typename UG_NS::template Entity::T*)subEntity, gridImp_)); } template GeometryType UGGridEntity<0,dim,GridImp>::type() const { if (dim==2) { switch (UG_NS::Tag(target_)) { case UG::D2::TRIANGLE : return GeometryTypes::triangle; case UG::D2::QUADRILATERAL : return GeometryTypes::quadrilateral; default : DUNE_THROW(GridError, "UGGridGeometry::type(): ERROR: Unknown type " << UG_NS::Tag(target_) << " found!"); } } else { // dim==3 switch (UG_NS::Tag(target_)) { case UG::D3::TETRAHEDRON : return GeometryTypes::tetrahedron; case UG::D3::PYRAMID : return GeometryTypes::pyramid; case UG::D3::PRISM : return GeometryTypes::prism; case UG::D3::HEXAHEDRON : return GeometryTypes::hexahedron; default : DUNE_THROW(GridError, "UGGridGeometry::type(): ERROR: Unknown type " << UG_NS::Tag(target_) << " found!"); } } } template void UGGridEntity < 0, dim ,GridImp >:: setToTarget(typename UG_NS::Element* target, const GridImp* gridImp) { target_ = target; geo_.setToTarget(target); gridImp_ = gridImp; } template UGGridHierarchicIterator UGGridEntity < 0, dim ,GridImp >::hbegin(int maxlevel) const { UGGridHierarchicIterator it(maxlevel,gridImp_); if (level()::Element* sonList[UG_NS::MAX_SONS]; UG_NS::GetSons(target_, sonList); // Load sons of old target onto the iterator stack for (int i=0; i::nSons(target_); i++) it.elementStack_.push(sonList[i]); it.entity_.impl().setToTarget( it.elementStack_.empty() ? nullptr : it.elementStack_.top(), gridImp_ ); } else { it.entity_.impl().setToTarget(nullptr,nullptr); } return it; } template< int dim, class GridImp> UGGridHierarchicIterator UGGridEntity < 0, dim ,GridImp >::hend(int maxlevel) const { return UGGridHierarchicIterator(maxlevel,gridImp_); } template auto UGGridEntity < 0, dim, GridImp>::geometryInFather () const -> LocalGeometry { // we need to have a father element typename UG_NS::Element* fatherElement = UG_NS::EFather(target_); if (!fatherElement) DUNE_THROW(GridError, "Called geometryInFather() for an entity which doesn't have a father!"); // The task is to find out the positions of the vertices of this element // in the local coordinate system of the father. // Get the 'context' of the father element. In UG-speak, the context is // the set of all nodes of an element's sons. They appear in a fixed // order, therefore we can infer the local positions in the father element. const int MAX_CORNERS_OF_ELEM = 8; // this is too much in 2d, but UG is that way const int MAX_NEW_CORNERS_DIM = (dim==2) ? 5 : 19; const typename UG_NS::Node* context[MAX_CORNERS_OF_ELEM + MAX_NEW_CORNERS_DIM]; UG_NS::GetNodeContext(fatherElement, context); // loop through all corner nodes auto cornerCoordinates = LocalGeometryImpl::makeCornerStorage(UG_NS::Corners_Of_Elem(target_)); for (int i=0; i::Corners_Of_Elem(target_); i++) { // get corner node pointer const typename UG_NS::Node* fnode = UG_NS::Corner(target_,i); // Find out where in the father's context this node is int idx = -1; for (int j=0; j::verticesUGtoDUNE(i,type()); if (dim==2) { switch (UG_NS::Tag(fatherElement)) { case UG::D2::TRIANGLE : { assert(idx<6); const double coords[6][2] = { // The corners {0,0}, {1,0}, {0,1}, // The edge midpoints {0.5,0}, {0.5,0.5}, {0,0.5} }; for (int j=0; j::Tag(fatherElement)) { case UG::D3::TETRAHEDRON : { // If this assert fails a refinement rule has been appeared which inserts // side midpoints. These have to be added then. assert(idx!=10 && idx!=11 && idx!=12 && idx!=13 && idx<15); const double coords[15][3] = { // The corners {0,0,0}, {1,0,0}, {0,1,0}, {0,0,1}, // The edge midpoints {0.5,0,0}, {0.5,0.5,0}, {0,0.5,0}, {0,0,0.5}, {0.5,0,0.5}, {0,0.5,0.5}, // Four side midpoints. I don't know whether they can actually appear {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // Element midpoints. Appears in some closure refinement rules {0.25,0.25,0.25} }; for (int j=0; j=19 && idx<24) && idx<25); const double coords[25][3] = { // The corners {0,0,0}, {1,0,0}, {0,1,0}, {0,0,1}, {1,0,1}, {0,1,1}, // The edge midpoints {0.5,0,0}, {0.5,0.5,0}, {0,0.5,0}, {0,0,0.5}, {1,0,0.5}, {0,1,0.5}, {0.5,0,1}, {0.5,0.5,1}, {0,0.5,1}, // A dummy for a midpoint of one of the two triangular faces, // which doesn't exist, because triangular faces have no midnodes {0,0,0}, // The midnodes of the three quadrilateral faces {0.5,0,0.5}, {0.5,0.5,0.5}, {0,0.5,0.5}, // Second triangular face {0,0,0}, // Padding due to suboptimal implementation in UG {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // Side midpoint for the second triangular face {0.333333333333333333, 0.333333333333333333, 0.5} }; for (int j=0; j >; template class UGGridEntity<3,3, const UGGrid<3> >; template class UGGridEntity<0,2, const UGGrid<2> >; template class UGGridEntity<0,3, const UGGrid<3> >; template class UGGridEntity<1,2, const UGGrid<2> >; template class UGGridEntity<1,3, const UGGrid<3> >; template class UGGridEntity<2,3, const UGGrid<3> >; template Grid<2, 2, double, UGGridFamily<2> >::Codim<0>::Entity UGGridEntity<0, 2, const UGGrid<2> >::subEntity<0>(int) const; template Grid<2, 2, double, UGGridFamily<2> >::Codim<1>::Entity UGGridEntity<0, 2, const UGGrid<2> >::subEntity<1>(int) const; template Grid<2, 2, double, UGGridFamily<2> >::Codim<2>::Entity UGGridEntity<0, 2, const UGGrid<2> >::subEntity<2>(int) const; template Grid<3, 3, double, UGGridFamily<3> >::Codim<0>::Entity UGGridEntity<0, 3, const UGGrid<3> >::subEntity<0>(int) const; template Grid<3, 3, double, UGGridFamily<3> >::Codim<1>::Entity UGGridEntity<0, 3, const UGGrid<3> >::subEntity<1>(int) const; template Grid<3, 3, double, UGGridFamily<3> >::Codim<2>::Entity UGGridEntity<0, 3, const UGGrid<3> >::subEntity<2>(int) const; template Grid<3, 3, double, UGGridFamily<3> >::Codim<3>::Entity UGGridEntity<0, 3, const UGGrid<3> >::subEntity<3>(int) const; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridentity.hh000066400000000000000000000450461511655130300216620ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRIDENTITY_HH #define DUNE_UGGRIDENTITY_HH /** \file * \brief The UGGridEntity class and its specializations */ #include #include #include #include namespace Dune { // Forward declarations template class UGGrid; template class UGGridEntitySeed; template class UGGridLevelIterator; template class UGGridLevelIntersectionIterator; template class UGGridLeafIntersectionIterator; template class UGGridHierarchicIterator; template class GridFactory; //********************************************************************** // // --UGGridEntity // --Entity // /** \brief The implementation of entities in a UGGrid \ingroup UGGrid A Grid is a container of grid entities. An entity is parametrized by the codimension. An entity of codimension c in dimension d is a d-c dimensional object. */ template class UGGridEntity { template friend class UGGridLeafIterator; template friend class UGGridLevelIterator; friend class UGGrid; template friend class UGGridLevelIndexSet; template friend class UGGridLeafIndexSet; template friend class UGGridIdSet; friend class UGGridEntitySeed; typedef typename GridImp::ctype UGCtype; typedef typename GridImp::Traits::template Codim::GeometryImpl GeometryImpl; template friend class GridFactory; public: UGGridEntity() : target_(nullptr) , gridImp_(nullptr) {} /** \brief Copy constructor */ UGGridEntity(const UGGridEntity& other) = default; /** \brief Move constructor */ UGGridEntity(UGGridEntity&& other) = default; UGGridEntity(typename UG_NS::template Entity::T* target, const GridImp* gridImp) { setToTarget(target,gridImp); } typedef typename GridImp::template Codim::Geometry Geometry; /** \brief The type of UGGrid Entity seeds */ typedef typename GridImp::Traits::template Codim::EntitySeed EntitySeed; //! level of this entity int level () const { return UG_NS::myLevel(target_); } /** \brief Return the entity type identifier */ GeometryType type() const; /** \brief The partition type for parallel computing */ PartitionType partitionType () const { #ifndef ModelP return InteriorEntity; #else if (UG_NS::Priority(target_) == UG_NS::PrioHGhost || UG_NS::Priority(target_) == UG_NS::PrioVGhost || UG_NS::Priority(target_) == UG_NS::PrioVHGhost) return GhostEntity; else if (hasBorderCopy()) return BorderEntity; else if (UG_NS::Priority(target_) == UG_NS::PrioMaster || UG_NS::Priority(target_) == UG_NS::PrioNone) return InteriorEntity; else DUNE_THROW(GridError, "Unknown priority " << UG_NS::Priority(target_)); #endif } /** \brief Get the partition type of each copy of a distributed entity * * This is a non-interface method, intended mainly for debugging and testing. * * \return Each pair in the return value contains a process number and the corresponding partition type */ std::vector > partitionTypes () const { std::vector > result; #ifndef ModelP result.push_back(std::make_pair(0, InteriorEntity)); #elif DUNE_UGGRID_DDD_InfoProcListRange const auto range = UG_NS::DDD_InfoProcListRange(gridImp_->multigrid_->dddContext(), UG_NS::ParHdr(target_)); for (auto&& [rank, priority] : range) { if (priority == UG_NS::PrioHGhost || priority == UG_NS::PrioVGhost || priority == UG_NS::PrioVHGhost) result.push_back(std::make_pair(rank, GhostEntity)); else { // The entity is not ghost. If it is (UG)PrioBorder somewhere, it is (Dune)Border. // Otherwise it is (Dune)Interior. bool hasBorderCopy = false; for (auto&& [rank2, priority2] : range) { if (priority2 == UG_NS::PrioBorder) { hasBorderCopy = true; break; } } result.push_back(std::make_pair(rank, (hasBorderCopy) ? BorderEntity : InteriorEntity)); } } #else int *plist = UG_NS::DDD_InfoProcList(gridImp_->multigrid_->dddContext(), UG_NS::ParHdr(target_)); for (int i = 0; plist[i] >= 0; i += 2) { int rank = plist[i]; auto priority = plist[i + 1]; if (priority == UG_NS::PrioHGhost || priority == UG_NS::PrioVGhost || priority == UG_NS::PrioVHGhost) result.push_back(std::make_pair(rank, GhostEntity)); else { // The entity is not ghost. If it is (UG)PrioBorder somewhere, it is (Dune)Border. // Otherwise it is (Dune)Interior. bool hasBorderCopy = false; for (int i = 0; plist[i] >= 0; i += 2) if (plist[i + 1] == UG_NS::PrioBorder) { hasBorderCopy = true; break; } result.push_back(std::make_pair(rank, (hasBorderCopy) ? BorderEntity : InteriorEntity)); } } #endif return result; } protected: #ifdef ModelP // \todo Unify with the following method bool hasBorderCopy() const { #if DUNE_UGGRID_DDD_InfoProcListRange for (auto&& [rank, priority] : UG_NS::DDD_InfoProcListRange( gridImp_->multigrid_->dddContext(), UG_NS::ParHdr(target_))) { if (priority == UG_NS::PrioBorder) return true; } #else int *plist = UG_NS::DDD_InfoProcList( gridImp_->multigrid_->dddContext(), UG_NS::ParHdr(target_)); for (int i = 0; plist[i] >= 0; i += 2) if (plist[i + 1] == UG_NS::PrioBorder) return true; #endif return false; } #endif public: //! geometry of this entity Geometry geometry () const { if constexpr ((dim-codim)==0) return Geometry( geo_ ); else return Geometry( *geo_ ); } /** \brief Get the seed corresponding to this entity */ EntitySeed seed () const { return EntitySeed( *this ); } /** \brief Return the number of subEntities of codimension codim. */ unsigned int subEntities (unsigned int cd) const { return referenceElement(type()).size(cd-codim); } typename UG_NS::template Entity::T* getTarget() const { return target_; } //! equality bool equals(const UGGridEntity& other) const { return getTarget() == other.getTarget(); } //! Copy assignment operator from an existing entity. UGGridEntity& operator=(const UGGridEntity& other) = default; //! Move assignment operator from an existing entity. UGGridEntity& operator=(UGGridEntity&& other) = default; private: /** \brief Set this entity to a particular UG entity */ void setToTarget(typename UG_NS::template Entity::T* target,const GridImp* gridImp) { gridImp_ = gridImp; target_ = target; if constexpr ((dim-codim)==1) // Edge entity { // Obtain the corner coordinates from UG UGCtype* cornerCoords[2*dim]; UG_NS::Corner_Coordinates(target_, cornerCoords); // convert to the type required by MultiLinearGeometry std::array, 2> geometryCoords; for (size_t i=0; i < 2; i++) for (size_t j=0; j < dim; j++) geometryCoords[i][j] = cornerCoords[i][j]; geo_ = std::make_optional(type(), std::move(geometryCoords)); } else if constexpr ((dim-codim)==2) // Facet entity { // obtain the corner coordinates from UG UGCtype* cornerCoords[4*dim]; UG_NS::Corner_Coordinates(target_, cornerCoords); // convert to the type required by MultiLinearGeometry size_t numCorners = type().isTriangle() ? 3 : 4; ReservedVector, 4> geometryCoords(numCorners); for(size_t i = 0; i < numCorners; i++) for (size_t j = 0; j < dim; j++) geometryCoords[UGGridRenumberer::verticesUGtoDUNE(i, type())][j] = cornerCoords[i][j]; geo_ = std::make_optional(type(), std::move(geometryCoords)); } else geo_.setToTarget(target); } // The geometric realization of the entity. It is a native UG type for vertices, // and a dune-geometry MultiLinearGeometry for edges and facets. std::conditional_t<(dim-codim)==0, GeometryImpl, std::optional > geo_; /** \brief The UG object that represents this entity * - 0d entities: node * - 1d entities: edge * - 2d entities in 3d grids: side vector */ typename UG_NS::template Entity::T* target_; const GridImp* gridImp_; }; /** \brief Specialization for codim-0-entities. * \ingroup UGGrid * * This class embodies the topological parts of elements of the grid. * It has an extended interface compared to the general entity class. * For example, Entities of codimension 0 allow to visit all neighbors. * * UGGrid only implements the cases dim==dimworld==2 and dim=dimworld==3. */ template class UGGridEntity<0,dim,GridImp> { friend class UGGrid; friend class UGGridLeafIntersectionIterator ; friend class UGGridHierarchicIterator ; template friend class UGGridLeafIterator; template friend class UGGridLevelIterator; typedef typename GridImp::ctype UGCtype; typedef typename GridImp::Traits::template Codim< 0 >::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim< 0 >::LocalGeometryImpl LocalGeometryImpl; public: typedef typename GridImp::template Codim<0>::Geometry Geometry; typedef typename GridImp::template Codim<0>::LocalGeometry LocalGeometry; //! The Iterator over neighbors on this level typedef UGGridLevelIntersectionIterator LevelIntersectionIterator; //! The Iterator over neighbors on the leaf level typedef UGGridLeafIntersectionIterator LeafIntersectionIterator; //! Iterator over descendants of the entity typedef UGGridHierarchicIterator HierarchicIterator; /** \brief The type of UGGrid Entity seeds */ typedef typename GridImp::Traits::template Codim<0>::EntitySeed EntitySeed; UGGridEntity() : target_(nullptr) , gridImp_(nullptr) {} UGGridEntity(typename UG_NS::Element* target, const GridImp* gridImp) { setToTarget(target,gridImp); } //! Level of this element int level () const { return UG_NS::myLevel(target_); } /** \brief Return the entity type identifier */ GeometryType type() const; /** \brief The partition type for parallel computing */ PartitionType partitionType () const { #ifndef ModelP return InteriorEntity; #else if (UG_NS::EPriority(target_) == UG_NS::PrioHGhost || UG_NS::EPriority(target_) == UG_NS::PrioVGhost || UG_NS::EPriority(target_) == UG_NS::PrioVHGhost) return GhostEntity; else return InteriorEntity; #endif } /** \brief Get the partition type of each copy of a distributed entity * * This is a non-interface method, intended mainly for debugging and testing. * * \return Each pair in the return value contains a process number and the corresponding partition type */ std::vector > partitionTypes () const { std::vector > result; #ifndef ModelP result.push_back(std::make_pair(0, InteriorEntity)); #elif DUNE_UGGRID_DDD_InfoProcListRange for (auto&& [rank, priority] : UG_NS::DDD_InfoProcListRange( gridImp_->multigrid_->dddContext(), &target_->ge.ddd)) { if (priority == UG_NS::PrioHGhost || priority == UG_NS::PrioVGhost || priority == UG_NS::PrioVHGhost) result.push_back(std::make_pair(rank, GhostEntity)); else result.push_back(std::make_pair(rank, InteriorEntity)); } #else int *plist = UG_NS::DDD_InfoProcList(gridImp_->multigrid_->dddContext(), &target_->ge.ddd); for (int i = 0; plist[i] >= 0; i += 2) { int rank = plist[i]; auto priority = plist[i + 1]; if (priority == UG_NS::PrioHGhost || priority == UG_NS::PrioVGhost || priority == UG_NS::PrioVHGhost) result.push_back(std::make_pair(rank, GhostEntity)); else result.push_back(std::make_pair(rank, InteriorEntity)); } #endif return result; } //! Geometry of this entity Geometry geometry () const { return Geometry( geo_ ); } /** \brief Get the seed corresponding to this entity */ EntitySeed seed () const { return EntitySeed( *this ); } /** \brief Return the number of subEntities of codimension codim. */ unsigned int subEntities (unsigned int codim) const { if (dim==3) { switch (codim) { case 0 : return 1; case 1 : return UG_NS::Sides_Of_Elem(target_); case 2 : return UG_NS::Edges_Of_Elem(target_); case 3 : return UG_NS::Corners_Of_Elem(target_); } } else { switch (codim) { case 0 : return 1; case 1 : return UG_NS::Edges_Of_Elem(target_); case 2 : return UG_NS::Corners_Of_Elem(target_); default : // do nothing for codim = 3 break; } } DUNE_THROW(GridError, "You can't call UGGridEntity<0,dim>::subEntities " << "with dim==" << dim << " and codim==" << codim << "!"); } /** \brief Provide access to sub entity i of given codimension. Entities * are numbered 0 ... subEntities(cc)-1 */ template typename GridImp::template Codim::Entity subEntity (int i) const; /** \todo It would be faster to not use -1 as the end marker but number of sides instead */ UGGridLeafIntersectionIterator ileafbegin () const { return UGGridLeafIntersectionIterator(target_, (isLeaf()) ? 0 : UG_NS::Sides_Of_Elem(target_),gridImp_); } UGGridLevelIntersectionIterator ilevelbegin () const { return UGGridLevelIntersectionIterator(target_, 0, gridImp_); } //! Reference to one past the last leaf neighbor UGGridLeafIntersectionIterator ileafend () const { return UGGridLeafIntersectionIterator(target_, UG_NS::Sides_Of_Elem(target_), gridImp_); } //! Reference to one past the last level neighbor UGGridLevelIntersectionIterator ilevelend () const { return UGGridLevelIntersectionIterator(target_, UG_NS::Sides_Of_Elem(target_),gridImp_); } //! returns true if Entity has NO children bool isLeaf() const { return UG_NS::isLeaf(target_); } //! returns true if element is of regular type bool isRegular() const { return UG_NS::isRegular(target_); } /** \brief Returns true if the entity has intersections with the boundary */ bool hasBoundaryIntersections() const { return UG_NS::isBoundaryElement(target_); } //! Inter-level access to father element on coarser grid. //! Assumes that meshes are nested. typename GridImp::template Codim<0>::Entity father () const { return typename GridImp::template Codim<0>::Entity(UGGridEntity(UG_NS::EFather(target_),gridImp_)); } //! returns true if father entity exists bool hasFather () const { return UG_NS::EFather(target_) != nullptr; } /*! Location of this element relative to the reference element element of the father. */ LocalGeometry geometryInFather () const; /*! Inter-level access to son elements on higher levels<=maxlevel. This is provided for sparsely stored nested unstructured meshes. Returns iterator to first son. */ UGGridHierarchicIterator hbegin (int maxlevel) const; //! Returns iterator to one past the last son UGGridHierarchicIterator hend (int maxlevel) const; //*************************************************************** // Interface for Adaptation //*************************************************************** //! returns true, if entity was refined during last adaptation cycle bool isNew() const; /*! \brief returns true, if entity might be coarsened during next adaptation cycle, which is true for entities that have been marked for coarsening or for entities that are not regular (i.e. isRegular returns false) */ bool mightVanish() const; //! void setToTarget(typename UG_NS::Element* target, const GridImp* gridImp); typename UG_NS::template Entity<0>::T* getTarget() const { return target_; } //! equality bool equals(const UGGridEntity& other) const { return getTarget() == other.getTarget(); } //! the current geometry GeometryImpl geo_; /** \brief The corresponding UG-internal data structure */ typename UG_NS::Element* target_; /** \brief Pointer to the grid that we are part of. * * We need that only to hand it over to the intersections, * which need it. */ const GridImp* gridImp_; }; // end of UGGridEntity codim = 0 } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridentityseed.hh000066400000000000000000000027571511655130300225250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_ENTITY_SEED_HH #define DUNE_UGGRID_ENTITY_SEED_HH /** \file * \brief Implementation of EntitySeed for the UGGrid grid manager */ namespace Dune { /** \brief Store a reference to an entity with a minimal memory footprint (one pointer) */ template class UGGridEntitySeed { // grid dimension constexpr static int dim = GridImp::dimension; public: //! codimension of underlying entity constexpr static int codimension = codim; //! default construct an invalid entity seed UGGridEntitySeed () : target_(nullptr) {} //! construct entity seed from entity UGGridEntitySeed (const UGGridEntity& entity) : target_(entity.getTarget()) {} //! check whether the EntitySeed refers to a valid Entity bool isValid() const { return target_ != nullptr; } /** \brief Access to the underlying UG data structure */ typename UG_NS::template Entity::T* target() const { return target_; } private: /** \brief Plain old pointer to the corresponding UG data structure */ typename UG_NS::template Entity::T* target_; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridfactory.cc000066400000000000000000000510621511655130300217760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include "boundaryextractor.hh" #include namespace Dune { /* The following three methods are the ones that UG calls to know about the geometry of the boundary. UG expects one static method for each coarse grid boundary segment. In order to let separate BoundarySegment objects handle the calls we let UG pass them along as 'data'. \param data The BoundarySegment object \param param Local coordinates on the boundary segment \param result The world coordinates of the corresponding boundary point */ static int boundarySegmentWrapper2d(void *data, double *param, FieldVector& result) { const BoundarySegment<2>* boundarySegment = static_cast*>(data); result = (*boundarySegment)(*((FieldVector*)param)); return 0; } static int boundarySegmentWrapper3dTriangle(void *data, double *param, FieldVector& result) { const BoundarySegment<3>* boundarySegment = static_cast*>(data); // UG produces coordinates in the triangle (0,0) -- (1,0) -- (1,1), // but we want them to be in (0,0) -- (1,0) -- (0,1) FieldVector local; local[0] = param[0]-param[1]; local[1] = param[1]; result = (*boundarySegment)(local); return 0; } static int boundarySegmentWrapper3dQuad(void *data, double *param, FieldVector& result) { const BoundarySegment<3>* boundarySegment = static_cast*>(data); result = (*boundarySegment)(*((FieldVector*)param)); return 0; } template GridFactory >:: GridFactory() { grid_ = new UGGrid; factoryOwnsGrid_ = true; createBegin(); } template GridFactory >:: GridFactory(UGGrid* grid) { grid_ = grid; factoryOwnsGrid_ = false; createBegin(); } template GridFactory >:: ~GridFactory() { if (grid_ && factoryOwnsGrid_) delete grid_; } template void GridFactory >:: insertVertex(const FieldVector >::ctype,dimworld>& pos) { vertexPositions_.push_back(pos); } template void GridFactory >:: insertElement(const GeometryType& type, const std::vector& vertices) { if (dimworld!=type.dim()) DUNE_THROW(GridError, "You cannot insert a " << type << " into a UGGrid<" << dimworld << ">!"); int newIdx = elementVertices_.size(); elementTypes_.push_back(vertices.size()); for (unsigned int i=0; i reorder the vertices elementVertices_[newIdx+2] = vertices[3]; elementVertices_[newIdx+3] = vertices[2]; } else if (type.isTetrahedron()) { if (vertices.size() != 4) DUNE_THROW(GridError, "You have requested to enter a tetrahedron, but you" << " have provided " << vertices.size() << " vertices!"); } else if (type.isPyramid()) { if (vertices.size() != 5) DUNE_THROW(GridError, "You have requested to enter a pyramid, but you" << " have provided " << vertices.size() << " vertices!"); // DUNE and UG numberings differ --> reorder the vertices elementVertices_[newIdx+2] = vertices[3]; elementVertices_[newIdx+3] = vertices[2]; } else if (type.isPrism()) { if (vertices.size() != 6) DUNE_THROW(GridError, "You have requested to enter a prism, but you" << " have provided " << vertices.size() << " vertices!"); } else if (type.isHexahedron()) { if (vertices.size() != 8) DUNE_THROW(GridError, "You have requested to enter a hexahedron, but you" << " have provided " << vertices.size() << " vertices!"); // DUNE and UG numberings differ --> reorder the vertices elementVertices_[newIdx+2] = vertices[3]; elementVertices_[newIdx+3] = vertices[2]; elementVertices_[newIdx+6] = vertices[7]; elementVertices_[newIdx+7] = vertices[6]; } else { DUNE_THROW(GridError, "You cannot insert a " << type << " into a UGGrid<" << dimworld << ">!"); } } template void GridFactory >:: insertBoundarySegment(const std::vector& vertices) { insertBoundarySegment(vertices, std::shared_ptr >()); } template void GridFactory >:: insertBoundarySegment(const std::vector& vertices, const std::shared_ptr > &boundarySegment) { std::array segmentVertices; for (size_t i=0; i UG vertex renumbering for quadrilateral boundary segments (3D only) if constexpr (dimworld == 3) { if (vertices.size()==4) { segmentVertices[2] = vertices[3]; segmentVertices[3] = vertices[2]; } } boundarySegmentVertices_.push_back(segmentVertices); // Append boundary segment class to the boundary segment class list, // to make sure they aren't deleted before the grid object grid_->boundarySegments_.push_back(boundarySegment); } template std::unique_ptr> GridFactory >:: createGrid() { // Prevent a crash when this method is called twice in a row // You never know who may do this... if (grid_==nullptr) return nullptr; // /////////////////////////////////////////////////////////////////////////////// // Communicate the grid information from the master to all other processes // // Rationale: Parallel Dune grids that are set up by providing a coarse grid // on rank 0 and then loadbalancing should not require that the grid be // provided to all processes directly. Usually UGGrid does that, because // it needs the grid only on rank 0, but the grid _boundary_ on all processes. // This patch makes the rank 0 process broadcast the entire coarse // grid information from rank 0 to all other processes before // starting the actual grid creation. That way, the user has to // supply the coarse grid only on rank 0 (as the specification says), // but still the UGGridFactory has all relevant information available // on all processes. // /////////////////////////////////////////////////////////////////////////////// const auto& comm = grid_->comm(); // Broadcast the vertex positions int numVertices = vertexPositions_.size(); comm.broadcast(&numVertices, 1, 0); vertexPositions_.resize(numVertices); comm.broadcast(&vertexPositions_[0], vertexPositions_.size(), 0); // Broadcast the element corners int numElementVertices = elementVertices_.size(); comm.broadcast(&numElementVertices, 1, 0); elementVertices_.resize(numElementVertices); comm.broadcast(&elementVertices_[0], elementVertices_.size(), 0); // Broadcast the geometry types int numElementTypes = elementTypes_.size(); comm.broadcast(&numElementTypes, 1, 0); elementTypes_.resize(numElementTypes); comm.broadcast(&elementTypes_[0], elementTypes_.size(), 0); // /////////////////////////////////////////// // Extract grid boundary segments // /////////////////////////////////////////// std::set > boundarySegments; typedef typename std::set >::iterator SetIterator; BoundaryExtractor::detectBoundarySegments(elementTypes_, elementVertices_, boundarySegments); std::vector isBoundaryNode; BoundaryExtractor::detectBoundaryNodes(boundarySegments, vertexPositions_.size(), isBoundaryNode); dverb << boundarySegments.size() << " boundary segments were found!" << std::endl; if (grid_->boundarySegments_.size() > boundarySegments.size()) DUNE_THROW(GridError, "You have supplied " << grid_->boundarySegments_.size() << " parametrized boundary segments, but the coarse grid has only " << boundarySegments.size() << " boundary faces!"); // Count number of nodes on the boundary int noOfBNodes = 0; for (unsigned int i=0; i nodePermutation; for (unsigned int i=0; inumBoundarySegments_ = boundarySegments.size(); auto ugDomain = std::make_unique::domain>(); ugDomain->numOfSegments = grid_->numBoundarySegments_; ugDomain->numOfCorners = noOfBNodes; // /////////////////////////////////////////// // Insert the boundary segments // /////////////////////////////////////////// unsigned int i; for (i=0; iboundarySegments_.size(); i++) { // Copy the vertices into a C-style array // We copy four vertices here even if the segment is a triangle -- it doesn't matter int vertices_c_style[dimworld*2-2]; for (int j=0; jboundarySegments_[i]) { typedef int (*BndSegFuncPtr)(void *, double *, FieldVector&); BndSegFuncPtr boundarySegmentWrapper; if constexpr (dimworld==2) boundarySegmentWrapper = boundarySegmentWrapper2d; else { if (vertices_c_style[3]==-1) // triangular face boundarySegmentWrapper = boundarySegmentWrapper3dTriangle; else boundarySegmentWrapper = boundarySegmentWrapper3dQuad; } // Actually create the segment ugDomain->boundarySegments.emplace_back(i, // Index of the segment vertices_c_style, boundarySegmentWrapper, grid_->boundarySegments_[i].get()); } else { // No explicit boundary parametrization has been given. We insert a linear segment int numVertices = (dimworld==2) ? 2 : ((boundarySegmentVertices_[i][3]==-1) ? 3 : 4); std::array, 2*(dimworld-1)> segmentCoordinates; for (int j=0; jlinearSegments.emplace_back(i, // id of segment numVertices, // Number of corners vertices_c_style, segmentCoordinates); } // ///////////////////////////////////////////////////////////////////// // Remove this segment from the set of computed boundary segments. // ///////////////////////////////////////////////////////////////////// UGGridBoundarySegment thisSegment; /** \todo Not nice: we need to copy because the array types are different */ for (int j=0; j<2*dimworld-2; j++) thisSegment[j] = boundarySegmentVertices_[i][j]; SetIterator boundaryElementFace = boundarySegments.find(thisSegment); if (boundaryElementFace==boundarySegments.end()) DUNE_THROW(GridError, "You have provided a boundary parametrization for" << " a segment which is not boundary segment in the grid!"); // Everything is fine. Delete the element face from the list to mark that it has been properly handled boundarySegments.erase(thisSegment); } // /////////////////////////////////////////////////////////////////////// // The boundary segments remaining in the std::set boundarySegments // have not been provided with an explicit parametrization. They are // inserted into the domain as straight boundary segments. // /////////////////////////////////////////////////////////////////////// SetIterator it = boundarySegments.begin(); for (; it != boundarySegments.end(); ++it, ++i) { const UGGridBoundarySegment& thisSegment = *it; // Copy the vertices into a C-style array int vertices_c_style[4]; for (int j=0; j, 2*(dimworld-1)> segmentCoordinates; for (int j=0; jlinearSegments.emplace_back(i, // id of segment thisSegment.numVertices(), // Number of corners vertices_c_style, segmentCoordinates); } ///////////////////////////////////////////////// // Set up a UG multigrid data structure ///////////////////////////////////////////////// std::string MultiGridName = grid_->name_; std::string FormatName = "DuneFormat" + std::to_string(dimworld) + "d"; grid_->bvp_->Domain = std::move(ugDomain); // Make sure there is no old multigrid object with the same name. // TODO: Can this happen at all? typename UG_NS::MultiGrid *theMG = UG_NS::GetMultigrid(MultiGridName.c_str()); if (theMG && DisposeMultiGrid(theMG)!=0) DUNE_THROW(GridError, "Closing old multigrid failed!"); // Create the actual multigrid data structure std::shared_ptr ppifContext; #if ModelP ppifContext = std::make_shared(grid_->comm()); #endif grid_->multigrid_ = UG_NS::CreateMultiGrid(MultiGridName.c_str(),grid_->bvp_,FormatName.c_str(),true,true, ppifContext); if (grid_->multigrid_==nullptr) DUNE_THROW(GridError, "Could not create multigrid"); // /////////////////////////////////////////////////////////////// // If we are in a parallel setting and we are _not_ the master // process we can stop here. // /////////////////////////////////////////////////////////////// #if ModelP const bool isMaster = grid_->multigrid_->ppifContext().isMaster(); #else const bool isMaster = (PPIF::me == PPIF::master); #endif if (not isMaster) { // Complete the UG-internal grid data structure even if we are // not the master process. (CreateAlgebra communicates via MPI // so we would be out of sync if we don't do this here...) if (CreateAlgebra(grid_->multigrid_) != UG_NS::GM_OK) DUNE_THROW(IOError, "Call of 'UG::D" << dimworld << "::CreateAlgebra' failed!"); // Create an empty levelIndexSet for level 0. // Even though it's empty until the first load balancing // it should still be there in case someone wants to access it. grid_->levelIndexSets_.resize(1); grid_->levelIndexSets_[0] = std::make_shared > >(); /* here all temp memory since CreateMultiGrid is released */ ReleaseTmpMem(grid_->multigrid_->theHeap, grid_->multigrid_->MarkKey); grid_->multigrid_->MarkKey = 0; // /////////////////////////////////////////////////// // hand over the grid and delete the member pointer // /////////////////////////////////////////////////// UGGrid* tmp = grid_; grid_ = nullptr; return std::unique_ptr>(tmp); } // //////////////////////////////////////////////// // Actually insert the interior vertices // //////////////////////////////////////////////// int nodeCounter = noOfBNodes; for (size_t i=0; i::InsertInnerNode(grid_->multigrid_->grids[0], &((vertexPositions_[i])[0])) == nullptr) DUNE_THROW(GridError, "Inserting a vertex into UGGrid failed!"); isBoundaryNode[i] = nodeCounter++; } vertexPositions_.resize(0); // //////////////////////////////////////////////// // Actually insert all the elements // //////////////////////////////////////////////// std::vector::Node*> nodePointers(isBoundaryNode.size()); for (typename UG_NS::Node* theNode=UG_NS::FirstNode(grid_->multigrid_->grids[0]); theNode!=nullptr; theNode=theNode->succ) nodePointers[theNode->id] = theNode; int idx = 0; for (size_t i=0; i::Node*> vertices(elementTypes_[i]); for (size_t j=0; jmultigrid_->grids[0], elementTypes_[i],&(vertices[0]),nullptr,nullptr,nullptr)==nullptr) DUNE_THROW(GridError, "Inserting element into UGGrid failed!"); } // Not needed any more elementTypes_.resize(0); elementVertices_.resize(0); // Complete the UG-internal grid data structure if (CreateAlgebra(grid_->multigrid_) != UG_NS::GM_OK) DUNE_THROW(IOError, "Call of 'UG::D" << dimworld << "::CreateAlgebra' failed!"); /* here all temp memory since CreateMultiGrid is released */ ReleaseTmpMem(grid_->multigrid_->theHeap, grid_->multigrid_->MarkKey); grid_->multigrid_->MarkKey = 0; // Set the local indices grid_->setIndices(true, &nodePermutation); // Clear refinement flags for (const auto& element : elements(grid_->levelGridView(0))) UG_NS::WriteCW(element.impl().target_, UG_NS::NEWEL_CE, 0); // /////////////////////////////////////////////////// // hand over the grid and delete the member pointer // /////////////////////////////////////////////////// UGGrid* tmp = grid_; grid_ = nullptr; return std::unique_ptr>(tmp); } template void GridFactory >:: createBegin() { // /////////////////////////////////////////////////////// // Clean up existing grid structure if there is one // /////////////////////////////////////////////////////// // Delete the UG multigrid if there is one (== createEnd() has already // been called once for this object) if (grid_->multigrid_) { // Set UG's currBVP variable to the BVP corresponding to this // grid. This is necessary if we have more than one UGGrid in use. // DisposeMultiGrid will crash if we don't do this //UG_NS::Set_Current_BVP(grid_->multigrid_->theBVP); // set the multigrid's bvp pointer to NULL to make sure the BVP // is not deleted grid_->multigrid_->theBVP = nullptr; UG_NS::DisposeMultiGrid(grid_->multigrid_); grid_->multigrid_ = nullptr; } // Delete levelIndexSets if there are any grid_->levelIndexSets_.resize(0); // ////////////////////////////////////////////////////////// // Clear all buffers used during coarse grid creation // ////////////////////////////////////////////////////////// grid_->boundarySegments_.resize(0); boundarySegmentVertices_.resize(0); elementTypes_.resize(0); elementVertices_.resize(0); vertexPositions_.resize(0); } // Explicit template instantiation template class GridFactory >; template class GridFactory >; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridfactory.hh000066400000000000000000000236171511655130300220150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_FACTORY_HH #define DUNE_UGGRID_FACTORY_HH /** \file \brief The specialization of the generic GridFactory for UGGrid \author Oliver Sander */ #include #include #include #include #include #include #include namespace Dune { /** \brief Specialization of the generic GridFactory for UGGrid \ingroup GridFactory

If you want to write a routine that reads a grid from some file into a Dune UGGrid object you have to know how to use the UGGrid grid factory. In the following we assume that you have a grid in some file format and an empty UGGrid object, created by one of its constructors. Hence, your file reader method signature may look like this:

     UGGrid<3>* readMyFileFormat(const std::string& filename)
     
Now, in order to create a valid UGGrid object do the following steps:

1) Create a GridFactory Object

Get a new GridFactory object by calling

     GridFactory > factory;
     

2) Enter the Vertices

Insert the grid vertices by calling

     factory.insertVertex(const FieldVector<double,dimworld>& position);
     

for each vertex. The order of insertion determines the level- and leaf indices of your level 0 vertices.

3) Enter the elements

For each element call

     factory.insertElement(Dune::GeometryType type, const std::vector<int>& vertices);
     

The parameters are

  • type - The element type. UG supports the types simplex and cube in 2d, and simplex, cube, prism, and pyramid in 3d.
  • vertices - The Ids of the vertices of this element.

The numbering of the vertices of each element is expected to follow the DUNE conventions. Refer to the page on reference elements for the details.

4) Parametrized Domains

UGGrid supports parametrized domains. That means that you can provide a smooth description of your grid boundary. The actual grid will always be piecewise linear; however, as you refine, the grid will approach your prescribed boundary. You don't have to do this. If your coarse grid boundary describes your domain well read on at Section 5.

In order to create curved boundary segments, for each segment you have to write a class which implements the correct geometry. These classes are then handed over to the UGGrid object. Boundary segment implementations must be derived from

     template <int dimworld> Dune::BoundarySegment
     
This is an abstract base class which requires you to overload the method
     virtual FieldVector< double, dimworld > operator() (const FieldVector< double, dimworld-1 > &local)
     

This methods must compute the world coordinates from the local ones on the boundary segment. Give these classes to your grid factory by calling

     factory.insertBoundarySegment(const std::vector<int>& vertices,
                             const BoundarySegment<dimworld> *boundarySegment);
     

Control over the allocated objects is taken from you, and the grid object will take care of their destruction.

5) Finish construction

To finish off the construction of the UGGrid object call

     std::unique_ptr > grid = factory.createGrid();
     

This time it is you who gets full responsibility for the allocated object.

Loading a Grid on a Parallel Machine

If you're working on a parallel machine, and you want to set up a parallel grid, proceed as described only on the rank-0 process. On the other processes just create a GridFactory and call createGrid() to obtain the grid object. This will create the grid on the master process and set up UG correctly on all other process. Call loadBalance() to actually distribute the grid.

\warning To use a parametrized boundary on a parallel machine you need to hand over the boundary segments to the grid factory on all processes. This behavior violates the Dune grid interface specification and will be corrected in the future.

*/ template class GridFactory > : public GridFactoryInterface > { /** \brief Type used by the grid for coordinates */ typedef typename UGGrid::ctype ctype; // UGGrid only in 2d and 3d static_assert(dimworld==2 || dimworld == 3, "UGGrid only in 2d and 3d"); public: /** \brief Default constructor */ GridFactory(); /** \brief Constructor for a given grid object If you already have your grid object constructed you can hand it over using this constructor. If you construct your factory class using this constructor the pointer handed over to you by the method createGrid() is the one you supplied here. */ GridFactory(UGGrid* grid); /** \brief Destructor */ ~GridFactory(); /** \brief Insert a vertex into the coarse grid */ virtual void insertVertex(const FieldVector& pos); /** \brief Insert an element into the coarse grid \param type The GeometryType of the new element \param vertices The vertices of the new element, using the DUNE numbering */ virtual void insertElement(const GeometryType& type, const std::vector& vertices); /** \brief Method to insert a boundary segment into a coarse grid Using this method is optional. It only influences the ordering of the segments \param vertices The indices of the vertices of the segment */ void insertBoundarySegment(const std::vector& vertices); /** \brief Method to insert an arbitrarily shaped boundary segment into a coarse grid \param vertices The indices of the vertices of the segment \param boundarySegment Class implementing the geometry of the boundary segment. */ void insertBoundarySegment(const std::vector& vertices, const std::shared_ptr > &boundarySegment); /** \brief Finalize grid creation and hand over the grid The receiver takes responsibility of the memory allocated for the grid */ virtual std::unique_ptr> createGrid(); static const int dimension = UGGrid::dimension; template< int codim > struct Codim { typedef typename UGGrid::template Codim< codim >::Entity Entity; }; /** \brief Return the number of the element in the order of insertion into the factory * * For UGGrid elements this number is the same as the element level index */ virtual unsigned int insertionIndex ( const typename Codim< 0 >::Entity &entity ) const { return UG_NS::levelIndex(entity.impl().target_); } /** \brief Return the number of the vertex in the order of insertion into the factory * * For UGGrid vertices this number is the same as the vertex level index */ virtual unsigned int insertionIndex ( const typename Codim< dimension >::Entity &entity ) const { return UG_NS::levelIndex(entity.impl().target_); } /** \brief Return the number of the intersection in the order of insertion into the factory * * For UGGrid intersections this number is the same as the boundary segment index */ virtual unsigned int insertionIndex ( const typename UGGrid::LeafIntersection &intersection ) const { return intersection.boundarySegmentIndex(); } /** \brief Return true if the intersection has been explicitly inserted into the factory */ virtual bool wasInserted ( const typename UGGrid::LeafIntersection &intersection ) const { return (insertionIndex( intersection ) < boundarySegmentVertices_.size()); } using Communication = typename UGGrid::Communication; /** \brief Return the Communication used by the grid factory * * Use the Communication available from the grid. */ Communication comm() const { return grid_->comm(); } private: // Initialize the grid structure in UG void createBegin(); // Pointer to the grid being built UGGrid* grid_; // True if the factory allocated the grid itself, false if the // grid was handed over from the outside bool factoryOwnsGrid_; /** \brief Buffer for the vertices of each explicitly given boundary segment */ std::vector > boundarySegmentVertices_; /** \brief While inserting the elements this array records the number of vertices of each element. */ std::vector elementTypes_; /** \brief While inserting the elements this array records the vertices of the elements. */ std::vector elementVertices_; /** \brief Buffer the vertices until createend() is called */ std::vector > vertexPositions_; }; } #endif dune-grid-2.11.0/dune/grid/uggrid/uggridgeometry.cc000066400000000000000000000143221511655130300221600ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include namespace Dune { /////////////////////////////////////////////////////////////////////// // // General implementation of UGGridGeometry mydim-> coorddim // /////////////////////////////////////////////////////////////////////// template< int mydim, int coorddim, class GridImp> GeometryType UGGridGeometry::type() const { switch (mydim) { case 0 : return GeometryTypes::vertex; case 1 : return GeometryTypes::line; case 2 : switch (UG_NS::Tag(target_)) { case UG::D2::TRIANGLE : return GeometryTypes::triangle; case UG::D2::QUADRILATERAL : return GeometryTypes::quadrilateral; default : DUNE_THROW(GridError, "UGGridGeometry::type(): ERROR: Unknown type " << UG_NS::Tag(target_) << " found!"); } case 3 : switch (UG_NS::Tag(target_)) { case UG::D3::TETRAHEDRON : return GeometryTypes::tetrahedron; case UG::D3::PYRAMID : return GeometryTypes::pyramid; case UG::D3::PRISM : return GeometryTypes::prism; case UG::D3::HEXAHEDRON : return GeometryTypes::hexahedron; default : DUNE_THROW(GridError, "UGGridGeometry::type(): ERROR: Unknown type " << UG_NS::Tag(target_) << " found!"); } } } template FieldVector UGGridGeometry:: corner(int i) const { // This geometry is a vertex if constexpr (mydim==0) return target_->myvertex->iv.x; // //////////////////////////////// // This geometry is an element // //////////////////////////////// assert(mydim==coorddim); i = UGGridRenumberer::verticesDUNEtoUG(i,type()); if constexpr (mydim==coorddim) return UG_NS::Corner(target_,i)->myvertex->iv.x; } template< int mydim, int coorddim, class GridImp> FieldVector UGGridGeometry:: global(const FieldVector& local) const { FieldVector globalCoord(0.0); // we are an actual element in UG // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[coorddim*coorddim]; int n = UG_NS::Corner_Coordinates(target_, cornerCoords); // Actually do the computation UG_NS::Local_To_Global(n, cornerCoords, local, globalCoord); return globalCoord; } // Maps a global coordinate within the element to a // local coordinate in its reference element template< int mydim, int coorddim, class GridImp> FieldVector UGGridGeometry:: local (const FieldVector& global) const { FieldVector result; // do nothing for a vertex if (mydim==0) return result; // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[coorddim*coorddim]; int n = UG_NS::Corner_Coordinates(target_, cornerCoords); // Actually do the computation /** \todo Why is this const_cast necessary? */ if constexpr (mydim!=0) UG_NS::GlobalToLocal(n, const_cast(cornerCoords), global, result); return result; } template< int mydim, int coorddim, class GridImp> typename GridImp::ctype UGGridGeometry:: integrationElement (const FieldVector& local) const { if (mydim==0) return 1; // Geometry is not affine --> the integrationElement cannot be cached if (!affine()) return std::abs(jacobianTransposed(local).determinant()); // Geometry is affine --> try to use the integrationElement from the cache if (!cachedIntegrationElement_) cachedIntegrationElement_.emplace(std::abs(jacobianTransposed(local).determinant())); return *cachedIntegrationElement_; } template< int mydim, int coorddim, class GridImp> FieldMatrix UGGridGeometry:: jacobianInverseTransposed (const FieldVector& local) const { if (!affine() || !cachedJacobianInverseTransposed_) { cachedJacobianInverseTransposed_.emplace(); // compile array of pointers to corner coordinates // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[coorddim*coorddim]; const int n = UG_NS::Corner_Coordinates(target_, cornerCoords); // compute the transformation onto the reference element (or vice versa?) UG_NS::JacobianInverseTransformation(n, cornerCoords, local, *cachedJacobianInverseTransposed_); } return *cachedJacobianInverseTransposed_; } template< int mydim, int coorddim, class GridImp> FieldMatrix UGGridGeometry:: jacobianTransposed (const FieldVector& local) const { if (!affine() || !cachedJacobianTransposed_) { cachedJacobianTransposed_.emplace(); // compile array of pointers to corner coordinates // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[coorddim*coorddim]; const int n = UG_NS::Corner_Coordinates(target_, cornerCoords); // compute the transformation onto the reference element (or vice versa?) UG_NS::JacobianTransformation(n, cornerCoords, local, *cachedJacobianTransposed_); } return *cachedJacobianTransposed_; } ///////////////////////////////////////////////////////////////////////////////// // Explicit template instantiations ///////////////////////////////////////////////////////////////////////////////// template class UGGridGeometry<0,2, const UGGrid<2> >; template class UGGridGeometry<2,2, const UGGrid<2> >; template class UGGridGeometry<0,3, const UGGrid<3> >; template class UGGridGeometry<3,3, const UGGrid<3> >; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridgeometry.hh000066400000000000000000000221621511655130300221730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRIDGEOMETRY_HH #define DUNE_UGGRIDGEOMETRY_HH /** \file * \brief The UGGridGeometry class and its specializations */ #include #include #include #include #include namespace Dune { /** \brief Defines the geometry part of a mesh entity. * \ingroup UGGrid \tparam mydim Dimension of the corresponding reference element \tparam coorddim Each corner is a point with coorddim coordinates. This version is actually used only for mydim==coorddim. The mydim class UGGridGeometry : public GeometryDefaultImplementation { typedef typename GridImp::ctype UGCtype; template friend class UGGridEntity; public: /** \brief Default constructor */ UGGridGeometry() {} /** \brief Return the element type identifier * * UGGrid supports triangles and quadrilaterals in 2D, and * tetrahedra, pyramids, prisms, and hexahedra in 3D. */ GeometryType type () const; //! returns true if type is simplex, false otherwise bool affine() const { if constexpr (mydim==0 || mydim==1) // Vertices and edges are always affine return true; else if constexpr (mydim==2) return UG_NS::Tag(target_)==UG::D2::TRIANGLE; else return UG_NS::Tag(target_)==UG::D3::TETRAHEDRON; } //! return the number of corners of this element. int corners () const { return UG_NS::Corners_Of_Elem(target_); } //! access to coordinates of corners. Index is the number of the corner FieldVector corner (int i) const; /** \brief Maps a local coordinate within reference element to * global coordinate in element */ FieldVector global (const FieldVector& local) const; /** \brief Maps a global coordinate within the element to a * local coordinate in its reference element */ FieldVector local (const FieldVector& global) const; /** Integration over a general element is done by integrating over the reference element and using the transformation from the reference element to the global element as follows: \f[\int\limits_{\Omega_e} f(x) dx = \int\limits_{\Omega_{ref}} f(g(l)) A(l) dl \f] where \f$g\f$ is the local to global mapping and \f$A(l)\f$ is the integration element. For a general map \f$g(l)\f$ involves partial derivatives of the map (surface element of the first kind if \f$d=2,w=3\f$, determinant of the Jacobian of the transformation for \f$d=w\f$, \f$\|dg/dl\|\f$ for \f$d=1\f$). For linear elements, the derivatives of the map with respect to local coordinates do not depend on the local coordinates and are the same over the whole element. For a structured mesh where all edges are parallel to the coordinate axes, the computation is the length, area or volume of the element is very simple to compute. Each grid module implements the integration element with optimal efficiency. This will directly translate in substantial savings in the computation of finite element stiffness matrices. */ UGCtype integrationElement (const FieldVector& local) const; UGCtype volume() const { if (mydim==0) return 1; // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[coorddim*coorddim]; int n = UG_NS::Corner_Coordinates(target_, cornerCoords); return UG_NS::Area_Of_Element(n, const_cast(cornerCoords)); } //! The inverse transpose of the Jacobian matrix of the mapping from the reference element to this element FieldMatrix jacobianInverseTransposed (const FieldVector& local) const; //! The transpose of the Jacobian matrix of the mapping from the reference element to this element FieldMatrix jacobianTransposed (const FieldVector& local) const; private: /** \brief Init the element with a given UG element */ void setToTarget(typename UG_NS::template Entity::T* target) { target_ = target; cachedIntegrationElement_.reset(); cachedJacobianTransposed_.reset(); cachedJacobianInverseTransposed_.reset(); } // in element mode this points to the element we map to // in coord_mode this is the element whose reference element is mapped into the father's one typename UG_NS::template Entity::T* target_; // If the element is affine, then the geometry Jacobian is constant, and only needs to be // computed once per element. Therefore, keep them in a cache. mutable std::optional cachedIntegrationElement_; mutable std::optional > cachedJacobianTransposed_; mutable std::optional > cachedJacobianInverseTransposed_; }; //! custom geometry traits with storage on the stack for the corners of cubes and simplicies template struct UGGridGeometryTraits : MultiLinearGeometryTraits { template class CornerStorage { // we only have simplices and cubes static constexpr std::size_t simplexCorners = mydim + 1; static constexpr std::size_t cubeCorners = (1 << mydim); // mydim^2 using Coordinate = FieldVector; public: using Type = std::conditional_t<(mydim < 2), std::array, // storage when simplex(dim) == cube(dim) ReservedVector>; // storage when simplex(dim) != cube(dim) }; }; /****************************************************************/ /* */ /* Specialization for faces in 3d */ /* */ /****************************************************************/ template class UGGridGeometry<2, 3, GridImp> : public MultiLinearGeometry> { public: // inherit constructor from MultiLinearGeometry using MultiLinearGeometry>::MultiLinearGeometry; // factory of uninitialized corner storage used to construct this geometry static auto makeCornerStorage(std::size_t count) { return ReservedVector, 4>(count); } }; /****************************************************************/ /* */ /* Specialization for edges in 3d */ /* */ /****************************************************************/ template class UGGridGeometry<1, 3, GridImp> : public MultiLinearGeometry> { public: // inherit constructor from MultiLinearGeometry using MultiLinearGeometry>::MultiLinearGeometry; // factory of uninitialized corner storage used to construct this geometry static auto makeCornerStorage(std::size_t) { return std::array, 2>(); } }; /****************************************************************/ /* */ /* Specialization for faces in 2d */ /* */ /****************************************************************/ template class UGGridGeometry <1, 2, GridImp> : public MultiLinearGeometry> { public: // inherit constructor from MultiLinearGeometry using MultiLinearGeometry>::MultiLinearGeometry; // factory of uninitialized corner storage used to construct this geometry static auto makeCornerStorage(std::size_t) { return std::array, 2>(); } }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridhieriterator.cc000066400000000000000000000032361511655130300230300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include namespace Dune { //*************************************************************** // // --UGGridHierarchicIterator // --HierarchicIterator // //*************************************************************** template void UGGridHierarchicIterator::increment() { if (elementStack_.empty()) return; const int dim = GridImp::dimension; const typename UG_NS::Element* oldTarget = elementStack_.top(); elementStack_.pop(); // Traverse the tree no deeper than maxlevel if (UG_NS::myLevel(oldTarget) < maxlevel_) { typename UG_NS::Element* sonList[UG_NS::MAX_SONS]; UG_NS::GetSons(oldTarget, sonList); // Load sons of old target onto the iterator stack for (int i=0; i::nSons(oldTarget); i++) elementStack_.push(sonList[i]); } if (elementStack_.empty()) this->entity_.impl().setToTarget(nullptr,nullptr); else this->entity_.impl().setToTarget(elementStack_.top(),gridImp_); } ///////////////////////////////////////////////////////////////////////////////// // Explicit template instantiations ///////////////////////////////////////////////////////////////////////////////// template class UGGridHierarchicIterator >; template class UGGridHierarchicIterator >; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridhieriterator.hh000066400000000000000000000036231511655130300230420ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGHIERITERATOR_HH #define DUNE_UGHIERITERATOR_HH /** \file * \brief The UGGridHierarchicIterator class */ #include #include namespace Dune { //********************************************************************** // // --UGGridHierarchicIterator // --HierarchicIterator /** \brief Iterator over the descendants of an entity. * \ingroup UGGrid Mesh entities of codimension 0 ("elements") allow to visit all entities of codimension 0 obtained through nested, hierarchic refinement of the entity. Iteration over this set of entities is provided by the HierarchicIterator, starting from a given entity. */ template class UGGridHierarchicIterator { friend class UGGridEntity<0,GridImp::dimension,GridImp>; public: typedef typename GridImp::template Codim<0>::Entity Entity; //! iterate only over elements constexpr static int codimension = 0; //! the default Constructor UGGridHierarchicIterator(int maxLevel, const GridImp* gridImp) : maxlevel_(maxLevel), gridImp_(gridImp) {} void increment(); //! dereferencing const Entity& dereference() const {return entity_;} //! equality bool equals(const UGGridHierarchicIterator& other) const { return entity_ == other.entity_; } private: //! The makeable entity that the iterator is pointing to Entity entity_; //! max level to go down int maxlevel_; std::stack::Element*> elementStack_; const GridImp* gridImp_; }; } // end namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridindexsets.cc000066400000000000000000000337031511655130300223370ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include namespace Dune { template void UGGridLevelIndexSet::update(const GridImp& grid, int level, std::vector* nodePermutation) { // Commit the index set to a specific level of a specific grid grid_ = &grid; level_ = level; // /////////////////////////////////// // clear index for codim dim-1 and 1 // /////////////////////////////////// for (const auto& element : elements(grid.levelGridView(level_))) { typename UG_NS::Element* target_ = element.impl().target_; // codim dim-1 for (unsigned int i=0; i(gt); int a = ref_el.subEntity(i,dim-1,0,dim); int b = ref_el.subEntity(i,dim-1,1,dim); int& index = UG_NS::levelIndex(UG_NS::GetEdge(UG_NS::Corner(target_, UGGridRenumberer::verticesDUNEtoUG(a,gt)), UG_NS::Corner(target_, UGGridRenumberer::verticesDUNEtoUG(b,gt)))); index = -1; } /** \todo codim 1 (faces) */ if (dim==3) for (unsigned int i=0; i::levelIndex(UG_NS::SideVector(target_,i)) = std::numeric_limits::max(); } // /////////////////////////////// // Init the codim::Element* target = element.impl().target_; // codim 0 (elements) GeometryType eType = element.type(); if (eType.isSimplex()) { UG_NS::levelIndex(target) = numSimplices_++; } else if (eType.isPyramid()) { UG_NS::levelIndex(target) = numPyramids_++; } else if (eType.isPrism()) { UG_NS::levelIndex(target) = numPrisms_++; } else if (eType.isCube()) { UG_NS::levelIndex(target) = numCubes_++; } else { DUNE_THROW(GridError, "Found the GeometryType " << element.type() << ", which should never occur in a UGGrid!"); } // codim dim-1 (edges) for (unsigned int i=0; i(eType); int a = ref_el.subEntity(i,dim-1,0,dim); int b = ref_el.subEntity(i,dim-1,1,dim); int& index = UG_NS::levelIndex(UG_NS::GetEdge(UG_NS::Corner(target, UGGridRenumberer::verticesDUNEtoUG(a,eType)), UG_NS::Corner(target, UGGridRenumberer::verticesDUNEtoUG(b,eType)))); if (index<0) index = numEdges_++; } // codim 1 (faces): todo if (dim==3) for (unsigned int i=0; i::levelIndex(UG_NS::SideVector(target,UGGridRenumberer::facesDUNEtoUG(i,eType))); if (index == std::numeric_limits::max()) { // not visited yet GeometryType gtType = referenceElement(eType).type(i,1); if (gtType.isSimplex()) { index = numTriFaces_++; } else if (gtType.isCube()) { index = numQuadFaces_++; } else { std::cout << "face geometry type is " << gtType << std::endl; DUNE_THROW(GridError, "wrong geometry type in face"); } } } } // Update the list of geometry types present myTypes_[0].resize(0); if (numSimplices_ > 0) myTypes_[0].push_back(GeometryTypes::simplex(dim)); if (numPyramids_ > 0) myTypes_[0].push_back(GeometryTypes::pyramid); if (numPrisms_ > 0) myTypes_[0].push_back(GeometryTypes::prism); if (numCubes_ > 0) myTypes_[0].push_back(GeometryTypes::cube(dim)); myTypes_[dim-1].resize(0); myTypes_[dim-1].push_back(GeometryTypes::line); if (dim==3) { myTypes_[1].resize(0); if (numTriFaces_ > 0) myTypes_[1].push_back(GeometryTypes::triangle); if (numQuadFaces_ > 0) myTypes_[1].push_back(GeometryTypes::quadrilateral); } // ////////////////////////////// // Init the vertex indices // ////////////////////////////// numVertices_ = 0; if (nodePermutation!=0 and level==0) { for (const auto& vertex : vertices(grid.levelGridView(level_))) UG_NS::levelIndex(vertex.impl().target_) = (*nodePermutation)[numVertices_++]; } else { for (const auto& vertex : vertices(grid.levelGridView(level_))) UG_NS::levelIndex(vertex.impl().target_) = numVertices_++; } /* for (; vIt!=vEndIt; ++vIt) UG_NS::levelIndex(vIt->impl().target_) = numVertices_++;*/ myTypes_[dim].resize(0); myTypes_[dim].push_back(GeometryTypes::vertex); } template void UGGridLeafIndexSet::update(std::vector* nodePermutation) { // ////////////////////////////////////////////////////// // Handle codim 1 and dim-1: levelwise from top to bottom // ////////////////////////////////////////////////////// // first loop : clear indices for (int level_=grid_.maxLevel(); level_>=0; level_--) { for (const auto& element : elements(grid_.levelGridView(level_))) { // get pointer to UG object typename UG_NS::Element* target_ = element.impl().target_; // codim dim-1 for (unsigned int i=0; i(gt); int a = ref_el.subEntity(i,dim-1,0,dim); int b = ref_el.subEntity(i,dim-1,1,dim); int& index = UG_NS::leafIndex(UG_NS::GetEdge(UG_NS::Corner(target_, UGGridRenumberer::verticesDUNEtoUG(a,gt)), UG_NS::Corner(target_, UGGridRenumberer::verticesDUNEtoUG(b,gt)))); index = -1; } // codim 1 (faces): todo if (dim==3) for (unsigned int i=0; i::leafIndex(UG_NS::SideVector(target_,UGGridRenumberer::facesDUNEtoUG(i,gt))); index = std::numeric_limits::max(); } // reset the isLeaf information of the nodes for (unsigned int i=0; i::Corner(target_,i)->isLeaf = false; } } } // init counters numEdges_ = 0; numTriFaces_ = 0; numQuadFaces_ = 0; // second loop : set indices for (int level_=grid_.maxLevel(); level_>=0; level_--) { // used to compute the coarsest level with leaf elements bool containsLeafElements = false; // this value is used in the parallel case, when a local grid may not contain any elements at all coarsestLevelWithLeafElements_ = 0; for (const auto& element : elements(grid_.levelGridView(level_))) { // we need only look at leaf elements if (!element.isLeaf()) continue; else containsLeafElements = true; // get pointer to UG object typename UG_NS::Element* target_ = element.impl().target_; // codim dim-1 (edges) for (unsigned int i=0; i(gt); int a = ref_el.subEntity(i,dim-1,0,dim); int b = ref_el.subEntity(i,dim-1,1,dim); int& index = UG_NS::leafIndex(UG_NS::GetEdge(UG_NS::Corner(target_, UGGridRenumberer::verticesDUNEtoUG(a,gt)), UG_NS::Corner(target_, UGGridRenumberer::verticesDUNEtoUG(b,gt)))); if (index<0) { // get new index and assign index = numEdges_++; // write index through to coarser grids typename UG_NS::Element* father_ = UG_NS::EFather(target_); while (father_!=0) { if (!UG_NS::hasCopy(father_)) break; // handle only copies UG_NS::leafIndex(UG_NS::GetEdge(UG_NS::Corner(father_, UGGridRenumberer::verticesDUNEtoUG(a,gt)), UG_NS::Corner(father_, UGGridRenumberer::verticesDUNEtoUG(b,gt)))) = index; father_ = UG_NS::EFather(father_); } } } // codim 1 (faces): todo if (dim==3) for (unsigned int i=0; i::leafIndex(UG_NS::SideVector(target_,UGGridRenumberer::facesDUNEtoUG(i,gt))); if (index==std::numeric_limits::max()) // not visited yet { // get new index and assign GeometryType gtType = referenceElement(gt).type(i,1); if (gtType.isSimplex()) index = numTriFaces_++; else if (gtType.isCube()) index = numQuadFaces_++; else { std::cout << "face geometry type is " << gtType << std::endl; DUNE_THROW(GridError, "wrong geometry type in face"); } // write index through to coarser grid typename UG_NS::Element* father_ = UG_NS::EFather(target_); while (father_!=0) { if (!UG_NS::hasCopy(father_)) break; // handle only copies UG_NS::leafIndex(UG_NS::SideVector(father_,UGGridRenumberer::facesDUNEtoUG(i,gt))) = index; father_ = UG_NS::EFather(father_); } } } // set the isLeaf information of the nodes based on the leaf elements for (unsigned int i=0; i< element.subEntities(dim); i++) { // no need to renumber, we are visiting all the corners typename UG_NS::Node* theNode = UG_NS::Corner(target_,i); theNode->isLeaf = true; } } if (containsLeafElements) coarsestLevelWithLeafElements_ = level_; } // Update the list of geometry types present myTypes_[dim-1].resize(0); myTypes_[dim-1].push_back(GeometryTypes::line); if (dim==3) { myTypes_[1].resize(0); if (numTriFaces_ > 0) myTypes_[1].push_back(GeometryTypes::triangle); if (numQuadFaces_ > 0) myTypes_[1].push_back(GeometryTypes::quadrilateral); } // /////////////////////////////// // Init the element indices // /////////////////////////////// numSimplices_ = 0; numPyramids_ = 0; numPrisms_ = 0; numCubes_ = 0; for (const auto& element : elements(grid_.leafGridView())) { GeometryType eType = element.type(); if (eType.isSimplex()) UG_NS::leafIndex(element.impl().target_) = numSimplices_++; else if (eType.isPyramid()) UG_NS::leafIndex(element.impl().target_) = numPyramids_++; else if (eType.isPrism()) UG_NS::leafIndex(element.impl().target_) = numPrisms_++; else if (eType.isCube()) UG_NS::leafIndex(element.impl().target_) = numCubes_++; else { DUNE_THROW(GridError, "Found the GeometryType " << eType << ", which should never occur in a UGGrid!"); } } // Update the list of geometry types present myTypes_[0].resize(0); if (numSimplices_ > 0) myTypes_[0].push_back(GeometryTypes::simplex(dim)); if (numPyramids_ > 0) myTypes_[0].push_back(GeometryTypes::pyramid); if (numPrisms_ > 0) myTypes_[0].push_back(GeometryTypes::prism); if (numCubes_ > 0) myTypes_[0].push_back(GeometryTypes::cube(dim)); // ////////////////////////////// // Init the vertex indices // ////////////////////////////// // leaf index in node writes through to vertex ! numVertices_ = 0; if (nodePermutation!=0 and grid_.maxLevel()==0) { for (const auto& vertex : vertices(grid_.leafGridView())) UG_NS::leafIndex(vertex.impl().target_) = (*nodePermutation)[numVertices_++]; } else { for (const auto& vertex : vertices(grid_.leafGridView())) UG_NS::leafIndex(vertex.impl().target_) = numVertices_++; } myTypes_[dim].resize(0); myTypes_[dim].push_back(GeometryTypes::vertex); } // Explicit template instantiations to compile the stuff in this file template class UGGridLevelIndexSet >; template class UGGridLevelIndexSet >; template class UGGridLeafIndexSet >; template class UGGridLeafIndexSet >; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridindexsets.hh000066400000000000000000000614421511655130300223520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_INDEXSETS_HH #define DUNE_UGGRID_INDEXSETS_HH /** \file \brief The index and id sets for the UGGrid class */ #include #include #include #include namespace Dune { template class UGGridLevelIndexSet : public IndexSet, UG::UINT> { constexpr static int dim = GridImp::dimension; public: /** \brief Default constructor Unfortunately we can't force the user to init grid_ and level_, because UGGridLevelIndexSets are meant to be stored in an array. \todo I want to make this constructor private, but I can't, because it is called by UGGrid through a std::vector::resize() */ UGGridLevelIndexSet () : level_(0), numSimplices_(0), numPyramids_(0), numPrisms_(0), numCubes_(0), numVertices_(0), numEdges_(0), numTriFaces_(0), numQuadFaces_(0) {} //! get index of an entity template unsigned int index (const typename GridImp::Traits::template Codim::Entity& e) const { return UG_NS::levelIndex(e.impl().getTarget()); } /** \brief Get index of subEntity of a codim cc entity * \param codim Codimension WITH RESPECT TO THE GRID of the subentity whose index we want */ template unsigned int subIndex (const typename GridImp::Traits::template Codim::Entity& entity, int i, unsigned int codim) const { // The entity is a vertex, so each subentity must be a vertex too (anything else is not supported) if (cc==dim) { assert(codim==dim); return UG_NS::levelIndex(entity.impl().getTarget()); } // The following block is for 2d grids if constexpr (dim==2) { // The entity is an element if constexpr (cc==0) { // Element indices if (codim==0) return UG_NS::levelIndex(entity.impl().getTarget()); // Edge indices if (codim==1) { auto ref_el = referenceElement(entity.type()); auto a = ref_el.subEntity(i,dim-1,0,dim); auto b = ref_el.subEntity(i,dim-1,1,dim); return UG_NS::levelIndex(UG_NS::GetEdge(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(a,entity.type())), UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(b,entity.type())))); } // Vertex indices if (codim==dim) return UG_NS::levelIndex(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(i,entity.type()))); } // The entity is an edge if constexpr (cc==1) return UG_NS::levelIndex(entity.impl().getTarget()->links[i].nbnode); } // The following block is for 3d grids if constexpr (dim==3) { // The entity is an element if constexpr (cc==0) { // Element indices if (codim==0) return UG_NS::levelIndex(entity.impl().getTarget()); // Face indices if (codim==1) return UG_NS::levelIndex(UG_NS::SideVector(entity.impl().getTarget(), UGGridRenumberer::facesDUNEtoUG(i,entity.type()))); // Edge indices if (codim==2) { auto ref_el = referenceElement(entity.type()); auto a = ref_el.subEntity(i,dim-1,0,dim); auto b = ref_el.subEntity(i,dim-1,1,dim); return UG_NS::levelIndex(UG_NS::GetEdge(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(a,entity.type())), UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(b,entity.type())))); } // Vertex indices if (codim==3) return UG_NS::levelIndex(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(i,entity.type()))); } // The entity is a face if constexpr (cc==1) { DUNE_THROW(NotImplemented, "Subindices of an element face"); } // The entity is an edge if constexpr (cc==2) return UG_NS::levelIndex(entity.impl().getTarget()->links[i].nbnode); } // Should never happen return std::numeric_limits::max(); } //! get number of entities of given codim, type and on this level std::size_t size (int codim) const { if (codim==0) return numSimplices_+numPyramids_+numPrisms_+numCubes_; if (codim==dim) return numVertices_; if (codim==dim-1) return numEdges_; if (codim==1) return numTriFaces_+numQuadFaces_; DUNE_THROW(NotImplemented, "wrong codim!"); } //! get number of entities of given codim, type and on this level std::size_t size (GeometryType type) const { int codim = GridImp::dimension-type.dim(); if (codim==0) { if (type.isSimplex()) return numSimplices_; else if (type.isPyramid()) return numPyramids_; else if (type.isPrism()) return numPrisms_; else if (type.isCube()) return numCubes_; else return 0; } if (codim==dim) { return numVertices_; } if (codim==dim-1) { return numEdges_; } if (codim==1) { if (type.isSimplex()) return numTriFaces_; else if (type.isCube()) return numQuadFaces_; else return 0; } DUNE_THROW(NotImplemented, "Wrong codim!"); } //! obtain all geometry types of entities in domain std::vector< GeometryType > types ( int codim ) const { return myTypes_[ codim ]; } /** \brief Return true if e is contained in the index set. \note If 'entity' is from another grid this method may still return 'true'. This is acceptable by the Dune grid interface specification. */ template bool contains (const EntityType& entity) const { return entity.level() == level_; } /** \brief Update the level indices. This method is called after each grid change */ void update(const GridImp& grid, int level, std::vector* nodePermutation=0); const GridImp* grid_; int level_; int numSimplices_; int numPyramids_; int numPrisms_; int numCubes_; int numVertices_; int numEdges_; int numTriFaces_; int numQuadFaces_; std::vector myTypes_[dim+1]; }; template class UGGridLeafIndexSet : public IndexSet, UG::UINT> { public: /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ constexpr static int dim = std::remove_const::type::dimension; //! constructor stores reference to a grid and level UGGridLeafIndexSet (const GridImp& g) : grid_(g), coarsestLevelWithLeafElements_(0) {} //! get index of an entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template int index (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { return UG_NS::leafIndex(e.impl().getTarget()); } //! get index of subEntity of a codim 0 entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template unsigned int subIndex (const typename std::remove_const::type::Traits::template Codim::Entity& entity, int i, unsigned int codim) const { // The entity is a vertex, so each subentity must be a vertex too (anything else is not supported) if (cc==dim) { assert(codim==dim); return UG_NS::leafIndex(entity.impl().getTarget()); } // The following block is for 2d grids if constexpr (dim==2) { // The entity is an element if constexpr (cc==0) { // Element indices if (codim==0) return UG_NS::leafIndex(entity.impl().getTarget()); // Edge indices if (codim==1) { auto ref_el = referenceElement(entity.type()); auto a = ref_el.subEntity(i,dim-1,0,dim); auto b = ref_el.subEntity(i,dim-1,1,dim); return UG_NS::leafIndex(UG_NS::GetEdge(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(a,entity.type())), UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(b,entity.type())))); } // Vertex indices if (codim==dim) return UG_NS::leafIndex(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(i,entity.type()))); } // The entity is an edge if constexpr (cc==1) return UG_NS::leafIndex(entity.impl().getTarget()->links[i].nbnode); } // The following block is for 3d grids if constexpr (dim==3) { // The entity is an element if constexpr (cc==0) { // Element indices if (codim==0) return UG_NS::leafIndex(entity.impl().getTarget()); // Face indices if (codim==1) return UG_NS::leafIndex(UG_NS::SideVector(entity.impl().getTarget(), UGGridRenumberer::facesDUNEtoUG(i,entity.type()))); // Edge indices if (codim==2) { auto ref_el = referenceElement(entity.type()); auto a = ref_el.subEntity(i,dim-1,0,dim); auto b = ref_el.subEntity(i,dim-1,1,dim); return UG_NS::leafIndex(UG_NS::GetEdge(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(a,entity.type())), UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(b,entity.type())))); } // Vertex indices if (codim==3) return UG_NS::leafIndex(UG_NS::Corner(entity.impl().getTarget(), UGGridRenumberer::verticesDUNEtoUG(i,entity.type()))); } // The entity is a face if constexpr (cc==1) { DUNE_THROW(NotImplemented, "Subindices of an element face"); } // The entity is an edge if constexpr (cc==2) return UG_NS::leafIndex(entity.impl().getTarget()->links[i].nbnode); } return std::numeric_limits::max(); } //! get number of entities of given codim and type std::size_t size (GeometryType type) const { if (type.dim()==GridImp::dimension) { if (type.isSimplex()) return numSimplices_; else if (type.isPyramid()) return numPyramids_; else if (type.isPrism()) return numPrisms_; else if (type.isCube()) return numCubes_; else return 0; } if (type.dim()==0) { return numVertices_; } if (type.dim()==1) { return numEdges_; } if (type.isTriangle()) return numTriFaces_; else if (type.isQuadrilateral()) return numQuadFaces_; return 0; } //! get number of entities of given codim std::size_t size (int codim) const { int s=0; for (GeometryType gt : types(codim)) s += size(gt); return s; } //! obtain all geometry types of entities in domain std::vector< GeometryType > types ( int codim ) const { return myTypes_[ codim ]; } /** \brief Return true if e is contained in the index set. \note If 'entity' is from another grid this method may still return 'true'. This is acceptable by the Dune grid interface specification. */ template bool contains (const EntityType& entity) const { return UG_NS::isLeaf(entity.impl().getTarget()); } /** \brief Update the leaf indices. This method is called after each grid change. */ void update(std::vector* nodePermutation=0); const GridImp& grid_; /** \brief The lowest level that contains leaf elements This corresponds to UG's fullRefineLevel, which is, unfortunately only computed if you use some nontrivial UG algebra. Thus we compute it ourselves, and use it to speed up the leaf iterators. */ unsigned int coarsestLevelWithLeafElements_; int numSimplices_; int numPyramids_; int numPrisms_; int numCubes_; int numVertices_; int numEdges_; int numTriFaces_; int numQuadFaces_; std::vector myTypes_[dim+1]; }; /** \brief Implementation class for the UGGrid Id sets The UGGridGlobalIdSet and the UGGridLocalIdSet are identical. This class implements them both at once. */ template class UGGridIdSet : public IdSet,typename UG_NS::type::dimension>::UG_ID_TYPE> { constexpr static int dim = std::remove_const::type::dimension; typedef typename std::pair::Element*, int> Face; /** \brief Look for copy of a face on the next-lower grid level. \todo This method is not implemented very efficiently */ static Face getFatherFace(const Face& face) { // set up result object Face resultFace; resultFace.first = UG_NS::EFather(face.first); // If there is no father element then we know there is no father face /** \bug This is not true when doing vertical load balancing. */ if (resultFace.first == nullptr) return resultFace; // Get all corners of the face std::set::Vertex*> corners; for (int i=0; i::Corners_Of_Side(face.first, face.second); i++) corners.insert(UG_NS::Corner(face.first, UG_NS::Corner_Of_Side(face.first, face.second, i))->myvertex); // Loop over all faces of the father element and look for a face that has the same vertices for (int i=0; i::Sides_Of_Elem(resultFace.first); i++) { // Copy father face into set std::set::Vertex*> fatherFaceCorners; for (int j=0; j::Corners_Of_Side(resultFace.first, i); j++) fatherFaceCorners.insert(UG_NS::Corner(resultFace.first, UG_NS::Corner_Of_Side(resultFace.first, i, j))->myvertex); // Do the vertex sets match? if (corners==fatherFaceCorners) { resultFace.second = i; return resultFace; } } // No father face found resultFace.first = nullptr; return resultFace; } public: //! constructor stores reference to a grid UGGridIdSet (const GridImp& g) : grid_(g) {} /** \brief Get id of an entity We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. \bug Since copies of different entities on different levels are supposed to have the same id, we look for the ancestor on the coarsest level that is still a copy of the entity we are interested in. However, the current implementation only searches on one processor, while with UG's vertical load balancing the ancestors of an entity may be distributed across different processors. This will lead to very-difficult-to-fix bugs. Unfortunately, the proper fix for this is not easy, either. */ template typename UG_NS::UG_ID_TYPE id (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { if (cd==0) { // If we're asked for the id of an element, and that element is a copy of its father, then // we return the id of the lowest ancestor that the element is a copy from. That way copies // of elements have the same id const typename UG_NS::Element* ancestor = (typename UG_NS::Element* const)(e.impl().getTarget()); /** \todo We should really be using an isCopy() method rather than hasCopy() */ while (UG_NS::EFather(ancestor) && UG_NS::hasCopy(UG_NS::EFather(ancestor))) ancestor = UG_NS::EFather(ancestor); return UG_NS::id(ancestor); } if (dim-cd==1) { const typename UG_NS::Edge* edge = (typename UG_NS::Edge* const)(e.impl().getTarget()); // If this edge is the copy of an edge on a lower level we return the id of that lower // edge, because Dune wants entities which are copies of each other to have the same id. // BUG: in the parallel setting, we only search on our own processor, but the lowest // copy may actually be on a different processor! const typename UG_NS::Edge* fatherEdge; fatherEdge = GetFatherEdge(edge); while (fatherEdge // fatherEdge exists // ... and it must be a true copy father && ( (fatherEdge->links[0].nbnode->myvertex == edge->links[0].nbnode->myvertex && fatherEdge->links[1].nbnode->myvertex == edge->links[1].nbnode->myvertex) || (fatherEdge->links[0].nbnode->myvertex == edge->links[1].nbnode->myvertex && fatherEdge->links[1].nbnode->myvertex == edge->links[0].nbnode->myvertex) ) ) { edge = fatherEdge; fatherEdge = GetFatherEdge(edge); } return UG_NS::id(edge); } if (cd == dim) { typename UG_NS::Node *node = reinterpret_cast::Node *>(e.impl().getTarget()); return UG_NS::id(node); } // The entity must be a facet in a 3d grid assert(cd==1 && dim==3); typename UG_NS::Vector *facet = reinterpret_cast::Vector *>(e.impl().getTarget()); // If 'facet' is the copy of a facet on a lower level we return the id of that lower-level // facet, because Dune wants entities that are copies of each other to have the same id. // BUG: in a distributed setting, we only search on our own process, but the lowest // copy may actually be on a different process! // Going up and down the refinement hierarchy can only be done through an // element that has 'facet' as a face. // TODO: Simplify this if ever SideVector objects get hierarchical information typename UG_NS::Element* supportingElement = (typename UG_NS::Element*)facet->object; int thisSideVectorUGNumbering = -1; // Dummy value for (int side=0; side::Sides_Of_Elem(supportingElement); side++) { auto sideVector = UG_NS::SideVector(supportingElement,side); if (sideVector==facet) thisSideVectorUGNumbering = side; } Face face(supportingElement, thisSideVectorUGNumbering); // Go down in the grid hierarchy as long as there is a copy father-facet Face fatherFace; fatherFace = getFatherFace(face); while (fatherFace.first) { face = fatherFace; fatherFace = getFatherFace(face); } // Actually return the facet id return UG_NS::id(UG_NS::SideVector(face.first, face.second)); } /** \brief Get id of subentity We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. \bug Since copies of different entities on different levels are supposed to have the same id, we look for the ancestor on the coarsest level that is still a copy of the entity we are interested in. However, the current implementation only searches on one processor, while with UG's vertical load balancing the ancestors of an entity may be distributed across different processors. This will lead to very-difficult-to-fix bugs. Unfortunately, the proper fix for this is not easy, either. */ typename UG_NS::UG_ID_TYPE subId (const typename std::remove_const::type::Traits::template Codim<0>::Entity& e, int i, unsigned int codim) const { if (codim==0) return id<0>(e); const typename UG_NS::Element* target = e.impl().getTarget(); GeometryType type = e.type(); if (dim-codim==1) { auto ref_el = referenceElement(type); auto a = ref_el.subEntity(i,dim-1,0,dim); auto b = ref_el.subEntity(i,dim-1,1,dim); const typename UG_NS::Edge* edge = UG_NS::GetEdge(UG_NS::Corner(target, UGGridRenumberer::verticesDUNEtoUG(a,type)), UG_NS::Corner(target, UGGridRenumberer::verticesDUNEtoUG(b,type))); // If this edge is the copy of an edge on a lower level we return the id of that lower // edge, because Dune wants entities which are copies of each other to have the same id. // BUG: in the parallel setting, we only search on our own processor, but the lowest // copy may actually be on a different processor! const typename UG_NS::Edge* fatherEdge; fatherEdge = GetFatherEdge(edge); while (fatherEdge // fatherEdge exists // ... and it must be a true copy father && ( (fatherEdge->links[0].nbnode->myvertex == edge->links[0].nbnode->myvertex && fatherEdge->links[1].nbnode->myvertex == edge->links[1].nbnode->myvertex) || (fatherEdge->links[0].nbnode->myvertex == edge->links[1].nbnode->myvertex && fatherEdge->links[1].nbnode->myvertex == edge->links[0].nbnode->myvertex) ) ) { edge = fatherEdge; fatherEdge = GetFatherEdge(edge); } return UG_NS::id(edge); } if (codim==1) { // Faces Face face(target, UGGridRenumberer::facesDUNEtoUG(i,type)); // If this face is the copy of a face on a lower level we return the id of that lower // face, because Dune wants entities which are copies of each other to have the same id. // BUG: in the parallel setting, we only search on our own processor, but the lowest // copy may actually be on a different processor! Face fatherFace; fatherFace = getFatherFace(face); while (fatherFace.first) { face = fatherFace; fatherFace = getFatherFace(face); } return UG_NS::id(UG_NS::SideVector(face.first, face.second)); } if (codim==dim) { return UG_NS::id(UG_NS::Corner(target, UGGridRenumberer::verticesDUNEtoUG(i,type))); } DUNE_THROW(GridError, "UGGrid<" << dim << ">::subId isn't implemented for codim==" << codim ); } //private: const GridImp& grid_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridintersectioniterators.hh000066400000000000000000000106271511655130300250060ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGINTERSECTIONIT_HH #define DUNE_UGINTERSECTIONIT_HH /** \file * \brief The UGGridIntersectionIterator class */ namespace Dune { /** \brief Implementation of the UGGrid LevelIntersectionIterator */ template class UGGridLevelIntersectionIterator { constexpr static int dim = GridImp::dimension; friend class UGGridEntity<0,dim,GridImp>; public: typedef Dune::Intersection< GridImp, Dune::UGGridLevelIntersection< GridImp > > Intersection; UGGridLevelIntersectionIterator() {} /** The default Constructor makes empty Iterator */ UGGridLevelIntersectionIterator(typename UG_NS::Element* center, int nb, const GridImp* gridImp) : intersection_(UGGridLevelIntersection(center,nb,gridImp)) {} //! equality bool equals(const UGGridLevelIntersectionIterator& other) const { return intersection_.impl().equals(other.intersection_.impl()); } //! prefix increment void increment() { intersection_.impl().neighborCount_++; intersection_.impl().geometry_.reset(); intersection_.impl().geometryInInside_.reset(); intersection_.impl().geometryInOutside_.reset(); } //! \brief dereferencing const Intersection & dereference() const { return intersection_; } private: mutable Intersection intersection_; }; /** \brief Implementation of the UGGrid LeafIntersectionIterator */ template class UGGridLeafIntersectionIterator { constexpr static int dim = GridImp::dimension; friend class UGGridEntity<0,dim,GridImp>; public: typedef Dune::Intersection< GridImp, Dune::UGGridLeafIntersection< GridImp > > Intersection; UGGridLeafIntersectionIterator() {} UGGridLeafIntersectionIterator(typename UG_NS::Element* center, int nb, const GridImp* gridImp) : intersection_(UGGridLeafIntersection(center,nb,gridImp)) {} //! equality bool equals(const UGGridLeafIntersectionIterator& other) const { return intersection_.impl().equals(other.intersection_.impl()); } /** \brief Prefix increment. The UG data structure does not directly contain information about leaf neighbors/intersections. Therefore getting that information is fairly expensive. In particular, it is too expensive to start looking for the next intersection whenever 'increment()' is called. Therefore, all intersections of one face of the 'inside' element are precomputed, and incrementing then traverses this precomputed list. If the list is exhausted the iterator advances to the next faces and precomputes all intersections there. */ void increment() { UGGridLeafIntersection& intersectionImp = intersection_.impl(); intersectionImp.subNeighborCount_++; using Face = typename UGGridLeafIntersection::Face; auto onLastFace = [&intersectionImp]{ // move to the next face intersectionImp.neighborCount_++; intersectionImp.subNeighborCount_ = 0; // if the next face is not the end iterator construct all intersections for it if (intersectionImp.neighborCount_ < UG_NS::Sides_Of_Elem(intersectionImp.center_)) intersectionImp.constructLeafSubfaces(); }; // are there no more intersections for the current element face? std::visit(orderedOverload( [&](std::monostate){onLastFace();}, [&](Face face){onLastFace();}, [&](const std::vector& faces){ if (intersectionImp.subNeighborCount_ >= faces.size() ) onLastFace(); } ), intersectionImp.leafSubFaces_); // make sure geometries are not taken from the cache the next time // the geometry{|InInside|InOutside} methods are called. intersectionImp.geometry_.reset(); intersectionImp.geometryInInside_.reset(); intersectionImp.geometryInOutside_.reset(); } //! \brief dereferencing const Intersection & dereference() const { return intersection_; } private: mutable Intersection intersection_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridintersections.cc000066400000000000000000000653621511655130300232300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include namespace Dune { namespace { template void computeOuterNormal( const typename UG_NS::Element* center, const int neighborCount, const FieldVector& local, FieldVector& outerNormal ) { // ////////////////////////////////////////////////////// // Implementation for 3D // ////////////////////////////////////////////////////// if constexpr (dim == 3) { if (UG_NS::Corners_Of_Side(center, neighborCount) == 3) { // A triangular intersection. The normals are constant const FieldVector& aPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center, neighborCount, 0))->myvertex->iv.x; const FieldVector& bPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center, neighborCount, 1))->myvertex->iv.x; const FieldVector& cPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center, neighborCount, 2))->myvertex->iv.x; const FieldVector ba = bPos - aPos; const FieldVector ca = cPos - aPos; // Cross product outerNormal[0] = ba[1]*ca[2] - ba[2]*ca[1]; outerNormal[1] = ba[2]*ca[0] - ba[0]*ca[2]; outerNormal[2] = ba[0]*ca[1] - ba[1]*ca[0]; } else { // A quadrilateral: compute the normal in each corner and do bilinear interpolation // The cornerNormals array uses UG corner numbering FieldVector cornerNormals[4]; for (int i=0; i<4; i++) { // Compute the normal on the i-th corner const FieldVector aPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center,neighborCount,i))->myvertex->iv.x; const FieldVector bPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center,neighborCount,(i+1)%4))->myvertex->iv.x; const FieldVector cPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center,neighborCount,(i+3)%4))->myvertex->iv.x; const FieldVector ba = bPos - aPos; const FieldVector ca = cPos - aPos; // Cross product cornerNormals[i][0] = ba[1]*ca[2] - ba[2]*ca[1]; cornerNormals[i][1] = ba[2]*ca[0] - ba[0]*ca[2]; cornerNormals[i][2] = ba[0]*ca[1] - ba[1]*ca[0]; } // Bilinear interpolation for (int i=0; i<3; i++) outerNormal[i] = (1-local[0])*(1-local[1])*cornerNormals[0][i] + local[0] * (1-local[1]) * cornerNormals[1][i] + local[0] * local[1] * cornerNormals[2][i] + (1-local[0]) * local[1] * cornerNormals[3][i]; } } else { // if (dim==3) ... else // ////////////////////////////////////////////////////// // Implementation for 2D // ////////////////////////////////////////////////////// // Get the vertices of this side. const FieldVector& aPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center, neighborCount, 0))->myvertex->iv.x; const FieldVector& bPos = UG_NS::Corner(center,UG_NS::Corner_Of_Side(center, neighborCount, 1))->myvertex->iv.x; // compute normal outerNormal[0] = bPos[1] - aPos[1]; outerNormal[1] = aPos[0] - bPos[0]; } } } /* namespace */ template auto UGGridLevelIntersection::outerNormal (const FaceVector& local) const -> const WorldVector& { computeOuterNormal(center_, neighborCount_, local, outerNormal_); return outerNormal_; } template< class GridImp> auto UGGridLevelIntersection::geometryInInside () const -> LocalGeometry { if (!geometryInInside_) { int numCornersOfSide = UG_NS::Corners_Of_Side(center_, neighborCount_); auto coordinates = LocalGeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::verticesDUNEtoUG(i, intersectionGeometryType); int cornerIdx = UG_NS::Corner_Of_Side(center_, neighborCount_, ugIdx); // get the corners local coordinates UG_NS::getCornerLocal(center_,cornerIdx,coordinates[i]); } geometryInInside_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } return LocalGeometry( *geometryInInside_ ); } template< class GridImp> auto UGGridLevelIntersection::geometry () const -> Geometry { if (!geometry_) { int numCornersOfSide = UG_NS::Corners_Of_Side(center_, neighborCount_); auto coordinates = GeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::verticesDUNEtoUG(i, intersectionGeometryType); int cornerIdx = UG_NS::Corner_Of_Side(center_, neighborCount_, ugIdx); coordinates[i] = UG_NS::Corner(center_, cornerIdx)->myvertex->iv.x; } geometry_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } return Geometry( *geometry_ ); } template auto UGGridLevelIntersection::geometryInOutside () const -> LocalGeometry { if (!geometryInOutside_) { typename UG_NS::Element *other; // if we have a neighbor on this level, then return it other = UG_NS::NbElem(center_, neighborCount_); if (!other) DUNE_THROW(GridError,"no neighbor found"); // /////////////////////////////////////// // go on and get the local coordinates // /////////////////////////////////////// int numCornersOfSide = UG_NS::Corners_Of_Side(center_,neighborCount_); auto coordinates = LocalGeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::Corner_Of_Side(center_, neighborCount_, i); const typename UG_NS::Node* node = UG_NS::Corner(center_,localCornerNumber); // get this node's local index in the neighbor element int j; for (j=0; j::Corners_Of_Elem(other); j++) if (UG_NS::Corner(other, j) == node) break; assert(j::Corners_Of_Elem(other)); // get the local coordinate there UG_NS::getCornerLocal(other,j,coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)]); } geometryInOutside_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } return LocalGeometry( *geometryInOutside_ ); } template< class GridImp> int UGGridLevelIntersection::indexInOutside () const { const typename UG_NS::Element *other; // Look for a neighbor on this level if ((other = UG_NS::NbElem(center_, neighborCount_)) == nullptr) DUNE_THROW(GridError,"There is no neighbor element!"); // Find the corresponding side in the neighbor element const int nSides = UG_NS::Sides_Of_Elem(other); int i; for (i=0; i::NbElem(other,i) == center_) break; // now we have to renumber the side i return UGGridRenumberer::facesUGtoDUNE(i, UG_NS::Tag(other)); } // ///////////////////////////////////////////////////////////////////////////// // Implementations for the class UGGridLeafIntersection // ///////////////////////////////////////////////////////////////////////////// /** \bug Doesn't work properly for nonplanar nonconforming quadrilateral faces, because the local coordinates are interpreted as being with respect to the element face. Instead, they should be interpreted with respect to the intersection. If the face is flat this doesn't matter. */ template auto UGGridLeafIntersection::outerNormal (const FaceVector& local) const -> const WorldVector& { computeOuterNormal(center_, neighborCount_, local, outerNormal_); return outerNormal_; } template< class GridImp> auto UGGridLeafIntersection< GridImp >::geometryInInside () const -> LocalGeometry { if (!geometryInInside_) { std::optional otherFace = getCurrentFace(); if (!otherFace // boundary intersection // or if this face is the intersection || UG_NS::myLevel(otherFace->first) <= UG_NS::myLevel(center_) || (UG_NS::myLevel(otherFace->first) > UG_NS::myLevel(center_) && std::holds_alternative(leafSubFaces_)) ) { // ////////////////////////////////////////////////////// // The easy case: a conforming intersection // ////////////////////////////////////////////////////// int numCornersOfSide = UG_NS::Corners_Of_Side(center_, neighborCount_); auto coordinates = LocalGeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::Corner_Of_Side(center_, neighborCount_, i); // get the corners local coordinates UG_NS::getCornerLocal(center_,cornerIdx,coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)]); } geometryInInside_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } else { int numCornersOfSide = UG_NS::Corners_Of_Side(otherFace->first, otherFace->second); auto coordinates = LocalGeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i& worldPos = UG_NS::Corner(otherFace->first, UG_NS::Corner_Of_Side(otherFace->first,otherFace->second,i))->myvertex->iv.x; // Get the local coordinate with respect to this element // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[dim*dim]; UG_NS::Corner_Coordinates(center_, cornerCoords); // Actually do the computation /** \todo Why is this const_cast necessary? */ UG_NS::GlobalToLocal(UG_NS::Corners_Of_Elem(center_), const_cast(cornerCoords), worldPos, coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)]); } geometryInInside_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } } return LocalGeometry( *geometryInInside_ ); } template< class GridImp> auto UGGridLeafIntersection< GridImp >::geometry () const -> Geometry { if (!geometry_) { std::optional otherFace = getCurrentFace(); if (!otherFace // boundary intersection // or if this face is the intersection || UG_NS::myLevel(otherFace->first) <= UG_NS::myLevel(center_) || (UG_NS::myLevel(otherFace->first) > UG_NS::myLevel(center_) && std::holds_alternative(leafSubFaces_)) ) { // ////////////////////////////////////////////////////// // The easy case: a conforming intersection // ////////////////////////////////////////////////////// int numCornersOfSide = UG_NS::Corners_Of_Side(center_, neighborCount_); auto coordinates = GeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::Corner_Of_Side(center_, neighborCount_, i); const typename UG_NS::Node* node = UG_NS::Corner(center_, cornerIdx); coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)] = node->myvertex->iv.x; } geometry_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } else { int numCornersOfSide = UG_NS::Corners_Of_Side(otherFace->first, otherFace->second); auto coordinates = GeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::Corner_Of_Side(otherFace->first, otherFace->second, i); // Get world coordinate of other element's vertex const FieldVector& worldPos = UG_NS::Corner(otherFace->first,cornerIdx)->myvertex->iv.x; // and poke them into the Geometry coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)] = worldPos; } geometry_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } } return Geometry( *geometry_ ); } /** \todo Needs to be checked for the nonconforming case */ template< class GridImp> auto UGGridLeafIntersection< GridImp >::geometryInOutside () const -> LocalGeometry { if (!geometryInOutside_) { std::optional otherFace = getCurrentFace(); if (!otherFace) DUNE_THROW(GridError, "There is no neighbor!"); if ( // if this face is the intersection UG_NS::myLevel(otherFace->first) <= UG_NS::myLevel(center_) || (UG_NS::myLevel(otherFace->first) > UG_NS::myLevel(center_) && std::holds_alternative(leafSubFaces_)) ) { int numCornersOfSide = UG_NS::Corners_Of_Side(center_, neighborCount_); auto coordinates = LocalGeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::Corner_Of_Side(center_, neighborCount_, i); // Get world coordinate of this element's vertex const FieldVector& worldPos = UG_NS::Corner(center_,cornerIdx)->myvertex->iv.x; // Get the local coordinate with respect to the other element // coorddim*coorddim is an upper bound for the number of vertices UGCtype* cornerCoords[dim*dim]; UG_NS::Corner_Coordinates(otherFace->first, cornerCoords); // Actually do the computation /** \todo Why is this const_cast necessary? */ UG_NS::GlobalToLocal(UG_NS::Corners_Of_Elem(otherFace->first), const_cast(cornerCoords), worldPos, coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)]); } geometryInOutside_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } else { int numCornersOfSide = UG_NS::Corners_Of_Side(otherFace->first, otherFace->second); auto coordinates = LocalGeometryImpl::makeCornerStorage(numCornersOfSide); GeometryType intersectionGeometryType = (numCornersOfSide == 4 ? GeometryTypes::cube(dim-1) : GeometryTypes::simplex(dim-1)); for (std::size_t i=0; i::Corner_Of_Side(otherFace->first,otherFace->second,i); UG_NS::getCornerLocal(otherFace->first, v, coordinates[UGGridRenumberer::verticesUGtoDUNE(i, intersectionGeometryType)]); } geometryInOutside_ = std::make_optional(intersectionGeometryType, std::move(coordinates)); } } return LocalGeometry( *geometryInOutside_ ); } template< class GridImp> int UGGridLeafIntersection::indexInOutside () const { std::optional otherFace = getCurrentFace(); if (!otherFace) DUNE_THROW(GridError,"There is no neighbor!"); #ifndef NDEBUG const int nSides = UG_NS::Sides_Of_Elem(otherFace->first); assert(otherFace->second < nSides); #endif // Renumber to DUNE numbering unsigned int tag = UG_NS::Tag(otherFace->first); return UGGridRenumberer::facesUGtoDUNE(otherFace->second, tag); } template int UGGridLeafIntersection::getFatherSide(const Face& currentFace) const { const typename UG_NS::Element* father = UG_NS::EFather(currentFace.first); // /////////////////////////////////////////////////////////////////////////////// // Find the topological father face // The implementation is different for 2d and 3d grids, because UG provides // more information in the 2d case. It is hence easier to handle. // /////////////////////////////////////////////////////////////////////////////// if (dim==2) { // Get the two nodes of the current element face const typename UG_NS::Node* n0 = UG_NS::Corner(currentFace.first, UG_NS::Corner_Of_Side(currentFace.first, currentFace.second, 0)); const typename UG_NS::Node* n1 = UG_NS::Corner(currentFace.first, UG_NS::Corner_Of_Side(currentFace.first, currentFace.second, 1)); // We assume that at least one of the two nodes has a father on the next-coarser level. // A node that doesn't corresponds to an edge. assert(!(UG::D2::ReadCW(n0, UG::D2::NTYPE_CE) == UG::D2::MID_NODE && UG::D2::ReadCW(n1, UG::D2::NTYPE_CE) == UG::D2::MID_NODE)); const typename UG_NS::Node* fatherN0, *fatherN1; if (UG::D2::ReadCW(n1, UG::D2::NTYPE_CE) == UG::D2::MID_NODE) { // n0 exists on the coarser level, but n1 doesn't const typename UG_NS::Edge* fatherEdge = (const typename UG_NS::Edge*)n1->father; fatherN0 = fatherEdge->links[0].nbnode; fatherN1 = fatherEdge->links[1].nbnode; } else if (UG::D2::ReadCW(n0, UG::D2::NTYPE_CE) == UG::D2::MID_NODE) { // n1 exists on the coarser level, but n0 doesn't const typename UG_NS::Edge* fatherEdge = (const typename UG_NS::Edge*)n0->father; fatherN0 = fatherEdge->links[0].nbnode; fatherN1 = fatherEdge->links[1].nbnode; } else { // This edge is a copy fatherN0 = (const typename UG_NS::Node*)n0->father; fatherN1 = (const typename UG_NS::Node*)n1->father; } // Find the corresponding side on the father element for (int i=0; i::Sides_Of_Elem(father); i++) { if ( (fatherN0 == UG_NS::Corner(father,UG_NS::Corner_Of_Side(father, i, 0)) && fatherN1 == UG_NS::Corner(father,UG_NS::Corner_Of_Side(father, i, 1))) || (fatherN0 == UG_NS::Corner(father,UG_NS::Corner_Of_Side(father, i, 1)) && fatherN1 == UG_NS::Corner(father,UG_NS::Corner_Of_Side(father, i, 0)))) return i; } DUNE_THROW(InvalidStateException,"getFatherSide() didn't find a father."); } else { // dim==3 // Get the nodes int nNodes = UG_NS::Corners_Of_Side(currentFace.first,currentFace.second); std::vector::Node*> n(nNodes); for (int i=0; i::Corner(currentFace.first,UG_NS::Corner_Of_Side(currentFace.first, currentFace.second, i)); std::set::Node*> fatherNodes; // No more than four father nodes for (int i=0; i::Node*)n[i]->father); break; case UG::D3::MID_NODE : fatherNodes.insert( ((const typename UG_NS::Edge*)n[i]->father)->links[0].nbnode ); fatherNodes.insert( ((const typename UG_NS::Edge*)n[i]->father)->links[1].nbnode ); break; default : break; // Do nothing } } /* When explicitly using anisotropic refinement rules without green closure there may be the case that a quad face is split into two quads and a triangle. In that case the triangle has two CORNER_NODEs and one MID_NODES. The current code does not know how to handle this situation. */ if (fatherNodes.size() < 3) DUNE_THROW(NotImplemented, "Anisotropic nonconforming grids are not fully implemented!"); // Find the corresponding side on the father element for (int i=0; i::Sides_Of_Elem(father); i++) { unsigned int found = 0; for (const auto& fn : fatherNodes) for (int k=0; k::Corners_Of_Side(father,i); k++) if (fn == UG_NS::Corner(father,UG_NS::Corner_Of_Side(father, i, k))) { found++; break; } if (found==fatherNodes.size()) return i; } } // Should never happen DUNE_THROW(GridError, "Reached code path that should never be reached"); } template< class GridImp> void UGGridLeafIntersection::constructLeafSubfaces() { // Do nothing if level neighbor doesn't exit typename UG_NS::Element* levelNeighbor = UG_NS::NbElem(center_, neighborCount_); leafSubFaces_ = std::monostate{}; // If the level neighbor exists and is leaf, then there is only a single leaf intersection if (levelNeighbor != nullptr && UG_NS::isLeaf(levelNeighbor)) { leafSubFaces_ = Face(levelNeighbor, numberInNeighbor(center_, levelNeighbor)); } // If the level neighbor does not exist, then leaf intersections exist only with neighbors // on lower levels, if they exist at all. Therefore we descend in the hierarchy towards // the coarsest grid until we have found a level neighbor. else if (levelNeighbor == nullptr) { // I am a leaf and the neighbor does not exist: go down Face currentFace(center_, neighborCount_); const typename UG_NS::Element* father = UG_NS::EFather(center_); while (father != nullptr #ifdef ModelP && !UG_NS::isGhost(father) #endif ) { // Get the father element side of the current element side int fatherSide = getFatherSide(currentFace); // Do we have a neighbor on across this side? If yes we have exactly one leaf intersection // with that neighbor. typename UG_NS::Element* otherElement = UG_NS::NbElem(father, fatherSide); if (otherElement) { const int nSides = UG_NS::Sides_Of_Elem(otherElement); for (int i=0; i::NbElem(otherElement,i) == father) { leafSubFaces_ = Face(otherElement, i); break; } break; } // Go further down currentFace = Face(father,fatherSide); father = UG_NS::EFather(father); } } // Third case: there is a neighbor but it is not leaf. Therefore we have to go up in the // hierarchy (i.e. towards finer grids) until we are on the leaf level. UG is nice enough // to provide descendents of element faces itself. We simply use that functionality. else { std::list list; std::size_t leafCount = 0; const int levelNeighborSide = numberInNeighbor(center_, levelNeighbor); list.emplace_back(levelNeighbor, levelNeighborSide); // ////////////////////////////////////////////////// // Get_Sons_of_ElementSide only computes direct sons. Therefore in order to get all // descendents (to then filter out the leaf descendents) we have to search iteratively. // We do a breadth-first search. // ////////////////////////////////////////////////// for (const auto& f : list) { const typename UG_NS::Element* theElement = f.first; UG::INT Sons_of_Side = 0; typename UG_NS::Element* SonList[UG_NS::MAX_SONS]; UG::INT SonSides[UG_NS::MAX_SONS]; if (!UG_NS::isLeaf(theElement)) { int rv = Get_Sons_of_ElementSide(theElement, f.second, // Input element side number &Sons_of_Side, // Number of topological sons of the element side SonList, // Output elements SonSides, // Output element side numbers true, false, true); if (rv!=0) DUNE_THROW(GridError, "Get_Sons_of_ElementSide returned with error value " << rv); for (int i=0; i &vec = leafSubFaces_.template emplace>(); vec.reserve(leafCount); std::copy_if(std::begin(list), std::end(list), std::back_inserter(vec), [](Face face) { return UG_NS::isLeaf(face.first); }); } } } // Explicit template instantiations to compile the stuff in this file template class UGGridLevelIntersection >; template class UGGridLevelIntersection >; template class UGGridLeafIntersection >; template class UGGridLeafIntersection >; } /* namespace Dune */ dune-grid-2.11.0/dune/grid/uggrid/uggridintersections.hh000066400000000000000000000406061511655130300232340ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_INTERSECTIONS_HH #define DUNE_UGGRID_INTERSECTIONS_HH #include #include #include #include #include #include /** \file * \brief The UGGridLeafIntersection and UGGridLevelIntersection classes */ namespace Dune { /** \brief Implementation class for an intersection with an element on the same level */ template class UGGridLevelIntersection { public: constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; private: friend class UGGridEntity<0,dim,GridImp>; // The type used to store coordinates typedef typename GridImp::ctype UGCtype; // The corresponding iterator needs to access all members friend class UGGridLevelIntersectionIterator; typedef FieldVector WorldVector; typedef FieldVector FaceVector; typedef typename GridImp::Traits::template Codim<1>::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim<1>::LocalGeometryImpl LocalGeometryImpl; public: typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::Entity Entity; UGGridLevelIntersection() : center_(nullptr) , neighborCount_(-1) // fixed marker value for invalid intersections to make equals() work , gridImp_(nullptr) {} /** The default Constructor makes empty Iterator \todo Should be private */ UGGridLevelIntersection(typename UG_NS::Element* center, int nb, const GridImp* gridImp) : center_(center), neighborCount_(nb), gridImp_(gridImp) {} //! equality bool equals(const UGGridLevelIntersection& i) const { return center_==i.center_ && neighborCount_ == i.neighborCount_; } //! return Entity on the inside of this intersection //! (that is the entity where we started this iterator) Entity inside() const { return Entity(UGGridEntity<0,dim,GridImp>(center_,gridImp_)); } //! return Entity on the outside of this intersection //! (that is the neighboring Entity) Entity outside() const { typename UG_NS::Element* otherelem = UG_NS::NbElem(center_, neighborCount_); if (otherelem==0) DUNE_THROW(GridError,"no neighbor found in outside()"); return Entity(UGGridEntity<0,dim,GridImp>(otherelem,gridImp_)); } //! return true if intersection is with boundary. bool boundary () const { return UG_NS::Side_On_Bnd(center_, neighborCount_); } //! return true if across the edge an neighbor on this level exists bool neighbor () const { return UG_NS::NbElem(center_, neighborCount_) != nullptr; } /** \brief return index of the corresponding coarse grid boundary segment */ size_t boundarySegmentIndex () const { #ifndef NDEBUG if (!boundary()) DUNE_THROW(GridError, "Calling boundarySegmentIndex() for a non-boundary intersection!"); #endif UG_NS::Set_Current_BVP(gridImp_->multigrid_->theBVP); return UG_NS::boundarySegmentIndex(center_, neighborCount_); } /** \brief Returns true, because UG level intersections are always conforming */ bool conforming() const { return true; } //! intersection of codimension 1 of this neighbor with element where //! iteration started. //! Here returned element is in LOCAL coordinates of the element //! where iteration started. LocalGeometry geometryInInside () const; //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in GLOBAL coordinates of the element where iteration started. Geometry geometry () const; /** \brief obtain the type of reference element for this intersection */ GeometryType type () const { return geometryInInside().type(); } //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in LOCAL coordinates of neighbor LocalGeometry geometryInOutside () const; //! local index of codim 1 entity in self where intersection is contained in int indexInInside () const { return UGGridRenumberer::facesUGtoDUNE(neighborCount_, UG_NS::Tag(center_)); } //! local index of codim 1 entity in neighbor where intersection is contained int indexInOutside () const; //! return outer normal const WorldVector& outerNormal (const FaceVector& local) const; //! return outer normal const WorldVector& integrationOuterNormal (const FaceVector& local) const { integrationOuterNormal_ = outerNormal(local); const UGCtype scale = geometry().integrationElement( local ) / integrationOuterNormal_.two_norm(); integrationOuterNormal_ *= scale; return integrationOuterNormal_; } //! return outer normal const WorldVector& unitOuterNormal (const FaceVector& local) const { unitOuterNormal_ = outerNormal(local); unitOuterNormal_ /= unitOuterNormal_.two_norm(); return unitOuterNormal_; } //! return outer normal const WorldVector& centerUnitOuterNormal () const { auto refElement = referenceElement(geometry()); return unitOuterNormal(refElement.position(0,0)); } private: //! vector storing the outer normal mutable WorldVector outerNormal_; mutable WorldVector integrationOuterNormal_; mutable WorldVector unitOuterNormal_; //! pointers holding the global and local geometries mutable std::optional geometry_; mutable std::optional geometryInInside_; mutable std::optional geometryInOutside_; //! The UG element the iterator was created from typename UG_NS::Element *center_; //! count on which neighbor we are looking at. Note that this is interpreted in UG's ordering! int neighborCount_; /** \brief The grid we belong to. We need it to call set_Current_BVP */ const GridImp* gridImp_; }; /** \brief Implementation class for a leaf intersection in a UGGrid */ template class UGGridLeafIntersection { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; friend class UGGridEntity<0,dim,GridImp>; // The type used to store coordinates typedef typename GridImp::ctype UGCtype; // An element face identified by the element and a face number typedef std::pair::Element*, int> Face; // The corresponding iterator needs to access all members friend class UGGridLeafIntersectionIterator; typedef FieldVector WorldVector; typedef FieldVector FaceVector; typedef typename GridImp::Traits::template Codim<1>::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim<1>::LocalGeometryImpl LocalGeometryImpl; public: typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; typedef typename GridImp::template Codim<0>::Entity Entity; UGGridLeafIntersection() : center_(nullptr) , neighborCount_(-1) // fixed marker value for invalid intersections to make equals() work , subNeighborCount_(~unsigned(0)) // fixed marker value for invalid intersections to make equals() work , gridImp_(nullptr) {} UGGridLeafIntersection(typename UG_NS::Element* center, int nb, const GridImp* gridImp) : center_(center), neighborCount_(nb), subNeighborCount_(0), gridImp_(gridImp) { if (neighborCount_ < UG_NS::Sides_Of_Elem(center_)) constructLeafSubfaces(); } //! equality bool equals(const UGGridLeafIntersection& other) const { return center_ == other.center_ && neighborCount_ == other.neighborCount_ && subNeighborCount_ == other.subNeighborCount_; } //! return Entity on the inside of this intersection //! (that is the Entity where we started this Iterator) Entity inside() const { return Entity(UGGridEntity<0,dim,GridImp>(center_,gridImp_)); } //! return Entity on the outside of this intersection //! (that is the neighboring Entity) Entity outside() const { std::optional otherelem = getCurrentFace(); if (!otherelem) DUNE_THROW(GridError,"no neighbor found in outside()"); /** \todo Remove the const_cast */ return Entity(UGGridEntity<0,dim,GridImp>(const_cast::Element*>(otherelem->first),gridImp_)); } //! return true if intersection is with boundary. bool boundary () const { return UG_NS::Side_On_Bnd(center_, neighborCount_); } //! return true if a neighbor element exists across this intersection bool neighbor () const { return getCurrentFace().has_value(); } /** \brief Return index of corresponding coarse grid boundary segment */ size_t boundarySegmentIndex () const { #ifndef NDEBUG if (!boundary()) DUNE_THROW(GridError, "Calling boundarySegmentIndex() for a non-boundary intersection!"); #endif UG_NS::Set_Current_BVP(gridImp_->multigrid_->theBVP); return UG_NS::boundarySegmentIndex(center_, neighborCount_); } /** \brief Is this intersection conforming? */ bool conforming() const { std::optional otherFace = getCurrentFace(); if (!otherFace // boundary intersection // inside and outside are on the same level || UG_NS::myLevel(otherFace->first) == UG_NS::myLevel(center_) // outside is on a higher level, but there is only one intersection || (UG_NS::myLevel(otherFace->first) > UG_NS::myLevel(center_) && std::holds_alternative(leafSubFaces_))) return true; const typename UG_NS::Element* outside = otherFace->first; // outside is on a lower level. we have to check whether vertices match int numInsideIntersectionVertices = UG_NS::Corners_Of_Side(center_, neighborCount_); int numOutsideIntersectionVertices = UG_NS::Corners_Of_Side(outside, otherFace->second); if (numInsideIntersectionVertices != numOutsideIntersectionVertices) return false; // Loop over all vertices of the face of this element that corresponds to this intersection for (int i=0; i::Vertex* insideVertex = UG_NS::Corner(center_, UG_NS::Corner_Of_Side(center_, neighborCount_, i))->myvertex; // Loop over all vertices of the corresponding element side of the outside element bool vertexFound = false; for (int j=0; j::Vertex* outsideVertex = UG_NS::Corner(outside, UG_NS::Corner_Of_Side(outside, otherFace->second, j))->myvertex; // Stop if we have found corresponding vertices if (insideVertex==outsideVertex) { vertexFound = true; break; } } // One of this face's vertices has not been found in the face of the outside element if (vertexFound == false) return false; } return true; } //! intersection of codimension 1 of this neighbor with element where //! iteration started. //! Here returned element is in LOCAL coordinates of the element //! where iteration started. LocalGeometry geometryInInside () const; //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in GLOBAL coordinates of the element where iteration started. Geometry geometry () const; //! intersection of codimension 1 of this neighbor with element where iteration started. //! Here returned element is in LOCAL coordinates of neighbor LocalGeometry geometryInOutside () const; /** \brief obtain the type of reference element for this intersection */ GeometryType type () const { return geometryInInside().type(); } //! local index of codim 1 entity in self where intersection is contained in int indexInInside () const { return UGGridRenumberer::facesUGtoDUNE(neighborCount_, UG_NS::Tag(center_)); } //! local index of codim 1 entity in neighbor where intersection is contained int indexInOutside () const; //! return outer normal, this should be dependent on local //! coordinates for higher order boundary const WorldVector& outerNormal (const FaceVector& local) const; //! return outer normal const WorldVector& integrationOuterNormal (const FaceVector& local) const { integrationOuterNormal_ = outerNormal(local); //integrationOuterNormal_ /= integrationOuterNormal_.two_norm(); //integrationOuterNormal_ *= geometry().integrationElement(local); const UGCtype scale = geometry().integrationElement( local ) / integrationOuterNormal_.two_norm(); integrationOuterNormal_ *= scale; return integrationOuterNormal_; } //! return outer normal const WorldVector& unitOuterNormal (const FaceVector& local) const { unitOuterNormal_ = outerNormal(local); unitOuterNormal_ /= unitOuterNormal_.two_norm(); return unitOuterNormal_; } //! return outer normal const WorldVector& centerUnitOuterNormal () const { auto refElement = referenceElement(geometry()); return unitOuterNormal(refElement.position(0,0)); } private: //********************************************************** // private methods //********************************************************** int numberInNeighbor(const typename UG_NS::Element* me, const typename UG_NS::Element* other) const { const int nSides = UG_NS::Sides_Of_Elem(other); for (int i=0; i::NbElem(other,i) == me) return i; // this point should not be reached, otherwise throw exception DUNE_THROW(InvalidStateException,"no consistency in numberInNeighbor"); return -1; } /** \brief Obtain current face */ std::optional getCurrentFace() const { return std::visit(orderedOverload( [&](std::monostate) -> std::optional { return std::nullopt;}, [&](Face face) -> std::optional { return face;}, [&](const std::vector& faces) -> std::optional { return faces[subNeighborCount_];} ), leafSubFaces_); } /** \brief Find the topological father face of a given fact*/ int getFatherSide(const Face& currentFace) const; /** \brief Precompute list of all leaf intersections of the current element face */ void constructLeafSubfaces(); //! vector storing the outer normal mutable WorldVector outerNormal_; mutable WorldVector integrationOuterNormal_; mutable WorldVector unitOuterNormal_; //! pointer to global and local intersection geometries mutable std::optional geometry_; mutable std::optional geometryInInside_; mutable std::optional geometryInOutside_; //! The UG element the iterator was created from typename UG_NS::Element *center_; //! count on which neighbor we are lookin' at. Note that this is interpreted in UG's ordering! int neighborCount_; /** \brief List of precomputed intersections and optimize for common case: when one or no faces exist */ std::variant> leafSubFaces_; /** \brief Current position in the leafSubFaces_ array */ unsigned int subNeighborCount_; /** \brief The grid we belong to. We need it to call set_Current_BVP */ const GridImp* gridImp_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridleafiterator.hh000066400000000000000000000147451511655130300230310ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRIDLEAFITERATOR_HH #define DUNE_UGGRIDLEAFITERATOR_HH /** \file * \brief The UGGridLeafIterator class */ #include namespace Dune { /** \brief Iterator over all entities of a given codimension and level of a grid. * \ingroup UGGrid */ template class UGGridLeafIterator { constexpr static int dim = GridImp::dimension; // The type of the UG entity we're pointing to typedef typename UG_NS::template Entity::T UGEntity; public: typedef typename GridImp::template Codim::Entity Entity; constexpr static int codimension = codim; /** \brief Constructor setting up a 'begin' iterator */ UGGridLeafIterator(const GridImp& grid) : grid_(&grid) { // Entities below this level are certainly not leaf entities int levelCounter = grid.leafIndexSet_.coarsestLevelWithLeafElements_; // If the grid is distributed, the grid on the 'coarsestLevelWithLeafElements_' may actually be empty, because // it is all on other processors. Therefore we have to also look at finer levels. // In a sequential program, the while loops always iterate exactly once. auto& entity = entity_.impl(); if (codim==dim) { if (pitype==All_Partition || pitype==Ghost_Partition) { do { entity.setToTarget((UGEntity*)UG_NS::PFirstNode(grid_->multigrid_->grids[levelCounter++]), grid_); } while (not entity.getTarget() and levelCounter <= grid.maxLevel()); } else { do { entity.setToTarget((UGEntity*)UG_NS::FirstNode(grid_->multigrid_->grids[levelCounter++]), grid_); } while (not entity.getTarget() and levelCounter <= grid.maxLevel()); } } else if (codim==0) { if (pitype==All_Partition || pitype==Ghost_Partition) { do { entity.setToTarget((UGEntity*)UG_NS::PFirstElement(grid_->multigrid_->grids[levelCounter++]), grid_); } while (not entity.getTarget() and levelCounter <= grid.maxLevel()); } else { do { entity.setToTarget((UGEntity*)UG_NS::FirstElement(grid_->multigrid_->grids[levelCounter++]), grid_); } while (not entity.getTarget() and levelCounter <= grid.maxLevel()); } } else DUNE_THROW(NotImplemented, "UGGrid leaf iterators for codimension " << codim); if (entity.getTarget() && ! (isLeaf() && isInPartition())) increment(); } /** \brief Constructor setting up an 'end' iterator */ UGGridLeafIterator() : grid_(nullptr) { entity_.impl().setToTarget(nullptr,nullptr); } //! prefix increment void increment() { // Increment until you find a leaf entity do { globalIncrement(); } while (entity_.impl().getTarget() && ! (isLeaf() && isInPartition())); } //! dereferencing const Entity& dereference() const {return entity_;} //! equality bool equals(const UGGridLeafIterator& other) const { return entity_ == other.entity_; } private: /** * \brief Return true iff the current entity is a leaf (element version) */ bool isLeaf(const typename UG_NS::Element* theElement) { return UG_NS::isLeaf(theElement); } /** * \brief Return true iff the current entity is a leaf (node version) */ bool isLeaf(const typename UG_NS::Node* theNode) { // in the case of nodes: only visit the uppermost entity if more than one is leaf if (theNode->son != nullptr) return false; return UG_NS::isLeaf(theNode); } /** * \brief Return true iff the current entity has the right PartitionType. */ bool isInPartition() { Dune::PartitionType entityPIType = entity_.impl().partitionType(); switch (pitype) { case All_Partition: return true; case Ghost_Partition: if (entityPIType == GhostEntity) return true; else return false; case Interior_Partition: if (entityPIType == InteriorEntity) return true; else return false; case InteriorBorder_Partition: case Overlap_Partition: case OverlapFront_Partition: if (entityPIType == BorderEntity || entityPIType == InteriorEntity) return true; else return false; default: DUNE_THROW(NotImplemented, "Unhandled partition iterator type " << pitype); } } /** * \brief Return true iff the current entity is a leaf entity */ bool isLeaf() { return isLeaf(entity_.impl().getTarget()); } /** \brief This increment makes the iterator wander over all entities on all levels */ void globalIncrement() { auto& entity = entity_.impl(); // Store the current level, so we know it even when pointing to an invalid entity int level = entity.level(); // Increment on this level entity.setToTarget(UG_NS::succ(entity.getTarget()), grid_); // If beyond the end of this level set to first of next level if (!entity.getTarget() && level < grid_->maxLevel()) { if (codim==dim) { if (pitype==All_Partition || pitype==Ghost_Partition) entity.setToTarget((UGEntity*)UG_NS::PFirstNode(grid_->multigrid_->grids[level+1]), grid_); else entity.setToTarget((UGEntity*)UG_NS::FirstNode(grid_->multigrid_->grids[level+1]), grid_); } else if (codim==0) { if (pitype==All_Partition || pitype==Ghost_Partition) entity.setToTarget((UGEntity*)UG_NS::PFirstElement(grid_->multigrid_->grids[level+1]), grid_); else entity.setToTarget((UGEntity*)UG_NS::FirstElement(grid_->multigrid_->grids[level+1]), grid_); } else DUNE_THROW(NotImplemented, "UGGrid leaf iterators for codimension " << codim); } } // ///////////////////////////////////// // Data members // ///////////////////////////////////// const GridImp* grid_; //! The makeable entity that the iterator is pointing to Entity entity_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridleveliterator.hh000066400000000000000000000100211511655130300232100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRIDLEVELITERATOR_HH #define DUNE_UGGRIDLEVELITERATOR_HH /** \file * \brief The UGGridLevelIterator class */ #include namespace Dune { //********************************************************************** // // --UGGridLevelIterator // --LevelIterator /** \brief Iterator over all entities of a given codimension and level of a grid. * \ingroup UGGrid */ template class UGGridLevelIterator { constexpr static int dim = GridImp::dimension; friend class UGGridEntity; friend class UGGridEntity<0, GridImp::dimension,GridImp>; // The type of the UG entity we're pointing to typedef typename UG_NS::template Entity::T UGEntity; public: typedef typename GridImp::template Codim::Entity Entity; constexpr static int codimension = codim; //! Constructor explicit UGGridLevelIterator() : gridImp_(nullptr) { entity_.impl().setToTarget(nullptr,nullptr); } //! Constructor explicit UGGridLevelIterator(const GridImp& gridImp, int level) : gridImp_(&gridImp) { auto& entity = entity_.impl(); typename UG_NS::Grid *theGrid = const_cast::Grid* >(gridImp_->multigrid_->grids[level]); assert(theGrid); if (codim==dim) { if (pitype==All_Partition || pitype==Ghost_Partition) entity.setToTarget((UGEntity*)UG_NS::PFirstNode(theGrid),gridImp_); else entity.setToTarget((UGEntity*)UG_NS::FirstNode(theGrid),gridImp_); } else if (codim==0) { if (pitype==All_Partition || pitype==Ghost_Partition) entity.setToTarget((UGEntity*)UG_NS::PFirstElement(theGrid),gridImp_); else entity.setToTarget((UGEntity*)UG_NS::FirstElement(theGrid),gridImp_); } else DUNE_THROW(NotImplemented, "UGGrid level iterators for codimension " << codim); if (entity.getTarget() && !entityOK_()) increment(); } //! prefix increment void increment() { auto& entity = entity_.impl(); assert(entity.level() == UG_NS::myLevel(entity.getTarget())); // Increment do { entity.setToTarget(UG_NS::succ(entity.getTarget()),gridImp_); } while (entity.getTarget() && !entityOK_()); } //! dereferencing const Entity& dereference() const {return entity_;} //! equality bool equals(const UGGridLevelIterator& other) const { return entity_ == other.entity_; } private: /** * \brief Return true iff the current entity is within the right * partition. */ bool entityOK_() { Dune::PartitionType entityPIType = entity_.impl().partitionType(); switch (pitype) { case All_Partition: return true; case Ghost_Partition: if (entityPIType == GhostEntity) return true; else return false; case Interior_Partition: if (entityPIType == InteriorEntity) return true; else return false; case InteriorBorder_Partition: case Overlap_Partition: case OverlapFront_Partition: if (entityPIType == BorderEntity || entityPIType == InteriorEntity) return true; else return false; default: DUNE_THROW(NotImplemented, "Unhandled partition iterator type " << pitype); } } // ///////////////////////////////////// // Data members // ///////////////////////////////////// const GridImp* gridImp_; //! The makeable entity that the iterator is pointing to Entity entity_; }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridlocalgeometry.hh000066400000000000000000000035401511655130300232050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_LOCALGEOMETRY_HH #define DUNE_UGGRID_LOCALGEOMETRY_HH /** \file * \brief The UGGridLocalGeometry class */ #include #include namespace Dune { /** \brief Geometry of an entity embedded in another element, not in the world space * \ingroup UGGrid \tparam mydim Dimension of the corresponding reference element \tparam coorddim Dimension of the coordinate space This class is just an adaptor that allows to use MultiLinearGeometry as the implementation for the UGGrid local geometries. We cannot use MultiLinearGeometry directly, because the template parameters are different. */ template class UGGridLocalGeometry : public MultiLinearGeometry> { public: // inherit constructor from MultiLinearGeometry using MultiLinearGeometry>::MultiLinearGeometry; // factory of uninitialized corner storage used to construct this geometry static auto makeCornerStorage(std::size_t count) { if constexpr (mydim < 2) // storage when simplex(dim) == cube(dim) return std::array, (1 << mydim)>{}; else // storage when simplex(dim) != cube(dim) return ReservedVector, (1 << mydim)>(count); } }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/uggridrenumberer.hh000066400000000000000000000245531511655130300225140ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGGRID_RENUMBERER_HH #define DUNE_UGGRID_RENUMBERER_HH /** \file \brief Contains a helper class that encapsulates the vertex numbering conversions between UG and DUNE The UG numbering conventions can be found in the file 'gm/element.c' of UG. */ #include namespace Dune { /** \brief Generic class which doesn't actually renumber anything. * * It is needed as the 1d implementation, used to set up intersections for 2d grids. */ template class UGGridRenumberer { public: /** \brief Turn a local vertex number from DUNE numbering to UG numbering */ static int verticesDUNEtoUG(int i, const GeometryType& type) { return i; } /** \brief Turn a local vertex number from UG numbering to DUNE numbering */ static int verticesUGtoDUNE(int i, const GeometryType& type) { return i; } }; /** \brief DUNE and UG use different local numberings for the subentities of elements. This class does the conversions for 2d-grids. \todo Is there an efficient and elegant way to remove one of the redundant facesUGtoDUNE methods? */ template <> class UGGridRenumberer<2> { public: /** \brief Turn a local edge number from DUNE numbering to UG numbering */ static int verticesDUNEtoUG(int i, const GeometryType& type) { if (type.isCube()) { // vertices of a quadrilateral const int renumbering[4] = {0, 1, 3, 2}; return renumbering[i]; } return i; } /** \brief Turn a local vertex number from UG numbering to DUNE numbering */ static int verticesUGtoDUNE(int i, const GeometryType& type) { if (type.isCube()) { // vertices of a quadrilateral const int renumbering[4] = {0, 1, 3, 2}; return renumbering[i]; } return i; } /** \brief Turn a local face number from DUNE numbering to UG numbering */ static int facesDUNEtoUG(int i, const GeometryType& type) { if (type.isCube()) { // faces of a quadrilateral const int renumbering[4] = {3, 1, 0, 2}; return renumbering[i]; } if (type.isSimplex()) { // faces of a triangle const int renumbering[3] = {0, 2, 1}; return renumbering[i]; } return i; } /** \brief Turn a local edge number from DUNE numbering to UG numbering */ static int edgesDUNEtoUG(int i, const GeometryType& type) { return facesDUNEtoUG(i, type); } /** \brief Turn a local face number from UG numbering to DUNE numbering */ static int facesUGtoDUNE(int i, const GeometryType& type) { if (type.isCube()) { // faces of a quadrilateral const int renumbering[4] = {2, 1, 3, 0}; return renumbering[i]; } else if (type.isSimplex()) { // faces of a triangle const int renumbering[3] = {0, 2, 1}; return renumbering[i]; } return i; } /** \brief Turn a local edge number from UG numbering to DUNE numbering */ static int edgesUGtoDUNE(int i, const GeometryType& type) { return facesUGtoDUNE(i, type); } /** \brief Turn a local face number from UG numbering to DUNE numbering * \param tag The UG way to specify element types. See the file ug/gm/gm.h for the possible values */ static int facesUGtoDUNE(int i, unsigned int tag) { if (tag == UG::D2::QUADRILATERAL) { // faces of a quadrilateral const int renumbering[4] = {2, 1, 3, 0}; return renumbering[i]; } else if (tag == UG::D2::TRIANGLE) { // faces of a triangle const int renumbering[3] = {0, 2, 1}; return renumbering[i]; } return i; } /** \brief Turn a local edge number from UG numbering to DUNE numbering * \param tag The UG way to specify element types. See the file ug/gm/gm.h for the possible values */ static int edgesUGtoDUNE(int i, unsigned int tag) { return facesUGtoDUNE(i, tag); } }; /** \brief DUNE and UG use different local numberings for the subentities of elements. This class does the conversions for 3d-grids. \todo Is there an efficient and elegant way to remove one of the redundant facesUGtoDUNE methods? */ template <> class UGGridRenumberer<3> { public: /** \brief Turn a local edge number from new DUNE numbering to UG numbering */ static int verticesDUNEtoUG(int i, const GeometryType& type) { if (type.isCube()) { const int renumbering[8] = {0, 1, 3, 2, 4, 5, 7, 6}; return renumbering[i]; } if (type.isPyramid()) { const int renumbering[5] = {0, 1, 3, 2, 4}; return renumbering[i]; } return i; } /** \brief Turn a local vertex number from UG numbering to DUNE numbering */ static int verticesUGtoDUNE(int i, const GeometryType& type) { if (type.isCube()) { const int renumbering[8] = {0, 1, 3, 2, 4, 5, 7, 6}; return renumbering[i]; } if (type.isPyramid()) { const int renumbering[5] = {0, 1, 3, 2, 4}; return renumbering[i]; } return i; } /** \brief Turn a local edge number from DUNE numbering to UG numbering */ static int edgesDUNEtoUG(int i, const GeometryType& type) { if (type.isCube()) { // edges of a hexahedron const int renumbering[12] = {4, 5, 7, 6, 3, 1, 0, 2, 11, 9, 8, 10}; return renumbering[i]; } if (type.isPrism()) { // edges of a prism const int renumbering[9] = {3, 4, 5, 0, 2, 1, 6, 8, 7}; return renumbering[i]; } if (type.isPyramid()) { // edges of a pyramid const int renumbering[8] = {3, 1, 0, 2, 4, 5, 7, 6}; return renumbering[i]; } if (type.isSimplex()) { // edges of a tetrahedon const int renumbering[6] = {0, 2, 1, 3, 4, 5}; return renumbering[i]; } return i; } /** \brief Turn a local edge number from UG numbering to DUNE numbering */ static int edgesUGtoDUNE(int i, const GeometryType& type) { if (type.isCube()) { // edges of a hexahedron const int renumbering[12] = {6, 5, 7, 4, 0, 1, 3, 2, 10, 9, 11, 8}; return renumbering[i]; } if (type.isPrism()) { // edges of a prism const int renumbering[9] = {3, 5, 4, 0, 1, 2, 6, 8, 7}; return renumbering[i]; } if (type.isPyramid()) { // edges of a pyramid const int renumbering[8] = {2, 1, 3, 0, 4, 5, 7, 6}; return renumbering[i]; } if (type.isSimplex()) { // edges of a tetrahedon const int renumbering[6] = {0, 2, 1, 3, 4, 5}; return renumbering[i]; } return i; } /** \brief Turn a local edge number from UG numbering to DUNE numbering * \param tag The UG way to specify element types. See the file ug/gm/gm.h for the possible values */ static int edgesUGtoDUNE(int i, unsigned int tag) { if (tag == UG::D3::HEXAHEDRON) { // edges of a hexahedron const int renumbering[12] = {6, 5, 7, 4, 0, 1, 3, 2, 10, 9, 11, 8}; return renumbering[i]; } if (tag == UG::D3::PRISM) { // edges of a prism const int renumbering[9] = {3, 5, 4, 0, 1, 2, 6, 8, 7}; return renumbering[i]; } if (tag == UG::D3::PYRAMID) { // edges of a pyramid const int renumbering[8] = {2, 1, 3, 0, 4, 5, 7, 6}; return renumbering[i]; } else if (tag == UG::D3::TETRAHEDRON) { // edges of a tetrahedon const int renumbering[6] = {0, 2, 1, 3, 4, 5}; return renumbering[i]; } return i; } /** \brief Turn a local face number from DUNE numbering to UG numbering */ static int facesDUNEtoUG(int i, const GeometryType& type) { if (type.isCube()) { // faces of a hexahedron const int renumbering[6] = {4, 2, 1, 3, 0, 5}; return renumbering[i]; } if (type.isPrism()) { // faces of a prism const int renumbering[5] = {1, 3, 2, 0, 4}; return renumbering[i]; } if (type.isPyramid()) { // faces of a pyramid const int renumbering[5] = {0, 4, 2, 1, 3}; return renumbering[i]; } if (type.isSimplex()) { // faces of a tetrahedon const int renumbering[4] = {0, 3, 2, 1}; return renumbering[i]; } return i; } /** \brief Turn a local face number from UG numbering to DUNE numbering */ static int facesUGtoDUNE(int i, const GeometryType& type) { if (type.isCube()) { // faces of a hexahedron const int renumbering[6] = {4, 2, 1, 3, 0, 5}; return renumbering[i]; } if (type.isPrism()) { // faces of a hexahedron const int renumbering[5] = {3, 0, 2, 1, 4}; return renumbering[i]; } if (type.isPyramid()) { // faces of a hexahedron const int renumbering[5] = {0, 3, 2, 4, 1}; return renumbering[i]; } if (type.isSimplex()) { // faces of a tetrahedon const int renumbering[4] = {0, 3, 2, 1}; return renumbering[i]; } return i; } /** \brief Turn a local face number from UG numbering to DUNE numbering * \param tag The UG way to specify element types. See the file ug/gm/gm.h for the possible values */ static int facesUGtoDUNE(int i, unsigned int tag) { if (tag == UG::D3::HEXAHEDRON) { // faces of a hexahedron const int renumbering[6] = {4, 2, 1, 3, 0, 5}; return renumbering[i]; } if (tag == UG::D3::PRISM) { // faces of a hexahedron const int renumbering[5] = {3, 0, 2, 1, 4}; return renumbering[i]; } if (tag == UG::D3::PYRAMID) { // faces of a hexahedron const int renumbering[5] = {0, 3, 2, 4, 1}; return renumbering[i]; } else if (tag == UG::D3::TETRAHEDRON) { // faces of a tetrahedon const int renumbering[4] = {0, 3, 2, 1}; return renumbering[i]; } return i; } }; } #endif dune-grid-2.11.0/dune/grid/uggrid/uggridviews.hh000066400000000000000000000321411511655130300214730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_UGGRID_UGGRIDVIEWS_HH #define DUNE_GRID_UGGRID_UGGRIDVIEWS_HH #include #include #include namespace Dune { template< class GridImp> class UGGridLevelGridView; template< class GridImp> class UGGridLeafGridView; /** \brief Collect several types associated to UGGrid LevelGridViews */ template< class GridImp> struct UGGridLevelGridViewTraits { typedef UGGridLevelGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid :: Traits :: LevelIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid :: Traits :: LevelIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid :: Traits :: LevelIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; template< int cd > struct Codim { typedef typename Grid :: Traits :: template Codim< cd > :: template Partition< All_Partition > :: LevelIterator Iterator; typedef typename Grid :: Traits :: template Codim< cd > :: Entity Entity; typedef typename Grid :: template Codim< cd > :: Geometry Geometry; typedef typename Grid :: template Codim< cd > :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template< PartitionIteratorType pit > struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid :: template Codim< cd > :: template Partition< pit > :: LevelIterator Iterator; }; }; constexpr static bool conforming = Capabilities :: isLevelwiseConforming< Grid > :: v; }; /** \brief Implementation class of LevelGridViews for UGGrid */ template< class GridImp> class UGGridLevelGridView { typedef UGGridLevelGridView This; public: typedef UGGridLevelGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Traits :: Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits :: template Codim {}; constexpr static bool conforming = Traits :: conforming; static constexpr int dimension = Grid::dimension; UGGridLevelGridView ( const Grid &grid, int level ) : grid_( &grid ), level_( level ) {} /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { assert( grid_ ); return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return grid().levelIndexSet( level_ ); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( level_, codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( level_, type ); } bool isConforming() const { return Traits::conforming; } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { if (!grid().multigrid_) DUNE_THROW(GridError, "The grid has not been properly initialized!"); if (!grid().multigrid_->grids[level_]) DUNE_THROW(GridError, "LevelIterator in nonexisting level " << level_ << " requested!"); return UGGridLevelIterator( grid(), level_ ); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator begin () const { if (!grid().multigrid_) DUNE_THROW(GridError, "The grid has not been properly initialized!"); if (!grid().multigrid_->grids[level_]) DUNE_THROW(GridError, "LevelIterator in nonexisting level " << level_ << " requested!"); return UGGridLevelIterator( grid(), level_ ); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return UGGridLevelIterator(); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator end () const { return UGGridLevelIterator(); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ilevelbegin(); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ilevelend(); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize(int codim) const { return 0; } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize(int codim) const { return (codim==0) ? 1 : 0; } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( CommDataHandleIF< DataHandleImp, DataType > &dataHandle, InterfaceType iftype, CommunicationDirection dir ) const { #ifdef ModelP Hybrid::forEach(std::make_index_sequence< Grid::dimension+1 >{}, [&](auto codim) { if (dataHandle.contains(Grid::dimension, codim)) grid().template communicateUG_(*this, level_, dataHandle, iftype, dir); }); #endif // ModelP } private: const Grid *grid_; int level_; }; template< class GridImp> struct UGGridLeafGridViewTraits { typedef UGGridLeafGridView< GridImp > GridViewImp; /** \brief type of the grid */ typedef typename std::remove_const::type Grid; /** \brief type of the index set */ typedef typename Grid :: Traits :: LeafIndexSet IndexSet; /** \brief type of the intersection */ typedef typename Grid :: Traits :: LeafIntersection Intersection; /** \brief type of the intersection iterator */ typedef typename Grid :: Traits :: LeafIntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Grid :: Traits :: Communication Communication; template< int cd > struct Codim { typedef typename Grid :: Traits :: template Codim< cd > :: template Partition< All_Partition > :: LeafIterator Iterator; typedef typename Grid :: Traits :: template Codim< cd > :: Entity Entity; typedef typename Grid :: template Codim< cd > :: Geometry Geometry; typedef typename Grid :: template Codim< cd > :: LocalGeometry LocalGeometry; /** \brief Define types needed to iterate over entities of a given partition type */ template struct Partition { /** \brief iterator over a given codim and partition type */ typedef typename Grid :: template Codim< cd > :: template Partition< pit > :: LeafIterator Iterator; }; }; constexpr static bool conforming = Capabilities :: isLeafwiseConforming< Grid > :: v; }; /** \brief Implementation class of LeafGridViews for UGGrid */ template< class GridImp > class UGGridLeafGridView { typedef UGGridLeafGridView This; public: typedef UGGridLeafGridViewTraits Traits; /** \brief type of the grid */ typedef typename Traits::Grid Grid; /** \brief type of the index set */ typedef typename Traits :: IndexSet IndexSet; /** \brief type of the intersection */ typedef typename Traits :: Intersection Intersection; /** \brief type of the intersection iterator */ typedef typename Traits :: IntersectionIterator IntersectionIterator; /** \brief type of the communication */ typedef typename Traits :: Communication Communication; /** \brief Codim Structure */ template< int cd > struct Codim : public Traits :: template Codim {}; constexpr static bool conforming = Traits :: conforming; static constexpr int dimension = Grid::dimension; public: UGGridLeafGridView ( const Grid &grid ) : grid_( &grid ) {} /** \brief obtain a const reference to the underlying hierarchic grid */ const Grid &grid () const { assert( grid_ ); return *grid_; } /** \brief obtain the index set */ const IndexSet &indexSet () const { return grid().leafIndexSet(); } /** \brief obtain number of entities in a given codimension */ int size ( int codim ) const { return grid().size( codim ); } /** \brief obtain number of entities with a given geometry type */ int size ( const GeometryType &type ) const { return grid().size( type ); } bool isConforming() const { return Traits::conforming; } /** \brief obtain begin iterator for this view */ template< int cd > typename Codim< cd > :: Iterator begin () const { return UGGridLeafIterator(grid()); } /** \brief obtain begin iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator begin () const { return UGGridLeafIterator(grid()); } /** \brief obtain end iterator for this view */ template< int cd > typename Codim< cd > :: Iterator end () const { return UGGridLeafIterator(); } /** \brief obtain end iterator for this view */ template< int cd, PartitionIteratorType pit > typename Codim< cd > :: template Partition< pit > :: Iterator end () const { return UGGridLeafIterator(); } /** \brief obtain begin intersection iterator with respect to this view */ IntersectionIterator ibegin ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ileafbegin(); } /** \brief obtain end intersection iterator with respect to this view */ IntersectionIterator iend ( const typename Codim< 0 > :: Entity &entity ) const { return entity.impl().ileafend(); } /** \brief obtain communication object */ const Communication &comm () const { return grid().comm(); } /** \brief Return size of the overlap region for a given codim on the grid view. */ int overlapSize(int codim) const { return 0; } /** \brief Return size of the ghost region for a given codim on the grid view. */ int ghostSize(int codim) const { return (codim==0) ? 1 : 0; } /** communicate data on this view */ template< class DataHandleImp, class DataType > void communicate ( CommDataHandleIF< DataHandleImp, DataType > &dataHandle, InterfaceType iftype, CommunicationDirection dir ) const { #ifdef ModelP Hybrid::forEach(std::make_index_sequence< Grid::dimension+1 >{}, [&](auto codim) { if (dataHandle.contains(Grid::dimension, codim)) grid().template communicateUG_(*this, -1, dataHandle, iftype, dir); }); #endif // ModelP } private: const Grid *grid_; }; } #endif // #ifndef DUNE_GRID_UGGRID_UGGRIDVIEWS_HH dune-grid-2.11.0/dune/grid/uggrid/ugincludes.hh000066400000000000000000000017321511655130300213000ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGINCLUDES_HH #define DUNE_UGINCLUDES_HH /** \file * \brief All includes of UG headers in one single spot All UG includes have to be made from this file, and from this file only! This is because undefAllMacros.pl takes all headers from this file and undefs the macros defined therein. */ #include #include #include #include #include #include #include #include #include #if defined ModelP #include #endif #endif dune-grid-2.11.0/dune/grid/uggrid/uglbgatherscatter.hh000066400000000000000000000115201511655130300226440ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_UGLBGATHERSCATTER_HH #define DUNE_UGLBGATHERSCATTER_HH namespace Dune { /** \brief Gather/scatter methods for dynamic loadbalancing with UGGrid */ class UGLBGatherScatter { // a last-in, first-out message buffer/queue template class LBMessageBuffer { friend class UGLBGatherScatter; static constexpr std::size_t size = sizeof(DataType); public: void read(DataType& x) { assert(bufferSize_ >= size); memcpy(&x, data_+bufferSize_-size, size); // decrease size without shrinking the allocated buffer bufferSize_ -= size; // if all item are read, deallocate the buffer if (bufferSize_ == 0) resize(0); } void write(const DataType& x) { resize(bufferSize_+size); memcpy(data_+bufferSize_-size, &x, size); } LBMessageBuffer() : bufferSize_(0), data_(nullptr) {} private: // copy num chars from this buffer to the ug buffer void copyDuneIntoUGBuffer(char* ugBuffer, std::size_t num) { // last-in, first-out assert(bufferSize_ >= num); for (std::size_t i = 0; i < num; i += size) std::copy(data_+bufferSize_-i-size, data_+bufferSize_-i, ugBuffer+i); resize(bufferSize_-num); } // copy num chars from the ug buffer to this buffer void copyUGIntoDuneBuffer(const char* ugBuffer, std::size_t num) { resize(bufferSize_+num); std::copy(ugBuffer, ugBuffer+num, data_+bufferSize_-num); } // resize internal buffer to newSize void resize(std::size_t newSize) { if (newSize == 0) { std::free(data_); data_ = nullptr; } else { if (void* mem = std::realloc(data_, newSize)) data_ = static_cast(mem); else throw std::bad_alloc(); } bufferSize_ = newSize; } std::size_t bufferSize_; char* data_; }; public: /** \brief Gather data before load balancing */ template static void gather(const GridView& gridView, DataHandle& dataHandle) { const int dim = GridView::dimension; // do nothing if nothing has to be done if (!dataHandle.contains(dim, codim)) return; // write the data into a global vector on process 0 // write the macrogrid index of each entity into the corresponding UG vector for (const auto &entity : entities(gridView, Codim())) { int numberOfParams = dataHandle.size(entity); if (!numberOfParams) continue; // obtain data from DUNE handle and write it into the UG message buffer using DataType = typename DataHandle::DataType; LBMessageBuffer lbMessageBuffer; dataHandle.gather(lbMessageBuffer, entity); auto ugEntity = entity.impl().getTarget(); assert(not ugEntity->message_buffer()); std::size_t buffer_size = numberOfParams * sizeof(DataType); char* buffer = static_cast(std::malloc(buffer_size)); ugEntity->message_buffer(buffer, buffer_size); lbMessageBuffer.copyDuneIntoUGBuffer(buffer, buffer_size); } } /** \brief Scatter data after load balancing */ template static void scatter(const GridView& gridView, DataHandle& dataHandle) { const int dim = GridView::dimension; // do nothing if nothing has to be done if (!dataHandle.contains(dim, codim)) return; // obtain the data from the global vector with help of // the macro index and scatter it for (const auto &entity : entities(gridView, Codim())) { // get data from UG message buffer and write to DUNE message buffer auto ugEntity = entity.impl().getTarget(); typedef typename DataHandle::DataType DataType; auto numberOfParams = ugEntity->message_buffer_size() / sizeof(DataType); if (!numberOfParams) continue; auto buffer = ugEntity->message_buffer(); assert(buffer); LBMessageBuffer lbMessageBuffer; lbMessageBuffer.copyUGIntoDuneBuffer(buffer, numberOfParams*sizeof(DataType)); // call the data handle with the message buffer dataHandle.scatter(lbMessageBuffer, entity, numberOfParams); // free object's local message buffer ugEntity->message_buffer_free(); } } }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/uggrid/ugmessagebuffer.hh000066400000000000000000000165051511655130300223140ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef UG_MESSAGE_BUFFER_HH #define UG_MESSAGE_BUFFER_HH #include #include #include namespace Dune { /** converts the UG speak message buffers to DUNE speak and vice-versa */ template class UGMessageBuffer { typedef UGMessageBuffer ThisType; typedef UGGrid GridType; typedef typename DataHandle::DataType DataType; using Entity = typename UGGrid::template Codim::Entity; using EntityImp = typename Entity::Implementation; UGMessageBuffer(void *ugData) { ugData_ = static_cast(ugData); }; public: void write(const DataType &t) { this->writeRaw_(t); } void read(DataType &t) { this->readRaw_(t); } private: friend class Dune::UGGrid; template void writeRaw_(const ValueType &v) { std::copy( reinterpret_cast(&v), reinterpret_cast(&v) + sizeof(ValueType), reinterpret_cast(ugData_) ); ugData_ += sizeof(ValueType); } template void readRaw_(ValueType &v) { std::copy( reinterpret_cast(ugData_), reinterpret_cast(ugData_) + sizeof(ValueType), reinterpret_cast(&v) ); ugData_ += sizeof(ValueType); } // called by DDD_IFOneway to serialize the data structure to // be sent static int ugGather_( DDD::DDDContext&, typename UG_NS::DDD_OBJ obj, void* data) { // cast the DDD object to a UG entity pointer auto ugEP = reinterpret_cast::template Entity::T*>(obj); // construct a DUNE entity from the UG entity pointer Entity entity(EntityImp(ugEP, grid_)); // safety check to only communicate what is needed if ((level == -1 && isToplevelLeaf(ugEP)) || entity.level() == level) { ThisType msgBuf(static_cast(data)); if (!duneDataHandle_->fixedSize(gridDim, codim)) msgBuf.template writeRaw_(duneDataHandle_->size(entity)); duneDataHandle_->gather(msgBuf, entity); } return 0; } // called by DDD_IFOneway to deserialize the data structure // that has been received static int ugScatter_( DDD::DDDContext&, typename UG_NS::DDD_OBJ obj, void* data) { // cast the DDD object to a UG entity pointer auto ugEP = reinterpret_cast::template Entity::T*>(obj); // construct a DUNE entity from the UG entity pointer Entity entity(EntityImp(ugEP, grid_)); // safety check to only communicate what is needed if ((level == -1 && isToplevelLeaf(ugEP)) || entity.level() == level) { ThisType msgBuf(static_cast(data)); int size; if (!duneDataHandle_->fixedSize(gridDim, codim)) msgBuf.readRaw_(size); else size = duneDataHandle_->size(entity); if (size > 0) duneDataHandle_->scatter(msgBuf, entity, size); } return 0; } /** \brief Test whether entity is leaf and has no copies on higher (i.e., finer) levels * * Entities of the leaf grid view are equivalence class of entities of the level view. * Therefore, the isLeaf method of the grid interface sometimes returns true for entities * that have copies on a finer level. In communication, we really want to call gather * and scatter for these entities only once. Therefore we use the following special * implementation that returns true only if an entity is leaf and it has now children. */ static bool isToplevelLeaf(const typename Dune::UG_NS::template Entity::T* ugEP) { // safety check to only communicate what is needed bool isLeaf = UG_NS::isLeaf(ugEP); // Edges: Simply checking isLeaf here will return 'true' for each top-level // leaf and *and* its lower-level copies (if it has any). However, we really // want only the highest-level copy, because otherwise gather will be called // more than once for that edge (interpreted as a leaf grid edge). Therefore // we need a tigher criterion. if constexpr (gridDim-codim==1) { if (isLeaf) { // isLeaf is true, i.e. we either are a top-level leaf or a copy of one. // If we are are lower-level copy then both of our end nodes have children, // and these two children are connected. auto nodeA = ugEP->links[0].nbnode; auto nodeB = ugEP->links[1].nbnode; if (nodeA->son && nodeB->son && UG_NS::GetEdge(nodeA->son, nodeB->son)) isLeaf = false; } } // Facets: No such handling is currently needed, because UGGridLeafIndexSet::update // does not assign leaf indices of leaf facets to their copy-fathers. // This may be a bug... return isLeaf; } // returns number of bytes required for the UG message buffer template static unsigned ugBufferSize(const GridView &gv) { // If the data handle claims to have the same number of data items for each entity // of the given codimension, then just ask for that numbering giving the first entity. if (duneDataHandle_->fixedSize(gridDim, codim)) { auto element = gv.template begin<0, InteriorBorder_Partition>(); if (element == gv.template end<0, InteriorBorder_Partition>()) { return 0; } return sizeof(DataType) * duneDataHandle_->size(element->template subEntity(0)); } // iterate over all entities, find the maximum size for // the current rank std::size_t maxSize = 0; if constexpr (codim==gridDim || codim==0) { for (const auto& entity : entities(gv, Codim(), Dune::Partitions::all)) maxSize = std::max(maxSize, duneDataHandle_->size(entity)); } else { for (const auto& element : elements(gv, Dune::Partitions::all)) { int numberOfSubentities = element.subEntities(codim); for (int k = 0; k < numberOfSubentities; k++) { const auto subEntity = element.template subEntity(k); maxSize = std::max(maxSize, duneDataHandle_->size(subEntity)); } } } // find maximum size for all ranks maxSize = gv.comm().max(maxSize); if (maxSize==0) return 0; // Add the size of an unsigned integer to the actual buffer size, // for storing the actual number of objects for each entity. return sizeof(unsigned) + sizeof(DataType)*maxSize; } static const GridType* grid_; static DataHandle *duneDataHandle_; static int level; char *ugData_; }; } // end namespace Dune #endif // UG_MESSAGE_BUFFER_HH dune-grid-2.11.0/dune/grid/uggrid/ugwrapper.hh000066400000000000000000001073271511655130300211610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \brief Encapsulates some UG macros and functions */ namespace Dune { /** \brief Encapsulates a few UG methods and macros * * This class provides a wrapper to several methods and macros from * UG. There are two reasons for doing this. First, we don't want * to call UG macros directly from DUNE, because they pollute the * namespace and therefore we undefine them all. Secondly, UG methods * appear in the namespaces UG::D2 and UG::D3, but we need the dimension * as a template parameter. */ #if UG_DIM == 2 template class UG_NS {}; #endif template<> class UG_NS< UG_DIM > { public: // ////////////////////////////////////////////// // Types exported by UG // ////////////////////////////////////////////// #if UG_DIM == 2 #define UG_NAMESPACE Dune::UG::D2 #else #define UG_NAMESPACE Dune::UG::D3 #endif enum Priorities { PrioNone = UG_NAMESPACE::PrioNone, PrioMaster = UG_NAMESPACE::PrioMaster, PrioBorder = UG_NAMESPACE::PrioBorder, PrioHGhost = UG_NAMESPACE::PrioHGhost, PrioVGhost = UG_NAMESPACE::PrioVGhost, PrioVHGhost = UG_NAMESPACE::PrioVHGhost }; typedef UG_NAMESPACE ::RefinementRule RefinementRule; typedef UG_NAMESPACE ::BndSegFuncPtr BndSegFuncPtr; /** \brief This is actually a type of the UG algebra, not the grid. * We need it to implement face indices and ids in 3d, since UG * doesn't actually have objects for faces in 3d grids. */ typedef UG_NAMESPACE ::vector Vector; /** \brief UG type for a hierarchical grid */ typedef UG_NAMESPACE ::multigrid MultiGrid; /** \brief UG type for a level grid */ typedef UG_NAMESPACE ::grid Grid; typedef UG_NAMESPACE ::edge Edge; typedef UG_NAMESPACE ::node Node; typedef UG_NAMESPACE ::element Element; typedef UG_NAMESPACE ::vertex Vertex; typedef UG_NAMESPACE ::domain domain; typedef UG_NAMESPACE ::STD_BVP STD_BVP; /** \brief Point on a UG boundary patch */ typedef UG_NAMESPACE ::BNDP BNDP; /** \brief Types of the subentities parametrized by the codimension. Gets specialized below */ template class Entity; // Type used for local and global ids #ifdef ModelP typedef UG_NAMESPACE::DDD_GID UG_ID_TYPE; #else typedef UG::INT UG_ID_TYPE; #endif #ifdef ModelP /* DDD Interfaces */ typedef UG_NAMESPACE::DDD_IF_DIR DDD_IF_DIR; typedef UG_NAMESPACE::DDD_IF DDD_IF; typedef UG_NAMESPACE::DDD_OBJ DDD_OBJ; typedef UG_NAMESPACE::DDD_HEADER DDD_HEADER; static void DDD_IFOneway( DDD::DDDContext& context, DDD_IF dddIf, DDD_IF_DIR dddIfDir, size_t s, UG_NAMESPACE::ComProcPtr2 gather, UG_NAMESPACE::ComProcPtr2 scatter ) { UG_NAMESPACE::DDD_IFOneway( context, dddIf, dddIfDir, s, gather, scatter); } #if DUNE_UGGRID_DDD_InfoProcListRange static auto DDD_InfoProcListRange(DDD::DDDContext& context, DDD_HEADER* hdr) noexcept { return UG_NAMESPACE::DDD_InfoProcListRange(context, hdr); } #else static int *DDD_InfoProcList( DDD::DDDContext& context, DDD_HEADER *hdr) { return UG_NAMESPACE::DDD_InfoProcList(context, hdr); } #endif static DDD_IF_DIR IF_FORWARD() { return UG_NAMESPACE::IF_FORWARD; } static DDD_IF_DIR IF_BACKWARD() { return UG_NAMESPACE::IF_BACKWARD; } /*! Master->HGhost/VHGhost */ static DDD_IF ElementIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).ElementIF; } /*! ElementSymmIF: Master/HGhost/VHGhost */ static DDD_IF ElementSymmIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).ElementSymmIF; } /*! ElementVIF: Master->VGhost/VHGhost */ static DDD_IF ElementVIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).ElementVIF; } /*! ElementSymmVIF: Master/VGhost/VHGhost" */ static DDD_IF ElementSymmVIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).ElementSymmVIF; } /*! Master->VGhost/HGhost/VHGhost */ static DDD_IF ElementVHIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).ElementVHIF; } /*! ElementSymmVHIF: Master/VGhost/HGhost/VHGhost */ static DDD_IF ElementSymmVHIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).ElementSymmVHIF; } /*! BorderNodeIF: Border->Master */ static DDD_IF BorderNodeIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).BorderNodeIF; } /*! BorderNodeSymmIF: Border/Master */ static DDD_IF BorderNodeSymmIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).BorderNodeSymmIF; } /*! OuterNodeIF: Master->HGhost/VGhost */ static DDD_IF OuterNodeIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).OuterNodeIF; } /*! NodeVIF: Master->VGhost/VHGhost */ static DDD_IF NodeVIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).NodeVIF; } /*! NodeIF: Master->VGhost/HGhost/VHGhost */ static DDD_IF NodeIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).NodeIF; } /*! NodeAllIF: All/All */ static DDD_IF NodeAllIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).NodeAllIF; } /*! Node_InteriorBorder_All_IF: Master/Border->All */ static DDD_IF NodeInteriorBorderAllIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).Node_InteriorBorder_All_IF; } /*! BorderVectorIF: Border->Master */ static DDD_IF BorderVectorIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).BorderVectorIF; } /*! BorderVectorSymmIF: Master/Border */ static DDD_IF BorderVectorSymmIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).BorderVectorSymmIF; } /*! OuterVectorIF: Master->HGhost/VHGhost */ static DDD_IF OuterVectorIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).OuterVectorIF; } /*! OuterVectorSymmIF: Master/Border/HGhost/VHGhost */ static DDD_IF OuterVectorSymmIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).OuterVectorSymmIF; } /*! VectorVIF: Master->VGhost/VHGhost */ static DDD_IF VectorVIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).VectorVIF; } /*! VectorVAllIF: Master/Border/VGhost/VHGhost->Master/Border */ static DDD_IF VectorVAllIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).VectorVAllIF; } /*! VectorIF: Master->VGhost/VHGhost/HGhost */ static DDD_IF VectorIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).VectorIF; } static DDD_IF FacetInteriorBorderAllIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).Facet_InteriorBorder_All_IF; } static DDD_IF FacetAllAllIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).Facet_All_All_IF; } /*! Master->HGhost/VHGhost */ static DDD_IF EdgeIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).EdgeIF; } /*! EdgeSymmIF: Master/HGhost/VHGhost */ static DDD_IF BorderEdgeSymmIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).BorderEdgeSymmIF; } /*! EdgeHIF: Master/HGhost/VHGhost */ static DDD_IF EdgeHIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).EdgeHIF; } /*! EdgeVHIF: Master->VGhost/HGhost/VHGhost */ static DDD_IF EdgeVHIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).EdgeVHIF; } /*! EdgeSymmVHIF: Master/VGhost/HGhost/VHGhost */ static DDD_IF EdgeSymmVHIF(const DDD::DDDContext& context) { return UG_NAMESPACE::ddd_ctrl(context).EdgeSymmVHIF; } /** \brief Encapsulates the UG EPRIO macro */ static int EPriority(const UG_NS< UG_DIM >::Element* element) { return EPRIO(element); } /** \brief Returns the priority of the side vector */ static int Priority(const UG_NS< UG_DIM >::Vector* side) { return PARHDR(side)->prio; } /** \brief Returns the priority of the edge (the UG EPRIO macro) */ static int Priority(const UG_NS< UG_DIM >::Edge* edge) { return PARHDR(edge)->prio; } /** \brief Returns the priority of the node (the UG EPRIO macro) */ static int Priority(const UG_NS< UG_DIM >::Node* node) { return PARHDR(node)->prio; } static DDD_HEADER* ParHdr(UG_NS< UG_DIM >::Vector *side) { return PARHDR(side); } static DDD_HEADER* ParHdr(UG_NS< UG_DIM >::Edge *edge) { return PARHDR(edge); } static DDD_HEADER* ParHdr(UG_NS< UG_DIM >::Node *node) { return PARHDR(node); } /** \brief This entry tells the UG load balancer what rank this particular element * is supposed to be sent to. */ static UG::INT& Partition(UG_NS< UG_DIM >::Element* element) { return PARTITION(element); } #endif // ////////////////////////////////////////////// // Constants exported by UG // ////////////////////////////////////////////// enum {GM_REFINE_NOT_CLOSED = UG_NAMESPACE ::GM_REFINE_NOT_CLOSED}; enum {GM_COPY_ALL = UG_NAMESPACE ::GM_COPY_ALL}; enum {GM_REFINE_TRULY_LOCAL = UG_NAMESPACE ::GM_REFINE_TRULY_LOCAL}; enum {GM_REFINE_PARALLEL = UG_NAMESPACE ::GM_REFINE_PARALLEL}; enum {GM_REFINE_NOHEAPTEST = UG_NAMESPACE ::GM_REFINE_NOHEAPTEST}; /** \brief Control word entries */ enum {NEWEL_CE = UG_NAMESPACE ::NEWEL_CE, COARSEN_CE = UG_NAMESPACE ::COARSEN_CE, ECLASS_CE = UG_NAMESPACE ::ECLASS_CE, MARK_CE = UG_NAMESPACE ::MARK_CE, REFINE_CE = UG_NAMESPACE ::REFINE_CE}; /** \brief Refinement rules */ enum {NO_REFINEMENT = UG_NAMESPACE ::NO_REFINEMENT, RED = UG_NAMESPACE ::RED, COARSE = UG_NAMESPACE ::COARSE}; enum {RED_CLASS = UG_NAMESPACE ::RED_CLASS}; enum {GM_OK = UG_NAMESPACE ::GM_OK}; enum {MAX_SONS = UG_NAMESPACE ::MAX_SONS}; /** \brief The PFIRSTNODE macro which returns the first node in a * grid even in a parallel setting. */ static UG_NS< UG_DIM >::Node* PFirstNode(const UG_NS< UG_DIM >::Grid* grid) { using UG_NAMESPACE ::PrioHGhost; using UG_NAMESPACE ::PrioVGhost; using UG_NAMESPACE ::PrioVHGhost; using UG_NAMESPACE ::PrioMaster; using UG_NAMESPACE ::PrioBorder; using UG_NAMESPACE ::ELEMENT_LIST; using UG_NAMESPACE ::NODE_LIST; return PFIRSTNODE(grid); } /** \brief The FIRSTNODE macro which returns the first node in a * grid even in a parallel setting. */ static UG_NS< UG_DIM >::Node* FirstNode(UG_NS< UG_DIM >::Grid* grid) { using UG_NAMESPACE ::PrioHGhost; using UG_NAMESPACE ::PrioVGhost; using UG_NAMESPACE ::PrioVHGhost; using UG_NAMESPACE ::PrioMaster; using UG_NAMESPACE ::PrioBorder; using UG_NAMESPACE ::ELEMENT_LIST; using UG_NAMESPACE ::NODE_LIST; return FIRSTNODE(grid); } /** \brief The PFIRSTELEMENT macro which returns the first element in a * grid even in a parallel setting. */ static UG_NS< UG_DIM >::Element* PFirstElement(const UG_NS< UG_DIM >::Grid* grid) { using UG_NAMESPACE ::PrioHGhost; using UG_NAMESPACE ::PrioVGhost; using UG_NAMESPACE ::PrioVHGhost; using UG_NAMESPACE ::PrioMaster; using UG_NAMESPACE ::PrioBorder; using UG_NAMESPACE ::ELEMENT_LIST; using UG_NAMESPACE ::NODE_LIST; return PFIRSTELEMENT(grid); } /** \brief The FIRSTELEMENT macro which returns the first element in a * grid even in a parallel setting. */ static UG_NS< UG_DIM >::Element* FirstElement(UG_NS< UG_DIM >::Grid* grid) { using UG_NAMESPACE ::PrioHGhost; using UG_NAMESPACE ::PrioVGhost; using UG_NAMESPACE ::PrioVHGhost; using UG_NAMESPACE ::PrioMaster; using UG_NAMESPACE ::PrioBorder; using UG_NAMESPACE ::ELEMENT_LIST; return FIRSTELEMENT(grid); } /** \brief Returns pointers to the coordinate arrays of a UG element */ static int Corner_Coordinates(const UG_NS< UG_DIM >::Element* theElement, double* x[]) { using UG_NAMESPACE ::NODE; using UG_NAMESPACE ::TRIANGLE; using UG_NAMESPACE ::QUADRILATERAL; using UG_NAMESPACE ::TETRAHEDRON; using UG_NAMESPACE ::PYRAMID; using UG_NAMESPACE ::PRISM; using UG_NAMESPACE ::n_offset; using UG::UINT; int n; CORNER_COORDINATES(theElement, n, x); return n; } /** \brief Returns pointers to the coordinate arrays of a UG node */ static int Corner_Coordinates(const UG_NS< UG_DIM >::Node* theNode, double* x[]) { x[0] = theNode->myvertex->iv.x.data(); return 1; } /** \brief Returns pointers to the coordinate arrays of a UG edge */ static int Corner_Coordinates(const UG_NS< UG_DIM >::Edge* theEdge, double* x[]) { x[0] = theEdge->links[0].nbnode->myvertex->iv.x.data(); x[1] = theEdge->links[1].nbnode->myvertex->iv.x.data(); return 2; } /** \brief Returns pointers to the coordinate arrays of a UG vector */ static int Corner_Coordinates(const UG_NS< UG_DIM >::Vector* theVector, double* x[]) { UG_NS< UG_DIM >::Element* center; unsigned int side; UG_NS< UG_DIM >::GetElementAndSideFromSideVector(theVector, center, side); int n = Corners_Of_Side(center, side); for (int i = 0; i < n; i++) { unsigned idxInElem = Corner_Of_Side(center, side, i); x[i] = Corner(center, idxInElem)->myvertex->iv.x.data(); } return n; } static int GlobalToLocal(int n, const double** cornerCoords, const FieldVector& EvalPoint, FieldVector& localCoord) { if (UG_DIM==2) // in 2d we can call this only for triangles and quadrilaterals assert(n==3 or n==4); else // in 3d: tetrahedra, pyramids, prisms, hexahedra assert(n==4 or n==5 or n==6 or n==8); return UG_NAMESPACE ::UG_GlobalToLocal(n, cornerCoords, EvalPoint, localCoord); } /** \brief Computes the element volume */ static double Area_Of_Element(int n, const double** cornerCoords) { double area = 0.0; using UG::DOUBLE; using UG_NAMESPACE ::DOUBLE_VECTOR; #if UG_DIM == 2 AREA_OF_ELEMENT_2D(n,cornerCoords,area); #else AREA_OF_ELEMENT_3D(n,cornerCoords,area); #endif return area; } static int myLevel (const UG_NS< UG_DIM >::Element* theElement) { using UG::UINT; return LEVEL(theElement); } static int myLevel (const UG_NS< UG_DIM >::Node* theNode) { using UG::UINT; return LEVEL(theNode); } static int myLevel (const UG_NS< UG_DIM >::Edge* theEdge) { using UG::UINT; return LEVEL(theEdge); } static int myLevel (const UG_NS< UG_DIM >::Vector* theVector) { return myLevel((UG_NS< UG_DIM >::Element*)VOBJECT(theVector)); } //! return true if element has an exact copy on the next level static bool hasCopy (const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::ELEMENT; using UG_NAMESPACE ::control_entries; using UG::UINT; using UG_NAMESPACE ::REFINECLASS_CE; using UG_NAMESPACE ::YELLOW_CLASS; return REFINECLASS(theElement) == YELLOW_CLASS; } //! Returns true if element is on level 0 or has been created by red refinement static bool isRegular (const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::ELEMENT; using UG_NAMESPACE ::control_entries; using UG::UINT; return ECLASS(theElement) == RED_CLASS; } //! \todo Please doc me! static int Sides_Of_Elem(const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; return SIDES_OF_ELEM(theElement); } //! Encapsulates the NBELEM macro static UG_NS::Element* NbElem(const UG_NS< UG_DIM >::Element* theElement, int nb) { using UG_NAMESPACE ::ELEMENT; using UG_NAMESPACE ::nb_offset; using UG::UINT; return NBELEM(theElement, nb); } static size_t boundarySegmentIndex(const UG_NS< UG_DIM >::Element* theElement, int nb) { using UG_NAMESPACE ::BNDS; using UG::UINT; using UG_NAMESPACE ::side_offset; BNDS* bnds = ELEM_BNDS(theElement,nb); size_t id = UG_NAMESPACE ::GetBoundarySegmentId(bnds); return id; } //! Returns true if the i-th side of the element is on the domain boundary static bool Side_On_Bnd(const UG_NS< UG_DIM >::Element* theElement, int i) { using UG_NAMESPACE ::BNDS; using UG_NAMESPACE ::BEOBJ; using UG_NAMESPACE ::side_offset; using UG::UINT; using UG_NAMESPACE ::GM_OBJECTS; return OBJT(theElement)==BEOBJ && SIDE_ON_BND(theElement, i); } //! Returns true if at least one face of the element is a boundary face static bool isBoundaryElement(const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::BEOBJ; using UG_NAMESPACE ::GM_OBJECTS; using UG::UINT; return OBJT(theElement)==BEOBJ; } //! \todo Please doc me! static int Edges_Of_Elem(const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; return EDGES_OF_ELEM(theElement); } //! \todo Please doc me! static int Corners_Of_Elem(const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; return CORNERS_OF_ELEM(theElement); } /** \Brief the 'number of corners' of a vertex, i.e., 1. Here for consistency \return 1 */ static int Corners_Of_Elem(const UG_NS< UG_DIM >::Node* theNode) { return 1; } //! Return number of corners of a given side static int Corners_Of_Side(const UG_NS< UG_DIM >::Element* theElement, int side) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; return CORNERS_OF_SIDE(theElement, side); } //! Return local number of a given corner of a given element side static int Corner_Of_Side(const UG_NS< UG_DIM >::Element* theElement, int side, int corner) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; return CORNER_OF_SIDE(theElement, side, corner); } //! Return local number of a given corner of a given element edge static int Corner_Of_Edge(const UG_NS< UG_DIM >::Element* theElement, int edge, int corner) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; return CORNER_OF_EDGE(theElement, edge, corner); } //! Return number of sons of an element static int nSons(const UG_NAMESPACE ::element* element) { return UG_NAMESPACE ::ReadCW(element, UG_NAMESPACE ::NSONS_CE); } static int GetSons(const UG_NAMESPACE ::element* element, UG_NAMESPACE ::element* sonList[MAX_SONS]) { return UG_NAMESPACE ::GetSons(element, sonList); } /** \todo Remove the const casts */ static int GetNodeContext(const UG_NAMESPACE ::element* element, const UG_NAMESPACE ::node** context) { return UG_NAMESPACE ::GetNodeContext(element, const_cast(context)); } //! Encapsulates the GRID_ATTR macro static int Grid_Attr(const UG_NS< UG_DIM >::Grid* grid) { return GRID_ATTR(grid); } static int MarkForRefinement(UG_NAMESPACE ::element* element, int rule, int data) { return UG_NAMESPACE ::MarkForRefinement(element, (UG_NAMESPACE ::RefinementRule)rule, data); } //! Encapsulates the TAG macro static unsigned int Tag(const UG_NS< UG_DIM >::Element* theElement) { using UG::UINT; return TAG(theElement); } //! Doesn't ever get called, but needs to be there to calm the compiler static unsigned int Tag(const UG_NS< UG_DIM >::Node* theNode) { DUNE_THROW(GridError, "Called method Tag() for a vertex. This should never happen!"); return 0; } //! get corner in local coordinates, corner number in UG's numbering system template static void getCornerLocal (const UG_NS< UG_DIM >::Element* theElement, int corner, FieldVector& local) { using UG_NAMESPACE ::element_descriptors; using UG::UINT; for (int i=0; i::Element* succ(const UG_NS< UG_DIM >::Element* theElement) { return theElement->ge.succ; } //! Next element in the UG nodes lists static UG_NS< UG_DIM >::Node* succ(const UG_NS< UG_DIM >::Node* theNode) { return theNode->succ; } //! Calm the compiler static void* succ(const void* theWhatever) { DUNE_THROW(NotImplemented, "No successor available for this kind of object"); return 0; } //! Return true if the element is a ghost element #ifdef ModelP static bool isGhost(const UG_NS< UG_DIM >::Element* theElement) { if (EPRIO(theElement) == PrioHGhost || EPRIO(theElement) == PrioVGhost || EPRIO(theElement) == PrioVHGhost) return true; else return false; } #endif //! Return true if the element is a leaf element static bool isLeaf(const UG_NS< UG_DIM >::Element* theElement) { using UG ::UINT; using UG_NAMESPACE ::CONTROL_ENTRY; using UG_NAMESPACE ::control_entries; return LEAFELEM(theElement); } //! Return true if the node is a leaf node static bool isLeaf(const UG_NS< UG_DIM >::Node* theNode) { return theNode->isLeaf; } //! Return true if the edge is a leaf edge static bool isLeaf(const UG_NS< UG_DIM >::Edge* theEdge) { return theEdge->leafIndex > -1; } //! Return true if the side vector is a leaf side vector static bool isLeaf(const UG_NS< UG_DIM >::Vector* theVector) { using UG_NAMESPACE ::VECTOR; using UG::UINT; // Since the vector cannot be asked directly, // the corresponding element is asked. return isLeaf((UG_NS< UG_DIM >::Element*)VOBJECT(theVector)); } // ///////////////////////////////////////////// // Level indices // ///////////////////////////////////////////// //! Gets the level index of a UG element static int& levelIndex(UG_NS< UG_DIM >::Element* theElement) { return theElement->ge.levelIndex; } //! Gets the level index of a UG element static const int& levelIndex(const UG_NS< UG_DIM >::Element* theElement) { return theElement->ge.levelIndex; } //! Gets the level index of a UG sidevector static UG::UINT& levelIndex(Vector* theVector) { #if UG_DIM == 2 DUNE_THROW(GridError, "levelIndex in side vector only in 3D!"); #endif return theVector->index; } //! Gets the level index of a UG sidevector static const UG::UINT& levelIndex(const Vector* theVector) { #if UG_DIM == 2 DUNE_THROW(GridError, "levelIndex in side vector only in 3D!"); #endif return theVector->index; } //! Gets the level index of a UG edge static int& levelIndex(UG_NS< UG_DIM >::Edge* theEdge) { return theEdge->levelIndex; } //! Gets the level index of a UG edge static const int& levelIndex(const UG_NS< UG_DIM >::Edge* theEdge) { return theEdge->levelIndex; } //! Gets the level index of a UG node static int& levelIndex(UG_NS< UG_DIM >::Node* theNode) { return theNode->levelIndex; } //! Gets the level index of a UG node static const int& levelIndex(const UG_NS< UG_DIM >::Node* theNode) { return theNode->levelIndex; } // ///////////////////////////////////////////// // Leaf indices // ///////////////////////////////////////////// //! Gets the leaf index of a UG element static int& leafIndex(UG_NS< UG_DIM >::Element* theElement) { return theElement->ge.leafIndex; } //! Gets the leaf index of a UG element static const int& leafIndex(const UG_NS< UG_DIM >::Element* theElement) { return theElement->ge.leafIndex; } //! Gets the leaf index of a UG sidevector static UG::UINT& leafIndex(Vector* theVector) { return theVector->leafIndex; } //! Gets the leaf index of a UG sidevector static const UG::UINT& leafIndex(const Vector* theVector) { return theVector->leafIndex; } //! Gets the leaf index of a UG edge static int& leafIndex(UG_NS< UG_DIM >::Edge* theEdge) { return theEdge->leafIndex; } //! Gets the leaf index of a UG edge static const int& leafIndex(const UG_NS< UG_DIM >::Edge* theEdge) { return theEdge->leafIndex; } //! Gets the leaf index of a UG node static int& leafIndex(UG_NS< UG_DIM >::Node* theNode) { return theNode->myvertex->iv.leafIndex; } //! Gets the leaf index of a UG node static const int& leafIndex(const UG_NS< UG_DIM >::Node* theNode) { return theNode->myvertex->iv.leafIndex; } // ///////////////////////////////////////////// // IDs // ///////////////////////////////////////////// //! Gets the index of a UG element static auto id(const UG_NS< UG_DIM >::Element* theElement) { #if defined ModelP return theElement->ge.ddd.gid; #else return theElement->ge.id; #endif } //! Gets the id of a UG facet static auto id(const UG_NS< UG_DIM >::Vector* theVector) { #ifdef ModelP return theVector->ddd.gid; #else auto id = theVector->id; // In sequential UG, two entities of different codimension can have the same id, // so let's encode the codimension in the id to make them differ. constexpr unsigned int codim = 1; // return id | (codim << 30); #endif } //! Gets the id of a UG edge static auto id(const UG_NS< UG_DIM >::Edge* theEdge) { #ifdef ModelP return theEdge->ddd.gid; #else auto id = theEdge->id; // In sequential UG, two entities of different codimension can have the same id, // so let's encode the codimension in the id to make them differ. constexpr unsigned int codim = UG_DIM-1; // return id | (codim << 30); #endif } //! Gets the index of a UG node static auto id(const UG_NS< UG_DIM >::Node* theNode) { #ifdef ModelP return theNode->myvertex->iv.ddd.gid; #else auto id = theNode->myvertex->iv.id; // In sequential UG, two entities of different codimension can have the same id, // so let's encode the codimension in the id to make them differ. constexpr unsigned int codim = UG_DIM; return id | (codim << 30); #endif } /** \brief Compute global coordinates of a point in local coordinates for an element */ static void Local_To_Global(int n, double** y, const FieldVector& local, FieldVector& global) { using UG::DOUBLE; LOCAL_TO_GLOBAL(n,y,local,global); } /** \brief Compute global coordinates of a point in local coordinates for a vertex */ static void Local_To_Global(int n, double** y, const FieldVector& local, FieldVector& global) { for (int i=0; i& local, FieldMatrix& mat) { using UG_NAMESPACE ::DOUBLE_VECTOR; using UG::DOUBLE; double det; INVERSE_TRANSFORMATION(n, x, local, mat, det); return 0; } /** \brief Dummy method for vertices */ static int JacobianInverseTransformation(int n, double** x, const FieldVector& local, FieldMatrix& mat) { return 0; } /** * \param n Number of corners of the element * \param x Coordinates of the corners of the element * \param local Local evaluation point * * \return The return type is int because the macro TRANSFORMATION * returns 1 on failure. */ static int JacobianTransformation(int n, double** x, const FieldVector& local, FieldMatrix& mat) { using UG_NAMESPACE ::DOUBLE_VECTOR; using UG::DOUBLE; TRANSFORMATION(n, x, local, mat); return 0; } /** \brief Dummy method for vertices */ static int JacobianTransformation(int n, double** x, const FieldVector& local, FieldMatrix& mat) { return 0; } //! Returns the i-th corner of a UG element static UG_NS< UG_DIM >::Node* Corner(const UG_NS< UG_DIM >::Element* theElement, int i) { using UG_NAMESPACE ::NODE; using UG_NAMESPACE ::n_offset; using UG::UINT; return CORNER(theElement, i); } //! Returns the i-th edge of a UG element static UG_NS< UG_DIM >::Edge* ElementEdge(const UG_NS< UG_DIM >::Element* theElement, int i) { using UG_NAMESPACE ::NODE; using UG_NAMESPACE ::n_offset; using UG::UINT; using UG_NAMESPACE ::element_descriptors; return GetEdge(CORNER(theElement, CORNER_OF_EDGE(theElement, i, 0)), CORNER(theElement, CORNER_OF_EDGE(theElement, i, 1))); } //! get edge from node i to node j (in UG's numbering ! static UG_NS< UG_DIM >::Edge* GetEdge (UG_NS< UG_DIM >::Node* nodei, UG_NS< UG_DIM >::Node* nodej) { return UG_NAMESPACE ::GetEdge(nodei,nodej); } //! access side vector from element (this is just a dummy to compile code also in 2d) static Vector* SideVector (const UG_NS< UG_DIM >::Element* theElement, int i) { #if UG_DIM == 2 DUNE_THROW(GridError, "side vector only in 3D!"); #else using UG::D3::VECTOR; using UG::D3::svector_offset; using UG::UINT; return SVECTOR(theElement,i); #endif } //! Access element from side vector static void GetElementAndSideFromSideVector(const UG_NS< UG_DIM >::Vector* theVector, UG_NS< UG_DIM >::Element*& theElement, unsigned int& side) { using UG_NAMESPACE ::VECTOR; using UG::UINT; theElement = (UG_NS< UG_DIM >::Element*)VOBJECT(theVector); side = VECTORSIDE(theVector); } /** \brief Return a pointer to the father of the given element */ static UG_NS< UG_DIM >::Element* EFather(const UG_NS< UG_DIM >::Element* theElement) { using UG_NAMESPACE ::ELEMENT; using UG_NAMESPACE ::father_offset; using UG::UINT; return EFATHER(theElement); } //! get father element of vertex static UG_NS< UG_DIM >::Element* NFather(UG_NS< UG_DIM >::Node* theNode) { return theNode->myvertex->iv.father; } //! get father node of vertex static UG_NS< UG_DIM >::Node* NodeNodeFather(UG_NS< UG_DIM >::Node* theNode) { using UG_NAMESPACE ::NDOBJ; using UG_NAMESPACE ::GM_OBJECTS; using UG::UINT; if (theNode->father==0) return 0; // no father at all if (OBJT(theNode->father)==NDOBJ) return (UG_NAMESPACE ::node*) theNode->father; else return 0; // may be edge or element } static unsigned int ReadCW(void* obj, int ce) { return UG_NAMESPACE ::ReadCW(obj, ce); } static void WriteCW(void* obj, int ce, int n) { UG_NAMESPACE ::WriteCW(obj, ce, n); } //! \todo Please doc me! static int InitUg(int* argcp, char*** argvp) { return UG_NAMESPACE ::InitUg(argcp, argvp); } static void ExitUg() { UG_NAMESPACE ::ExitUg(); } static int DisposeMultiGrid(UG_NAMESPACE ::multigrid* mg) { return UG_NAMESPACE ::DisposeMultiGrid(mg); } //! Set the current boundary value problem static void Set_Current_BVP(UG_NAMESPACE ::STD_BVP* thisBVP) { UG_NAMESPACE ::Set_Current_BVP(thisBVP); } /** \brief Create new point on the grid boundary by giving local coordinates. Global coordinates are computed automatically using the domain boundary information. The point is not inserted as a new vertex in the grid! */ static BNDP *BNDP_CreateBndP(UG::HEAP *Heap, BNDP *theBndP0, BNDP *theBndP1, UG::DOUBLE lcoord) { return UG_NAMESPACE::BNDP_CreateBndP(Heap, theBndP0, theBndP1, lcoord); } /** \brief Get global position of a point on the grid boundary */ static UG::INT BNDP_Global(BNDP *theBndP, FieldVector& global) { return UG_NAMESPACE::BNDP_Global(theBndP, global); } /** \brief Delete a grid boundary point */ static UG::INT BNDP_Dispose(UG::HEAP *Heap, BNDP *theBndP) { return UG_NAMESPACE::BNDP_Dispose(Heap, theBndP); } //! Get UG multigrid object from its name static UG_NS< UG_DIM >::MultiGrid* GetMultigrid(const char* name) { return UG_NAMESPACE ::GetMultigrid(name); } /** \brief Load-balance the grid by recursive coordinate bisection */ static void lbs(const char *argv, UG_NAMESPACE ::multigrid *theMG) { #ifdef ModelP return UG_NAMESPACE ::lbs(argv, theMG); #endif } //! An UG-internal load balancing method static int TransferGridFromLevel(UG_NAMESPACE ::multigrid *theMG, int level) { #ifdef ModelP return UG_NAMESPACE ::TransferGridFromLevel(theMG,level); #else return 0; #endif } static MultiGrid *CreateMultiGrid(const char *MultigridName, STD_BVP *theBVP, const char *format, int optimizedIE, int insertMesh, std::shared_ptr ppifContext = nullptr) { return UG_NAMESPACE ::CreateMultiGrid(const_cast(MultigridName), theBVP, format, optimizedIE, insertMesh, ppifContext); } static void* InsertInnerNode(UG_NAMESPACE ::grid* grid, const double* pos) { return UG_NAMESPACE ::InsertInnerNode(grid, pos); } }; template <> class UG_NS< UG_DIM >::Entity<0> { public: typedef UG_NAMESPACE ::element T; }; template <> class UG_NS< UG_DIM >::Entity< UG_DIM - 1 > { public: typedef UG_NAMESPACE ::edge T; }; #if UG_DIM == 3 template <> class UG_NS< UG_DIM >::Entity<1> { public: typedef UG_NAMESPACE ::vector T; }; #endif template <> class UG_NS< UG_DIM >::Entity< UG_DIM > { public: typedef UG_NAMESPACE ::node T; }; #undef UG_NAMESPACE } // namespace Dune dune-grid-2.11.0/dune/grid/uggrid/undefAllMacros.pl000077500000000000000000000040441511655130300220530ustar00rootroot00000000000000#!/usr/bin/perl -w # SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # TODO: Detect location of UG from the DUNE build system $UGROOT = "/home/sander/uginst"; # Counts the total number of #undefs emitted $counter = 0; # open output file $outfilename = "ug_undefs.hh"; unless (open OUTFILE, ">$outfilename") { die "Couldn't open $outfilename for writing!\n"; } # Loop over all the files given in the command line and # recursively parse them for macro definitions. foreach $file (@ARGV) { # Write header comment print OUTFILE "/** \\file\n"; print OUTFILE "* \\brief Contains #undefs for all preprocessor macros\n"; print OUTFILE "* defined by UG.\n"; print OUTFILE "*\n"; print OUTFILE "* This file is created automatically by the perl script undefAllMacros.pl.\n"; print OUTFILE "*/\n\n"; # Parse the file itself emitUndefs($file); # Makedepend recursively searches for more included headers. # Warnings appear because the system headers will not be found. # Those warnings get piped to /dev/null. foreach $_ (`makedepend -f- -w 20 -Y$UGROOT/include -DModelP $file 2>/dev/null`) { # The output of makedepend has the form # file.o: header.h # We look for the ".o:" Everything that follows must be a header file if (/\.o\:\s(\S+\.h)/) { emitUndefs($1); } } } print "Undef'ed $counter #defines!\n"; close(OUTFILE); ############################################################## # This subroutine reads the file given as the first argument # and issues an #undef for each macro found. ############################################################## sub emitUndefs { print "Parsing $_[0]\n"; unless (open INFILE, "$_[0]") { die "Couldn't open $_[0] for reading!\n"; } while() { # looks for lines that define a C macro if (/\#define\s+(\w+)/) { print OUTFILE "#undef $1\n"; $counter = $counter + 1; } } close (INFILE); } dune-grid-2.11.0/dune/grid/utility/000077500000000000000000000000001511655130300170345ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/utility/CMakeLists.txt000066400000000000000000000012751511655130300216010ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(test) set(HEADERS entitycommhelper.hh globalindexset.hh gridinfo-gmsh-main.hh gridinfo.hh gridtype.hh hierarchicsearch.hh hostgridaccess.hh multiindex.hh parmetisgridpartitioner.hh persistentcontainer.hh persistentcontainerinterface.hh persistentcontainermap.hh persistentcontainervector.hh persistentcontainerwrapper.hh structuredgridfactory.hh tensorgridfactory.hh vertexorderfactory.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/utility) dune-grid-2.11.0/dune/grid/utility/entitycommhelper.hh000066400000000000000000000045001511655130300227440ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_ENTITYCOMMHELPER_HH #define DUNE_ENTITYCOMMHELPER_HH #include namespace Dune { template< InterfaceType iftype > struct EntityCommHelper; template<> struct EntityCommHelper< InteriorBorder_InteriorBorder_Interface > { static bool send ( const PartitionType p ) { //return (p == InteriorEntity) || (p == BorderEntity); return (p == BorderEntity); } static bool receive ( const PartitionType p ) { //return (p == InteriorEntity) || (p == BorderEntity); return (p == BorderEntity); } }; template<> struct EntityCommHelper< InteriorBorder_All_Interface > { static bool send ( const PartitionType p ) { return (p == InteriorEntity) || (p == BorderEntity); } static bool receive ( const PartitionType p ) { //return true; return (p != InteriorEntity); } }; template<> struct EntityCommHelper< Overlap_OverlapFront_Interface > { static bool send ( const PartitionType p ) { //return (p == InteriorEntity) || (p == BorderEntity) || (p == OverlapEntity); return (p != FrontEntity) && (p != GhostEntity); } static bool receive ( const PartitionType p ) { //return (p == InteriorEntity) || (p == BorderEntity) || (p == OverlapEntity) || (p == FrontEntity); return (p != GhostEntity); } }; template<> struct EntityCommHelper< Overlap_All_Interface > { static bool send ( const PartitionType p ) { //return (p == InteriorEntity) || (p == BorderEntity) || (p == OverlapEntity); return (p != FrontEntity) && (p != GhostEntity); } static bool receive ([[maybe_unused]] const PartitionType p) { return true; } }; template<> struct EntityCommHelper< All_All_Interface > { static bool send ([[maybe_unused]] const PartitionType p) { return true; } static bool receive ([[maybe_unused]] const PartitionType p) { return true; } }; } // namespace Dune #endif // #ifndef DUNE_ENTITYCOMMHELPER_HH dune-grid-2.11.0/dune/grid/utility/globalindexset.hh000066400000000000000000000465071511655130300223750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * * \brief Provides a globally unique index for all entities of a distributed Dune grid * * Such functionality is relevant for a number of applications: * - Map a degree of freedom associated with an entity to its * location in a global matrix or global vector * - Such indices for elements are needed as input to external mesh partitioners * - Using matrix and vector routines from the PETSc or trilinos parallel linear algebra * packages for distributed memory parallel computers. * * Method: (1) The UniqueEntityPartition class assigns an owner process to each entity * * (2) Compute the number of entities that are owned by each process * * (3) we communicate the index of entities that are owned by the process to processes * that also contain these entities but do not own them, so that on a non-owner process * we have information on the index of the entity that it got from the owner-process; * * \author Benedikt Oswald, Patrick Leidenberger, Oliver Sander * * \attention globally unique indices are ONLY provided for entities of the * InteriorBorder_Partition type, NOT for the Ghost_Partition type !!! * * \bug This code will most likely not work on grids with more than one element type. * Please ask on the mailing list if you need this feature. * \note The interface in this file is experimental, and may change without prior notice. */ #ifndef DUNE_GRID_UTILITY_GLOBALINDEXSET_HH #define DUNE_GRID_UTILITY_GLOBALINDEXSET_HH /** \brief Include standard header files. */ #include #include #include #include #include #include #include /** include base class functionality for the communication interface */ #include #include /** include parallel capability */ #if HAVE_MPI #include #endif namespace Dune { /** \brief Calculate globally unique index over all processes in a Dune grid */ template class GlobalIndexSet { public: /** \brief The number type used for global indices */ typedef int Index; /** \brief Helper class to provide access to subentity PartitionTypes with a run-time codimension * * This class can be removed if there is ever a method 'subPartitionType' similar to 'subIndex', * that takes a run-time codimension argument. */ template struct SubPartitionTypeProvider { /** \brief Get PartitionType of the i-th subentity of codimension 'codim' of entity 'entity' */ static PartitionType get(const Entity& entity, int codim, int i) { if (codim==Codim) return entity.template subEntity(i).partitionType(); else return SubPartitionTypeProvider::get(entity, codim, i); } }; template struct SubPartitionTypeProvider { static PartitionType get(const Entity& entity, int /*codim*/, int i) { return entity.template subEntity<0>(i).partitionType(); } }; private: /** define data types */ typedef typename GridView::Grid Grid; typedef typename GridView::Grid::GlobalIdSet GlobalIdSet; typedef typename GridView::Grid::GlobalIdSet::IdType IdType; typedef typename GridView::Traits::template Codim<0>::Iterator Iterator; typedef typename Grid::Communication Communication; typedef std::map MapId2Index; typedef std::map IndexMap; /*********************************************************************************************/ /* calculate unique partitioning for all entities of a given codim in a given GridView, */ /* assuming they all have the same geometry, i.e. codim, type */ /*********************************************************************************************/ class UniqueEntityPartition { private: /* A DataHandle class to calculate the minimum of a std::vector which is accompanied by an index set */ template // mapper type and vector type class MinimumExchange : public Dune::CommDataHandleIF,typename V::value_type> { public: //! export type of data for message buffer typedef typename V::value_type DataType; //! returns true if data for this codim should be communicated bool contains (int /*dim*/, unsigned int codim) const { return codim==indexSetCodim_; } //! returns true if size per entity of given dim and codim is a constant bool fixedSize (int /*dim*/, int /*codim*/) const { return true ; } /*! how many objects of type DataType have to be sent for a given entity * * Note: Only the sender side needs to know this size. */ template std::size_t size (EntityType&) const { return 1 ; } /*! pack data from user to message buffer */ template void gather (MessageBuffer& buff, const EntityType& e) const { buff.write(v_[indexset_.index(e)]); } /** \brief Unpack data from message buffer to user * * \param n The number of objects sent by the sender */ template void scatter (MessageBuffer& buff, const EntityType& e, std::size_t) { DataType x; buff.read(x); if (x>=0) // other is -1 means, he does not want it v_[indexset_.index(e)] = std::min(x,v_[indexset_.index(e)]); } //! constructor MinimumExchange (const IS& indexset, V& v, unsigned int indexSetCodim) : indexset_(indexset), v_(v), indexSetCodim_(indexSetCodim) {} private: const IS& indexset_; V& v_; unsigned int indexSetCodim_; }; public: /*! \brief Constructor needs to know the grid function space */ UniqueEntityPartition (const GridView& gridview, unsigned int codim) : assignment_(gridview.size(codim)) { /** extract types from the GridView data type */ typedef typename GridView::IndexSet IndexSet; // assign own rank to entities that I might have for (auto it = gridview.template begin<0>(); it!=gridview.template end<0>(); ++it) for (unsigned int i=0; isubEntities(codim); i++) { // Evil hack: I need to call subEntity, which needs the entity codimension as a static parameter. // However, we only have it as a run-time parameter. PartitionType subPartitionType = SubPartitionTypeProvider::Entity, GridView::dimension>::get(*it,codim,i); assignment_[gridview.indexSet().subIndex(*it,i,codim)] = ( subPartitionType==Dune::InteriorEntity or subPartitionType==Dune::BorderEntity ) ? gridview.comm().rank() // set to own rank : - 1; // it is a ghost entity, I will not possibly own it. } /** exchange entity index through communication */ MinimumExchange > dh(gridview.indexSet(),assignment_,codim); gridview.communicate(dh,Dune::All_All_Interface,Dune::ForwardCommunication); } /** \brief Which rank is the i-th entity assigned to? */ int owner(std::size_t i) { return assignment_[i]; } /** \brief Report the number of entities assigned to the rank 'rank' */ std::size_t numOwners(int rank) const { return std::count(assignment_.begin(), assignment_.end(), rank); } private: std::vector assignment_; }; private: /* A DataHandle class to communicate the global index from the * owning to the non-owning entity; the class is based on the MinimumExchange * class in the parallelsolver.hh header file. */ class IndexExchange : public Dune::CommDataHandleIF { public: //! returns true if data for this codim should be communicated bool contains (int /*dim*/, unsigned int codim) const { return codim==indexSetCodim_; } //! returns true if size per entity of given dim and codim is a constant bool fixedSize (int /*dim*/, int /*codim*/) const { return true; } /** \brief How many objects of type DataType have to be sent for a given entity * * \note Only the sender side needs to know this size. */ template std::size_t size (EntityType&) const { return 1; } /*! pack data from user to message buffer */ template void gather (MessageBuffer& buff, const EntityType& e) const { IdType id=globalidset_.id(e); if (indexSetCodim_==0) buff.write(mapid2entity_[id]); else buff.write((*mapid2entity_.find(id)).second); } /** \brief Unpack data from message buffer to user * * \param n The number of objects sent by the sender */ template void scatter (MessageBuffer& buff, const EntityType& entity, std::size_t) { Index x; buff.read(x); /** only if the incoming index is a valid one, * i.e. if it is greater than zero, will it be * inserted as the global index; it is made * sure in the upper class, i.e. GlobalIndexSet, * that non-owning processes use -1 to mark an entity * that they do not own. */ if(x >= 0) { const IdType id = globalidset_.id(entity); if (indexSetCodim_==0) mapid2entity_[id] = x; else { mapid2entity_.erase(id); mapid2entity_.insert(std::make_pair(id,x)); const Index lindex = indexSet_.index(entity); localGlobalMap_[lindex] = x; } } } //! constructor IndexExchange (const GlobalIdSet& globalidset, MapId2Index& mapid2entity, const typename GridView::IndexSet& localIndexSet, IndexMap& localGlobal, unsigned int indexSetCodim) : globalidset_(globalidset), mapid2entity_(mapid2entity), indexSet_(localIndexSet), localGlobalMap_(localGlobal), indexSetCodim_(indexSetCodim) {} private: const GlobalIdSet& globalidset_; MapId2Index& mapid2entity_; const typename GridView::IndexSet& indexSet_; IndexMap& localGlobalMap_; unsigned int indexSetCodim_; }; public: /** \brief Constructor for a given GridView * * This constructor calculates the complete set of global unique indices so that we can then * later query the global index, by directly passing the entity in question. */ GlobalIndexSet(const GridView& gridview, int codim) : gridview_(gridview), codim_(codim) { int rank = gridview.comm().rank(); int size = gridview.comm().size(); const typename GridView::IndexSet& indexSet = gridview.indexSet(); std::unique_ptr uniqueEntityPartition; if (codim_!=0) uniqueEntityPartition = std::make_unique(gridview,codim_); int nLocalEntity = (codim_==0) ? std::distance(gridview.template begin<0, Dune::Interior_Partition>(), gridview.template end<0, Dune::Interior_Partition>()) : uniqueEntityPartition->numOwners(rank); // Compute the global, non-redundant number of entities, i.e. the number of entities in the set // without double, aka. redundant entities, on the interprocessor boundary via global reduce. */ nGlobalEntity_ = gridview.comm().template sum(nLocalEntity); /* communicate the number of locally owned entities to all other processes so that the respective offset * can be calculated on the respective processor; we use the Dune mpi communication facility * for this; first, we gather the number of locally owned entities on the root process and, second, we * broadcast the array to all processes where the respective offset can be calculated. */ std::vector offset(size); std::fill(offset.begin(), offset.end(), 0); /** Share number of locally owned entities */ gridview_.comm().template allgather(&nLocalEntity, 1, offset.data()); int myoffset = 0; for (int i=1; i(); iter!=gridview_.template end<0>(); ++iter) { const IdType id = globalIdSet.id(*iter); /** retrieve the entity's id */ /** if the entity is owned by the process, go ahead with computing the global index */ if (iter->partitionType() == Dune::InteriorEntity) { const Index gindex = myoffset + globalcontrib; /** compute global index */ globalIndex_[id] = gindex; /** insert pair (key, datum) into the map */ globalcontrib++; /** increment contribution to global index */ } /** if entity is not owned, insert -1 to signal not yet calculated global index */ else { globalIndex_[id] = -1; /** insert pair (key, datum) into the map */ } } } else // if (codim==0) else { std::vector firstTime(gridview_.size(codim_)); std::fill(firstTime.begin(), firstTime.end(), true); for(Iterator iter = gridview_.template begin<0>();iter!=gridview_.template end<0>(); ++iter) { for (std::size_t i=0; isubEntities(codim_); i++) { IdType id=globalIdSet.subId(*iter,i,codim_); Index idx = gridview_.indexSet().subIndex(*iter,i,codim_); if (!firstTime[idx] ) continue; firstTime[idx] = false; if (uniqueEntityPartition->owner(idx) == rank) /** if the entity is owned by the process, go ahead with computing the global index */ { const Index gindex = myoffset + globalcontrib; /** compute global index */ globalIndex_.insert(std::make_pair(id,gindex)); /** insert pair (key, value) into the map */ const Index lindex = idx; localGlobalMap_[lindex] = gindex; globalcontrib++; /** increment contribution to global index */ } else /** if entity is not owned, insert -1 to signal not yet calculated global index */ { globalIndex_.insert(std::make_pair(id,-1)); } } } } // 2nd stage of global index calculation: communicate global index for non-owned entities // Create the data handle and communicate. IndexExchange dataHandle(globalIdSet,globalIndex_,indexSet,localGlobalMap_,codim_); gridview_.communicate(dataHandle, Dune::All_All_Interface, Dune::ForwardCommunication); } /** \brief Return the global index of a given entity */ template Index index(const Entity& entity) const { if (codim_==0) { /** global unique index is only applicable for inter or border type entities */ const GlobalIdSet& globalIdSet = gridview_.grid().globalIdSet(); /** retrieve globally unique Id set */ const IdType id = globalIdSet.id(entity); /** obtain the entity's id */ const Index gindex = globalIndex_.find(id)->second; /** retrieve the global index in the map with the id as key */ return gindex; } else return localGlobalMap_.find(gridview_.indexSet().index(entity))->second; } /** \brief Return the global index of a subentity of a given entity * * \param i Number of the requested subentity among all subentities of the given codimension * \param codim Codimension of the requested subentity */ template Index subIndex(const Entity& entity, unsigned int i, unsigned int codim) const { if (codim_==0) { /** global unique index is only applicable for inter or border type entities */ const GlobalIdSet& globalIdSet = gridview_.grid().globalIdSet(); /** retrieve globally unique Id set */ const IdType id = globalIdSet.subId(entity,i,codim); /** obtain the entity's id */ const Index gindex = globalIndex_.find(id)->second; /** retrieve the global index in the map with the id as key */ return gindex; } else return localGlobalMap_.find(gridview_.indexSet().subIndex(entity,i,codim))->second; } /** \brief Return the total number of entities over all processes that we have indices for * * \param codim If this matches GlobalIndexSet codimension, the number of entities is returned. * Otherwise, zero is returned. */ unsigned int size(unsigned int codim) const { return (codim_==codim) ? nGlobalEntity_ : 0; } protected: const GridView gridview_; /** \brief Codimension of the entities that we hold indices for */ unsigned int codim_; //! Global number of entities, i.e. number of entities without rendundant entities on interprocessor boundaries int nGlobalEntity_; IndexMap localGlobalMap_; /** \brief Stores global index of entities with entity's globally unique id as key */ MapId2Index globalIndex_; }; } // namespace Dune #endif /* DUNE_GRID_UTILITY_GLOBALINDEXSET_HH */ dune-grid-2.11.0/dune/grid/utility/gridinfo-gmsh-main.hh000066400000000000000000000146471511655130300230500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_UTILITY_GRIDINFO_GMSH_MAIN_HH #define DUNE_GRID_UTILITY_GRIDINFO_GMSH_MAIN_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** \file * \author Jö Fahlke * \date 2011 * * \brief Generic main() function for printing information about a mesh read * from a .msh-file. * * This header contains a generic main() function. To use it for your grid, * write a .cc file like this: \code #include #include const std::string programName = "dune-gridinfo-gmsh-mygrid-3d"; typedef Dune::MyGrid<3> Grid; #include \endcode * Write an automake target for your program as usual. No special libraries * are needed for you program, beyond what is needed for the grid in question. */ #ifdef HEADERCHECK // define so headercheck will run const std::string programName = "headercheck"; #endif // HEADERCHECK #ifndef DOXYGEN namespace { // anonymous namespace so we don't freakishly conflict with another usage() // function that may be linked in from another compilation unit. void usage(std::ostream &stream) { stream << "USAGE:\n" << " " << programName << " [-R REFINES] GRIDFILE\n" << "\n" << "PARAMETERS:\n" << " -R REFINES How many global refines to do after reading\n" << " (default: 0)\n" << " GRIDFILE Name of the .msh file to read the grid from.\n" << std::flush; } bool prefix_match(const std::string &prefix, const std::string &str) { return str.compare(0,prefix.size(), prefix) == 0; } void error_argument_required(const std::string &opt) { std::cerr << "Error: option " << opt << " requires argument\n"; usage(std::cerr); std::exit(1); } void error_unknown_option(const std::string &opt) { std::cerr << "Error: unknown option: " << opt << "\n"; usage(std::cerr); std::exit(1); } void error_parsing_optarg(const std::string &opt, const std::string &error) { std::cerr << "Error: option " << opt << ": " << error << "\n"; usage(std::cerr); std::exit(1); } template void parse(const std::string &arg, T &val) { std::istringstream s(arg); s >> val; bool good = !s.fail(); if(good) { char dummy; s >> dummy; good = s.fail() && s.eof(); } if(!good) { std::ostringstream s; s << "Can't parse \"" << arg << "\" as a " << Dune::className(val); throw std::runtime_error(s.str()); } } std::size_t refines = 0; std::string gridFileName = ""; void parseOptions(int argc, char **argv) { std::vector params; for(++argv; *argv; ++argv) { std::string arg = *argv; if(prefix_match("-", arg)) { std::string opt = arg; if(opt == "--") { for(++argv; *argv; ++argv) params.push_back(*argv); break; } else if(prefix_match("-h", opt) || prefix_match("-?", opt) || opt == "--help") { usage(std::cout); std::exit(0); } else if(opt == "-R" || opt == "--global-refines") { ++argv; if(!*argv) error_argument_required(opt); try { parse(*argv, refines); } catch(const std::runtime_error &e) { error_parsing_optarg(opt, e.what()); } } else if(prefix_match("-R", opt)) { try { parse(*argv+std::strlen("-R"), refines); } catch(const std::runtime_error &e) { error_parsing_optarg(opt, e.what()); } } else if(prefix_match("--global-refines=", opt)) { try { parse(*argv+std::strlen("--global-refines="), refines); } catch(const std::runtime_error &e) { error_parsing_optarg(opt, e.what()); } } else error_unknown_option(opt); } else params.push_back(arg); } // check command line arguments if(params.size() < 1) { std::cerr << "Need name of a .msh file to read.\n" << std::endl; usage(std::cerr); std::exit(1); } if(params.size() > 1) { std::cerr << "Too many arguments.\n" << std::endl; usage(std::cerr); std::exit(1); } gridFileName = params[0]; } } #ifndef HEADERCHECK int main(int argc, char **argv) { try { const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); // check that we are not run through mpirun if(mpiHelper.size() > 1) { if(mpiHelper.rank() == 0) std::cerr << programName << ": Sorry, this program works only in " << "serial." << std::endl; return 1; } parseOptions(argc, argv); // read grid typedef Dune::GmshReader Reader; std::shared_ptr gridp(Reader::read(gridFileName)); gridp->globalRefine(refines); // collect information Dune::GridViewInfo gridViewInfo; Dune::fillGridViewInfoSerial(gridp->leafGridView(), gridViewInfo); // print it std::cout << gridViewInfo << std::flush; } catch(const std::exception &e) { std::cerr << "Caught exception of type " << Dune::className(e) << std::endl << "e.what(): " << e.what() << std::endl; throw; } catch(const Dune::Exception &e) { std::cerr << "Caught exception of type " << Dune::className(e) << std::endl << "Exception message: " << e << std::endl; throw; } catch(const std::string &s) { std::cerr << "Caught exception of type " << Dune::className(s) << std::endl << "Exception message: " << s << std::endl; throw; } catch(...) { std::cerr << "Caught exception of unknown type" << std::endl; throw; } } #endif // !HEADERCHECK #endif // !DOXYGEN #endif // DUNE_GRID_UTILITY_GRIDINFO_GMSH_MAIN_HH dune-grid-2.11.0/dune/grid/utility/gridinfo.hh000066400000000000000000000235331511655130300211640ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_UTILITY_GRIDINFO_HH #define DUNE_GRID_UTILITY_GRIDINFO_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { //! Structure to hold statistical information about one type of entity template struct EntityInfo { //! number of entities in the set std::size_t count; //! minimum volume of all entities in the set. /** * If the set is empty, this is \f$+\infty\f$. If the volume of the * entities cannot be determined (some instance of the none GeometryType) * this is NaN. */ ctype volumeMin; //! maximum volume of all entities in the set. /** * If the set is empty, this is \f$-\infty\f$. If the volume of the * entities cannot be determined (some instance of the none GeometryType) * this is NaN. */ ctype volumeMax; //! sum of volumes of all entities in the set. /** * If the set is empty, this is 0. If the volume of the entities cannot * be determined (some instance of the none GeometryType) this is NaN. */ ctype volumeSum; //! initialize the structure /** * This assumes an empty set of entities so that information can be added * later: \c count is set to 0, \c volumeMin to +infinity, and \c * volumeMax to -infinity. */ EntityInfo() : count(0), volumeMin(std::numeric_limits::infinity()), volumeMax(-std::numeric_limits::infinity()), volumeSum(0) { } }; //! Comparison object to sort GeometryType by majorly dimension /** * This differs from the standard GeometryType::operator<() in that it puts * more emphasis on the dimension than the isNone() property. If it is used * as the comparison object in a map where the key is of type GeometryType, * all entries of one dimension will be lumped together. */ struct GridViewInfoGTCompare : public std::binary_function { //! compare two GeometryTypes inline bool operator()(const GeometryType &a, const GeometryType &b) const { return a.dim() < b.dim() || (a.dim() == b.dim() && (a.isNone() < b.isNone() || (a.isNone() == b.isNone() && (a.id() >> 1) < (b.id() >> 1)))); // topologyId is set to 0 for None, so no harm im comparing them even if // isNone()==true } }; //! structure to hold information about a certain GridView. /** * This is a map from GeometryType to EntityInfo structures. The entries in * the map are sorted in dimension-first, isNone()-second, and * topologyId-last order. */ template struct GridViewInfo : public std::map, GridViewInfoGTCompare> { //! name of the grid class this information was extracted from std::string gridName; //! name of the class of the GridView this information was extracted from std::string gridViewName; //! name of the partition this information was extracted from /** * May be empty if not applicable (serial grids, for instance) or may be a * combination of partitions such as "interior+border". */ std::string partitionName; //! print the information contained in this object /** * \param stream Stream object to print to. * \param prefix Prefix to print in front of each line. * * Sample output: * \verbatim * prefix> * \endverbatim * * If \c gridName, \c gridViewName, or \c partitionName is empty, the * corresponding line is not printed and no extra indentation is added for * the subsequent lines. */ void print(std::ostream &stream, std::string prefix) const { if(!gridName.empty()) { stream << prefix << gridName << ":\n"; prefix += " "; } if(!gridViewName.empty()) { stream << prefix << gridViewName << ":\n"; prefix += " "; } if(!partitionName.empty()) { stream << prefix << partitionName << ":\n"; prefix += " "; } typedef typename GridViewInfo::const_iterator Iterator; std::size_t dim = ~0; const Iterator &end = this->end(); for(Iterator it = this->begin(); it != end; ++it) { if(it->first.dim() != dim) { dim = it->first.dim(); stream << prefix << "Dim = " << dim << ":\n"; } stream << prefix << " " << it->first << ": Count = " << it->second.count << ", Volume range = " << "(" << it->second.volumeMin << ".." << it->second.volumeMax << "), Total volume = " << it->second.volumeSum << "\n"; } } }; //! write a GridViewInfo object /** * \relates GridViewInfo * * This is equivalent to callinf info.print(stream, ""). */ template std::ostream &operator<<(std::ostream &stream, const GridViewInfo &info) { info.print(stream, ""); return stream; } #ifndef DOXYGEN //! operation for Hybrid::forEach Internally used by fillGridViewInfoSerial template struct FillGridInfoOperation { template static void apply(const Entity &e, const Mapper &mapper, Visited &visited, const typename Entity::Geometry &geo, RefElem refelem, GridViewInfo &gridViewInfo) { typedef typename Entity::Geometry::ctype ctype; static const std::size_t dimw = Entity::Geometry::coorddimension; static const std::size_t dim = Entity::dimension; std::vector > coords; for(int i = 0; i < refelem.size(codim); ++i) { int index = mapper.map(e, i, codim); if(visited[index]) continue; visited[index] = true; GeometryType gt = refelem.type(i, codim); coords.clear(); coords.resize( refelem.size(i, codim, dim) ); for(std::size_t corner = 0; corner < coords.size(); ++corner) coords[ corner ] = geo.corner( refelem.subEntity( i, codim, corner, dim ) ); MultiLinearGeometry mygeo(gt, coords); ctype volume = mygeo.volume(); EntityInfo &ei = gridViewInfo[mygeo.type()]; ei.volumeMin = std::min(ei.volumeMin, volume); ei.volumeMax = std::max(ei.volumeMax, volume); ei.volumeSum += volume; } } }; #endif // !DOXYGEN //! fill a GridViewInfo structure from a serial grid /** * If used on a parallel grid, it will gather information for entities of * all partitions on each rank locally. */ template void fillGridViewInfoSerial(const GV &gv, GridViewInfo &gridViewInfo) { typedef typename GV::ctype ctype; static const std::size_t dim = GV::dimension; typedef typename GV::template Codim<0>::Iterator EIterator; typedef typename GV::template Codim<0>::Geometry EGeometry; typedef typename GV::IndexSet IndexSet; typedef typename GridViewInfo::iterator InfoIterator; typedef ReferenceElements RefElems; MultipleCodimMultipleGeomTypeMapper mapper(gv, [](GeometryType gt, int) { return gt.dim() < GV::dimension; } ); std::vector visited(mapper.size(), false); gridViewInfo.gridName = className(); gridViewInfo.gridViewName = className(); gridViewInfo.partitionName = ""; gridViewInfo.clear(); const EIterator &eend = gv.template end<0>(); for(EIterator eit = gv.template begin<0>(); eit != eend; ++eit) { ctype volume = eit->geometry().volume(); EntityInfo &ei = gridViewInfo[eit->type()]; ei.volumeMin = std::min(ei.volumeMin, volume); ei.volumeMax = std::max(ei.volumeMax, volume); ei.volumeSum += volume; if(!eit->type().isNone()) { const EGeometry &geo = eit->geometry(); Hybrid::forEach(std::make_index_sequence< dim >{}, [ & ](auto i){ FillGridInfoOperation< i+1 >::apply(*eit, mapper, visited, geo, RefElems::general(eit->type()), gridViewInfo); } ); } } GeometryType gt = GeometryTypes::none(dim); if(gridViewInfo.count(gt) > 0) { for(std::size_t codim = 0; codim < dim; ++codim) { gt = GeometryTypes::none(dim-codim); EntityInfo & ei = gridViewInfo[gt]; ei.volumeMin = ei.volumeMax = ei.volumeSum = std::numeric_limits::quiet_NaN(); } gt = GeometryTypes::none(0); EntityInfo & ei = gridViewInfo[gt]; ei.volumeMin = ei.volumeMax = ei.volumeSum = 0; } const InfoIterator &end = gridViewInfo.end(); const IndexSet &is = gv.indexSet(); for(InfoIterator it = gridViewInfo.begin(); it != end; ++it) { it->second.count = is.size(it->first); if(it->second.count == 0) DUNE_THROW(Exception, "Found Entities of geomentry type " << it->first << " while iterating through the grid, but " "indexSet.size() == 0 for that geometry type"); } } } // namespace Dune #endif // DUNE_GRID_UTILITY_GRIDINFO_HH dune-grid-2.11.0/dune/grid/utility/gridtype.hh000066400000000000000000000017421511655130300212100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRIDTYPE_HH #define DUNE_GRIDTYPE_HH /** * @file * @author Andreas Dedner * * @brief This file can be included directly following config.h to * test if a grid type was correctly selected. * **/ #include // HAVE_GRIDTYPE #ifndef HEADERCHECK // NOGRID is used to specify that no default was set during configure // If NOGRID and HAVE_GRIDTYPE are both not set then no grid was selected // and an error is produced #if defined NOGRID #if ! HAVE_GRIDTYPE #error "No grid type selected, use GRIDTYPE=..." #endif #else #if ! HAVE_GRIDTYPE #error "No grid type selected, typo in GRIDTYPE=...?" #endif #endif #endif // HEADERCHECK #endif // DUNE_GRIDTYPE_HH dune-grid-2.11.0/dune/grid/utility/hierarchicsearch.hh000066400000000000000000000136421511655130300226520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_HIERARCHICSEARCH_HH #define DUNE_GRID_HIERARCHICSEARCH_HH /** @file @brief Utility class for hierarchically searching for an Entity containing a given point. */ #include #include #include #include #include #include #include #include #include namespace Dune { /** @brief Search an IndexSet for an Entity containing a given point. */ template class HierarchicSearch { protected: //! get dimension from the grid constexpr static int dim = Grid::dimension; //! get world dimension from the grid constexpr static int dimw = Grid::dimensionworld; //! get coord type from the grid typedef typename Grid::ctype ct; //! get entity from the grid typedef typename Grid::template Codim<0>::Entity Entity; //! type of HierarchicIterator typedef typename Grid::HierarchicIterator HierarchicIterator; static std::string formatEntityInformation ( const Entity &e ) { const typename Entity::Geometry &geo = e.geometry(); std::ostringstream info; info << "level=" << e.level() << " " << "partition=" << e.partitionType() << " " << "center=(" << geo.center() << ") " << "corners=[(" << geo.corner(0) << ")"; for(int i = 1; i < geo.corners(); ++i) info << " (" << e.geometry().corner(i) << ")"; info << "]"; return info.str(); } /** internal helper method @param[in] entity Entity whose children should be searched @param[in] global Point you are searching for Search the child entity containing point global. Recursively recursively continue until we found an entity that is part of the IndexSet. */ Entity hFindEntity ( const Entity &entity, const FieldVector& global) const { // type of element geometry typedef typename Entity::Geometry Geometry; // type of local coordinate typedef typename Geometry::LocalCoordinate LocalCoordinate; const int childLevel = entity.level()+1 ; // loop over all child Entities const HierarchicIterator end = entity.hend( childLevel ); for( HierarchicIterator it = entity.hbegin( childLevel ); it != end; ++it ) { Entity child = *it; Geometry geo = child.geometry(); LocalCoordinate local = geo.local(global); if (referenceElement( geo ).checkInside(local)) { // return if we found the leaf, else search through the child entities if( indexSet_.contains( child ) ) return child; else return hFindEntity( child, global ); } } std::ostringstream children; HierarchicIterator it = entity.hbegin( childLevel ); if(it != end) { children << "{" << formatEntityInformation(*it) << "}"; for( ++it; it != end; ++it ) children << " {" << formatEntityInformation(*it) << "}"; } DUNE_THROW(Exception, "{" << className(*this) << "} Unexpected " "internal Error: none of the children of the entity " "{" << formatEntityInformation(entity) << "} contains " "coordinate (" << global << "). Children are: " "[" << children.str() << "]."); } public: /** @brief Construct a HierarchicSearch object from a Grid and an IndexSet */ HierarchicSearch(const Grid & g, const IS & is) : grid_(g), indexSet_(is) {} /** @brief Search the IndexSet of this HierarchicSearch for an Entity containing point global. \exception GridError No element of the coarse grid contains the given coordinate. */ Entity findEntity(const FieldVector& global) const { return findEntity(global); } /** @brief Search the IndexSet of this HierarchicSearch for an Entity containing point global. \exception GridError No element of the coarse grid contains the given coordinate. */ template Entity findEntity(const FieldVector& global) const { typedef typename Grid::LevelGridView LevelGV; const LevelGV &gv = grid_.levelGridView(0); //! type of LevelIterator typedef typename LevelGV::template Codim<0>::template Partition::Iterator LevelIterator; // type of element geometry typedef typename Entity::Geometry Geometry; // type of local coordinate typedef typename Geometry::LocalCoordinate LocalCoordinate; // loop over macro level const LevelIterator end = gv.template end<0, partition>(); for (LevelIterator it = gv.template begin<0, partition>(); it != end; ++it) { Entity entity = *it; Geometry geo = entity.geometry(); LocalCoordinate local = geo.local( global ); if( !referenceElement( geo ).checkInside( local ) ) continue; if( (int(dim) != int(dimw)) && ((geo.global( local ) - global).two_norm() > 1e-8) ) continue; // return if we found the leaf, else search through the child entities if( indexSet_.contains( entity ) ) return entity; else return hFindEntity( entity, global ); } DUNE_THROW( GridError, "Coordinate " << global << " is outside the grid." ); } protected: const Grid& grid_; const IS& indexSet_; }; } // end namespace Dune #endif // DUNE_GRID_HIERARCHICSEARCH_HH dune-grid-2.11.0/dune/grid/utility/hostgridaccess.hh000066400000000000000000000124131511655130300223630ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_HOSTGRIDACCESS_HH #define DUNE_GRID_HOSTGRIDACCESS_HH #include #include namespace Dune { // External Forward Declarations // ----------------------------- template< class HostGrid, class CoordFunction, class Allocator > class GeometryGrid; template< class > class IdentityGrid; // HostGridAccess // -------------- template< class Grid > struct HostGridAccess; /** \class HostGridAccess * \brief provides access to host grid objects from GeometryGrid * * \tparam GeometryGrid * * \nosubgrouping */ template< class HG, class CoordFunction, class Allocator > struct HostGridAccess< GeometryGrid< HG, CoordFunction, Allocator > > { /** \name Exported Types * \{ */ typedef GeometryGrid< HG, CoordFunction, Allocator > Grid; //! type of HostGrid typedef typename Grid::HostGrid HostGrid; /** \} */ /** \brief A Traits struct that collects return types of class member methods. * * \tparam codim codimension */ template< int codim > struct Codim { //! type of the GeometryGrid entity typedef typename Grid::template Codim< codim >::Entity Entity; //! type of the host entity typedef typename HostGrid::template Codim< codim >::Entity HostEntity; }; //! type of the GeometryGrid leaf intersection typedef typename Grid::Traits::LeafIntersection LeafIntersection; //! type of the GeometryGrid level intersection typedef typename Grid::Traits::LevelIntersection LevelIntersection; //! type of the host leaf intersection typedef typename HostGrid::Traits::LeafIntersection HostLeafIntersection; //! type of the host level intersection typedef typename HostGrid::Traits::LevelIntersection HostLevelIntersection; /** \brief Get underlying HostGrid. * \param[in] grid GeometryGrid * \returns HostGrid */ static const HostGrid &hostGrid ( const Grid &grid ) { return grid.hostGrid(); } template< class Entity > static const typename Codim< Entity::codimension >::HostEntity & hostEntity ( const Entity &entity ) { return hostEntity< Entity::codimension >( entity ); } template< int codim > static const typename Codim< codim >::HostEntity & hostEntity ( const typename Codim< codim >::Entity &entity ) { return entity.impl().hostEntity(); } template< class HostIntersection > static const HostIntersection & hostIntersection ( const Intersection< const Grid, GeoGrid::Intersection< const Grid, HostIntersection > > &intersection ) { return intersection.impl().hostIntersection(); } }; /** \class HostGridAccess * \brief provides access to host grid objects from IdentityGrid * * \tparam IdentityGrid meta grid, whose host grid shall be accessed * * \nosubgrouping */ template< class HG > struct HostGridAccess< IdentityGrid< HG > > { /** \name Exported Types * \{ */ typedef IdentityGrid< HG > Grid; //! type of HostGrid typedef HG HostGrid; /** \} */ /** \brief A Traits struct that collects return types of class member methods. * * \tparam codim codimension */ template< int codim > struct Codim { //! type of the IdGrid entity typedef typename Grid::template Codim< codim >::Entity Entity; //! type of the host entity typedef typename HostGrid::template Codim< codim >::Entity HostEntity; }; //! type of the IdGrid leaf intersection typedef typename Grid::Traits::LeafIntersection LeafIntersection; //! type of the IdGrid level intersection typedef typename Grid::Traits::LevelIntersection LevelIntersection; //! type of the host leaf intersection typedef typename HostGrid::Traits::LeafIntersection HostLeafIntersection; //! type of the host level intersection typedef typename HostGrid::Traits::LevelIntersection HostLevelIntersection; /** \brief Get underlying HostGrid. * \param[in] grid grid, whose host grid shall be returned * \returns HostGrid */ static const HostGrid &hostGrid ( const Grid &grid ) { return grid.getHostGrid(); } template< class Entity > static const typename Codim< Entity::codimension >::HostEntity & hostEntity ( const Entity &entity ) { return hostEntity< Entity::codimension >( entity ); } template< int codim > static const typename Codim< codim >::HostEntity & hostEntity ( const typename Codim< codim >::Entity &entity ) { return *entity.impl().hostEntity_; } static const HostLeafIntersection & hostIntersection ( const LeafIntersection &intersection ) { return *intersection.impl().hostIterator_; } static const HostLevelIntersection & hostIntersection ( const LevelIntersection &intersection ) { return *intersection.impl().hostIterator_; } }; } // namespace Dune #endif // #ifndef DUNE_GRID_HOSTGRIDACCESS_HH dune-grid-2.11.0/dune/grid/utility/multiindex.hh000066400000000000000000000026611511655130300215440ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_GRID_UTILITY_MULTIINDEX_HH #define DUNE_GRID_UTILITY_MULTIINDEX_HH /** \file * \brief Implements a multiindex with arbitrary dimension and fixed index ranges * This is used by various factory classes. */ #include namespace Dune { namespace FactoryUtilities { template class MultiIndex : public std::array { // The range of each component std::array limits_; public: /** \brief Constructor with a given range for each digit */ MultiIndex(const std::array& limits) : limits_(limits) { std::fill(this->begin(), this->end(), 0); } /** \brief Increment the MultiIndex */ MultiIndex& operator++() { for (std::size_t i=0; i #include #include #include #include #include #include #include #if HAVE_PARMETIS #include // only enable for ParMETIS because the implementation uses functions that // are not emulated by scotch #ifdef PARMETIS_MAJOR_VERSION namespace Dune { /** \brief Compute a repartitioning of a Dune grid using ParMetis * * \author Benjamin Bykowski */ template struct ParMetisGridPartitioner { // define index type as provided by ParMETIS #if PARMETIS_MAJOR_VERSION > 3 typedef idx_t idx_type; typedef ::real_t real_type; #else typedef int idx_type; typedef float real_type; #endif // PARMETIS_MAJOR_VERSION > 3 constexpr static int dimension = GridView::dimension; /** \brief Create an initial partitioning of a Dune grid, i.e., not taking into account communication cost * * This pipes a Dune grid into the method ParMETIS_V3_PartMeshKway (see the ParMetis documentation for details) * * \param gv The grid view to be partitioned * \param mpihelper The MPIHelper object, needed to get the MPI communicator * * \return std::vector with one uint per All_Partition element. For each element, the entry is the * number of the partition the element is assigned to. */ static std::vector partition(const GridView& gv, const Dune::MPIHelper& mpihelper) { const unsigned numElements = gv.size(0); std::vector part(numElements); // Setup parameters for ParMETIS idx_type wgtflag = 0; // we don't use weights idx_type numflag = 0; // we are using C-style arrays idx_type ncon = 1; // number of balance constraints idx_type ncommonnodes = 2; // number of nodes elements must have in common to be considered adjacent to each other idx_type options[4] = {0, 0, 0, 0}; // use default values for random seed, output and coupling idx_type edgecut; // will store number of edges cut by partition idx_type nparts = mpihelper.size(); // number of parts equals number of processes std::vector tpwgts(ncon*nparts, 1./nparts); // load per subdomain and weight (same load on every process) std::vector ubvec(ncon, 1.05); // weight tolerance (same weight tolerance for every weight there is) // The difference elmdist[i+1] - elmdist[i] is the number of nodes that are on process i std::vector elmdist(nparts+1); elmdist[0] = 0; std::fill(elmdist.begin()+1, elmdist.end(), gv.size(0)); // all elements are on process zero // Create and fill arrays "eptr", where eptr[i] is the number of vertices that belong to the i-th element, and // "eind" contains the vertex-numbers of the i-the element in eind[eptr[i]] to eind[eptr[i+1]-1] std::vector eptr, eind; int numVertices = 0; eptr.push_back(numVertices); for (const auto& element : elements(gv, Partitions::interior)) { const size_t curNumVertices = referenceElement(element.type()).size(dimension); numVertices += curNumVertices; eptr.push_back(numVertices); for (size_t k = 0; k < curNumVertices; ++k) eind.push_back(gv.indexSet().subIndex(element, k, dimension)); } // Partition mesh using ParMETIS if (0 == mpihelper.rank()) { MPI_Comm comm = Dune::MPIHelper::getLocalCommunicator(); #if PARMETIS_MAJOR_VERSION >= 4 const int OK = #endif ParMETIS_V3_PartMeshKway(elmdist.data(), eptr.data(), eind.data(), NULL, &wgtflag, &numflag, &ncon, &ncommonnodes, &nparts, tpwgts.data(), ubvec.data(), options, &edgecut, reinterpret_cast(part.data()), &comm); #if PARMETIS_MAJOR_VERSION >= 4 if (OK != METIS_OK) DUNE_THROW(Dune::Exception, "ParMETIS returned an error code."); #endif } return part; } /** \brief Create a repartitioning of a distributed Dune grid * * This pipes a Dune grid into the method ParMETIS_V3_AdaptiveRepart (see the ParMetis documentation for details) * * \param gv The grid view to be partitioned * \param mpihelper The MPIHelper object, needed to get the MPI communicator * \param itr ParMetis parameter to balance grid transport cost vs. communication cost for the redistributed grid. * * \return std::vector with one uint per All_Partition element. For each Interior_Partition element, the entry is the * number of the partition the element is assigned to. */ static std::vector repartition(const GridView& gv, const Dune::MPIHelper& mpihelper, real_type itr = 1000) { // Create global index map GlobalIndexSet globalIndex(gv,0); int numElements = std::distance(gv.template begin<0, Interior_Partition>(), gv.template end<0, Interior_Partition>()); std::vector interiorPart(numElements); // Setup parameters for ParMETIS idx_type wgtflag = 0; // we don't use weights idx_type numflag = 0; // we are using C-style arrays idx_type ncon = 1; // number of balance constraints idx_type options[4] = {0, 0, 0, 0}; // use default values for random seed, output and coupling idx_type edgecut; // will store number of edges cut by partition idx_type nparts = mpihelper.size(); // number of parts equals number of processes std::vector tpwgts(ncon*nparts, 1./nparts); // load per subdomain and weight (same load on every process) std::vector ubvec(ncon, 1.05); // weight tolerance (same weight tolerance for every weight there is) MPI_Comm comm = Dune::MPIHelper::getCommunicator(); // Make the number of interior elements of each processor available to all processors std::vector offset(gv.comm().size()); std::fill(offset.begin(), offset.end(), 0); gv.comm().template allgather(&numElements, 1, offset.data()); // The difference vtxdist[i+1] - vtxdist[i] is the number of elements that are on process i std::vector vtxdist(gv.comm().size()+1); vtxdist[0] = 0; for (unsigned int i=1; i xadj, adjncy; xadj.push_back(0); for (const auto& element : elements(gv, Partitions::interior)) { size_t numNeighbors = 0; for (const auto& in : intersections(gv, element)) { if (in.neighbor()) { adjncy.push_back(globalIndex.index(in.outside())); ++numNeighbors; } } xadj.push_back(xadj.back() + numNeighbors); } #if PARMETIS_MAJOR_VERSION >= 4 const int OK = #endif ParMETIS_V3_AdaptiveRepart(vtxdist.data(), xadj.data(), adjncy.data(), NULL, NULL, NULL, &wgtflag, &numflag, &ncon, &nparts, tpwgts.data(), ubvec.data(), &itr, options, &edgecut, reinterpret_cast(interiorPart.data()), &comm); #if PARMETIS_MAJOR_VERSION >= 4 if (OK != METIS_OK) DUNE_THROW(Dune::Exception, "ParMETIS returned error code " << OK); #endif // At this point, interiorPart contains a target rank for each interior element, and they are sorted // by the order in which the grid view traverses them. Now we need to do two things: // a) Add additional dummy entries for the ghost elements // b) Use the element index for the actual ordering. Since there may be different types of elements, // we cannot use the index set directly, but have to go through a Mapper. typedef MultipleCodimMultipleGeomTypeMapper ElementMapper; ElementMapper elementMapper(gv, mcmgElementLayout()); std::vector part(gv.size(0)); std::fill(part.begin(), part.end(), 0); unsigned int c = 0; for (const auto& element : elements(gv, Partitions::interior)) part[elementMapper.index(element)] = interiorPart[c++]; return part; } }; } // namespace Dune #else // PARMETIS_MAJOR_VERSION #warning "You seem to be using the ParMETIS emulation layer of scotch, which does not work with this file." #endif #else // HAVE_PARMETIS #warning "PARMETIS was not found, please check your configuration" #endif #endif // DUNE_GRID_UTILITY_PARMETISGRIDPARTITIONER_HH dune-grid-2.11.0/dune/grid/utility/persistentcontainer.hh000066400000000000000000000047541511655130300234720ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PERSISTENTCONTAINER_HH #define DUNE_PERSISTENTCONTAINER_HH #include #include namespace Dune { /** \brief A class for storing data during an adaptation cycle. * * \copydetails PersistentContainerInterface */ template< class G, class T > class PersistentContainer : public PersistentContainerMap< G, typename G::LocalIdSet, std::map< typename G::LocalIdSet::IdType, T > > { typedef PersistentContainerMap< G, typename G::LocalIdSet, std::map< typename G::LocalIdSet::IdType, T > > Base; public: typedef typename Base::Grid Grid; typedef typename Base::Value Value; PersistentContainer ( const Grid &grid, int codim, const Value &value = Value() ) : Base( grid, codim, grid.localIdSet(), value ) {} }; /** \brief refer PersistentContainer to the implementation of the mutable grid */ template< class Grid, class T > class PersistentContainer< const Grid, T > : public PersistentContainer< Grid, T > { typedef PersistentContainer< Grid, T > Base; public: typedef typename Base::Value Value; PersistentContainer ( const typename Base::Grid &grid, int codim, const Value &value = Value() ) : Base(grid, codim, value) {} }; } // namespace Dune #if 0 // the following implementation can be used for a grid providing a hash for the id type #include namespace Dune { template< G, class T > class PersistentContainer : public PersistentContainerMap< G, typename G::LocalIdSet, std::unordered_map< typename G::LocalIdSet::IdType, T > > { typedef PersistentContainerMap< G, typename G::LocalIdSet, std::unordered_map< typename G::LocalIdSet::IdType, T > > Base; public: typedef typename Base::Grid Grid; typedef typename Base::Value Value; PersistentContainer ( const Grid &grid, int codim, const Value &value ) : Base( grid, codim, grid.localIdSet(), value ) {} }; } // namespace Dune #endif // #if 0 namespace std { template< class G, class T > inline void swap ( Dune::PersistentContainer< G, T > &a, Dune::PersistentContainer< G, T > &b ) { a.swap( b ); } } // namespace std #endif // #ifndef DUNE_PERSISTENTCONTAINER_HH dune-grid-2.11.0/dune/grid/utility/persistentcontainerinterface.hh000066400000000000000000000165331511655130300253510ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PERSISTENTCONTAINERINTERFACE_HH #define DUNE_PERSISTENTCONTAINERINTERFACE_HH #ifndef HEADERCHECK #error "This header exists for documentation purposes only and should never be included directly." #endif namespace Dune { /** \brief Persistent storage of data on all entities of a grid. * * This container allows to store data which is to remain persistent * even during adaptation cycles. * It provides storage for all entities in the hierarchy of a given * codimension (provided dynamically during construction) and behaves much * like an STL container. * * The container stores one entry for each entity in the hierarchical grid. * However, it may also store some additional entries, which are not (or no * longer) attached to an entity. * * After grid modification the method resize must be called to ensure entries * for each entity in the modified grid. * Accessing newly created entities before calling resize results in * undefined behavior (e.g., a segmentation fault). * To reduce the amount of overallocated entries, the method shrinkToFit * may be called. * It is explicitly possible that the grid adapts any persistent containers * directly during the adaptation process. * * The containers are also be persistent over backup / restore of the grid. * After 'shrinkToFit', the entries in the container (and their order) must * match those of a newly created container, even after a backup and restore * of the grid. * * There is a default implementation based on std::map but a grid * implementation may provide a specialized implementation. * Grids with a hashable id type can use std::unordered_map to store * the data by simply deriving their PersistentContainer from * Dune::PersistentContainerMap. * For grids providing an id set suitable addressing vector-like storages, * i.e., the id is an integral type and a method size() is provided, * Dune::PersistentContainerVector can be used. * * \tparam G Grid type * \tparam T Container's value type */ template< class G, class T > class PersistentContainerInterface { typedef PersistentContainerInterface< G, T > This; struct ImplementationDefined; public: typedef G Grid; typedef T Value; typedef ImplementationDefined Size; typedef ImplementationDefined ConstIterator; typedef ImplementationDefined Iterator; // construction /** \brief constructor * * \param[in] grid reference to the grid to attach data to * \param[in] codim codimension to attach data to * \param[in] value value for initial entries * * \note All implementations must provide at least this constructor. */ PersistentContainerInterface ( Grid &grid, int codim, const Value &value = Value() ); /** \brief copy constructor */ PersistentContainerInterface ( const This &other ); /** \brief assignment operator */ const This &operator= ( const This &other ); // element access /** \brief access the data associated with an entity * * \note The entity must be of the same codimension as the container */ template< class Entity > const Value &operator[] ( const Entity &entity ) const; /** \brief access the data associated with an entity * * \note The entity must be of the same codimension as the container */ template< class Entity > Value &operator[] ( const Entity &entity ); /** \brief access the data associated with a subentity * * \note The codimension of the entity must be less or equal to the * codimension of the container. */ template< class Entity > const Value &operator() ( const Entity &entity, int subEntity ) const; /** \brief access the data associated with a subentity * * \note The codimension of the entity must be less or equal to the * codimension of the container. */ template< class Entity > Value &operator() ( const Entity &entity, int subEntity ); // capacity /** \brief number of entries in the container * * \note The number of entries in the container may be large than the * number of entities in the grid. */ Size size () const; /** \brief reserve memory for all entities in the grid * * This method will enlarge the container such that there is an * entry for each entity. * * After a grid modification, this method must be called before accessing * any data associated to newly created entities. * * \note The container might still hold entries for entities that no * longer exist in the grid. * While those entries ca no longer be accessed through an entity, * iterators will still stop at such entries. */ void resize ( const Value &value = Value() ); /** \brief remove unnecessary entries from container * * This method will remove entries from the container that can no longer * be accessed from the grid. * * The entries in the container (and their order) must match those of a * newly created container. * This property must be persistent over backup / restore of the grid. * * \note This method is merely a hint to the container. * According to the container's internal addressing rules, some * inaccessible entries might remain in the container. */ void shrinkToFit (); // modifiers /** \brief set all accessible entries to a given value * * \note It is undefined, whether the inaccessible values are also * motified. */ void fill ( const Value &value ); /** \brief exchange the content of the container with another one * * \note std::swap is overloaded to refor to this method */ void swap ( This &other ); // iterators /** \brief returns an iterator pointing to the first element of the container * * \note Iterators stop at all entries of the container, even if they are * no longer accessible from the grid. */ ConstIterator begin () const; /** \brief returns an iterator pointing to the first element of the container * * \note Iterators stop at all entries of the container, even if they are * no longer accessible from the grid. */ Iterator begin (); /** \brief returns an iterator pointing to the last element of the container * * \note Iterators stop at all entries of the container, even if they are * no longer accessible from the grid. */ ConstIterator end () const; /** \brief returns an iterator pointing to the last element of the container * * \note Iterators stop at all entries of the container, even if they are * no longer accessible from the grid. */ Iterator end (); // information /** \brief return the codimension, the container attaches data to */ int codimension () const; }; } // namespace Dune #endif // #ifndef DUNE_PERSISTENTCONTAINERINTERFACE_HH dune-grid-2.11.0/dune/grid/utility/persistentcontainermap.hh000066400000000000000000000211251511655130300241570ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PERSISTENTCONTAINERMAP_HH #define DUNE_PERSISTENTCONTAINERMAP_HH #include #include #include #include #include #include #include namespace Dune { // PersistentContainerMap // ---------------------- /** \brief map-based implementation of the PersistentContainer */ template< class G, class IdSet, class Map > class PersistentContainerMap { typedef PersistentContainerMap< G, IdSet, Map > This; protected: template< class reference, class iterator > class IteratorWrapper; public: typedef G Grid; typedef typename Map::mapped_type Value; typedef typename Map::size_type Size; typedef IteratorWrapper< const Value, typename Map::const_iterator > ConstIterator; typedef IteratorWrapper< Value, typename Map::iterator > Iterator; PersistentContainerMap ( const Grid &grid, int codim, const IdSet &idSet, const Value &value ) : grid_( &grid ), codim_( codim ), idSet_( &idSet ), data_() { resize( value ); } template< class Entity > const Value &operator[] ( const Entity &entity ) const { assert( Entity::codimension == codimension() ); typename Map::const_iterator pos = data_.find( idSet().id( entity ) ); assert( pos != data_.end() ); return pos->second; } template< class Entity > Value &operator[] ( const Entity &entity ) { assert( Entity::codimension == codimension() ); typename Map::iterator pos = data_.find( idSet().id( entity ) ); assert( pos != data_.end() ); return pos->second; } template< class Entity > const Value &operator() ( const Entity &entity, int subEntity ) const { typename Map::const_iterator pos = data_.find( idSet().subId( entity, subEntity, codimension() ) ); assert( pos != data_.end() ); return pos->second; } template< class Entity > Value &operator() ( const Entity &entity, int subEntity ) { typename Map::iterator pos = data_.find( idSet().subId( entity, subEntity, codimension() ) ); assert( pos != data_.end() ); return pos->second; } Size size () const { return data_.size(); } void resize ( const Value &value = Value() ) { Hybrid::forEach( std::make_index_sequence< Grid::dimension+1 >{}, [ & ]( auto i ){ if( int(i) == this->codimension() ) this->template resize< i >( value ); } ); } void shrinkToFit () {} void fill ( const Value &value ) { std::fill( begin(), end(), value ); } void swap ( This &other ) { std::swap( grid_, other.grid_ ); std::swap( codim_, other.codim_ ); std::swap( idSet_, other.idSet_ ); std::swap( data_, other.data_ ); } ConstIterator begin () const; Iterator begin (); ConstIterator end () const; Iterator end (); int codimension () const { return codim_; } protected: const Grid &grid () const { return *grid_; } template< int codim > void resize ( const Value &value ); template< int codim > void migrateLevel ( int level, const Value &value, Map &data, std::integral_constant< bool, true > ); template< int codim > void migrateLevel ( int level, const Value &value, Map &data, std::integral_constant< bool, false > ); static void migrateEntry ( const typename IdSet::IdType &id, const Value &value, Map &oldData, Map &newData ); const IdSet &idSet () const { return *idSet_; } const Grid *grid_; int codim_; const IdSet *idSet_; Map data_; }; // PersistentContainerMap::IteratorWrapper // --------------------------------------- template< class G, class IdSet, class Map > template< class value, class iterator > class PersistentContainerMap< G, IdSet, Map >::IteratorWrapper : public iterator { typedef IteratorWrapper< const value, typename Map::const_iterator > ConstWrapper; public: IteratorWrapper ( const iterator &it ) : it_( it ) {} operator ConstWrapper () const { return ConstWrapper( it_ ); } value &operator* () { return it_->second; } value *operator-> () { return &(it_->second); } bool operator== ( const IteratorWrapper &other ) const { return (it_ == other.it_); } bool operator!= ( const IteratorWrapper &other ) const { return (it_ != other.it_); } IteratorWrapper &operator++ () { ++it_; return *this; } private: iterator it_; }; // Implementation of PersistentContainerMap // ---------------------------------------- template< class G, class IdSet, class Map > inline typename PersistentContainerMap< G, IdSet, Map >::ConstIterator PersistentContainerMap< G, IdSet, Map >::begin () const { return ConstIterator( data_.begin() ); } template< class G, class IdSet, class Map > inline typename PersistentContainerMap< G, IdSet, Map >::Iterator PersistentContainerMap< G, IdSet, Map >::begin () { return Iterator( data_.begin() ); } template< class G, class IdSet, class Map > inline typename PersistentContainerMap< G, IdSet, Map >::ConstIterator PersistentContainerMap< G, IdSet, Map >::end () const { return ConstIterator( data_.end() ); } template< class G, class IdSet, class Map > inline typename PersistentContainerMap< G, IdSet, Map >::Iterator PersistentContainerMap< G, IdSet, Map >::end () { return Iterator( data_.end() ); } template< class G, class IdSet, class Map > template< int codim > inline void PersistentContainerMap< G, IdSet, Map >::resize ( const Value &value ) { std::integral_constant< bool, Capabilities::hasEntityIterator< Grid, codim >::v > hasEntityIterator; assert( codim == codimension() ); // create empty map and swap it with current map (no need to copy twice) Map data; std::swap( data, data_ ); // copy all data from old map into new one (adding new entries, if necessary) const int maxLevel = grid().maxLevel(); for ( int level = 0; level <= maxLevel; ++level ) migrateLevel< codim >( level, value, data, hasEntityIterator ); } template< class G, class IdSet, class Map > template< int codim > inline void PersistentContainerMap< G, IdSet, Map > ::migrateLevel ( int level, const Value &value, Map &data, std::integral_constant< bool, true > ) { typedef typename Grid::LevelGridView LevelView; typedef typename LevelView::template Codim< codim >::Iterator LevelIterator; const LevelView levelView = grid().levelGridView( level ); const LevelIterator end = levelView.template end< codim >(); for( LevelIterator it = levelView.template begin< codim >(); it != end; ++it ) migrateEntry( idSet().id( *it ), value, data, data_ ); } template< class G, class IdSet, class Map > template< int codim > inline void PersistentContainerMap< G, IdSet, Map > ::migrateLevel ( int level, const Value &value, Map &data, std::integral_constant< bool, false > ) { typedef typename Grid::LevelGridView LevelView; typedef typename LevelView::template Codim< 0 >::Iterator LevelIterator; const LevelView levelView = grid().levelGridView( level ); const LevelIterator end = levelView.template end< 0 >(); for( LevelIterator it = levelView.template begin< 0 >(); it != end; ++it ) { const typename LevelIterator::Entity &entity = *it; const int subEntities = entity.subEntities( codim ); for( int i = 0; i < subEntities; ++i ) migrateEntry( idSet().subId( entity, i, codim ), value, data, data_ ); } } template< class G, class IdSet, class Map > inline void PersistentContainerMap< G, IdSet, Map > ::migrateEntry ( const typename IdSet::IdType &id, const Value &value, Map &oldData, Map &newData ) { // insert entry for id const std::pair< typename Map::iterator, bool > inserted = newData.insert( std::make_pair( id, value ) ); // if entry did not exist previously, copy data if( inserted.second ) { const typename Map::iterator pos = oldData.find( id ); if( pos != oldData.end() ) { inserted.first->second = pos->second; oldData.erase( pos ); } } } } // namespace Dune #endif // #ifndef DUNE_PERSISTENTCONTAINERMAP_HH dune-grid-2.11.0/dune/grid/utility/persistentcontainervector.hh000066400000000000000000000111551511655130300247060ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PERSISTENTCONTAINERVECTOR_HH #define DUNE_PERSISTENTCONTAINERVECTOR_HH #include #include namespace Dune { // PersistentContainerVector // ------------------------- /** * \brief vector-based implementation of the PersistentContainer * * Some grid implementations, like YaspGrid, can provide consecutive, * zero-based, persistent indices for the entire grid hierarchy. * This implementation of a PersistentContainer uses such an index set and * a std::vector-like container to store user data in an efficient and * persistent manner. * * \note The persistent index set is actually allowed to be non-consecutive, * i.e., some indices might not be assigned to an entity. * As the result of the size method on the index set is used to allocate * storage for the vector, it must be larger than the largest used index. * * \note It is sufficient if the index set provides indices to the codimension * the persistent container is created for. * Neither the method types() nor the method contains() need to be * implemented. * * \note The persistent container is currently restricted to index sets * containing a single geometry type. * * \todo Actually, we use a mapper rather than an index set. * This would automatically resolve two problems: * - support multiple geometry types, * - the requirement to store a reference to the index set * . * * \tparam G type of grid * \tparam IndexSet type of persistent index set * \tparam Vector type of vector to store the data in */ template< class G, class IndexSet, class Vector > class PersistentContainerVector { typedef PersistentContainerVector< G, IndexSet, Vector > This; public: typedef G Grid; typedef typename Vector::value_type Value; typedef typename Vector::size_type Size; typedef typename Vector::const_iterator ConstIterator; typedef typename Vector::iterator Iterator; typedef typename Vector::allocator_type Allocator; PersistentContainerVector ( const IndexSet &indexSet, int codim, const Value &value, const Allocator &allocator = Allocator() ) : codim_( codim ), indexSet_( &indexSet ), data_( indexSet.size( codim ), value, allocator ) {} template< class Entity > const Value &operator[] ( const Entity &entity ) const { assert( Entity::codimension == codimension() ); const Size index = indexSet().index( entity ); assert( index < data_.size() ); return data_[ index ]; } template< class Entity > Value &operator[] ( const Entity &entity ) { assert( Entity::codimension == codimension() ); const Size index = indexSet().index( entity ); assert( index < data_.size() ); return data_[ index ]; } template< class Entity > const Value &operator() ( const Entity &entity, int subEntity ) const { const Size index = indexSet().subIndex( entity, subEntity, codimension() ); assert( index < data_.size() ); return data_[ index ]; } template< class Entity > Value &operator() ( const Entity &entity, int subEntity ) { const Size index = indexSet().subIndex( entity, subEntity, codimension() ); assert( index < data_.size() ); return data_[ index ]; } Size size () const { return data_.size(); } void resize ( const Value &value = Value() ) { const Size indexSetSize = indexSet().size( codimension() ); data_.resize( indexSetSize, value ); } void shrinkToFit () {} void fill ( const Value &value ) { std::fill( begin(), end(), value ); } void swap ( This &other ) { std::swap( codim_, other.codim_ ); std::swap( indexSet_, other.indexSet_ ); std::swap( data_, other.data_ ); } ConstIterator begin () const { return data_.begin(); } Iterator begin () { return data_.begin(); } ConstIterator end () const { return data_.end(); } Iterator end () { return data_.end(); } int codimension () const { return codim_; } protected: const IndexSet &indexSet () const { return *indexSet_; } int codim_; const IndexSet *indexSet_; Vector data_; }; } // namespace Dune #endif // #ifndef DUNE_PERSISTENTCONTAINERVECTOR_HH dune-grid-2.11.0/dune/grid/utility/persistentcontainerwrapper.hh000066400000000000000000000055261511655130300250710ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PERSISTENTCONTAINERWRAPPER_HH #define DUNE_PERSISTENTCONTAINERWRAPPER_HH #include #include namespace Dune { // PersistentContainerWrapper // -------------------------- template< class G, class T > class PersistentContainerWrapper { typedef PersistentContainerWrapper< G, T > This; typedef Dune::HostGridAccess< G > HostGridAccess; typedef typename HostGridAccess::HostGrid HostGrid; typedef PersistentContainer< HostGrid, T > PersistentContainerHostGrid; public: typedef G Grid; typedef typename PersistentContainer< HostGrid, T >::Value Value; typedef typename PersistentContainer< HostGrid, T >::Size Size; typedef typename PersistentContainer< HostGrid, T >::Iterator Iterator; typedef typename PersistentContainer< HostGrid, T >::ConstIterator ConstIterator; PersistentContainerWrapper ( const Grid &grid, int codim, const Value &value = Value() ) : hostContainer_( HostGridAccess::hostGrid( grid ), codim, value ) {} template< class Entity > const Value &operator[] ( const Entity &entity ) const { return hostContainer_[ HostGridAccess::hostEntity( entity ) ]; } template< class Entity > Value &operator[] ( const Entity &entity ) { return hostContainer_[ HostGridAccess::hostEntity( entity ) ]; } template< class Entity > const Value &operator() ( const Entity &entity, int subEntity ) const { return hostContainer_( HostGridAccess::hostEntity( entity ), subEntity ); } template< class Entity > Value &operator() ( const Entity &entity, int subEntity ) { return hostContainer_( HostGridAccess::hostEntity( entity ), subEntity ); } Size size () const { return hostContainer_.size(); } void resize ( const Value &value = Value() ) { hostContainer_.resize( value ); } void shrinkToFit () { return hostContainer_.shrinkToFit(); } void fill ( const Value &value = Value() ) { hostContainer_.fill( value ); } void swap ( This &other ) { hostContainer_.swap( other.hostContainer_ ); } ConstIterator begin () const { return hostContainer_.begin(); } Iterator begin () { return hostContainer_.begin(); } ConstIterator end () const { return hostContainer_.end(); } Iterator end () { return hostContainer_.end(); } int codimension () const { return hostContainer_.codimension(); } protected: PersistentContainer< HostGrid, T > hostContainer_; }; } // namespace Dune #endif // #ifndef DUNE_PERSISTENTCONTAINERWRAPPER_HH dune-grid-2.11.0/dune/grid/utility/structuredgridfactory.hh000066400000000000000000000226061511655130300240250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_STRUCTURED_GRID_FACTORY_HH #define DUNE_STRUCTURED_GRID_FACTORY_HH /** \file \brief A class to construct structured cube and simplex grids using the grid factory */ #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \brief Construct structured cube and simplex grids in unstructured grid managers */ template class StructuredGridFactory { typedef typename GridType::ctype ctype; static const int dim = GridType::dimension; static const int dimworld = GridType::dimensionworld; /** \brief Insert a structured set of vertices into the factory */ static void insertVertices(GridFactory& factory, const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& vertices) { FactoryUtilities::MultiIndex index(vertices); // Compute the total number of vertices to be created int numVertices = index.cycle(); // Create vertices for (int i=0; i pos(0); for (int j=0; j computeUnitOffsets(const std::array& vertices) { std::array unitOffsets; if (dim>0) // paranoia unitOffsets[0] = 1; for (int i=1; i& factory, const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { if (factory.comm().rank() == 0) { // Insert uniformly spaced vertices std::array vertices = elements; for( size_t i = 0; i < vertices.size(); ++i ) vertices[i]++; // Insert vertices for structured grid into the factory insertVertices(factory, lowerLeft, upperRight, vertices); // Compute the index offsets needed to move to the adjacent // vertices in the different coordinate directions std::array unitOffsets = computeUnitOffsets(vertices); // Compute an element template (the cube at (0,...,0). All // other cubes are constructed by moving this template around unsigned int nCorners = 1< cornersTemplate(nCorners,0); for (size_t i=0; i index(elements); // Compute the total number of elementss to be created int numElements = index.cycle(); for (int i=0; i corners = cornersTemplate; for (size_t j=0; j createCubeGrid( const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { GridFactory factory; createCubeGrid(factory, lowerLeft, upperRight, elements); return std::unique_ptr(factory.createGrid()); } /** \brief insert structured simplex grid into grid factory This works in all dimensions. The Coxeter-Freudenthal-Kuhn triangulation is used, which splits each cube into dim! (i.e., dim faculty) simplices. See Allgower and Georg, 'Numerical Path Following' for a description. If the grid dimension is less than the world dimension, the coefficients (dim+1,...,dimworld) in the vertex coordinates are set to the corresponding values of the lowerLeft input argument. \param factory grid factory used for creating the grid \param lowerLeft Lower left corner of the grid \param upperRight Upper right corner of the grid \param elements Number of elements in each coordinate direction */ static void createSimplexGrid( GridFactory& factory, const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { if(factory.comm().rank() == 0) { // Insert uniformly spaced vertices std::array vertices = elements; for (std::size_t i=0; i unitOffsets = computeUnitOffsets(vertices); // Loop over all "cubes", and split up each cube into dim! // (factorial) simplices FactoryUtilities::MultiIndex elementsIndex(elements); size_t cycle = elementsIndex.cycle(); for (size_t i=0; i permutation(dim); for (int j=0; j corners(dim+1); corners[0] = base; for (int j=0; j createSimplexGrid( const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { GridFactory factory; createSimplexGrid(factory, lowerLeft, upperRight, elements); return std::unique_ptr(factory.createGrid()); } }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/utility/tensorgridfactory.hh000066400000000000000000000327761511655130300231440ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_GRID_UTILITY_TENSORGRIDFACTORY_HH #define DUNE_GRID_UTILITY_TENSORGRIDFACTORY_HH /** \file * \brief This file provides a factory class for tensorproduct * grids. This is a collection of methods to generate monotonous * sequences as needed for a tensorproduct grid. Apart * from easy ones for locally equidistant grids, there are also * more involved methods like splitting a range according to a * geometric series. * * The grid generation process is implemented for unstructured grids * and for YaspGrid. * * \author Dominic Kempf */ #include #include #include #include #include #include #include namespace Dune { // forward declaration of TensorGridFactoryCreator, which is the real factory // that should be specialized for each grid. template class TensorGridFactoryCreator; /** \brief A factory class for conveniently creating tensorproduct grids * * \tparam Grid the grid type */ template class TensorGridFactory { public: typedef typename Grid::Traits::Communication Comm; typedef typename Grid::ctype ctype; static const int dim = Grid::dimension; std::unique_ptr createGrid(Comm comm = Comm()) { TensorGridFactoryCreator creator(*this); return creator.createGrid(comm); } std::array , dim> coords() const { return _coords; } //! allow to manually tune the factory by overloading operator[] to export the coordinate vectors in the coordinate directories. std::vector& operator[](std::size_t d) { return _coords[d]; } //! allow to manually tune the factory by overloading operator[] to export the coordinate vectors in the coordinate directories. const std::vector& operator[](std::size_t d) const { return _coords[d]; } /** \brief set a starting value in a given direction d * \param d the coordinate direction * \param value the value to set * * This resizes the coordinate vector for the given direction to 1. * Not using this function will result in 0.0 to be used as a lower * bound of the coordinate range. */ void setStart (int d, ctype value) { _coords[d].resize(1); _coords[d][0] = value; } /** \brief pushs n intervals of length h in direction d * \param d the coordinate direction * \param n the number of intervals to add * \param h the interval length * * Given a vector with last element \f$x_0\f$, this will add elements * \f$x_1,\dots ,x_n\f$ such that \f$x_i=x_0+i*h\f$. */ void fillIntervals (int d, int n, ctype h) { emptyCheck (d); for (int i = 0; i < n; i++) _coords[d].push_back (_coords[d].back () + h); } /** \brief fills the range to end with n intervals in direction d * \param d the coordinate direction * \param n the number of intervals to add * \param end the coordinate on the upper border of the range * * Given a vector with last element \f$x_0\f$, this will add elements * \f$x_1,\dots ,x_n\f$ such that \f$x_i=x_0+i*\frac{end-x_0}{n}\f$. */ void fillRange (int d, int n, ctype end) { emptyCheck (d); const ctype h = (end - _coords[d].back ()) / n; for (int i = 0; i < n - 1; i++) _coords[d].push_back (_coords[d].back () + h); _coords[d].push_back (end); } /** \brief adds intervals in direction d until a given coordinate is reached * \param d the coordinate direction * \param h the interval length * \param end the coordinate on the upper border of the range * * Given a vector with last element \f$x_0\f$, this will add elements * \f$x_1,\dots ,x_n\f$ such that \f$x_n < end < x_n + h\f$ and \f$x_{i+1}-x_i = h\f$. */ void fillUntil (int d, ctype h, ctype end) { emptyCheck (d); while (_coords[d].back () < end) _coords[d].push_back (_coords[d].back () + h); } /** \brief adds n intervals in direction d with a given length ratio and a given starting interval length. * \param d the coordinate direction * \param n the number of intervals to add * \param ratio the ratio of \f$ h_{i+1}\f$ to \f$h_i\f$ * \param h0 the starting interval length (optional) * * Given a vector with last element \f$x_0\f$, this will add elements * \f$x_1,\dots ,x_n\f$ such that \f$h_{i+1}=qh_i\f$ for a given ratio * \f$q\f$ and interval length \f$h_i=x_{i+1}-x_i\f$. The first interval length * can either be explicitly given or be deduced by multiplying the ratio * with the last interval length in the container. */ void geometricFillIntervals (int d, int n, ctype ratio, ctype h0 = static_cast (0)) { emptyCheck (d); ctype h = h0; if (h0 == static_cast(0)) h = lastInterval (d) * ratio; for (int i = 0; i < n; i++) { _coords[d].push_back (_coords[d].back () + h); h *= ratio; } } /** \brief adds intervals in direction d according with a given length ratio until a given coordinate is reached * \param d the coordinate direction * \param ratio the ratio of \f$h_{i+1}\f$ to \f$h_i\f$ * \param end the coordinate on the right border of the range * \param h0 the starting interval length (optional) * * Given a vector with last element \f$x_0\f$, this will add elements * \f$x_1,\dots ,x_n\f$ such that - with \f$h_i=x_{i+1}-x_i\f$ - \f$h_{i+1}=qh_i\f$ * for a given ratio \f$q\f$ and that \f$x_n < end < x_n + h\f$. The first interval * length can either be explicitly given or be deduced by multiplying the ratio with * the last interval length in the container. */ void geometricFillUntil (int d, ctype ratio, ctype end, ctype h0 = static_cast (0)) { emptyCheck (d); ctype h = h0; if (h0 == static_cast(0)) h = lastInterval (d) * ratio; while (_coords[d].back () < end) { _coords[d].push_back (_coords[d].back () + h); h *= ratio; } } /** \brief fills a coordinate range in direction d with n intervals according to a geometric series * \param d the coordinate direction * \param n the number of intervals to add * \param end the coordinate of the upper border of the range * \param h the interval length to start or end with (see below) (optional) * \param first true if the given h is to be the first interval, false if last one * * Given a vector with last element \f$x_0\f$, this will add elements * \f$x_1,\dots ,x_n\f$ such that the ratio \f$h_{i+1} / h_i\f$ is fixed throughout * the range and \f$x_n=end\f$, while \f$h_i=x_{i+1}-x_i\f$ is the interval length. * The first interval length can either be explicitly given or be deduced by taking * the last interval length in the container. By setting the optional parameter first * to false, the given h can instead be used as last interval length in the range. */ void geometricFillRange (int d, int n, ctype end, ctype h = static_cast (0), bool first = true) { emptyCheck (d); if (h < 1e-8) h = lastInterval (d); ctype ratio = newton (n, _coords[d].back (), end, h); if (!first) { h = h * pow (ratio, n - 1); ratio = 1 / ratio; } for (int i = 0; i < n - 1; i++) { _coords[d].push_back (_coords[d].back () + h); h *= ratio; } _coords[d].push_back (end); } //! print the coordinate information given to the factory so far void print() { for (int i=0; i meshsize; for (auto it = _coords[i].begin(); it != _coords[i].end()-1;) { meshsize.push_back(-1.*(*it)); ++it; meshsize.back() += *it; } for (auto it = meshsize.begin(); it != meshsize.end(); ++it) std::cout << *it << " "; std::cout << std::endl << "Ratios between interval lengths: "; std::vector ratios; for (auto it = meshsize.begin(); it != meshsize.end() - 1 ;) ratios.push_back((1./(*it)) * *(++it)); for (auto it = ratios.begin(); it != ratios.end(); ++it) std::cout << *it << " "; std::cout << std::endl << std::endl << std::endl; } } private: // check whether the ith component is empty and add a 0.0 entry if so void emptyCheck (int i) { if (_coords[i].empty ()) _coords[i].push_back (static_cast (0)); } // returns the last interval length in direction d ctype lastInterval (int d) { if (_coords[d].size () < 2) DUNE_THROW( GridError, "Not enough elements in coordinate container to deduce interval length in TensorYaspFactory"); else return _coords[d].back () - _coords[d][_coords[d].size () - 2]; } /** this implements a simple newton iteration for the function * \f$f(x) = -x^n+\frac{x_e-x_s}{h} (x-1)+1\f$ */ ctype newton (int n, ctype x_s, ctype x_e, ctype h) { ctype m = (x_e - x_s) / h; ctype xold = 0.0; ctype xnew = x_e - x_s; while (std::abs (xnew - xold) > 1E-8) { xold = xnew; xnew = xold - (-pow (xold, n) + m * xold - m + 1) / (-n * pow (xold, n - 1) + m); } if (std::abs (xnew - 1) < 1E-6) { xold = x_e - x_s; xnew = 0.0; while (std::abs (xnew - xold) > 1E-8) { xold = xnew; xnew = xold - (-pow (xold, n) + m * xold - m + 1) / (-n * pow (xold, n - 1) + m); } } return xnew; } std::array, dim> _coords; }; // class that implements the actual grid creation process. The default is implementing // standard creation for unstructured grids. Provide a specialization for other grids. template class TensorGridFactoryCreator { public: typedef typename Grid::Traits::Communication Comm; typedef typename Grid::ctype ctype; static const int dim = Grid::dimension; TensorGridFactoryCreator(const TensorGridFactory& factory) : _factory(factory) {} std::unique_ptr createGrid(Comm comm) { // The grid factory GridFactory fac; if (comm.rank() == 0) { // determine the size of the grid std::array vsizes, esizes; std::size_t size = 1; for (std::size_t i = 0; i index(vsizes); for (std::size_t i=0; i position; for (std::size_t j = 0; j offsets; offsets[0] = 1; for (std::size_t i=1; i cornersTemplate(nCorners,0); for (size_t i=0; i eindex(esizes); // Compute the total number of elements to be created int numElements = eindex.cycle(); for (int i=0; i corners = cornersTemplate; for (size_t j=0; j(fac.createGrid()); } private: const TensorGridFactory& _factory; }; template class TensorGridFactoryCreator > > { public: typedef YaspGrid > Grid; typedef typename Grid::Communication Comm; TensorGridFactoryCreator(const TensorGridFactory& factory) : _factory(factory) {} std::unique_ptr createGrid(Comm comm) { return std::make_unique(_factory.coords(), std::bitset(0ULL), 1, comm); } private: const TensorGridFactory& _factory; }; } #endif dune-grid-2.11.0/dune/grid/utility/test/000077500000000000000000000000001511655130300200135ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/utility/test/CMakeLists.txt000066400000000000000000000007671511655130300225650ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # Link all test targets in this directory against Dune::Grid link_libraries(Dune::Grid) dune_add_test(SOURCES globalindexsettest.cc) dune_add_test(SOURCES persistentcontainertest.cc) dune_add_test(SOURCES structuredgridfactorytest.cc) dune_add_test(SOURCES tensorgridfactorytest.cc) dune_add_test(SOURCES vertexordertest.cc) dune-grid-2.11.0/dune/grid/utility/test/globalindexsettest.cc000066400000000000000000000120421511655130300242250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include // HAVE_DUNE_UGGRID #include #include #include #include using namespace Dune; /** \brief Perform various consistency checks on a GlobalIndexSet object */ template void checkIndexSet(const GridView& gridView, const GlobalIndexSet& indexSet) { // Collect global indices on the current process std::vector::Index> indices; for (auto it = gridView.template begin<0>(); it != gridView.template end<0>(); ++it) // Loop over all subEntities for (size_t i=0; isubEntities(codim); i++) { assert( indexSet.index(it->template subEntity(i)) == indexSet.subIndex(*it, i, codim) ); indices.push_back(indexSet.index(it->template subEntity(i))); } ///////////////////////////////////////////////////////////////////////// // Sent the locally collected global indices to the root process ///////////////////////////////////////////////////////////////////////// std::vector sizes(gridView.comm().size()); int share = indices.size(); gridView.comm().template allgather(&share, 1, sizes.data()); std::vector offsets(sizes.size()); for (size_t k = 0; k < offsets.size(); ++k) offsets[k] = std::accumulate(sizes.begin(), sizes.begin() + k, 0); std::vector::Index> indicesGlobal; if (gridView.comm().rank() == 0) indicesGlobal.resize(std::accumulate(sizes.begin(), sizes.end(), 0)); gridView.comm().gatherv(indices.data(), indices.size(), indicesGlobal.data(), sizes.data(), offsets.data(), 0); // root rank ///////////////////////////////////////////////////////////////////////////////// // Check whether the set of global indices is consecutive and starts at zero. // (It may contain multiple entries, though.) ///////////////////////////////////////////////////////////////////////////////// // To check we remove the duplicates std::sort(indicesGlobal.begin(), indicesGlobal.end()); auto last = std::unique(indicesGlobal.begin(), indicesGlobal.end()); indicesGlobal.erase(last, indicesGlobal.end()); if (gridView.comm().rank()==0) for (size_t i=0; i GridType; std::array elements = {4, 4}; FieldVector bbox = {10, 10}; std::bitset periodic(0); unsigned int overlap = 1; GridType grid(MPI_COMM_WORLD, bbox, elements, periodic, overlap); typedef GridType::LeafGridView GridView; GridView gridView = grid.leafGridView(); #endif #if HAVE_DUNE_UGGRID typedef UGGrid GridType; std::array elements = { {8, 8} }; FieldVector lower = {0, 0}; FieldVector bbox = {10, 10}; std::shared_ptr grid = StructuredGridFactory::createCubeGrid(lower, bbox, elements); typedef GridType::LeafGridView GridView; GridView gridView = grid->leafGridView(); grid->loadBalance(); ///////////////////////////////////////////////////// // Create and check global index sets ///////////////////////////////////////////////////// // elements if (mpiHelper.rank() == 0) std::cout << "Elements" << std::endl; GlobalIndexSet elementIndexSet(gridView,0); checkIndexSet(gridView, elementIndexSet); // edges if (mpiHelper.rank() == 0) std::cout << "Edges" << std::endl; GlobalIndexSet edgeIndexSet(gridView,1); checkIndexSet(gridView, edgeIndexSet); // vertices if (mpiHelper.rank() == 0) std::cout << "Vertices" << std::endl; GlobalIndexSet vertexIndexSet(gridView,2); checkIndexSet(gridView, vertexIndexSet); #endif return 0; } catch (const Dune::Exception &e) { std::cerr << e << std::endl; throw; } catch (...) { std::cerr << "Generic exception!" << std::endl; throw; } dune-grid-2.11.0/dune/grid/utility/test/persistentcontainertest.cc000066400000000000000000000130421511655130300253250ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief A unit test for the PersistentContainer */ #include #include #include // HAVE_DUNE_UGGRID #include #if HAVE_DUNE_UGGRID #include #endif #include #include using namespace Dune; template struct Data { typedef FieldVector Coord; Data() : used(false) {} Data(const Coord &x) : coord(x), used(true) {} Coord coord; bool used; }; template bool test(GridType &grid) { bool ret = true; typedef Data DataType; PersistentContainer container0(grid,0); PersistentContainer container1(grid,1); PersistentContainer container2(grid,2); PersistentContainer ccontainer0(grid,0); PersistentContainer ccontainer1(grid,1); PersistentContainer ccontainer2(grid,2); typedef typename GridType::LeafGridView GridView; const GridView &view = grid.leafGridView(); typedef typename GridView::template Codim<0>::Iterator EIterator; { const EIterator &eend = view.template end<0>(); for(EIterator eit = view.template begin<0>(); eit != eend; ++eit) { auto geometry = eit->geometry(); ccontainer0[*eit] = container0[*eit] = geometry.center(); auto refElement = referenceElement(geometry); for (unsigned int i=0; isubEntities(1); ++i) ccontainer1(*eit,i) = container1(*eit,i) = geometry.global( refElement.position(i,1) ); for (unsigned int i=0; isubEntities(2); ++i) container2(*eit,i) = geometry.global( refElement.position(i,2) ); } } (void) container0.size(); (void) container1.size(); (void) container2.size(); (void) ccontainer0.size(); (void) ccontainer1.size(); (void) ccontainer2.size(); grid.globalRefine(1); container0.resize(); container1.resize(); container2.resize(); ccontainer0.resize(); ccontainer1.resize(); ccontainer2.resize(); { const EIterator &eend = view.template end<0>(); for(EIterator eit = view.template begin<0>(); eit != eend; ++eit) { if (container0[*eit].used == true) { std::cout << "ERROR: a new element is marked as 'used' in the container - stop testing" << std::endl; ret = false; break; } if (ccontainer0[*eit].used == true) { std::cout << "ERROR: a new element is marked as 'used' in the const container - stop testing" << std::endl; ret = false; break; } typename GridType::template Codim<0>::Entity up = eit->father(); while ( !container0[up].used ) { if (up.level() == 0) { std::cout << "ERROR: could not find a father element in container - stop testing" << std::endl; ret = false; break; } up = up.father(); } if ( ( container0[up].coord - up.geometry().center() ).two_norm() > 1e-8 ) { std::cout << "ERROR: wrong data stored in container0 - stop testing" << std::endl; ret = false; break; } auto refElement = Dune::referenceElement< typename GridType::ctype, GridType::dimension >( eit->type() ); for (unsigned int i=0; isubEntities(1); ++i) if ( ( container1(up,i).coord - up.geometry().global( refElement.position(i,1) ) ).two_norm() > 1e-8 ) { std::cout << "ERROR: wrong data stored in container1 - stop testing" << std::endl; ret = false; break; } for (unsigned int i=0; isubEntities(2); ++i) if ( ( container2(up,i).coord - up.geometry().global( refElement.position(i,2) ) ).two_norm() > 1e-8 ) { std::cout << "ERROR: wrong data stored in container1 - stop testing" << std::endl; ret = false; break; } } } return ret; } int main (int argc , char **argv) try { // this method calls MPI_Init, if MPI is enabled MPIHelper::instance(argc,argv); // ///////////////////////////////////////////////////////////////////////////// // Test YaspGrid // ///////////////////////////////////////////////////////////////////////////// { typedef YaspGrid<2> GridType; FieldVector Len; Len = 1.0; std::array s = { {2, 6} }; std::bitset<2> p; int overlap = 1; GridType grid(Len,s,p,overlap); std::cout << "Testing YaspGrid" << std::endl; test(grid); } #if HAVE_DUNE_UGGRID // ///////////////////////////////////////////////////////////////////////////// // Test UGGrid // ///////////////////////////////////////////////////////////////////////////// { typedef UGGrid<2> GridType; FieldVector lowerLeft{0.0, 0.0}; FieldVector upperRight{1.0, 1.0}; std::array cells = { {2, 6} }; const auto gridPtr = StructuredGridFactory::createCubeGrid(lowerLeft, upperRight, cells); std::cout << "Testing UGGrid" << std::endl; test(*gridPtr); } #endif return 0; } catch (Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/utility/test/structuredgridfactorytest.cc000066400000000000000000000230561511655130300256720ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief A unit test for the StructuredGridFactory */ #include #include #include #include #include #include // HAVE_DUNE_UGGRID #include #include #if HAVE_DUNE_UGGRID #include #endif #include #include using namespace Dune; Dune::TestSuite checkNEntities(const char* gridName, const char* entityName, int n, int nExpected) { Dune::TestSuite t; t.check(nExpected == n) << gridName << ": has " << n << " " << entityName << ", but expected " << nExpected; return t; } int main (int argc , char **argv) try { Dune::TestSuite t; // this method calls MPI_Init, if MPI is enabled MPIHelper::instance(argc,argv); // ///////////////////////////////////////////////////////////////////////////// // Test 1d grids // ///////////////////////////////////////////////////////////////////////////// // Test creation of 1d cube grids std::array elements1d; elements1d.fill(4); std::shared_ptr onedCubeGrid = StructuredGridFactory::createCubeGrid(FieldVector(0), FieldVector(1), elements1d); t.subTest(checkNEntities("onedCubeGrid", "vertices", onedCubeGrid->size(1), static_cast(elements1d[0]+1))); t.subTest(checkNEntities("onedCubeGrid", "elements", onedCubeGrid->size(0), static_cast(elements1d[0]))); gridcheck(*onedCubeGrid); // Test creation of 1d simplex grids std::shared_ptr onedSimplexGrid = StructuredGridFactory::createSimplexGrid(FieldVector(0), FieldVector(1), elements1d); t.subTest(checkNEntities("onedSimplexGrid", "vertices", onedSimplexGrid->size(1), static_cast(elements1d[0]+1))); t.subTest(checkNEntities("onedSimplexGrid", "elements", onedSimplexGrid->size(0), static_cast(elements1d[0]))); gridcheck(*onedSimplexGrid); // Test creation of 1d YaspGrid std::shared_ptr > yaspGrid1d = StructuredGridFactory >::createCubeGrid(FieldVector(0), FieldVector(1), elements1d); t.subTest(checkNEntities("yaspGrid1d", "vertices", yaspGrid1d->size(1),static_cast(elements1d[0]+1))); t.subTest(checkNEntities("yaspGrid1d", "elements", yaspGrid1d->size(1),static_cast(elements1d[0]+1))); gridcheck(*yaspGrid1d); { std::shared_ptr > > yaspGridOff1d = StructuredGridFactory > >::createCubeGrid(FieldVector(-1.), FieldVector(1), elements1d); t.subTest(checkNEntities("yaspGridOff1d", "vertices", yaspGridOff1d->size(1),static_cast(elements1d[0]+1))); t.subTest(checkNEntities("yaspGridOff1d", "elements", yaspGridOff1d->size(1),static_cast(elements1d[0]+1))); gridcheck(*yaspGridOff1d); } // ///////////////////////////////////////////////////////////////////////////// // Test 2d grids // ///////////////////////////////////////////////////////////////////////////// std::array elements2d; elements2d.fill(4); unsigned int numVertices2d = (elements2d[0]+1) * (elements2d[1]+1); unsigned int numCubes2d = elements2d[0] * elements2d[1]; // Test creation of 2d YaspGrid std::shared_ptr > yaspGrid2d = StructuredGridFactory >::createCubeGrid(FieldVector(0), FieldVector(1), elements2d); t.subTest(checkNEntities("yaspGrid2d", "vertices", yaspGrid2d->size(2), static_cast(numVertices2d))); t.subTest(checkNEntities("yaspGrid2d", "elements", yaspGrid2d->size(0), static_cast(numCubes2d))); gridcheck(*yaspGrid2d); { std::shared_ptr > > yaspGridOff2d = StructuredGridFactory > >::createCubeGrid(FieldVector(0), FieldVector(1), elements2d); t.subTest(checkNEntities("yaspGridOff2d", "vertices", yaspGridOff2d->size(2), static_cast(numVertices2d))); t.subTest(checkNEntities("yaspGridOff2d", "elements", yaspGridOff2d->size(0), static_cast(numCubes2d))); gridcheck(*yaspGridOff2d); } // Test creation of 2d cube grid using UG #if HAVE_DUNE_UGGRID typedef UGGrid<2> QuadrilateralGridType; std::shared_ptr quadrilateralGrid = StructuredGridFactory::createCubeGrid(FieldVector(0), FieldVector(1), elements2d); t.subTest(checkNEntities("quadrilateralGrid", "vertices", quadrilateralGrid->size(2), static_cast(numVertices2d))); t.subTest(checkNEntities("quadrilateralGrid", "elements", quadrilateralGrid->size(0), static_cast(numCubes2d))); gridcheck(*quadrilateralGrid); #else std::cout << "WARNING: 2d cube grids not tested because no suitable grid implementation is available!" << std::endl; #endif // Test creation of 2d triangle grid using UG #if HAVE_DUNE_UGGRID typedef UGGrid<2> TriangleGridType; std::shared_ptr triangleGrid = StructuredGridFactory::createSimplexGrid(FieldVector(0), FieldVector(1), elements2d); t.subTest(checkNEntities("triangleGrid", "vertices", triangleGrid->size(2), static_cast(numVertices2d))); // each cube gets split into 2 triangles t.subTest(checkNEntities("triangleGrid", "elements", triangleGrid->size(0), static_cast(2*numCubes2d))); gridcheck(*triangleGrid); #else std::cout << "WARNING: 2d simplicial grids not tested because no suitable grid implementation is available!" << std::endl; #endif // ///////////////////////////////////////////////////////////////////////////// // Test 3d grids // ///////////////////////////////////////////////////////////////////////////// // Test creation of 3d cube grids #if HAVE_DUNE_UGGRID typedef UGGrid<3> HexahedralGridType; std::array elements3d; elements3d.fill(4); unsigned int numVertices3d = (elements3d[0]+1) * (elements3d[1]+1) * (elements3d[2]+1); unsigned int numCubes3d = elements3d[0] * elements3d[1] * elements3d[2]; std::shared_ptr hexahedralGrid = StructuredGridFactory::createCubeGrid(FieldVector(0), FieldVector(1), elements3d); t.subTest(checkNEntities("hexahedralGrid", "vertices", hexahedralGrid->size(3), numVertices3d)); t.subTest(checkNEntities("hexahedralGrid", "elements", hexahedralGrid->size(0), numCubes3d)); gridcheck(*hexahedralGrid); #else std::cout << "WARNING: 3d cube grids not tested because no suitable grid implementation is available!" << std::endl; #endif // Test creation of 3d simplex grids #if HAVE_DUNE_UGGRID typedef UGGrid<3> TetrahedralGridType; std::shared_ptr tetrahedralGrid = StructuredGridFactory::createSimplexGrid(FieldVector(0), FieldVector(1), elements3d); t.subTest(checkNEntities("tetrahedralGrid", "vertices", tetrahedralGrid->size(3), numVertices3d)); // each cube gets split into 6 tetrahedra t.subTest(checkNEntities("tetrahedralGrid", "elements", tetrahedralGrid->size(0), 6*numCubes3d)); gridcheck(*tetrahedralGrid); #else std::cout << "WARNING: 3d simplicial grids not tested because no suitable grid implementation is available!" << std::endl; #endif return t.exit(); } catch (Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/utility/test/tensorgridfactorytest.cc000066400000000000000000000042431511655130300247750ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief A unit test for the TensorGridFactory */ #include #include #include #include // HAVE_DUNE_UGGRID #include #if HAVE_DUNE_UGGRID #include #endif #include #include #include using namespace Dune; template void fillFactory(TensorGridFactory& f) { for (int i = 0; i fac1; fillFactory(fac1); { auto grid = fac1.createGrid(); gridcheck(*grid); std::cout << "OneDgrid with " << grid->size(0) << " cells created." << std::endl; } #if HAVE_DUNE_UGGRID // Test UGGrid TensorGridFactory > fac3; fillFactory(fac3); { auto grid = fac3.createGrid(); gridcheck(*grid); std::cout << "UGGrid<2> with " << grid->size(0) << " cells created." << std::endl; } TensorGridFactory > fac4; fillFactory(fac4); { auto grid = fac4.createGrid(); gridcheck(*grid); std::cout << "UGGrid<3> with " << grid->size(0) << " cells created." << std::endl; } #endif // Test YaspGrid TensorGridFactory > > fac5; fillFactory(fac5); { auto grid = fac5.createGrid(); gridcheck(*grid); std::cout << "YaspGrid with " << grid->size(0) << " cells created." << std::endl; } return 0; } catch (Exception &e) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/utility/test/vertexordertest.cc000066400000000000000000000311351511655130300235760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file \brief A unit test for the VertexOrder classes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // HAVE_DUNE_UGGRID #include #include #include "../structuredgridfactory.hh" #include "../vertexorderfactory.hh" void fail(int &result) { result = 1; } void pass(int &result) { if(result == 77) result = 0; } //! test consistency on one dimension and element template void testElementDim(const std::integral_constant&, const VertexOrder &vo) { static const std::size_t dim = VertexOrder::dimension; static const std::size_t codim = dim - mydim; auto refelem = Dune::referenceElement(vo.type()); std::vector subOrder, tmp; for(int subentity = 0; subentity < refelem.size(codim); ++subentity) { std::size_t voSize = std::distance(vo.begin(codim, subentity), vo.end(codim, subentity)); std::size_t refSize = refelem.size(subentity, codim, dim); if(voSize != refSize) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subentity << ": Number of vertices: " << voSize << " in " "VertexOrder but " << refSize << " in reference element"); subOrder.resize(voSize); Dune::reduceOrder(vo.begin(codim, subentity), vo.end(codim, subentity), subOrder.begin()); vo.getReduced(codim, subentity, tmp); if(!(subOrder == tmp)) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subentity << ": Reduced vertex numbering from VertexOrder " "does not match manually reduced vertex numbering"); } } // test inter-dimensional consistency template void testElementInterdim(const std::integral_constant&, const VertexOrder &vo) { testElementDim(std::integral_constant(), vo); static const std::size_t dim = VertexOrder::dimension; static const std::size_t codim = dim - mydim; auto refelem = Dune::referenceElement(vo.type()); std::vector subOrder, tmp, subsubOrder; for(int subentity = 0; subentity < refelem.size(codim); ++subentity) { auto subrefelem = Dune::referenceElement(refelem.type(subentity, codim)); subOrder.assign(vo.begin(codim, subentity), vo.end(codim, subentity)); for(int subsubentity = 0; subsubentity < subrefelem.size(1); ++subsubentity) { tmp.resize(subrefelem.size(subsubentity, 1, mydim)); for(std::size_t vertex = 0; vertex < tmp.size(); ++vertex) tmp[vertex] = subOrder[subrefelem.subEntity(subsubentity, 1, vertex, mydim)]; subsubOrder.resize(tmp.size()); Dune::reduceOrder(tmp.begin(), tmp.end(), subsubOrder.begin()); vo.getReduced(codim+1, refelem.subEntity(subentity, codim, subsubentity, codim+1), tmp); if(!(subsubOrder == tmp)) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subentity << ": Sub-Codim " << codim+1 <<": Sub-Subentity " << subsubentity << ": Vertex numbering from subentity does " "not match vertex numbering from sub-subentity."); } } } template void testElementInterdim(const std::integral_constant&, const VertexOrder &vo) { testElementDim(std::integral_constant(), vo); } template void testNeighborDim(const std::integral_constant&, const VertexOrder &vo_s, const VertexOrder &vo_n, const Intersection &is) { static const std::size_t dim = VertexOrder::dimension; static const std::size_t codim = dim - mydim; auto refelem_s = Dune::referenceElement(vo_s.type()); auto refelem_n = Dune::referenceElement(vo_n.type()); std::size_t index_s = is.indexInInside(); std::size_t index_n = is.indexInOutside(); typedef typename Intersection::Entity Entity; Entity inside = is.inside(); Entity outside = is.outside(); typedef typename Entity::Geometry Geometry; const Geometry &geo_s = inside.geometry(); const Geometry &geo_n = outside.geometry(); typedef typename Intersection::ctype DF; typedef Dune::FieldVector DomainW; DF eps = std::pow(geo_s.volume(), 1.0/dim)*1e-6; std::vector order_s; std::vector order_n; for(int subentity_s = 0; subentity_s < refelem_s.size(index_s, 1, codim); ++subentity_s) { std::size_t subindex_s = refelem_s.subEntity(index_s, 1, subentity_s, codim); DomainW subpos = geo_s.global(refelem_s.position(subindex_s, codim)); int subentity_n = 0; std::size_t subindex_n = 0; for(; subentity_n < refelem_n.size(index_n, 1, codim); ++subentity_n) { subindex_n = refelem_n.subEntity(index_n, 1, subentity_n, codim); if((subpos - geo_n.global(refelem_s.position(subindex_n, codim)) ).two_norm() < eps) break; } if(subentity_n == refelem_n.size(index_n, 1, codim)) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subindex_s << ": Can't find corresponding subentity in " "neighbor"); vo_s.getReduced(codim, subindex_s, order_s); vo_n.getReduced(codim, subindex_n, order_n); if(order_s.size() != order_n.size()) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subindex_s << ": Number of vertices is " << order_s.size() << " in inside but " << order_n.size() << " in outside"); for(std::size_t i_s = 0; i_s < order_s.size(); ++i_s) { std::size_t i_n = 0; for(; i_n < order_n.size(); ++i_n) if(order_s[i_s] == order_n[i_n]) break; if(i_n == order_n.size()) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subindex_s << ": Vertex " << i_s << ": Can't find " "corresponding vertex in neighbor"); DomainW pos_s = geo_s.corner(refelem_s.subEntity(subindex_s, codim, i_s, dim)); DomainW pos_n = geo_n.corner(refelem_n.subEntity(subindex_n, codim, i_n, dim)); if((pos_s - pos_n).two_norm() > eps) DUNE_THROW(Dune::Exception, "Codim " << codim << ": Subentity " << subindex_s << " at " << subpos << ": Vertex " << i_s << " " "is at " << pos_s << "; Neighbor at " << geo_n.center() << ": Subentity " << subindex_n << ": " "Vertex " << i_n << " is at " << pos_n); } } } template void testNeighbor(const std::integral_constant&, const VertexOrder &vo_s, const VertexOrder &vo_n, const Intersection &is) { testNeighborDim(std::integral_constant(), vo_s, vo_n, is); } template void testNeighbor(const std::integral_constant&, const VertexOrder &vo_s, const VertexOrder &vo_n, const Intersection &is) { testNeighbor(std::integral_constant(), vo_s, vo_n, is); testNeighborDim(std::integral_constant(), vo_s, vo_n, is); } template void testVertexOrder(const GV& gv, const VertexOrderFactory &voFactory, int& result) { pass(result); static const std::size_t dim = GV::dimension; typedef typename VertexOrderFactory::template VertexOrder::type VertexOrder; typedef typename GV::template Codim<0>::Iterator EIterator; typedef typename GV::IntersectionIterator IIterator; const EIterator &eend = gv.template end<0>(); for(EIterator eit = gv.template begin<0>(); eit != eend; ++eit) try { VertexOrder vo = voFactory.make(*eit); testElementInterdim(std::integral_constant(), vo); const IIterator &iend = gv.iend(*eit); for(IIterator iit = gv.ibegin(*eit); iit != iend; ++iit) if(iit->neighbor()) { VertexOrder vo_n = voFactory.make(iit->outside()); testNeighbor(std::integral_constant(), vo, vo_n, *iit); } } catch(const Dune::Exception &e) { std::cout << "Element at " << eit->geometry().center() << ": " << e.what() << std::endl; fail(result); } } template void testVertexOrderByIdSimplices(int &result) { static const std::size_t dim = Grid::dimension; static const std::size_t dimworld = Grid::dimensionworld; typedef typename Grid::ctype DF; typedef Dune::FieldVector Domain; std::array elements; std::fill(elements.begin(), elements.end(), 4); std::shared_ptr gridp = Dune::StructuredGridFactory:: createSimplexGrid(Domain(0), Domain(1), elements); typedef typename Grid::GlobalIdSet IdSet; typedef Dune::VertexOrderByIdFactory VOFactory; VOFactory voFactory(gridp->globalIdSet()); testVertexOrder<0>(gridp->leafGridView(), voFactory, result); } template void testVertexOrderByIdCubes(int &result) { static const std::size_t dim = Grid::dimension; static const std::size_t dimworld = Grid::dimensionworld; typedef typename Grid::ctype DF; typedef Dune::FieldVector Domain; std::array elements; std::fill(elements.begin(), elements.end(), 4); std::shared_ptr gridp = Dune::StructuredGridFactory:: createCubeGrid(Domain(0), Domain(1), elements); typedef typename Grid::GlobalIdSet IdSet; typedef Dune::VertexOrderByIdFactory VOFactory; VOFactory voFactory(gridp->globalIdSet()); testVertexOrder<0>(gridp->leafGridView(), voFactory, result); } int main (int argc , char **argv) try { // this method calls MPI_Init, if MPI is enabled Dune::MPIHelper::instance(argc,argv); int result = 77; ////////////////////////////////////////////////////////////////////// // Test 1d grids ////////////////////////////////////////////////////////////////////// std::cout << "= Testing 1D" << std::endl; std::cout << "== Testing OneDGrid" << std::endl; testVertexOrderByIdCubes(result); ////////////////////////////////////////////////////////////////////// // Test 2d grids ////////////////////////////////////////////////////////////////////// std::cout << "= Testing 2D" << std::endl; #if HAVE_DUNE_UGGRID std::cout << "== Testing UGGrid<2> with simplices" << std::endl; testVertexOrderByIdCubes >(result); std::cout << "== Testing UGGrid<2> with cubes" << std::endl; testVertexOrderByIdSimplices >(result); #endif ////////////////////////////////////////////////////////////////////// // Test 3d grids ////////////////////////////////////////////////////////////////////// std::cout << "= Testing 3D" << std::endl; #if HAVE_DUNE_UGGRID std::cout << "== Testing UGGrid<3> with simplices" << std::endl; testVertexOrderByIdCubes >(result); std::cout << "== Testing UGGrid<3> with cubes" << std::endl; testVertexOrderByIdSimplices >(result); #endif return result; } catch (const Dune::Exception &e) { std::cerr << e << std::endl; throw; } catch (...) { std::cerr << "Generic exception!" << std::endl; throw; } dune-grid-2.11.0/dune/grid/utility/vertexorderfactory.hh000066400000000000000000000052751511655130300233270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_UTILITY_VERTEXORDERFACTORY_HH #define DUNE_GRID_UTILITY_VERTEXORDERFACTORY_HH #include #include #include #include #include #include namespace Dune { //! Factory for GeneralVertexOrder objects using an IdSet /** * \tparam IdSet Type used to get the ids of the vertices. * \tparam Index Type of the indices provided by the vertex ordering * object. Must be integral, may be non-negative. * * \warning The Interface of the VertexOrder stuff is subject to change. It * is currently needed to use some global-valued finite elements * from dune-localfunctions. * * \sa GeneralVertexOrder, reduceOrder() */ template class VertexOrderByIdFactory { const IdSet& idset; public: //! type of vertex order object may depend on the dimension of the element template struct VertexOrder { //! type of vertex order object typedef GeneralVertexOrder type; }; //! construct a factory object /** * \tparam idset_ IdSet to use to extract the vertex ids. * * This factory object stores a reference to the IdSet object. The * factory object's value will become singular when the stored reference * becomes invalid. The only valid operation on a factory with singular * value is destruction, all other operations will result in undefined * behaviour. */ VertexOrderByIdFactory(const IdSet &idset_) : idset(idset_) { } //! construct a vertex ordering object /** * \param e Grid element to create the vertex ordering object for. * * The returned object will remain valid even after the factory has become * singular or has been destroyed. */ template typename VertexOrder::type make(const Element &e) const { std::size_t size = referenceElement(e.geometry()).size(Element::mydimension); std::vector ids(size); for(std::size_t i = 0; i < size; ++i) ids[i] = idset.subId(e, i, Element::mydimension); return GeneralVertexOrder (e.type(), ids.begin(), ids.end()); } }; } // namespace Dune #endif // DUNE_GRID_UTILITY_VERTEXORDERFACTORY_HH dune-grid-2.11.0/dune/grid/yaspgrid.hh000066400000000000000000002366611511655130300175120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRID_HH #define DUNE_GRID_YASPGRID_HH #include #include #include #include #include #include #include #include #include // the grid base classes #include // the capabilities #include #include #include #include #include #include #include #include #include #include #include #if HAVE_MPI #include #endif /*! \file yaspgrid.hh * YaspGrid stands for yet another structured parallel grid. * It will implement the dune grid interface for structured grids * with arbitrary overlap, parallel features with two overlap * models, periodic boundaries and a fast implementation allowing on-the-fly computations. */ namespace Dune { /* some sizes for building global ids */ const int yaspgrid_dim_bits = 24; // bits for encoding each dimension const int yaspgrid_level_bits = 5; // bits for encoding level number //************************************************************************ // forward declaration of templates template class YaspGrid; template class YaspGeometry; template class YaspEntity; template class YaspEntitySeed; template class YaspLevelIterator; template class YaspIntersectionIterator; template class YaspIntersection; template class YaspHierarchicIterator; template class YaspIndexSet; template class YaspGlobalIdSet; template class YaspPersistentContainerIndex; } // namespace Dune #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { #if HAVE_MPI using YaspCommunication = Communication; #else using YaspCommunication = Communication; #endif template struct YaspGridFamily { typedef YaspCommunication CCType; typedef GridTraits, YaspGeometry,YaspEntity, YaspLevelIterator, // type used for the level iterator YaspIntersection, // leaf intersection YaspIntersection, // level intersection YaspIntersectionIterator, // leaf intersection iter YaspIntersectionIterator, // level intersection iter YaspHierarchicIterator, YaspLevelIterator, // type used for the leaf(!) iterator YaspIndexSet< const YaspGrid< dim, Coordinates >, false >, // level index set YaspIndexSet< const YaspGrid< dim, Coordinates >, true >, // leaf index set YaspGlobalIdSet >, bigunsignedint, YaspGlobalIdSet >, bigunsignedint, CCType, DefaultLevelGridViewTraits, DefaultLeafGridViewTraits, YaspEntitySeed, YaspGeometry, unsigned int, std::array> Traits; }; #ifndef DOXYGEN template struct YaspCommunicateMeta { template static void comm (const G& g, DataHandle& data, InterfaceType iftype, CommunicationDirection dir, int level) { if (data.contains(dim,codim)) { g.template communicateCodim(data,iftype,dir,level); } YaspCommunicateMeta::comm(g,data,iftype,dir,level); } }; template struct YaspCommunicateMeta { template static void comm (const G& g, DataHandle& data, InterfaceType iftype, CommunicationDirection dir, int level) { if (data.contains(dim,0)) g.template communicateCodim(data,iftype,dir,level); } }; #endif //************************************************************************ /*! * \brief [ provides \ref Dune::Grid ] * \brief Provides a distributed structured cube mesh. * \ingroup GridImplementations * * YaspGrid stands for yet another structured parallel grid. * It implements the dune grid interface for structured grids * with arbitrary overlap (including zero), * periodic boundaries, and a fast implementation allowing on-the-fly computations. * * YaspGrid supports three coordinate modes: \ref EquidistantCoordinates, * \ref EquidistantOffsetCoordinates, and \ref Dune::TensorProductCoordinates. * * \tparam dim The dimension of the grid and its surrounding world * \tparam Coordinates The coordinate mode of the grid. */ template > class YaspGrid : public GridDefaultImplementation > { template friend class YaspLevelIterator; template friend class YaspHierarchicIterator; using Base = GridDefaultImplementation >; protected: public: //! Type used for coordinates typedef typename Coordinates::ctype ctype; using Communication = typename Base::Communication; #ifndef DOXYGEN typedef typename Dune::YGrid YGrid; typedef typename Dune::YGridList::Intersection Intersection; /** \brief A single grid level within a YaspGrid */ struct YGridLevel { /** \brief Level number of this level grid */ int level() const { return level_; } Coordinates coords; std::array overlapfront; std::array, Dune::power(2,dim)> overlapfront_data; std::array overlap; std::array, Dune::power(2,dim)> overlap_data; std::array interiorborder; std::array, Dune::power(2,dim)> interiorborder_data; std::array interior; std::array, Dune::power(2,dim)> interior_data; std::array,dim+1> send_overlapfront_overlapfront; std::array, Dune::power(2,dim)> send_overlapfront_overlapfront_data; std::array,dim+1> recv_overlapfront_overlapfront; std::array, Dune::power(2,dim)> recv_overlapfront_overlapfront_data; std::array,dim+1> send_overlap_overlapfront; std::array, Dune::power(2,dim)> send_overlap_overlapfront_data; std::array,dim+1> recv_overlapfront_overlap; std::array, Dune::power(2,dim)> recv_overlapfront_overlap_data; std::array,dim+1> send_interiorborder_interiorborder; std::array, Dune::power(2,dim)> send_interiorborder_interiorborder_data; std::array,dim+1> recv_interiorborder_interiorborder; std::array, Dune::power(2,dim)> recv_interiorborder_interiorborder_data; std::array,dim+1> send_interiorborder_overlapfront; std::array, Dune::power(2,dim)> send_interiorborder_overlapfront_data; std::array,dim+1> recv_overlapfront_interiorborder; std::array, Dune::power(2,dim)> recv_overlapfront_interiorborder_data; // general YaspGrid* mg; // each grid level knows its multigrid int overlapSize; // in mesh cells on this level bool keepOverlap; /** \brief The level number within the YaspGrid level hierarchy */ int level_; }; //! define types used for arguments typedef std::array iTupel; typedef FieldVector fTupel; // communication tag used by multigrid enum { tag = 17 }; #endif //! return reference to torus const Torus& torus () const { return _torus; } //! return number of cells on finest level in given direction on all processors int globalSize(int i) const { return levelSize(maxLevel(),i); } //! return number of cells on finest level on all processors iTupel globalSize() const { return levelSize(maxLevel()); } //! return size of the grid (in cells) on level l in direction i int levelSize(int l, int i) const { return _coarseSize[i] * (1 << l); } //! return size vector of the grid (in cells) on level l iTupel levelSize(int l) const { iTupel s; for (int i=0; i::const_iterator YGridLevelIterator; //! return iterator pointing to coarsest level YGridLevelIterator begin () const { return _levels.begin(); } //! return iterator pointing to given level YGridLevelIterator begin (int i) const { if (i<0 || i>maxLevel()) DUNE_THROW(GridError, "level not existing"); return std::next(_levels.begin(), i); } //! return iterator pointing to one past the finest level YGridLevelIterator end () const { return _levels.end(); } // static method to create the default partitioning strategy static const Yasp::Partitioning* defaultPartitioner() { static Yasp::DefaultPartitioning lb; return & lb; } protected: /** \brief Make a new YGridLevel structure * * \param coords the coordinate container * \param periodic indicate periodicity for each direction * \param o_interior origin of interior (non-overlapping) cell decomposition * \param overlap to be used on this grid level */ void makelevel (const Coordinates& coords, std::bitset periodic, iTupel o_interior, int overlap) { YGridLevel& g = _levels.back(); g.overlapSize = overlap; g.mg = this; g.level_ = maxLevel(); g.coords = coords; g.keepOverlap = keep_ovlp; using Dune::power; // set the inserting positions in the corresponding arrays of YGridLevelStructure typename std::array, power(2,dim)>::iterator overlapfront_it = g.overlapfront_data.begin(); typename std::array, power(2,dim)>::iterator overlap_it = g.overlap_data.begin(); typename std::array, power(2,dim)>::iterator interiorborder_it = g.interiorborder_data.begin(); typename std::array, power(2,dim)>::iterator interior_it = g.interior_data.begin(); typename std::array, power(2,dim)>::iterator send_overlapfront_overlapfront_it = g.send_overlapfront_overlapfront_data.begin(); typename std::array, power(2,dim)>::iterator recv_overlapfront_overlapfront_it = g.recv_overlapfront_overlapfront_data.begin(); typename std::array, power(2,dim)>::iterator send_overlap_overlapfront_it = g.send_overlap_overlapfront_data.begin(); typename std::array, power(2,dim)>::iterator recv_overlapfront_overlap_it = g.recv_overlapfront_overlap_data.begin(); typename std::array, power(2,dim)>::iterator send_interiorborder_interiorborder_it = g.send_interiorborder_interiorborder_data.begin(); typename std::array, power(2,dim)>::iterator recv_interiorborder_interiorborder_it = g.recv_interiorborder_interiorborder_data.begin(); typename std::array, power(2,dim)>::iterator send_interiorborder_overlapfront_it = g.send_interiorborder_overlapfront_data.begin(); typename std::array, power(2,dim)>::iterator recv_overlapfront_interiorborder_it = g.recv_overlapfront_interiorborder_data.begin(); // have a null array for constructor calls around std::array n; std::fill(n.begin(), n.end(), 0); // determine origin of the grid with overlap and store whether an overlap area exists in direction i. std::bitset ovlp_low(0ULL); std::bitset ovlp_up(0ULL); iTupel o_overlap; iTupel s_overlap; // determine at where we have overlap and how big the size of the overlap partition is for (int i=0; i r(index); if (r.count() != dim-codim) continue; // get an origin and a size array for subsequent modification std::array origin(o_overlap); std::array size(s_overlap); // build overlapfront // we have to extend the element size by one in all directions without shift. for (int i=0; i(origin, r, &g.coords, size, n, size); // build overlap for (int i=0; i(origin,size,*overlapfront_it); // build interiorborder for (int i=0; i(origin,size,*overlapfront_it); // build interior for (int i=0; i(origin, size, *overlapfront_it); intersections(*overlapfront_it,*overlapfront_it,*send_overlapfront_overlapfront_it, *recv_overlapfront_overlapfront_it); intersections(*overlap_it,*overlapfront_it,*send_overlap_overlapfront_it, *recv_overlapfront_overlap_it); intersections(*interiorborder_it,*interiorborder_it,*send_interiorborder_interiorborder_it,*recv_interiorborder_interiorborder_it); intersections(*interiorborder_it,*overlapfront_it,*send_interiorborder_overlapfront_it,*recv_overlapfront_interiorborder_it); // advance all iterators pointing to the next insertion point ++overlapfront_it; ++overlap_it; ++interiorborder_it; ++interior_it; ++send_overlapfront_overlapfront_it; ++recv_overlapfront_overlapfront_it; ++send_overlap_overlapfront_it; ++recv_overlapfront_overlap_it; ++send_interiorborder_interiorborder_it; ++recv_interiorborder_interiorborder_it; ++send_interiorborder_overlapfront_it; ++recv_overlapfront_interiorborder_it; } // set end iterators in the corresponding ygrids g.overlapfront[codim].finalize(&*overlapfront_it); g.overlap[codim].finalize(&*overlap_it); g.interiorborder[codim].finalize(&*interiorborder_it); g.interior[codim].finalize(&*interior_it); g.send_overlapfront_overlapfront[codim].finalize(send_overlapfront_overlapfront_it,g.overlapfront[codim]); g.recv_overlapfront_overlapfront[codim].finalize(recv_overlapfront_overlapfront_it,g.overlapfront[codim]); g.send_overlap_overlapfront[codim].finalize(send_overlap_overlapfront_it,g.overlapfront[codim]); g.recv_overlapfront_overlap[codim].finalize(recv_overlapfront_overlap_it,g.overlapfront[codim]); g.send_interiorborder_interiorborder[codim].finalize(send_interiorborder_interiorborder_it,g.overlapfront[codim]); g.recv_interiorborder_interiorborder[codim].finalize(recv_interiorborder_interiorborder_it,g.overlapfront[codim]); g.send_interiorborder_overlapfront[codim].finalize(send_interiorborder_overlapfront_it,g.overlapfront[codim]); g.recv_overlapfront_interiorborder[codim].finalize(recv_overlapfront_interiorborder_it,g.overlapfront[codim]); } } #ifndef DOXYGEN /** \brief special data structure to communicate ygrids * Historically, this was needed because Ygrids had virtual functions and * a communicated virtual function table pointer introduced a bug. After the * change to tensorproductgrid, the dynamic polymorphism was removed, still this * is kept because it allows to communicate ygrids, that only have index, but no * coordinate information. This is sufficient, because all communicated YGrids are * intersected with a local grid, which has coordinate information. */ struct mpifriendly_ygrid { mpifriendly_ygrid () { std::fill(origin.begin(), origin.end(), 0); std::fill(size.begin(), size.end(), 0); } mpifriendly_ygrid (const YGridComponent& grid) : origin(grid.origin()), size(grid.size()) {} iTupel origin; iTupel size; }; #endif /** \brief Construct list of intersections with neighboring processors * * \param recvgrid the grid stored in this processor * \param sendgrid the subgrid to be sent to neighboring processors * \param[out] sendlist the deque to fill with send intersections * \param[out] recvlist the deque to fill with recv intersections */ void intersections(const YGridComponent& sendgrid, const YGridComponent& recvgrid, std::deque& sendlist, std::deque& recvlist) { iTupel size = globalSize(); // the exchange buffers std::vector > send_recvgrid(_torus.neighbors()); std::vector > recv_recvgrid(_torus.neighbors()); std::vector > send_sendgrid(_torus.neighbors()); std::vector > recv_sendgrid(_torus.neighbors()); // new exchange buffers to send simple struct without virtual functions std::vector mpifriendly_send_recvgrid(_torus.neighbors()); std::vector mpifriendly_recv_recvgrid(_torus.neighbors()); std::vector mpifriendly_send_sendgrid(_torus.neighbors()); std::vector mpifriendly_recv_sendgrid(_torus.neighbors()); // fill send buffers; iterate over all neighboring processes // non-periodic case is handled automatically because intersection will be zero for (typename Torus::ProcListIterator i=_torus.sendbegin(); i!=_torus.sendend(); ++i) { // determine if we communicate with this neighbor (and what) bool skip = false; iTupel coord = _torus.coord(); // my coordinates iTupel delta = i.delta(); // delta to neighbor iTupel nb = coord; // the neighbor for (int k=0; k=_torus.dims(k)) { if (_periodic[k]) v[k] -= size[k]; else skip = true; } // neither might be true, then v=0 } // store moved grids in send buffers if (!skip) { send_sendgrid[i.index()] = sendgrid.move(v); send_recvgrid[i.index()] = recvgrid.move(v); } else { send_sendgrid[i.index()] = YGridComponent(); send_recvgrid[i.index()] = YGridComponent(); } } // issue send requests for sendgrid being sent to all neighbors for (typename Torus::ProcListIterator i=_torus.sendbegin(); i!=_torus.sendend(); ++i) { mpifriendly_send_sendgrid[i.index()] = mpifriendly_ygrid(send_sendgrid[i.index()]); _torus.send(i.rank(), &mpifriendly_send_sendgrid[i.index()], sizeof(mpifriendly_ygrid)); } // issue recv requests for sendgrids of neighbors for (typename Torus::ProcListIterator i=_torus.recvbegin(); i!=_torus.recvend(); ++i) _torus.recv(i.rank(), &mpifriendly_recv_sendgrid[i.index()], sizeof(mpifriendly_ygrid)); // exchange the sendgrids _torus.exchange(); // issue send requests for recvgrid being sent to all neighbors for (typename Torus::ProcListIterator i=_torus.sendbegin(); i!=_torus.sendend(); ++i) { mpifriendly_send_recvgrid[i.index()] = mpifriendly_ygrid(send_recvgrid[i.index()]); _torus.send(i.rank(), &mpifriendly_send_recvgrid[i.index()], sizeof(mpifriendly_ygrid)); } // issue recv requests for recvgrid of neighbors for (typename Torus::ProcListIterator i=_torus.recvbegin(); i!=_torus.recvend(); ++i) _torus.recv(i.rank(), &mpifriendly_recv_recvgrid[i.index()], sizeof(mpifriendly_ygrid)); // exchange the recvgrid _torus.exchange(); // process receive buffers and compute intersections for (typename Torus::ProcListIterator i=_torus.recvbegin(); i!=_torus.recvend(); ++i) { // what must be sent to this neighbor Intersection send_intersection{}; mpifriendly_ygrid yg = mpifriendly_recv_recvgrid[i.index()]; recv_recvgrid[i.index()] = YGridComponent(yg.origin,yg.size); send_intersection.grid = sendgrid.intersection(recv_recvgrid[i.index()]); send_intersection.rank = i.rank(); send_intersection.distance = i.distance(); if (!send_intersection.grid.empty()) sendlist.push_front(send_intersection); Intersection recv_intersection{}; yg = mpifriendly_recv_sendgrid[i.index()]; recv_sendgrid[i.index()] = YGridComponent(yg.origin,yg.size); recv_intersection.grid = recvgrid.intersection(recv_sendgrid[i.index()]); recv_intersection.rank = i.rank(); recv_intersection.distance = i.distance(); if(!recv_intersection.grid.empty()) recvlist.push_back(recv_intersection); } } protected: typedef const YaspGrid GridImp; void init() { indexsets.push_back( std::make_shared< YaspIndexSet, false > >(*this,0) ); boundarysegmentssize(); } void boundarysegmentssize() { // sizes of local macro grid std::array sides; { for (int i=0; ioverlap[0].dataBegin()->origin(i) == 0)+ (begin()->overlap[0].dataBegin()->origin(i) + begin()->overlap[0].dataBegin()->size(i) == levelSize(0,i))); } } nBSegments = 0; for (int k=0; koverlap[0].dataBegin()->size(l); } nBSegments += sides[k]*offset; } } public: // define the persistent index type typedef bigunsignedint PersistentIndexType; //! the GridFamily of this grid typedef YaspGridFamily GridFamily; // the Traits typedef typename YaspGridFamily::Traits Traits; // need for friend declarations in entity typedef YaspIndexSet, false > LevelIndexSetType; typedef YaspIndexSet, true > LeafIndexSetType; typedef YaspGlobalIdSet > GlobalIdSetType; /** Standard constructor for a YaspGrid with a given Coordinates object * @param coordinates Object that stores or computes the vertex coordinates * @param periodic tells if direction is periodic or not * @param overlap size of overlap on coarsest grid (same in all directions) * @param comm the communication object for this grid. An MPI communicator can be given here. * @param partitioner pointer to an overloaded Yasp::Partitioning instance */ YaspGrid (const Coordinates& coordinates, std::bitset periodic = std::bitset(0ULL), int overlap = 1, Communication comm = Communication(), const Yasp::Partitioning* partitioner = defaultPartitioner()) : ccobj(comm) , leafIndexSet_(*this) , _periodic(periodic) , _overlap(overlap) , keep_ovlp(true) , adaptRefCount(0) , adaptActive(false) { _levels.resize(1); // Number of elements per coordinate direction on the coarsest level for (std::size_t i=0; i >::value || std::is_same >::value) { for (std::size_t i=0; i >::value) { //determine sizes of vector to correctly construct torus structure and store for later size requests for (int i=0; i >::value) ? 1 : 2; // check whether the grid is large enough to be overlapping for (int i=0; i >::value || std::is_same >::value) { iTupel s_overlap(s_interior); for (int i=0; i 0) || (periodic[i])) s_overlap[i] += overlap; if ((o_interior[i] + s_interior[i] + overlap <= _coarseSize[i]) || (periodic[i])) s_overlap[i] += overlap; } FieldVector upperRightWithOverlap; for (int i=0; i>) { // New coordinate object that additionally contains the overlap elements EquidistantCoordinates coordinatesWithOverlap(upperRightWithOverlap,s_overlap); // add level (the this-> is needed to make g++-6 happy) this->makelevel(coordinatesWithOverlap,periodic,o_interior,overlap); } if constexpr (std::is_same_v>) { Dune::FieldVector lowerleft; for (int i=0; i coordinatesWithOverlap(lowerleft,upperRightWithOverlap,s_overlap); // add level (the this-> is needed to make g++-6 happy) this->makelevel(coordinatesWithOverlap,periodic,o_interior,overlap); } } if constexpr (std::is_same_v>) { std::array,dim> newCoords; std::array offset(o_interior); // find the relevant part of the coords vector for this processor and copy it to newCoords for (int i=0; i 0) { begin = begin - overlap; offset[i] -= overlap; } if (o_interior[i] + s_interior[i] + overlap < _coarseSize[i]) end = end + overlap; //copy the selected part in the new coord vector newCoords[i].resize(end-begin); auto newCoordsIt = newCoords[i].begin(); for (std::size_t j=begin; j= _coarseSize[i])) { // we need to add the first cells to the end of newcoords for (int j=0; j cells to the begin of newcoords std::size_t reverseCounter = coordinates.size(i); for (int j=0; j coordinatesWithOverlap(newCoords, offset); // add level (the this-> is needed to make g++-6 happy) this->makelevel(coordinatesWithOverlap,periodic,o_interior,overlap); } init(); } /** Standard constructor for an equidistant YaspGrid * @param L extension of the domain * @param s number of cells on coarse mesh in each direction * @param periodic tells if direction is periodic or not * @param overlap size of overlap on coarsest grid (same in all directions) * @param comm the communication object for this grid. An MPI communicator can be given here. * @param partitioner pointer to an overloaded Yasp::Partitioning instance */ template >, int> = 0> YaspGrid (Dune::FieldVector L, std::array s, std::bitset periodic = std::bitset{0ULL}, int overlap = 1, Communication comm = Communication(), const Yasp::Partitioning* partitioner = defaultPartitioner()) : ccobj(comm), _torus(comm,tag,s,overlap,partitioner), leafIndexSet_(*this), _L(L), _periodic(periodic), _coarseSize(s), _overlap(overlap), keep_ovlp(true), adaptRefCount(0), adaptActive(false) { _levels.resize(1); iTupel o; std::fill(o.begin(), o.end(), 0); iTupel o_interior(o); iTupel s_interior(s); _torus.partition(_torus.rank(),o,s,o_interior,s_interior); #if HAVE_MPI // check whether the grid is large enough to be overlapping for (int i=0; i 0) || (periodic[i])) s_overlap[i] += overlap; if ((o_interior[i] + s_interior[i] + overlap <= _coarseSize[i]) || (periodic[i])) s_overlap[i] += overlap; } FieldVector upperRightWithOverlap; for (int i=0; i cc(upperRightWithOverlap,s_overlap); // add level makelevel(cc,periodic,o_interior,overlap); init(); } /** Constructor for an equidistant YaspGrid with non-trivial origin * @param lowerleft Lower left corner of the domain * @param upperright Upper right corner of the domain * @param s number of cells on coarse mesh in each direction * @param periodic tells if direction is periodic or not * @param overlap size of overlap on coarsest grid (same in all directions) * @param comm the communication object for this grid. An MPI communicator can be given here. * @param partitioner pointer to an overloaded Yasp::Partitioning instance */ template >, int> = 0> YaspGrid (Dune::FieldVector lowerleft, Dune::FieldVector upperright, std::array s, std::bitset periodic = std::bitset(0ULL), int overlap = 1, Communication comm = Communication(), const Yasp::Partitioning* partitioner = defaultPartitioner()) : ccobj(comm), _torus(comm,tag,s,overlap,partitioner), leafIndexSet_(*this), _L(upperright - lowerleft), _periodic(periodic), _coarseSize(s), _overlap(overlap), keep_ovlp(true), adaptRefCount(0), adaptActive(false) { _levels.resize(1); iTupel o; std::fill(o.begin(), o.end(), 0); iTupel o_interior(o); iTupel s_interior(s); _torus.partition(_torus.rank(),o,s,o_interior,s_interior); #if HAVE_MPI // check whether the grid is large enough to be overlapping for (int i=0; i 0) || (periodic[i])) s_overlap[i] += overlap; if ((o_interior[i] + s_interior[i] + overlap <= _coarseSize[i]) || (periodic[i])) s_overlap[i] += overlap; } FieldVector upperRightWithOverlap; for (int i=0; i cc(lowerleft,upperRightWithOverlap,s_overlap); // add level makelevel(cc,periodic,o_interior,overlap); init(); } /** @brief Standard constructor for a tensorproduct YaspGrid * @param coords coordinate vectors to be used for coarse grid * @param periodic tells if direction is periodic or not * @param overlap size of overlap on coarsest grid (same in all directions) * @param comm the communication object for this grid. An MPI communicator can be given here. * @param partitioner pointer to an overloaded Yasp::Partitioning instance */ template >, int> = 0> YaspGrid (std::array, std::size_t{dim}> coords, std::bitset periodic = std::bitset(0ULL), int overlap = 1, Communication comm = Communication(), const Yasp::Partitioning* partitioner = defaultPartitioner()) : ccobj(comm), _torus(comm,tag,Dune::Yasp::sizeArray(coords),overlap,partitioner), leafIndexSet_(*this), _periodic(periodic), _overlap(overlap), keep_ovlp(true), adaptRefCount(0), adaptActive(false) { if (!Dune::Yasp::checkIfMonotonous(coords)) DUNE_THROW(Dune::GridError,"Setup of a tensorproduct grid requires monotonous sequences of coordinates."); _levels.resize(1); //determine sizes of vector to correctly construct torus structure and store for later size requests for (int i=0; i,dim> newcoords; std::array offset(o_interior); // find the relevant part of the coords vector for this processor and copy it to newcoords for (int i=0; i::iterator begin = coords[i].begin() + o_interior[i]; typename std::vector::iterator end = begin + s_interior[i] + 1; // check whether we are not at the physical boundary. In that case overlap is a simple // extension of the coordinate range to be used if (o_interior[i] - overlap > 0) { begin = begin - overlap; offset[i] -= overlap; } if (o_interior[i] + s_interior[i] + overlap < _coarseSize[i]) end = end + overlap; //copy the selected part in the new coord vector newcoords[i].resize(end-begin); std::copy(begin, end, newcoords[i].begin()); // check whether we are at the physical boundary and a have a periodic grid. // In this case the coordinate vector has to be tweaked manually. if ((periodic[i]) && (o_interior[i] + s_interior[i] + overlap >= _coarseSize[i])) { // we need to add the first cells to the end of newcoords typename std::vector::iterator it = coords[i].begin(); for (int j=0; j cells to the begin of newcoords typename std::vector::iterator it = coords[i].end() - 1; for (int j=0; j cc(newcoords, offset); // add level makelevel(cc,periodic,o_interior,overlap); init(); } private: /** @brief Constructor for a tensorproduct YaspGrid with only coordinate * information on this processor * @param comm MPI communicator where this mesh is distributed to * @param coords coordinate vectors to be used for coarse grid * @param periodic tells if direction is periodic or not * @param overlap size of overlap on coarsest grid (same in all directions) * @param coarseSize the coarse size of the global grid * @param partitioner pointer to an overloaded Yasp::Partitioning instance * * @warning The construction of overlapping coordinate ranges is * an error-prone procedure. For this reason, it is kept private. * You can safely use it through BackupRestoreFacility. All other * use is not supported for the moment. */ YaspGrid (std::array, std::size_t{dim}> coords, std::bitset periodic, int overlap, Communication comm, std::array coarseSize, const Yasp::Partitioning* partitioner = defaultPartitioner()) : ccobj(comm), _torus(comm,tag,coarseSize,overlap,partitioner), leafIndexSet_(*this), _periodic(periodic), _coarseSize(coarseSize), _overlap(overlap), keep_ovlp(true), adaptRefCount(0), adaptActive(false) { // check whether YaspGrid has been given the correct template parameter static_assert(std::is_same >::value, "YaspGrid coordinate container template parameter and given constructor values do not match!"); if (!Dune::Yasp::checkIfMonotonous(coords)) DUNE_THROW(Dune::GridError,"Setup of a tensorproduct grid requires monotonous sequences of coordinates."); for (int i=0; i o; std::fill(o.begin(), o.end(), 0); std::array o_interior(o); std::array s_interior(coarseSize); _torus.partition(_torus.rank(),o,coarseSize,o_interior,s_interior); // get offset by modifying o_interior according to overlap std::array offset(o_interior); for (int i=0; i 0)) offset[i] -= overlap; TensorProductCoordinates cc(coords, offset); // add level makelevel(cc,periodic,o_interior,overlap); init(); } // the backup restore facility needs to be able to use above constructor friend struct BackupRestoreFacility >; // do not copy this class YaspGrid(const YaspGrid&); public: /*! Return maximum level defined in this grid. Levels are numbered 0 ... maxlevel with 0 the coarsest level. */ int maxLevel() const { return _levels.size()-1; } //! refine the grid refCount times. void globalRefine (int refCount) { if (refCount < -maxLevel()) DUNE_THROW(GridError, "Only " << maxLevel() << " levels left. " << "Coarsening " << -refCount << " levels requested!"); // If refCount is negative then coarsen the grid for (int k=refCount; k<0; k++) { // create an empty grid level YGridLevel empty; _levels.back() = empty; // reduce maxlevel _levels.pop_back(); indexsets.pop_back(); } // If refCount is positive refine the grid for (int k=0; k ovlp_low(0ULL), ovlp_up(0ULL); for (int i=0; iorigin(i) > 0 || _periodic[i]) ovlp_low[i] = true; if (cg.overlap[0].dataBegin()->max(i) + 1 < globalSize(i) || _periodic[i]) ovlp_up[i] = true; } Coordinates newcont(cg.coords.refine(ovlp_low, ovlp_up, cg.overlapSize, keep_ovlp)); int overlap = (keep_ovlp) ? 2*cg.overlapSize : cg.overlapSize; //determine new origin iTupel o_interior; for (int i=0; iorigin(i); // add level _levels.resize(_levels.size() + 1); makelevel(newcont,_periodic,o_interior,overlap); indexsets.push_back( std::make_shared, false > >(*this,maxLevel()) ); } } /** \brief set options for refinement @param keepPhysicalOverlap [true] keep the physical size of the overlap, [false] keep the number of cells in the overlap. Default is [true]. */ void refineOptions (bool keepPhysicalOverlap) { keep_ovlp = keepPhysicalOverlap; } /** \brief Marks an entity to be refined/coarsened in a subsequent adapt. \param[in] refCount Number of subdivisions that should be applied. Negative value means coarsening. \param[in] e Entity to Entity that should be refined \return true if Entity was marked, false otherwise. \note - On yaspgrid marking one element will mark all other elements of the level as well - If refCount is lower than refCount of a previous mark-call, nothing is changed */ bool mark( int refCount, const typename Traits::template Codim<0>::Entity & e ) { assert(adaptActive == false); if (e.level() != maxLevel()) return false; adaptRefCount = std::max(adaptRefCount, refCount); return true; } /** \brief returns adaptation mark for given entity \param[in] e Entity for which adaptation mark should be determined \return int adaptation mark, here the default value 0 is returned */ int getMark ( const typename Traits::template Codim<0>::Entity &e ) const { return ( e.level() == maxLevel() ) ? adaptRefCount : 0; } //! map adapt to global refine bool adapt () { globalRefine(adaptRefCount); return (adaptRefCount > 0); } //! returns true, if the grid will be coarsened bool preAdapt () { adaptActive = true; adaptRefCount = comm().max(adaptRefCount); return (adaptRefCount < 0); } //! clean up some markers void postAdapt() { adaptActive = false; adaptRefCount = 0; } //! one past the end on this level template typename Traits::template Codim::template Partition::LevelIterator lbegin (int level) const { return levelbegin(level); } //! Iterator to one past the last entity of given codim on level for partition type template typename Traits::template Codim::template Partition::LevelIterator lend (int level) const { return levelend(level); } //! version without second template parameter for convenience template typename Traits::template Codim::template Partition::LevelIterator lbegin (int level) const { return levelbegin(level); } //! version without second template parameter for convenience template typename Traits::template Codim::template Partition::LevelIterator lend (int level) const { return levelend(level); } //! return LeafIterator which points to the first entity in maxLevel template typename Traits::template Codim::template Partition::LeafIterator leafbegin () const { return levelbegin(maxLevel()); } //! return LeafIterator which points behind the last entity in maxLevel template typename Traits::template Codim::template Partition::LeafIterator leafend () const { return levelend(maxLevel()); } //! return LeafIterator which points to the first entity in maxLevel template typename Traits::template Codim::template Partition::LeafIterator leafbegin () const { return levelbegin(maxLevel()); } //! return LeafIterator which points behind the last entity in maxLevel template typename Traits::template Codim::template Partition::LeafIterator leafend () const { return levelend(maxLevel()); } // \brief obtain Entity from EntitySeed. */ template typename Traits::template Codim::Entity entity(const Seed& seed) const { const int codim = Seed::codimension; YGridLevelIterator g = begin(seed.impl().level()); typedef typename Traits::template Codim::Entity Entity; typedef YaspEntity EntityImp; typedef typename YGrid::Iterator YIterator; return Entity(EntityImp(g,YIterator(g->overlapfront[codim],seed.impl().coord(),seed.impl().offset()))); } //! return size (= distance in graph) of overlap region int overlapSize (int level, [[maybe_unused]] int codim) const { YGridLevelIterator g = begin(level); return g->overlapSize; } //! return size (= distance in graph) of overlap region int overlapSize ([[maybe_unused]] int odim) const { YGridLevelIterator g = begin(maxLevel()); return g->overlapSize; } //! return size (= distance in graph) of ghost region int ghostSize ([[maybe_unused]] int level, [[maybe_unused]] int codim) const { return 0; } //! return size (= distance in graph) of ghost region int ghostSize ([[maybe_unused]] int codim) const { return 0; } //! number of entities per level and codim in this process int size (int level, int codim) const { YGridLevelIterator g = begin(level); // sum over all components of the codimension int count = 0; for (auto it = g->overlapfront[codim].dataBegin(); it != g->overlapfront[codim].dataEnd(); ++it) count += it->totalsize(); return count; } //! number of leaf entities per codim in this process int size (int codim) const { return size(maxLevel(),codim); } //! number of entities per level and geometry type in this process int size (int level, GeometryType type) const { return (type.isCube()) ? size(level,dim-type.dim()) : 0; } //! number of leaf entities per geometry type in this process int size (GeometryType type) const { return size(maxLevel(),type); } //! \brief returns the number of boundary segments within the macro grid size_t numBoundarySegments () const { return nBSegments; } //! \brief returns the size of the physical domain const Dune::FieldVector& domainSize () const { return _L; } /*! The new communication interface communicate objects for all codims on a given level */ template void communicate (CommDataHandleIF & data, InterfaceType iftype, CommunicationDirection dir, int level) const { YaspCommunicateMeta::comm(*this,data,iftype,dir,level); } /*! The new communication interface communicate objects for all codims on the leaf grid */ template void communicate (CommDataHandleIF & data, InterfaceType iftype, CommunicationDirection dir) const { YaspCommunicateMeta::comm(*this,data,iftype,dir,this->maxLevel()); } /*! The new communication interface communicate objects for one codim */ template void communicateCodim (DataHandle& data, InterfaceType iftype, CommunicationDirection dir, int level) const { // check input if (!data.contains(dim,codim)) return; // should have been checked outside // data types typedef typename DataHandle::DataType DataType; // access to grid level YGridLevelIterator g = begin(level); // find send/recv lists or throw error const YGridList* sendlist = 0; const YGridList* recvlist = 0; if (iftype==InteriorBorder_InteriorBorder_Interface) { sendlist = &g->send_interiorborder_interiorborder[codim]; recvlist = &g->recv_interiorborder_interiorborder[codim]; } if (iftype==InteriorBorder_All_Interface) { sendlist = &g->send_interiorborder_overlapfront[codim]; recvlist = &g->recv_overlapfront_interiorborder[codim]; } if (iftype==Overlap_OverlapFront_Interface || iftype==Overlap_All_Interface) { sendlist = &g->send_overlap_overlapfront[codim]; recvlist = &g->recv_overlapfront_overlap[codim]; } if (iftype==All_All_Interface) { sendlist = &g->send_overlapfront_overlapfront[codim]; recvlist = &g->recv_overlapfront_overlapfront[codim]; } // change communication direction? if (dir==BackwardCommunication) std::swap(sendlist,recvlist); int cnt; // Size computation (requires communication if variable size) std::vector send_size(sendlist->size(),-1); // map rank to total number of objects (of type DataType) to be sent std::vector recv_size(recvlist->size(),-1); // map rank to total number of objects (of type DataType) to be recvd std::vector send_sizes(sendlist->size(),static_cast(0)); // map rank to array giving number of objects per entity to be sent std::vector recv_sizes(recvlist->size(),static_cast(0)); // map rank to array giving number of objects per entity to be recvd // define type to iterate over send and recv lists typedef typename YGridList::Iterator ListIt; if (data.fixedSize(dim,codim)) { // fixed size: just take a dummy entity, size can be computed without communication cnt=0; for (ListIt is=sendlist->begin(); is!=sendlist->end(); ++is) { typename Traits::template Codim::template Partition::LevelIterator it(YaspLevelIterator(g, typename YGrid::Iterator(is->yg))); send_size[cnt] = is->grid.totalsize() * data.size(*it); cnt++; } cnt=0; for (ListIt is=recvlist->begin(); is!=recvlist->end(); ++is) { typename Traits::template Codim::template Partition::LevelIterator it(YaspLevelIterator(g, typename YGrid::Iterator(is->yg))); recv_size[cnt] = is->grid.totalsize() * data.size(*it); cnt++; } } else { // variable size case: sender side determines the size cnt=0; for (ListIt is=sendlist->begin(); is!=sendlist->end(); ++is) { // allocate send buffer for sizes per entity size_t *buf = new size_t[is->grid.totalsize()]; send_sizes[cnt] = buf; // loop over entities and ask for size int i=0; size_t n=0; typename Traits::template Codim::template Partition::LevelIterator it(YaspLevelIterator(g, typename YGrid::Iterator(is->yg))); typename Traits::template Codim::template Partition::LevelIterator itend(YaspLevelIterator(g, typename YGrid::Iterator(is->yg,true))); for ( ; it!=itend; ++it) { buf[i] = data.size(*it); n += buf[i]; i++; } // now we know the size for this rank send_size[cnt] = n; // hand over send request to torus class torus().send(is->rank,buf,is->grid.totalsize()*sizeof(size_t)); cnt++; } // allocate recv buffers for sizes and store receive request cnt=0; for (ListIt is=recvlist->begin(); is!=recvlist->end(); ++is) { // allocate recv buffer size_t *buf = new size_t[is->grid.totalsize()]; recv_sizes[cnt] = buf; // hand over recv request to torus class torus().recv(is->rank,buf,is->grid.totalsize()*sizeof(size_t)); cnt++; } // exchange all size buffers now torus().exchange(); // release send size buffers cnt=0; for (ListIt is=sendlist->begin(); is!=sendlist->end(); ++is) { delete[] send_sizes[cnt]; send_sizes[cnt] = 0; cnt++; } // process receive size buffers cnt=0; for (ListIt is=recvlist->begin(); is!=recvlist->end(); ++is) { // get recv buffer size_t *buf = recv_sizes[cnt]; // compute total size size_t n=0; for (int i=0; igrid.totalsize(); ++i) n += buf[i]; // ... and store it recv_size[cnt] = n; ++cnt; } } // allocate & fill the send buffers & store send request std::vector sends(sendlist->size(), static_cast(0)); // store pointers to send buffers cnt=0; for (ListIt is=sendlist->begin(); is!=sendlist->end(); ++is) { // allocate send buffer DataType *buf = new DataType[send_size[cnt]]; // remember send buffer sends[cnt] = buf; // make a message buffer MessageBuffer mb(buf); // fill send buffer; iterate over cells in intersection typename Traits::template Codim::template Partition::LevelIterator it(YaspLevelIterator(g, typename YGrid::Iterator(is->yg))); typename Traits::template Codim::template Partition::LevelIterator itend(YaspLevelIterator(g, typename YGrid::Iterator(is->yg,true))); for ( ; it!=itend; ++it) data.gather(mb,*it); // hand over send request to torus class torus().send(is->rank,buf,send_size[cnt]*sizeof(DataType)); cnt++; } // allocate recv buffers and store receive request std::vector recvs(recvlist->size(),static_cast(0)); // store pointers to send buffers cnt=0; for (ListIt is=recvlist->begin(); is!=recvlist->end(); ++is) { // allocate recv buffer DataType *buf = new DataType[recv_size[cnt]]; // remember recv buffer recvs[cnt] = buf; // hand over recv request to torus class torus().recv(is->rank,buf,recv_size[cnt]*sizeof(DataType)); cnt++; } // exchange all buffers now torus().exchange(); // release send buffers cnt=0; for (ListIt is=sendlist->begin(); is!=sendlist->end(); ++is) { delete[] sends[cnt]; sends[cnt] = 0; cnt++; } // process receive buffers and delete them cnt=0; for (ListIt is=recvlist->begin(); is!=recvlist->end(); ++is) { // get recv buffer DataType *buf = recvs[cnt]; // make a message buffer MessageBuffer mb(buf); // copy data from receive buffer; iterate over cells in intersection if (data.fixedSize(dim,codim)) { typename Traits::template Codim::template Partition::LevelIterator it(YaspLevelIterator(g, typename YGrid::Iterator(is->yg))); size_t n=data.size(*it); typename Traits::template Codim::template Partition::LevelIterator itend(YaspLevelIterator(g, typename YGrid::Iterator(is->yg,true))); for ( ; it!=itend; ++it) data.scatter(mb,*it,n); } else { int i=0; size_t *sbuf = recv_sizes[cnt]; typename Traits::template Codim::template Partition::LevelIterator it(YaspLevelIterator(g, typename YGrid::Iterator(is->yg))); typename Traits::template Codim::template Partition::LevelIterator itend(YaspLevelIterator(g, typename YGrid::Iterator(is->yg,true))); for ( ; it!=itend; ++it) data.scatter(mb,*it,sbuf[i++]); delete[] sbuf; } // delete buffer delete[] buf; // hier krachts ! cnt++; } } // The new index sets from DDM 11.07.2005 const typename Traits::GlobalIdSet& globalIdSet() const { return theglobalidset; } const typename Traits::LocalIdSet& localIdSet() const { return theglobalidset; } const typename Traits::LevelIndexSet& levelIndexSet(int level) const { if (level<0 || level>maxLevel()) DUNE_THROW(RangeError, "level out of range"); return *(indexsets[level]); } const typename Traits::LeafIndexSet& leafIndexSet() const { return leafIndexSet_; } /*! @brief return a communication object */ const Communication& comm () const { return ccobj; } private: // number of boundary segments of the level 0 grid int nBSegments; // Index classes need access to the real entity friend class Dune::YaspIndexSet, true >; friend class Dune::YaspIndexSet, false >; friend class Dune::YaspGlobalIdSet >; friend class Dune::YaspPersistentContainerIndex >; friend class Dune::YaspIntersectionIterator >; friend class Dune::YaspIntersection >; friend class Dune::YaspEntity<0, dim, const Dune::YaspGrid >; template class EntityImp_> friend class Entity; template class MessageBuffer { public: // Constructor MessageBuffer (DT *p) { a=p; i=0; j=0; } // write data to message buffer, acts like a stream ! template void write (const Y& data) { static_assert(( std::is_same::value ), "DataType mismatch"); a[i++] = data; } // read data from message buffer, acts like a stream ! template void read (Y& data) const { static_assert(( std::is_same::value ), "DataType mismatch"); data = a[j++]; } private: DT *a; int i; mutable int j; }; //! one past the end on this level template YaspLevelIterator levelbegin (int level) const { YGridLevelIterator g = begin(level); if (level<0 || level>maxLevel()) DUNE_THROW(RangeError, "level out of range"); if (pitype==Interior_Partition) return YaspLevelIterator(g,g->interior[cd].begin()); if (pitype==InteriorBorder_Partition) return YaspLevelIterator(g,g->interiorborder[cd].begin()); if (pitype==Overlap_Partition) return YaspLevelIterator(g,g->overlap[cd].begin()); if (pitype<=All_Partition) return YaspLevelIterator(g,g->overlapfront[cd].begin()); if (pitype==Ghost_Partition) return levelend (level); DUNE_THROW(GridError, "YaspLevelIterator with this codim or partition type not implemented"); } //! Iterator to one past the last entity of given codim on level for partition type template YaspLevelIterator levelend (int level) const { YGridLevelIterator g = begin(level); if (level<0 || level>maxLevel()) DUNE_THROW(RangeError, "level out of range"); if (pitype==Interior_Partition) return YaspLevelIterator(g,g->interior[cd].end()); if (pitype==InteriorBorder_Partition) return YaspLevelIterator(g,g->interiorborder[cd].end()); if (pitype==Overlap_Partition) return YaspLevelIterator(g,g->overlap[cd].end()); if (pitype<=All_Partition || pitype == Ghost_Partition) return YaspLevelIterator(g,g->overlapfront[cd].end()); DUNE_THROW(GridError, "YaspLevelIterator with this codim or partition type not implemented"); } Communication ccobj; Torus _torus; std::vector< std::shared_ptr< YaspIndexSet, false > > > indexsets; YaspIndexSet, true> leafIndexSet_; YaspGlobalIdSet > theglobalidset; Dune::FieldVector _L; iTupel _s; std::bitset _periodic; iTupel _coarseSize; ReservedVector _levels; int _overlap; bool keep_ovlp; int adaptRefCount; bool adaptActive; }; // Class template deduction guides template YaspGrid(FieldVector, std::array, std::bitset = std::bitset{0ULL}, int = 1, YaspCommunication = YaspCommunication(), const Yasp::Partitioning* = YaspGrid>::defaultPartitioner()) -> YaspGrid< dim, EquidistantCoordinates >; template YaspGrid(FieldVector, FieldVector, std::array, std::bitset = std::bitset{0ULL}, int = 1, YaspCommunication = YaspCommunication(), const Yasp::Partitioning* = YaspGrid>::defaultPartitioner()) -> YaspGrid< dim, EquidistantOffsetCoordinates >; template YaspGrid(std::array, dim>, std::bitset = std::bitset{0ULL}, int = 1, YaspCommunication = YaspCommunication(), const Yasp::Partitioning* = YaspGrid>::defaultPartitioner()) -> YaspGrid< int{dim}, TensorProductCoordinates >; //! Output operator for multigrids template std::ostream& operator<< (std::ostream& s, const YaspGrid& grid) { int rank = grid.torus().rank(); s << "[" << rank << "]:" << " YaspGrid maxlevel=" << grid.maxLevel() << std::endl; s << "Printing the torus: " <::YGridLevelIterator g=grid.begin(); g!=grid.end(); ++g) { s << "[" << rank << "]: " << std::endl; s << "[" << rank << "]: " << "==========================================" << std::endl; s << "[" << rank << "]: " << "level=" << g->level() << std::endl; for (int codim = 0; codim < d + 1; ++codim) { s << "[" << rank << "]: " << "overlapfront[" << codim << "]: " << g->overlapfront[codim] << std::endl; s << "[" << rank << "]: " << "overlap[" << codim << "]: " << g->overlap[codim] << std::endl; s << "[" << rank << "]: " << "interiorborder[" << codim << "]: " << g->interiorborder[codim] << std::endl; s << "[" << rank << "]: " << "interior[" << codim << "]: " << g->interior[codim] << std::endl; typedef typename YGridList::Iterator I; for (I i=g->send_overlapfront_overlapfront[codim].begin(); i!=g->send_overlapfront_overlapfront[codim].end(); ++i) s << "[" << rank << "]: " << " s_of_of[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->recv_overlapfront_overlapfront[codim].begin(); i!=g->recv_overlapfront_overlapfront[codim].end(); ++i) s << "[" << rank << "]: " << " r_of_of[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->send_overlap_overlapfront[codim].begin(); i!=g->send_overlap_overlapfront[codim].end(); ++i) s << "[" << rank << "]: " << " s_o_of[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->recv_overlapfront_overlap[codim].begin(); i!=g->recv_overlapfront_overlap[codim].end(); ++i) s << "[" << rank << "]: " << " r_of_o[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->send_interiorborder_interiorborder[codim].begin(); i!=g->send_interiorborder_interiorborder[codim].end(); ++i) s << "[" << rank << "]: " << " s_ib_ib[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->recv_interiorborder_interiorborder[codim].begin(); i!=g->recv_interiorborder_interiorborder[codim].end(); ++i) s << "[" << rank << "]: " << " r_ib_ib[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->send_interiorborder_overlapfront[codim].begin(); i!=g->send_interiorborder_overlapfront[codim].end(); ++i) s << "[" << rank << "]: " << " s_ib_of[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; for (I i=g->recv_overlapfront_interiorborder[codim].begin(); i!=g->recv_overlapfront_interiorborder[codim].end(); ++i) s << "[" << rank << "]: " << " r_of_ib[" << codim << "] to rank " << i->rank << " " << i->grid << std::endl; } } s << std::endl; return s; } namespace Capabilities { /** \struct hasEntity \ingroup YaspGrid */ /** \struct hasBackupRestoreFacilities \ingroup YaspGrid */ template struct hasBackupRestoreFacilities< YaspGrid > { static const bool v = true; }; /** \brief YaspGrid has only one geometry type for codim 0 entities \ingroup YaspGrid */ template struct hasSingleGeometryType< YaspGrid > { static const bool v = true; static const unsigned int topologyId = GeometryTypes::cube(dim).id(); }; /** \brief YaspGrid is a Cartesian grid \ingroup YaspGrid */ template struct isCartesian< YaspGrid > { static const bool v = true; }; /** \brief YaspGrid has entities for all codimensions \ingroup YaspGrid */ template struct hasEntity< YaspGrid, codim> { static const bool v = true; }; /** * \brief YaspGrid can iterate over all codimensions * \ingroup YaspGrid **/ template struct hasEntityIterator, codim> { static const bool v = true; }; /** \brief YaspGrid can communicate on all codimensions * \ingroup YaspGrid */ template struct canCommunicate< YaspGrid< dim, Coordinates>, codim > { static const bool v = true; }; /** \brief YaspGrid is levelwise conforming \ingroup YaspGrid */ template struct isLevelwiseConforming< YaspGrid > { static const bool v = true; }; /** \brief YaspGrid is leafwise conforming \ingroup YaspGrid */ template struct isLeafwiseConforming< YaspGrid > { static const bool v = true; }; /** \brief YaspGrid is viewThreadSafe \ingroup YaspGrid */ template struct viewThreadSafe< YaspGrid > { static const bool v = true; }; } } // end namespace // Include the specialization of the StructuredGridFactory class for YaspGrid #include // Include the specialization of the BackupRestoreFacility class for YaspGrid #include #endif dune-grid-2.11.0/dune/grid/yaspgrid/000077500000000000000000000000001511655130300171535ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/yaspgrid/CMakeLists.txt000066400000000000000000000013271511655130300217160ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS backuprestore.hh coordinates.hh partitioning.hh structuredyaspgridfactory.hh torus.hh yaspgridentity.hh yaspgridentityseed.hh yaspgridgeometry.hh yaspgridhierarchiciterator.hh yaspgridindexsets.hh yaspgridintersection.hh yaspgridintersectioniterator.hh yaspgrididset.hh yaspgridleveliterator.hh yaspgridpersistentcontainer.hh ygrid.hh) exclude_all_but_from_headercheck(backuprestore.hh torus.hh coordinates.hh ygrid.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/yaspgrid/) dune-grid-2.11.0/dune/grid/yaspgrid/backuprestore.hh000066400000000000000000000264471511655130300223620ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRID_BACKUPRESTORE_HH #define DUNE_GRID_YASPGRID_BACKUPRESTORE_HH //- system headers #include #include //- Dune headers #include #include #include #include // bump this version number up if you introduce any changes // to the output format of the YaspGrid BackupRestoreFacility. #define YASPGRID_BACKUPRESTORE_FORMAT_VERSION 2 namespace Dune { template struct MaybeHaveOrigin { template static void writeOrigin(S& /* s */, const Coordinates& /* coord */) {} template static void readOrigin(S& /* s */, Dune::FieldVector& /* coord */) {} template static typename Dune::YaspGrid* createGrid( const Dune::FieldVector& /* lowerleft */, A... args) { return new Dune::YaspGrid(args...); } }; template struct MaybeHaveOrigin > { typedef typename Dune::EquidistantOffsetCoordinates Coordinates; template static void writeOrigin(S& s, const Coordinates& coord) { s << "Origin: "; for (int i=0; i static void readOrigin(S& s, Dune::FieldVector& coord) { std::string token; s >> token; for (int i=0; i> coord[i]; } template static typename Dune::YaspGrid* createGrid( const Dune::FieldVector& lowerleft, const Dune::FieldVector& extension, A... args) { Dune::FieldVector upperright(lowerleft); upperright += extension; return new Dune::YaspGrid(lowerleft, upperright, args...); } }; /** \copydoc Dune::BackupRestoreFacility */ template struct BackupRestoreFacility > { // type of grid typedef typename Dune::YaspGrid Grid; typedef typename Grid::ctype ctype; typedef typename Grid::Traits::Communication Comm; /** \copydoc BackupRestoreFacility::backup() */ static void backup ( const Grid &grid, const std::string &filename ) { if (grid.comm().rank() == 0) { std::ofstream file(filename); if( file ) { backup(grid,file); file.close(); } else std::cerr << "ERROR: BackupRestoreFacility::backup: couldn't open file `" << filename << "'" << std::endl; } } /** \copydoc BackupRestoreFacility::backup() */ static void backup ( const Grid &grid, std::ostream &stream ) { stream << "YaspGrid BackupRestore Format Version: " << YASPGRID_BACKUPRESTORE_FORMAT_VERSION << std::endl; stream << "Torus structure: "; for (int i=0; ikeepOverlap ? "1" : "0") << " "; stream << std::endl; stream << "Coarse Size: "; for (int i=0; icoords.meshsize(i,0) << " "; stream << std::endl; MaybeHaveOrigin::writeOrigin(stream, grid.begin()->coords); } /** \copydoc BackupRestoreFacility::restore(const std::string &) * \param comm Communication object. */ static Grid *restore (const std::string &filename, Comm comm = Comm()) { std::ifstream file(filename); if( file ) return restore(file,comm); else { std::cerr << "ERROR: BackupRestoreFacility::restore: couldn't open file `" << filename << "'" << std::endl; return 0; } } /** \copydoc BackupRestoreFacility::restore(std::istream &) * \param comm Communication object. */ static Grid *restore (std::istream &stream, Comm comm = Comm()) { std::string input; int version; stream >> input >> input >> input >> input; stream >> version; if (version != YASPGRID_BACKUPRESTORE_FORMAT_VERSION) DUNE_THROW(Dune::Exception, "Your YaspGrid backup file is written in an outdated format!"); std::array torus_dims; stream >> input >> input; for (int i=0; i> torus_dims[i]; int refinement; stream >> input >> input; stream >> refinement; std::bitset periodic; bool b; stream >> input; for (int i=0; i> b; periodic[i] = b; } int overlap; stream >> input; stream >> overlap; std::vector physicalOverlapSize; physicalOverlapSize.resize(refinement); stream >> input; for (int i=0; i> b; physicalOverlapSize[i] = b; } std::array coarseSize; stream >> input >> input; for (int i=0; i> coarseSize[i]; Dune::FieldVector h; stream >> input; for (int i=0; i> h[i]; Dune::FieldVector origin; MaybeHaveOrigin::readOrigin(stream, origin); // the constructor takes the upper right corner... Dune::FieldVector length(h); for (int i=0; i lb(torus_dims); Grid* grid = MaybeHaveOrigin::createGrid(origin, length, coarseSize, periodic, overlap, comm, &lb); for (int i=0; irefineOptions(physicalOverlapSize[i]); grid->globalRefine(1); } return grid; } }; /** \copydoc Dune::BackupRestoreFacility */ template struct BackupRestoreFacility > > { // type of grid typedef YaspGrid > Grid; typedef typename Grid::Traits::Communication Comm; /** \copydoc BackupRestoreFacility::backup() */ static void backup ( const Grid &grid, const std::string &filename ) { std::ostringstream filename_str; filename_str << filename << grid.comm().rank(); std::ofstream file( filename_str.str() ); if( file ) { backup(grid,file); file.close(); } else std::cerr << "ERROR: BackupRestoreFacility::backup: couldn't open file `" << filename_str.str() << "'" << std::endl; } /** \copydoc BackupRestoreFacility::backup() */ static void backup ( const Grid &grid, std::ostream &stream ) { stream << "YaspGrid BackupRestore Format Version: " << YASPGRID_BACKUPRESTORE_FORMAT_VERSION << std::endl; stream << "Torus structure: "; for (int i=0; ikeepOverlap ? "1" : "0") << " "; stream << std::endl; stream << "Coarse Size: "; for (int i=0; icoords.print(stream); } /** * \copydoc Dune::BackupRestoreFacility::restore() * \param comm Communication object. */ static Grid *restore (const std::string &filename, Comm comm = Comm()) { std::ostringstream filename_str; filename_str << filename; filename_str << comm.rank(); std::ifstream file(filename_str.str()); if( file ) return restore(file, comm); else { std::cerr << "ERROR: BackupRestoreFacility::restore: couldn't open file `" << filename_str.str() << "'" << std::endl; return 0; } } /** * \copydoc BackupRestoreFacility::restore() * \param comm Communication object. */ static Grid *restore (std::istream &stream, Comm comm = Comm()) { std::string input; int version; stream >> input >> input >> input >> input; stream >> version; if (version != YASPGRID_BACKUPRESTORE_FORMAT_VERSION) DUNE_THROW(Dune::Exception, "Your YaspGrid backup file is written in an outdated format!"); std::array torus_dims; stream >> input >> input; for (int i=0; i> torus_dims[i]; int refinement; stream >> input >> input; stream >> refinement; std::bitset periodic; bool b; stream >> input; for (int i=0; i> b; periodic[i] = b; } int overlap; stream >> input; stream >> overlap; std::vector physicalOverlapSize; physicalOverlapSize.resize(refinement); stream >> input; for (int i=0; i> b; physicalOverlapSize[i] = b; } std::array coarseSize; stream >> input >> input; for (int i=0; i> coarseSize[i]; std::array,dim> coords; stream >> input >> input >> input >> input; for (int d=0; d> input >> input; int size; stream >> size; stream >> input; ctype tmp; coords[d].resize(size); for (int i=0; i> tmp; coords[d][i] = tmp; } } Yasp::FixedSizePartitioning lb(torus_dims); Grid* grid = new Grid(coords, periodic, overlap, comm, coarseSize, &lb); for (int i=0; irefineOptions(physicalOverlapSize[i]); grid->globalRefine(1); } return grid; } }; } // namespace Dune #endif // #ifndef DUNE_GRID_YASPGRID_BACKUPRESTORE_HH dune-grid-2.11.0/dune/grid/yaspgrid/coordinates.hh000066400000000000000000000276741511655130300220260ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRID_COORDINATES_HH #define DUNE_GRID_YASPGRID_COORDINATES_HH #include #include #include #include /** \file * \brief This provides container classes for the coordinates to be used in YaspGrid * Upon implementation of the tensorproduct feature, the coordinate information has * been encapsulated to keep performance for the equidistant grid. Containers for * equidistant and tensorproduct grids are provided here. */ namespace Dune { /** \brief Container for equidistant coordinates in a YaspGrid * @tparam ct the coordinate type * @tparam dim the dimension of the grid */ template class EquidistantCoordinates { public: //! export the coordinate type typedef ct ctype; //! export dimension static const int dimension = dim; /** \brief default constructor */ EquidistantCoordinates() {} /** \brief construct a container with all necessary information * \param upperRight upper right corner of the domain * \param s the size (in codim 0 elements) of the grid on this processor * the size information is kept with this container, because this is the natural * way to handle this for a tensorproduct grid. */ EquidistantCoordinates(const Dune::FieldVector& upperRight, const std::array& s) : _s(s) { for (int i=0; i refine(std::bitset ovlp_low, std::bitset ovlp_up, int overlap, bool keep_ovlp) const { //determine new size and meshsize std::array news; Dune::FieldVector newUpperRight; for (int i=0; i(newUpperRight,news); } /** \brief print information on this container */ void print(std::ostream& s) const { s << "Printing equidistant coordinate information:" << std::endl; s << "Meshsize: " << _h << std::endl << "Size: " << _s << std::endl; } private: Dune::FieldVector _h; std::array _s; }; template inline std::ostream& operator<< (std::ostream& s, EquidistantCoordinates& c) { c.print(s); return s; } /** \brief Container for equidistant coordinates in a YaspGrid with non-trivial origin * @tparam ct the coordinate type * @tparam dim the dimension of the grid */ template class EquidistantOffsetCoordinates { public: //! export the coordinate type typedef ct ctype; //! export dimension static const int dimension = dim; /** \brief default constructor */ EquidistantOffsetCoordinates() {} /** \brief construct a container with all necessary information * \param lowerLeft the lower left corner of the grid * \param upperRight the upper right corner of the grid * \param s the size (in codim 0 elements) of the grid on this processor * * the size information is kept with this container, because this is the natural * way to handle this for a tensorproduct grid. */ EquidistantOffsetCoordinates(const Dune::FieldVector& lowerLeft, const Dune::FieldVector& upperRight, const std::array& s) : _origin(lowerLeft), _s(s) { for (int i=0; i refine(std::bitset ovlp_low, std::bitset ovlp_up, int overlap, bool keep_ovlp) const { //determine new size and meshsize std::array news; Dune::FieldVector newUpperRight; for (int i=0; i(_origin,newUpperRight,news); } /** \brief print information on this container */ void print(std::ostream& s) const { s << "Printing equidistant coordinate information:" << std::endl; s << "Meshsize: " << _h << std::endl << "Size: " << _s << std::endl; s << "Offset to origin: " << _origin << std::endl; } private: Dune::FieldVector _origin; Dune::FieldVector _h; std::array _s; }; template inline std::ostream& operator<< (std::ostream& s, EquidistantOffsetCoordinates& c) { c.print(s); return s; } /** \brief Coordinate container for a tensor product YaspGrid * @tparam ct the coordinate type * @tparam dim the dimension of the grid */ template class TensorProductCoordinates { public: //! export the coordinate type typedef ct ctype; //! export dimension static const int dimension = dim; /** \brief the default constructor */ TensorProductCoordinates() {} /** \brief construct a container with all necessary information * \param c the array of coordinate vectors * \param offset the offset between global origin and processor origin * the size information is deduced from c. Storing offset allows for use of * global coordinates in the YaspGrid code. */ TensorProductCoordinates(const std::array,dim>& c, const std::array& offset) : _c(c),_offset(offset) {} /** \returns the meshsize in given direction at given position * \param d the direction to be used * \param i the global coordinate index where to return the meshsize */ inline ct meshsize(int d, int i) const { return _c[d][i+1-_offset[d]] - _c[d][i-_offset[d]]; } /** \returns a coordinate given a direction and an index * \param d the direction to be used * \param i the global coordinate index */ inline ct coordinate(int d, int i) const { return _c[d][i-_offset[d]]; } /** \returns the size in given direction * \param d the direction to be used */ inline int size(int d) const { return _c[d].size() - 1; } /** \returns a container that represents the same grid after one step of uniform refinement * \param ovlp_low whether we have an overlap area at the lower processor boundary * \param ovlp_up whether we have an overlap area at the upper processor boundary * \param overlap the size of the overlap region * \param keep_ovlp the refinement option parameter to be used */ TensorProductCoordinates refine(std::bitset ovlp_low, std::bitset ovlp_up, int overlap, bool keep_ovlp) const { std::array,dim> newcoords; std::array newoffset(_offset); for (int i=0; i::const_iterator it = _c[i].begin(); typename std::vector::const_iterator end = _c[i].end()-1; typename std::vector::iterator iit = newcoords[i].begin() - 1; if (!keep_ovlp) { if (ovlp_low[i]) { it += overlap/2; if (overlap%2) *(++iit) = (*it + *(++it)) / ct(2.); } if (ovlp_up[i]) end -= overlap/2; } for (;it!=end;) { *(++iit) = *it; *(++iit) = (*it + *(++it)) / ct(2.); } if (++iit != newcoords[i].end()) *iit = *it; } return TensorProductCoordinates(newcoords, newoffset); } /** \brief print information on this container */ void print(std::ostream& s) const { s << "Printing TensorProduct Coordinate information:" << std::endl; for (int i=0; i,dim> _c; std::array _offset; }; template inline std::ostream& operator<< (std::ostream& s, TensorProductCoordinates& c) { c.print(s); return s; } namespace Yasp { template bool checkIfMonotonous(const std::array, dim>& coords) { for (std::size_t i=0; i} imagemask } bind ] def /PaintProc { pop exec fill } def currentdict end /P4 exch def /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % Polyline 30.000 slw n 3150 1125 m 5850 1125 l 5850 3150 l 3150 3150 l cp gs /PC [[1.00 1.00 1.00] [1.00 0.00 0.00]] def 15.00 15.00 sc P4 [16 0 0 -16 210.00 75.00] PATmp PATsp ef gr PATusp gs col4 s gr % Polyline 7.500 slw n 1350 765 m 1350 3780 l gs col0 s gr % Polyline n 1575 765 m 1575 3780 l gs col0 s gr % Polyline n 1800 765 m 1800 3780 l gs col0 s gr % Polyline n 2025 765 m 2025 3780 l gs col0 s gr % Polyline n 2250 765 m 2250 3780 l gs col0 s gr % Polyline n 2475 765 m 2475 3780 l gs col0 s gr % Polyline n 2700 765 m 2700 3780 l gs col0 s gr % Polyline n 2925 765 m 2925 3780 l gs col0 s gr % Polyline n 3150 765 m 3150 3780 l gs col0 s gr % Polyline n 3375 765 m 3375 3780 l gs col0 s gr % Polyline n 3600 765 m 3600 3780 l gs col0 s gr % Polyline n 3825 765 m 3825 3780 l gs col0 s gr % Polyline n 4050 765 m 4050 3780 l gs col0 s gr % Polyline n 4275 765 m 4275 3780 l gs col0 s gr % Polyline n 4500 765 m 4500 3780 l gs col0 s gr % Polyline n 4725 765 m 4725 3780 l gs col0 s gr % Polyline n 4950 765 m 4950 3780 l gs col0 s gr % Polyline n 5175 765 m 5175 3780 l gs col0 s gr % Polyline n 5400 765 m 5400 3780 l gs col0 s gr % Polyline n 5625 765 m 5625 3780 l gs col0 s gr % Polyline n 5850 765 m 5850 3780 l gs col0 s gr % Polyline n 6075 765 m 6075 3780 l gs col0 s gr % Polyline n 6300 765 m 6300 3780 l gs col0 s gr % Polyline n 6525 765 m 6525 3780 l gs col0 s gr % Polyline n 6750 765 m 6750 3780 l gs col0 s gr % Polyline n 1125 900 m 6975 900 l gs col0 s gr % Polyline n 1125 1125 m 6975 1125 l gs col0 s gr % Polyline n 1125 1350 m 6975 1350 l gs col0 s gr % Polyline n 1125 1575 m 6975 1575 l gs col0 s gr % Polyline n 1125 1800 m 6975 1800 l gs col0 s gr % Polyline n 1125 2025 m 6975 2025 l gs col0 s gr % Polyline n 1125 2250 m 6975 2250 l gs col0 s gr % Polyline n 1125 2475 m 6975 2475 l gs col0 s gr % Polyline n 1125 2700 m 6975 2700 l gs col0 s gr % Polyline n 1125 2925 m 6975 2925 l gs col0 s gr % Polyline n 1125 3150 m 6975 3150 l gs col0 s gr % Polyline n 1125 3375 m 6975 3375 l gs col0 s gr % Polyline n 1125 3600 m 6975 3600 l gs col0 s gr % Polyline n 3240 3015 m 2295 4140 l gs col0 s gr /Times-Roman ff 180.00 scf sf 3195 3960 m gs 1 -1 sc (2) col0 sh gr /Times-Roman ff 180.00 scf sf 3420 3960 m gs 1 -1 sc (3) col0 sh gr /Times-Roman ff 180.00 scf sf 3645 3960 m gs 1 -1 sc (4) col0 sh gr /Times-Roman ff 180.00 scf sf 3870 3960 m gs 1 -1 sc (5) col0 sh gr /Times-Roman ff 180.00 scf sf 4095 3960 m gs 1 -1 sc (6) col0 sh gr /Times-Roman ff 180.00 scf sf 4320 3960 m gs 1 -1 sc (7) col0 sh gr /Times-Roman ff 180.00 scf sf 4545 3960 m gs 1 -1 sc (8) col0 sh gr /Times-Roman ff 180.00 scf sf 4770 3960 m gs 1 -1 sc (9) col0 sh gr /Times-Roman ff 180.00 scf sf 4950 3960 m gs 1 -1 sc (10) col0 sh gr /Times-Roman ff 180.00 scf sf 5175 3960 m gs 1 -1 sc (11) col0 sh gr /Times-Roman ff 180.00 scf sf 5400 3960 m gs 1 -1 sc (12) col0 sh gr /Times-Roman ff 180.00 scf sf 5625 3960 m gs 1 -1 sc (13) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2430 m gs 1 -1 sc (12) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1980 m gs 1 -1 sc (14) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1755 m gs 1 -1 sc (14) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1305 m gs 1 -1 sc (16) col0 sh gr /Times-Roman ff 180.00 scf sf 990 3105 m gs 1 -1 sc (9) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2880 m gs 1 -1 sc (10) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2655 m gs 1 -1 sc (11) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2205 m gs 1 -1 sc (13) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1530 m gs 1 -1 sc (15) col0 sh gr /Times-Roman ff 180.00 scf sf 2070 4365 m gs 1 -1 sc (origin = \(2,9\)) col0 sh gr /Times-Roman ff 180.00 scf sf 3735 4365 m gs 1 -1 sc (size = \(12,9\)) col0 sh gr $F2psEnd rs end dune-grid-2.11.0/dune/grid/yaspgrid/grid.eps.license000066400000000000000000000002501511655130300222270ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/yaspgrid/grid.fig000066400000000000000000000072771511655130300206040ustar00rootroot00000000000000#FIG 3.2 Landscape Center Metric A4 100.00 Single -2 1200 2 6 1350 765 2250 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1350 765 1350 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1575 765 1575 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1800 765 1800 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2025 765 2025 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2250 765 2250 3780 -6 6 2475 765 3375 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2475 765 2475 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2700 765 2700 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2925 765 2925 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3150 765 3150 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3375 765 3375 3780 -6 6 3600 765 4500 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3600 765 3600 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3825 765 3825 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4050 765 4050 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4275 765 4275 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4500 765 4500 3780 -6 6 4725 765 5625 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4725 765 4725 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4950 765 4950 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5175 765 5175 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5400 765 5400 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5625 765 5625 3780 -6 6 5850 765 6750 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5850 765 5850 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6075 765 6075 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6300 765 6300 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6525 765 6525 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6750 765 6750 3780 -6 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 900 6975 900 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1125 6975 1125 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1350 6975 1350 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1575 6975 1575 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1800 6975 1800 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2025 6975 2025 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2250 6975 2250 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2475 6975 2475 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2700 6975 2700 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2925 6975 2925 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 3150 6975 3150 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 3375 6975 3375 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 3600 6975 3600 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3240 3015 2295 4140 2 2 0 3 4 7 52 0 44 0.000 0 0 -1 0 0 5 3150 1125 5850 1125 5850 3150 3150 3150 3150 1125 4 0 0 50 0 0 12 0.0000 2 135 90 3195 3960 2\001 4 0 0 50 0 0 12 0.0000 2 135 90 3420 3960 3\001 4 0 0 50 0 0 12 0.0000 2 135 90 3645 3960 4\001 4 0 0 50 0 0 12 0.0000 2 135 90 3870 3960 5\001 4 0 0 50 0 0 12 0.0000 2 135 90 4095 3960 6\001 4 0 0 50 0 0 12 0.0000 2 135 90 4320 3960 7\001 4 0 0 50 0 0 12 0.0000 2 135 90 4545 3960 8\001 4 0 0 50 0 0 12 0.0000 2 135 90 4770 3960 9\001 4 0 0 50 0 0 12 0.0000 2 135 180 4950 3960 10\001 4 0 0 50 0 0 12 0.0000 2 135 180 5175 3960 11\001 4 0 0 50 0 0 12 0.0000 2 135 180 5400 3960 12\001 4 0 0 50 0 0 12 0.0000 2 135 180 5625 3960 13\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2430 12\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1980 14\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1755 14\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1305 16\001 4 0 0 50 0 0 12 0.0000 2 135 90 990 3105 9\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2880 10\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2655 11\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2205 13\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1530 15\001 4 0 0 50 0 0 12 0.0000 2 180 990 2070 4365 origin = (2,9)\001 4 0 0 50 0 0 12 0.0000 2 180 975 3735 4365 size = (12,9)\001 dune-grid-2.11.0/dune/grid/yaspgrid/grid.fig.license000066400000000000000000000002501511655130300222050ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/yaspgrid/grid.png000066400000000000000000000025661511655130300206170ustar00rootroot00000000000000PNG  IHDR# k PLTE^(IDATxn8/{ y]l搓 "ǜG@ S.)ɻj)@2(0R2IʜֱΚO+a+#%*΃2r0**Fo>v]\^zG|@˯PO7onnx޿n=<ݿ޽y|mNBnۯ[ݲw⻽hq/(i( 3t$ D$d$D$<70000W2LDF”#(qaFP2. D$ D$K0qṙ\BHCIH9Ph!}$B@P"P".Vƅ\+ GZH3 c~%FJh! C~%"aȯd\+ ~0 Ź*g}-Y%SPB{a5f$3 k>[H֘\x؅ qaP2d_ATz4 P 3Jh!́B i%P Bɸ0raȯd\BܑF}iP[H̯^x. ޤYHiIX7Jyd\y*;0p2PB¶P.-P7r$\ D$ e kaP|oYK4;5HCEH U85ԕj^&7[hXePFEj(K {("5Ve_NmP+=T堸(i{f=3:mϋbPDY=9AcSQKQVeFG Œ:eU|kbZdT}]7pxx_ :gp:%\5 : #include namespace Dune { namespace Yasp { /** \defgroup YaspGridPartitioning YaspGrid Partitioning \brief Interface and implementations of different partitioning strategies for YaspGrid If you want to write your own partitioner, inherit from Yasp::Partitioning and implement the partition() method. You can also browse this file for already available useful partitioners, like Yasp::FixedSizePartitioning. \ingroup YaspGrid */ /** \brief a base class for the yaspgrid partitioning strategy */ template class Partitioning { public: using iTupel = std::array; virtual ~Partitioning() = default; virtual void partition(const iTupel&, int, iTupel&, int) const = 0; }; template class DefaultPartitioning : public Partitioning { public: using iTupel = std::array; /** \brief Distribute a structured grid across a set of processors * * \param [in] size Number of elements in each coordinate direction, for the entire grid * \param [in] P Number of processors */ void partition (const iTupel& size, int P, iTupel& dims, int overlap) const final { double opt=1E100; iTupel trydims; trydims.fill(-1); dims.fill(-1); optimize_dims(d-1,size,P,dims,trydims,opt,overlap); if (dims[0] == -1) DUNE_THROW(Dune::GridError, "Failed to find a suitable partition"); } private: void optimize_dims (int i, const iTupel& size, int P, iTupel& dims, iTupel& trydims, double &opt, int overlap ) const { if (i>0) // test all subdivisions recursively { for (int k=1; k<=P; k++) if ( P%k==0 // k divides P and ( k == 1 // no neighbors or size[i] / k >= 2*overlap // size sufficient for overlap ) ) { // P divisible by k trydims[i] = k; optimize_dims(i-1,size,P/k,dims,trydims,opt,overlap); } } else { // found a possible combination if ( P == 1 // no neighbors or size[0] / P >= 2*overlap // size sufficient for overlap ) trydims[0] = P; else return; // check for optimality double m = -1.0; for (int k=0; k0.0001) mm*=3; if ( mm > m ) m = mm; } //if (_rank==0) std::cout << "optimize_dims: " << size << " | " << trydims << " norm=" << m << std::endl; if (m class PowerDPartitioning : public Partitioning { public: typedef std::array iTupel; virtual ~PowerDPartitioning() {} void partition (const iTupel& /*size*/, int P, iTupel& dims, int /*overlap*/) const final { for (int i=1; i<=P; ++i) if (Dune::power(i, d) == P) { std::fill(dims.begin(), dims.end(),i); return; } DUNE_THROW(GridError, "Power partitioning failed: your number of processes needs to be a " << d << "-th power."); } }; /** \brief Implement partitioner that gets a fixed partitioning from an array * If the given partitioning doesn't match the number of processors, the grid should * be distributed to, an exception is thrown. */ template class FixedSizePartitioning : public Partitioning { public: FixedSizePartitioning(const std::array& dims) : _dims(dims) {} virtual ~FixedSizePartitioning() {} void partition(const std::array&, int P, std::array& dims, int /*overlap*/) const final { int prod = 1; for (int i=0; i _dims; }; /** \endgroup */ } } #endif dune-grid-2.11.0/dune/grid/yaspgrid/structuredyaspgridfactory.hh000066400000000000000000000122271511655130300250370ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRID_STRUCTUREDYASPGRIDFACTORY_HH #define DUNE_GRID_YASPGRID_STRUCTUREDYASPGRIDFACTORY_HH #include #include /** \file * \brief Specialization of the StructuredGridFactory class for YaspGrid */ namespace Dune { /** \brief Specialization of the StructuredGridFactory for YaspGrid This allows a YaspGrid to be constructed using the StructuredGridFactory just like the unstructured Grids. There are two limitations: \li YaspGrid does not support simplices \li If the lower left corner should not be at the origin, the second template parameter of Yaspgrid has to be chosen as Dune::EquidistantOffsetCoordinates. */ template class StructuredGridFactory > > { typedef YaspGrid > GridType; static const int dimworld = GridType::dimensionworld; public: /** \brief Create a structured cube grid \param lowerLeft Lower left corner of the grid \param upperRight Upper right corner of the grid \param elements Number of elements in each coordinate direction \note The default variant of YaspGrid only supports lowerLeft at the origin. Use YaspGrid > instead for non-trivial origin. */ static std::unique_ptr createCubeGrid(const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { using std::abs; for(int d = 0; d < dimworld; ++d) if(abs(lowerLeft[d]) > abs(upperRight[d])*1e-10) DUNE_THROW(GridError, className() << "::createCubeGrid(): You have to use Yaspgrid > as your" "grid type for non-trivial origin." ); // construct array of ints instead of unsigned ints std::array elem; std::copy(elements.begin(), elements.end(), elem.begin()); return std::make_unique(upperRight, elem, std::bitset(), 1); // default constructor of bitset sets to zero } /** \brief Create a structured simplex grid \note Simplices are not supported in YaspGrid, so this functions unconditionally throws a GridError. */ static std::unique_ptr createSimplexGrid(const FieldVector&, const FieldVector&, const std::array&) { DUNE_THROW(GridError, className() << "::createSimplexGrid(): Simplices are not supported " "by YaspGrid."); } }; /** \brief Specialization of the StructuredGridFactory for YaspGrid This allows a YaspGrid to be constructed using the StructuredGridFactory just like the unstructured Grids. Only limitation: limitations: \li YaspGrid does not support simplices */ template class StructuredGridFactory > > { typedef YaspGrid > GridType; static const int dimworld = GridType::dimensionworld; public: /** \brief Create a structured cube grid \param lowerLeft Lower left corner of the grid \param upperRight Upper right corner of the grid \param elements Number of elements in each coordinate direction */ static std::unique_ptr createCubeGrid(const FieldVector& lowerLeft, const FieldVector& upperRight, const std::array& elements) { // construct array of ints instead of unsigned ints std::array elem; std::copy(elements.begin(), elements.end(), elem.begin()); return std::make_unique(lowerLeft, upperRight, elem, std::bitset(), 1); // default constructor of bitset sets to zero } /** \brief Create a structured simplex grid \note Simplices are not supported in YaspGrid, so this functions unconditionally throws a GridError. */ static std::unique_ptr createSimplexGrid(const FieldVector&, const FieldVector&, const std::array&) { DUNE_THROW(GridError, className() << "::createSimplexGrid(): Simplices are not supported " "by YaspGrid."); } }; } // namespace Dune #endif dune-grid-2.11.0/dune/grid/yaspgrid/subgrid.eps000066400000000000000000000410371511655130300213300ustar00rootroot00000000000000%!PS-Adobe-2.0 EPSF-2.0 %%Title: subgrid.eps %%Creator: fig2dev Version 3.2 Patchlevel 3d %%CreationDate: Thu Jul 24 10:49:17 2003 %%For: peter@cray (Peter Bastian,,,) %%BoundingBox: 0 0 378 248 %%Magnification: 1.0000 %%EndComments /MyAppDict 100 dict dup begin def /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 248 moveto 0 0 lineto 378 0 lineto 378 248 lineto closepath clip newpath -62.4 295.4 translate 1 -1 scale % This junk string is used by the show operators /PATsstr 1 string def /PATawidthshow { % cx cy cchar rx ry string % Loop over each character in the string { % cx cy cchar rx ry char % Show the character dup % cx cy cchar rx ry char char PATsstr dup 0 4 -1 roll put % cx cy cchar rx ry char (char) false charpath % cx cy cchar rx ry char /clip load PATdraw % Move past the character (charpath modified the % current point) currentpoint % cx cy cchar rx ry char x y newpath moveto % cx cy cchar rx ry char % Reposition by cx,cy if the character in the string is cchar 3 index eq { % cx cy cchar rx ry 4 index 4 index rmoveto } if % Reposition all characters by rx ry 2 copy rmoveto % cx cy cchar rx ry } forall pop pop pop pop pop % - currentpoint newpath moveto } bind def /PATcg { 7 dict dup begin /lw currentlinewidth def /lc currentlinecap def /lj currentlinejoin def /ml currentmiterlimit def /ds [ currentdash ] def /cc [ currentrgbcolor ] def /cm matrix currentmatrix def end } bind def % PATdraw - calculates the boundaries of the object and % fills it with the current pattern /PATdraw { % proc save exch PATpcalc % proc nw nh px py 5 -1 roll exec % nw nh px py newpath PATfill % - restore } bind def % PATfill - performs the tiling for the shape /PATfill { % nw nh px py PATfill - PATDict /CurrentPattern get dup begin setfont % Set the coordinate system to Pattern Space PatternGState PATsg % Set the color for uncolored pattezns PaintType 2 eq { PATDict /PColor get PATsc } if % Create the string for showing 3 index string % nw nh px py str % Loop for each of the pattern sources 0 1 Multi 1 sub { % nw nh px py str source % Move to the starting location 3 index 3 index % nw nh px py str source px py moveto % nw nh px py str source % For multiple sources, set the appropriate color Multi 1 ne { dup PC exch get PATsc } if % Set the appropriate string for the source 0 1 7 index 1 sub { 2 index exch 2 index put } for pop % Loop over the number of vertical cells 3 index % nw nh px py str nh { % nw nh px py str currentpoint % nw nh px py str cx cy 2 index oldshow % nw nh px py str cx cy YStep add moveto % nw nh px py str } repeat % nw nh px py str } for 5 { pop } repeat end } bind def % PATkshow - kshow with the current pattezn /PATkshow { % proc string exch bind % string proc 1 index 0 get % string proc char % Loop over all but the last character in the string 0 1 4 index length 2 sub { % string proc char idx % Find the n+1th character in the string 3 index exch 1 add get % string proe char char+1 exch 2 copy % strinq proc char+1 char char+1 char % Now show the nth character PATsstr dup 0 4 -1 roll put % string proc chr+1 chr chr+1 (chr) false charpath % string proc char+1 char char+1 /clip load PATdraw % Move past the character (charpath modified the current point) currentpoint newpath moveto % Execute the user proc (should consume char and char+1) mark 3 1 roll % string proc char+1 mark char char+1 4 index exec % string proc char+1 mark... cleartomark % string proc char+1 } for % Now display the last character PATsstr dup 0 4 -1 roll put % string proc (char+1) false charpath % string proc /clip load PATdraw neewath pop pop % - } bind def % PATmp - the makepattern equivalent /PATmp { % patdict patmtx PATmp patinstance exch dup length 7 add % We will add 6 new entries plus 1 FID dict copy % Create a new dictionary begin % Matrix to install when painting the pattern TilingType PATtcalc /PatternGState PATcg def PatternGState /cm 3 -1 roll put % Check for multi pattern sources (Level 1 fast color patterns) currentdict /Multi known not { /Multi 1 def } if % Font dictionary definitions /FontType 3 def % Create a dummy encoding vector /Encoding 256 array def 3 string 0 1 255 { Encoding exch dup 3 index cvs cvn put } for pop /FontMatrix matrix def /FontBBox BBox def /BuildChar { mark 3 1 roll % mark dict char exch begin Multi 1 ne {PaintData exch get}{pop} ifelse % mark [paintdata] PaintType 2 eq Multi 1 ne or { XStep 0 FontBBox aload pop setcachedevice } { XStep 0 setcharwidth } ifelse currentdict % mark [paintdata] dict /PaintProc load % mark [paintdata] dict paintproc end gsave false PATredef exec true PATredef grestore cleartomark % - } bind def currentdict end % newdict /foo exch % /foo newlict definefont % newfont } bind def % PATpcalc - calculates the starting point and width/height % of the tile fill for the shape /PATpcalc { % - PATpcalc nw nh px py PATDict /CurrentPattern get begin gsave % Set up the coordinate system to Pattern Space % and lock down pattern PatternGState /cm get setmatrix BBox aload pop pop pop translate % Determine the bounding box of the shape pathbbox % llx lly urx ury grestore % Determine (nw, nh) the # of cells to paint width and height PatHeight div ceiling % llx lly urx qh 4 1 roll % qh llx lly urx PatWidth div ceiling % qh llx lly qw 4 1 roll % qw qh llx lly PatHeight div floor % qw qh llx ph 4 1 roll % ph qw qh llx PatWidth div floor % ph qw qh pw 4 1 roll % pw ph qw qh 2 index sub cvi abs % pw ph qs qh-ph exch 3 index sub cvi abs exch % pw ph nw=qw-pw nh=qh-ph % Determine the starting point of the pattern fill %(px, py) 4 2 roll % nw nh pw ph PatHeight mul % nw nh pw py exch % nw nh py pw PatWidth mul exch % nw nh px py end } bind def % Save the original routines so that we can use them later on /oldfill /fill load def /oldeofill /eofill load def /oldstroke /stroke load def /oldshow /show load def /oldashow /ashow load def /oldwidthshow /widthshow load def /oldawidthshow /awidthshow load def /oldkshow /kshow load def % These defs are necessary so that subsequent procs don't bind in % the originals /fill { oldfill } bind def /eofill { oldeofill } bind def /stroke { oldstroke } bind def /show { oldshow } bind def /ashow { oldashow } bind def /widthshow { oldwidthshow } bind def /awidthshow { oldawidthshow } bind def /kshow { oldkshow } bind def /PATredef { MyAppDict begin { /fill { /clip load PATdraw newpath } bind def /eofill { /eoclip load PATdraw newpath } bind def /stroke { PATstroke } bind def /show { 0 0 null 0 0 6 -1 roll PATawidthshow } bind def /ashow { 0 0 null 6 3 roll PATawidthshow } bind def /widthshow { 0 0 3 -1 roll PATawidthshow } bind def /awidthshow { PATawidthshow } bind def /kshow { PATkshow } bind def } { /fill { oldfill } bind def /eofill { oldeofill } bind def /stroke { oldstroke } bind def /show { oldshow } bind def /ashow { oldashow } bind def /widthshow { oldwidthshow } bind def /awidthshow { oldawidthshow } bind def /kshow { oldkshow } bind def } ifelse end } bind def false PATredef % Conditionally define setcmykcolor if not available /setcmykcolor where { pop } { /setcmykcolor { 1 sub 4 1 roll 3 { 3 index add neg dup 0 lt { pop 0 } if 3 1 roll } repeat setrgbcolor - pop } bind def } ifelse /PATsc { % colorarray aload length % c1 ... cn length dup 1 eq { pop setgray } { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse } bind def /PATsg { % dict begin lw setlinewidth lc setlinecap lj setlinejoin ml setmiterlimit ds aload pop setdash cc aload pop setrgbcolor cm setmatrix end } bind def /PATDict 3 dict def /PATsp { true PATredef PATDict begin /CurrentPattern exch def % If it's an uncolored pattern, save the color CurrentPattern /PaintType get 2 eq { /PColor exch def } if /CColor [ currentrgbcolor ] def end } bind def % PATstroke - stroke with the current pattern /PATstroke { countdictstack save mark { currentpoint strokepath moveto PATpcalc % proc nw nh px py clip newpath PATfill } stopped { (*** PATstroke Warning: Path is too complex, stroking with gray) = cleartomark restore countdictstack exch sub dup 0 gt { { end } repeat } { pop } ifelse gsave 0.5 setgray oldstroke grestore } { pop restore pop } ifelse newpath } bind def /PATtcalc { % modmtx tilingtype PATtcalc tilematrix % Note: tiling types 2 and 3 are not supported gsave exch concat % tilingtype matrix currentmatrix exch % cmtx tilingtype % Tiling type 1 and 3: constant spacing 2 ne { % Distort the pattern so that it occupies % an integral number of device pixels dup 4 get exch dup 5 get exch % tx ty cmtx XStep 0 dtransform round exch round exch % tx ty cmtx dx.x dx.y XStep div exch XStep div exch % tx ty cmtx a b 0 YStep dtransform round exch round exch % tx ty cmtx a b dy.x dy.y YStep div exch YStep div exch % tx ty cmtx a b c d 7 -3 roll astore % { a b c d tx ty } } if grestore } bind def /PATusp { false PATredef PATDict begin CColor PATsc end } bind def % left45 11 dict begin /PaintType 1 def /PatternType 1 def /TilingType 1 def /BBox [0 0 1 1] def /XStep 1 def /YStep 1 def /PatWidth 1 def /PatHeight 1 def /Multi 2 def /PaintData [ { clippath } bind { 20 20 true [ 20 0 0 -20 0 20 ] {<8020004010002008001004000802000401000200 8001004000802000401080200040100020080010 0400080200040100020080010040008020004010>} imagemask } bind ] def /PaintProc { pop exec fill } def currentdict end /P4 exch def /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % Polyline 30.000 slw n 3150 1125 m 5850 1125 l 5850 3150 l 3150 3150 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 1.00]] def 15.00 15.00 sc P4 [16 0 0 -16 210.00 75.00] PATmp PATsp ef gr PATusp gs col1 s gr % Polyline n 4275 1350 m 5400 1350 l 5400 2700 l 4275 2700 l cp gs /PC [[1.00 1.00 1.00] [1.00 0.00 0.00]] def 15.00 15.00 sc P4 [16 0 0 -16 285.00 90.00] PATmp PATsp ef gr PATusp gs col4 s gr % Polyline 7.500 slw n 1350 765 m 1350 3780 l gs col0 s gr % Polyline n 1575 765 m 1575 3780 l gs col0 s gr % Polyline n 1800 765 m 1800 3780 l gs col0 s gr % Polyline n 2025 765 m 2025 3780 l gs col0 s gr % Polyline n 2250 765 m 2250 3780 l gs col0 s gr % Polyline n 2475 765 m 2475 3780 l gs col0 s gr % Polyline n 2700 765 m 2700 3780 l gs col0 s gr % Polyline n 2925 765 m 2925 3780 l gs col0 s gr % Polyline n 3150 765 m 3150 3780 l gs col0 s gr % Polyline n 3375 765 m 3375 3780 l gs col0 s gr % Polyline n 3600 765 m 3600 3780 l gs col0 s gr % Polyline n 3825 765 m 3825 3780 l gs col0 s gr % Polyline n 4050 765 m 4050 3780 l gs col0 s gr % Polyline n 4275 765 m 4275 3780 l gs col0 s gr % Polyline n 4500 765 m 4500 3780 l gs col0 s gr % Polyline n 4725 765 m 4725 3780 l gs col0 s gr % Polyline n 4950 765 m 4950 3780 l gs col0 s gr % Polyline n 5175 765 m 5175 3780 l gs col0 s gr % Polyline n 5400 765 m 5400 3780 l gs col0 s gr % Polyline n 5625 765 m 5625 3780 l gs col0 s gr % Polyline n 5850 765 m 5850 3780 l gs col0 s gr % Polyline n 6075 765 m 6075 3780 l gs col0 s gr % Polyline n 6300 765 m 6300 3780 l gs col0 s gr % Polyline n 6525 765 m 6525 3780 l gs col0 s gr % Polyline n 6750 765 m 6750 3780 l gs col0 s gr % Polyline n 1125 900 m 6975 900 l gs col0 s gr % Polyline n 1125 1125 m 6975 1125 l gs col0 s gr % Polyline n 1125 1350 m 6975 1350 l gs col0 s gr % Polyline n 1125 1575 m 6975 1575 l gs col0 s gr % Polyline n 1125 1800 m 6975 1800 l gs col0 s gr % Polyline n 1125 2025 m 6975 2025 l gs col0 s gr % Polyline n 1125 2250 m 6975 2250 l gs col0 s gr % Polyline n 1125 2475 m 6975 2475 l gs col0 s gr % Polyline n 1125 2700 m 6975 2700 l gs col0 s gr % Polyline n 1125 2925 m 6975 2925 l gs col0 s gr % Polyline n 1125 3150 m 6975 3150 l gs col0 s gr % Polyline n 1125 3375 m 6975 3375 l gs col0 s gr % Polyline n 1125 3600 m 6975 3600 l gs col0 s gr % Polyline gs clippath 3214 3038 m 3238 3093 l 3376 3032 l 3255 3053 l 3352 2977 l cp eoclip n 4365 2565 m 3240 3060 l gs col0 s gr gr % arrowhead n 3352 2977 m 3255 3053 l 3376 3032 l col0 s /Times-Roman ff 180.00 scf sf 3195 3960 m gs 1 -1 sc (2) col0 sh gr /Times-Roman ff 180.00 scf sf 3420 3960 m gs 1 -1 sc (3) col0 sh gr /Times-Roman ff 180.00 scf sf 3645 3960 m gs 1 -1 sc (4) col0 sh gr /Times-Roman ff 180.00 scf sf 3870 3960 m gs 1 -1 sc (5) col0 sh gr /Times-Roman ff 180.00 scf sf 4095 3960 m gs 1 -1 sc (6) col0 sh gr /Times-Roman ff 180.00 scf sf 4320 3960 m gs 1 -1 sc (7) col0 sh gr /Times-Roman ff 180.00 scf sf 4545 3960 m gs 1 -1 sc (8) col0 sh gr /Times-Roman ff 180.00 scf sf 4770 3960 m gs 1 -1 sc (9) col0 sh gr /Times-Roman ff 180.00 scf sf 4950 3960 m gs 1 -1 sc (10) col0 sh gr /Times-Roman ff 180.00 scf sf 5175 3960 m gs 1 -1 sc (11) col0 sh gr /Times-Roman ff 180.00 scf sf 5400 3960 m gs 1 -1 sc (12) col0 sh gr /Times-Roman ff 180.00 scf sf 5625 3960 m gs 1 -1 sc (13) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2430 m gs 1 -1 sc (12) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1980 m gs 1 -1 sc (14) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1755 m gs 1 -1 sc (14) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1305 m gs 1 -1 sc (16) col0 sh gr /Times-Roman ff 180.00 scf sf 990 3105 m gs 1 -1 sc (9) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2880 m gs 1 -1 sc (10) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2655 m gs 1 -1 sc (11) col0 sh gr /Times-Roman ff 180.00 scf sf 990 2205 m gs 1 -1 sc (13) col0 sh gr /Times-Roman ff 180.00 scf sf 990 1530 m gs 1 -1 sc (15) col0 sh gr /Times-Roman ff 180.00 scf sf 5130 4410 m gs 1 -1 sc (offset = \(5,2\)) col0 sh gr /Times-Roman ff 180.00 scf sf 5130 4635 m gs 1 -1 sc (supersize = \(12,9\)) col0 sh gr /Times-Roman ff 180.00 scf sf 5130 4185 m gs 1 -1 sc (size = \(5,6\)) col0 sh gr /Times-Roman ff 180.00 scf sf 3690 4185 m gs 1 -1 sc (origin = \(7,11\)) col0 sh gr $F2psEnd rs end dune-grid-2.11.0/dune/grid/yaspgrid/subgrid.eps.license000066400000000000000000000002501511655130300227410ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/yaspgrid/subgrid.fig000066400000000000000000000076641511655130300213160ustar00rootroot00000000000000#FIG 3.2 Landscape Center Metric A4 100.00 Single -2 1200 2 6 1350 765 2250 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1350 765 1350 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1575 765 1575 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1800 765 1800 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2025 765 2025 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2250 765 2250 3780 -6 6 2475 765 3375 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2475 765 2475 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2700 765 2700 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 2925 765 2925 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3150 765 3150 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3375 765 3375 3780 -6 6 3600 765 4500 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3600 765 3600 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 3825 765 3825 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4050 765 4050 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4275 765 4275 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4500 765 4500 3780 -6 6 4725 765 5625 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4725 765 4725 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 4950 765 4950 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5175 765 5175 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5400 765 5400 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5625 765 5625 3780 -6 6 5850 765 6750 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 5850 765 5850 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6075 765 6075 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6300 765 6300 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6525 765 6525 3780 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 6750 765 6750 3780 -6 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 900 6975 900 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1125 6975 1125 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1350 6975 1350 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1575 6975 1575 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 1800 6975 1800 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2025 6975 2025 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2250 6975 2250 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2475 6975 2475 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2700 6975 2700 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 2925 6975 2925 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 3150 6975 3150 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 3375 6975 3375 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 1125 3600 6975 3600 2 2 0 3 1 7 52 0 44 0.000 0 0 -1 0 0 5 3150 1125 5850 1125 5850 3150 3150 3150 3150 1125 2 2 0 3 4 7 51 0 44 0.000 0 0 -1 0 0 5 4275 1350 5400 1350 5400 2700 4275 2700 4275 1350 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4365 2565 3240 3060 4 0 0 50 0 0 12 0.0000 2 135 90 3195 3960 2\001 4 0 0 50 0 0 12 0.0000 2 135 90 3420 3960 3\001 4 0 0 50 0 0 12 0.0000 2 135 90 3645 3960 4\001 4 0 0 50 0 0 12 0.0000 2 135 90 3870 3960 5\001 4 0 0 50 0 0 12 0.0000 2 135 90 4095 3960 6\001 4 0 0 50 0 0 12 0.0000 2 135 90 4320 3960 7\001 4 0 0 50 0 0 12 0.0000 2 135 90 4545 3960 8\001 4 0 0 50 0 0 12 0.0000 2 135 90 4770 3960 9\001 4 0 0 50 0 0 12 0.0000 2 135 180 4950 3960 10\001 4 0 0 50 0 0 12 0.0000 2 135 180 5175 3960 11\001 4 0 0 50 0 0 12 0.0000 2 135 180 5400 3960 12\001 4 0 0 50 0 0 12 0.0000 2 135 180 5625 3960 13\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2430 12\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1980 14\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1755 14\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1305 16\001 4 0 0 50 0 0 12 0.0000 2 135 90 990 3105 9\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2880 10\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2655 11\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 2205 13\001 4 0 0 50 0 0 12 0.0000 2 135 180 990 1530 15\001 4 0 0 50 0 0 12 0.0000 2 180 1020 5130 4410 offset = (5,2)\001 4 0 0 50 0 0 12 0.0000 2 180 1395 5130 4635 supersize = (12,9)\001 4 0 0 50 0 0 12 0.0000 2 180 885 5130 4185 size = (5,6)\001 4 0 0 50 0 0 12 0.0000 2 180 1080 3690 4185 origin = (7,11)\001 dune-grid-2.11.0/dune/grid/yaspgrid/subgrid.fig.license000066400000000000000000000002501511655130300227170ustar00rootroot00000000000000SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune-grid-2.11.0/dune/grid/yaspgrid/subgrid.png000066400000000000000000000033641511655130300213260ustar00rootroot00000000000000PNG  IHDR=vH PLTE#IDATx1o6U \iz**; -!m"Sੀ* ixg?vCFGItw'UrȀ;G_'ydVIQW*TUVꜷfգ<ʣArУ<ʣ<ʣ^p8v>nUT(>zqw2CfxO+* cPơh$B9$|0X#_9$|jqi ꑼ>|zW7W%B9$|>nN?>>W%B9$|nE"‾Z a_9$|`E"‾/a8$|`E$!/a"P X.,(>e 3AMI\(CVD&=^zq( }0E"aD+ P$ơH$CHH"P4f1E(cLNq ]8+o 1 cP4FH$34DҘF(Q&B(!raTTƙH$Dn 1s.0nh9 5HK ƅ1}[¡­BM8T\c~]pᕿ@.<Dž9E Y${$D΅W~.V,EҘ)h/P(],Å_Q8%akk.&٧$o{~@zHxzYTJ]Q nm7mc=Ҹq`I{[N¢={Q(K›F&.~o5H/C9Ԋުu*$1*Ϻ1U.js@2 oImsu9 ?s)>TIJD6}RIPAPQ(ǠhN*EI%g?TTdm޿QQUzGyGy>4GyGyT'Q-**(YU6KBY5TxLb ݡA /2Dz?uQ&""6(ar7R@2D9N i"1(B ,ҵ(stdw(Yt[PxL (^e L*̳;(PrYqbZS!Իj5W@$\a-PCJ<~_d*y6T)h2 ŸLWLD(AD:sTwRn$CIT (9Ki@"B@bJl dgeJ!%5 ؅ŊGH/WE }Ỻ~eq4 ϟ8(Qr #include #include #include #include #include #if HAVE_MPI #include #endif #include #include #include #include "partitioning.hh" /** \file * \brief This file provides the infrastructure for toroidal communication in YaspGrid. */ namespace Dune { /*! Torus provides all the functionality to handle a toroidal communication structure: - Map a set of processes (given by an MPI communicator) to a torus of dimension d. The "optimal" torus dimensions are determined by a coarse mesh. The maximum side length is minimized. - Provide lists of neighboring processes and a method for nearest neighbor exchange using asynchronous communication with MPI. The periodic case is handled where one process might have to exchange several messages with the same process. (Logically, a process has always \f$3^d-1\f$ neighbors, but several of these logical neighbors might be identical) - Provide means to partition a grid to the torus. */ template class Torus { public: //! type used to pass tupels in and out typedef std::array iTupel; private: struct CommPartner { int rank; iTupel delta; int index; }; struct CommTask { int rank; // process to send to / receive from int size; // size of buffer void *buffer; // buffer to send / receive }; public: //! constructor making uninitialized object Torus () {} //! make partitioner from communicator and coarse mesh size Torus (Communication comm, int tag, iTupel size, int overlap, const Yasp::Partitioning* partitioner) : _comm(comm), _tag(tag) { // determine dimensions partitioner->partition(size, _comm.size(), _dims, overlap); // compute increments for lexicographic ordering int inc = 1; for (int i=0; i=0; i--) if (c[i]<0 || c[i]>=_dims[i]) return false; return true; } //! map rank to coordinate in torus using lexicographic ordering iTupel rank_to_coord (int rank) const { iTupel coord; rank = rank%_comm.size(); for (int i=d-1; i>=0; i--) { coord[i] = rank/_increment[i]; rank = rank%_increment[i]; } return coord; } //! map coordinate in torus to rank using lexicographic ordering int coord_to_rank (iTupel coord) const { for (int i=0; i1 && coord[i]==_dims[i]-1) c += power; power *= 2; } return c; } //! assign color to given rank int color (int rank) const { return color(rank_to_coord(rank)); } //! return the number of neighbors, which is \f$3^d-1\f$ int neighbors () const { int n=1; for (int i=0; i periodic) const { iTupel coord = rank_to_coord(_comm.rank()); // my own coordinate with 0 <= c_i < dims_i for (int i=0; i no neighbor if (coord[i]==0 && periodic[i]==false) return false; } if (delta[i]>0) { // if I am on the boundary and domain is not periodic => no neighbor if (coord[i]==_dims[i]-1 && periodic[i]==false) return false; } } return true; } /** \brief partition the given grid onto the torus and return the piece of the process with given rank; returns load imbalance * @param rank rank of our processor * @param origin_in global origin * @param size_in global size * @param origin_out origin of this processors interior * @param size_out size of this processors interior */ double partition (int rank, iTupel origin_in, iTupel size_in, iTupel& origin_out, iTupel& size_out) const { iTupel coord = rank_to_coord(rank); double maxsize = 1; double sz = 1; // make a tensor product partition for (int i=0; i::const_iterator iter) { i = iter; } //! return rank of neighboring process int rank () const { return i->rank; } //! return distance vector iTupel delta () const { return i->delta; } //! return index in proclist int index () const { return i->index; } //! return 1-norm of distance vector int distance () const { int dist = 0; iTupel delta=i->delta; for (int j=0; j::const_iterator i; }; //! first process in send list ProcListIterator sendbegin () const { return ProcListIterator(_sendlist.begin()); } //! end of send list ProcListIterator sendend () const { return ProcListIterator(_sendlist.end()); } //! first process in receive list ProcListIterator recvbegin () const { return ProcListIterator(_recvlist.begin()); } //! last process in receive list ProcListIterator recvend () const { return ProcListIterator(_recvlist.end()); } //! store a send request; buffers are sent in order; handles also local requests with memcpy void send (int rank, void* buffer, int size) const { CommTask task; task.rank = rank; task.buffer = buffer; task.size = size; if (rank!=_comm.rank()) _sendrequests.push_back(task); else _localsendrequests.push_back(task); } //! store a receive request; buffers are received in order; handles also local requests with memcpy void recv (int rank, void* buffer, int size) const { CommTask task; task.rank = rank; task.buffer = buffer; task.size = size; if (rank!=_comm.rank()) _recvrequests.push_back(task); else _localrecvrequests.push_back(task); } //! exchange messages stored in request buffers; clear request buffers afterwards void exchange () const { // handle local requests first if (_localsendrequests.size()!=_localrecvrequests.size()) { std::cout << "[" << rank() << "]: ERROR: local sends/receives do not match in exchange!" << std::endl; return; } for (unsigned int i=0; i<_localsendrequests.size(); i++) { if (_localsendrequests[i].size!=_localrecvrequests[i].size) { std::cout << "[" << rank() << "]: ERROR: size in local sends/receive does not match in exchange!" << std::endl; return; } memcpy(_localrecvrequests[i].buffer,_localsendrequests[i].buffer,_localsendrequests[i].size); } _localsendrequests.clear(); _localrecvrequests.clear(); #if HAVE_MPI // handle foreign requests std::vector requests(_sendrequests.size() + _recvrequests.size()); MPI_Request* req = requests.data(); // issue sends to foreign processes for (unsigned int i=0; i<_sendrequests.size(); i++) if (_sendrequests[i].rank!=rank()) { // std::cout << "[" << rank() << "]" << " send " << _sendrequests[i].size << " bytes " // << "to " << _sendrequests[i].rank << " p=" << _sendrequests[i].buffer << std::endl; MPI_Isend(_sendrequests[i].buffer, _sendrequests[i].size, MPI_BYTE, _sendrequests[i].rank, _tag, _comm, req++); } // issue receives from foreign processes for (unsigned int i=0; i<_recvrequests.size(); i++) if (_recvrequests[i].rank!=rank()) { // std::cout << "[" << rank() << "]" << " recv " << _recvrequests[i].size << " bytes " // << "fm " << _recvrequests[i].rank << " p=" << _recvrequests[i].buffer << std::endl; MPI_Irecv(_recvrequests[i].buffer, _recvrequests[i].size, MPI_BYTE, _recvrequests[i].rank, _tag, _comm, req++); } // Wait for communication to complete MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE); // clear request buffers _sendrequests.clear(); _recvrequests.clear(); #endif } //! global max double global_max (double x) const { double res = 0.0; _comm.template allreduce,double>(&x, &res, 1); return res; } //! print contents of torus object void print (std::ostream& s) const { s << "[" << rank() << "]: Torus " << procs() << " processor(s) arranged as " << dims() << std::endl; for (ProcListIterator i=sendbegin(); i!=sendend(); ++i) { s << "[" << rank() << "]: send to " << "rank=" << i.rank() << " index=" << i.index() << " delta=" << i.delta() << " dist=" << i.distance() << std::endl; } for (ProcListIterator i=recvbegin(); i!=recvend(); ++i) { s << "[" << rank() << "]: recv from " << "rank=" << i.rank() << " index=" << i.index() << " delta=" << i.delta() << " dist=" << i.distance() << std::endl; } } private: void proclists () { // compile the full neighbor list CommPartner cp; iTupel delta; std::fill(delta.begin(), delta.end(), -1); bool ready = false; iTupel me, nb; me = rank_to_coord(_comm.rank()); int index = 0; int last = neighbors()-1; while (!ready) { // find neighbors coordinates for (int i=0; i _sendlist; std::deque _recvlist; mutable std::vector _sendrequests; mutable std::vector _recvrequests; mutable std::vector _localsendrequests; mutable std::vector _localrecvrequests; }; //! Output operator for Torus template inline std::ostream& operator<< (std::ostream& s, const Torus & t) { t.print(s); return s; } } #endif dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridentity.hh000066400000000000000000000673671511655130300225760ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDENTITY_HH #define DUNE_GRID_YASPGRIDENTITY_HH #include #include /** \file * \brief the YaspEntity class and its specializations * YaspEntity realizes the concept a mesh entity. We have specializations for - codim==0 (elements), because they have an extended interface - codim==dim (vertices), because they use a special constructor of the AxisAlignedCubeGeometry and are the only entities in a globally refined grid, that may also exist on another level. The general version implements all other codimensions. */ //======================================================================== namespace Dune { namespace Yasp { #ifndef DOXYGEN // table for quick evaluation of binomial coefficients template struct BinomialTable { // evaluation - note that in general d!=n, n is only the // maximum value of d (in our case dimworld) static constexpr int evaluate(int d, int c) { return _values[_offsets[d] + c]; } private: // prevent construction BinomialTable() = delete; // compute binomial(r, c) and advance row `r` and column `c` static constexpr int nextValue(int& r, int& c) { const auto result = Dune::binomial(r, c); c += 1; if (c > r) { r += 1; c = 0; } return result; } template static constexpr std::array computeValues(std::index_sequence) { int r = 0, c = 0; return {{ ((void)I, nextValue(r, c))... }}; } template static constexpr std::array computeOffsets(std::index_sequence) { return {{ (I*(I+1)/2)... }}; } static constexpr std::array _values = computeValues(std::make_index_sequence<(n+1)*(n+2)/2>{}); static constexpr std::array _offsets = computeOffsets(std::make_index_sequence{}); }; /** \returns number of subentities of given codim in a cube of dimension dim * \tparam dimworld the maximum dimension the table holds entries for * \param d the dimension of the cube * \param c the codimension we are interested in * That number is d choose c times 2^c. */ template constexpr int subEnt(int d, int c) { return (d < c ? 0 : BinomialTable::evaluate(d,c) << c); } // Make a table mapping all subentities of a codim 0 entity to a value. // F is the functor to be evaluated. template struct EntityShiftTable { typedef std::bitset value_type; static value_type evaluate(int i, int codim) { return {_values[_offsets[codim] + i]}; } private: // prevent construction EntityShiftTable() = delete; // compute offset of codimension `codim` entities and advance `offset` static constexpr int nextOffset(int& offset, int codim) { if (codim == 0) { offset = 0; return 0; } offset += subEnt(dim, codim-1); return offset; } template static constexpr std::array computeOffsets(std::index_sequence) { int offset = 0; return {{ (nextOffset(offset, I))... }}; } // compute shift table entry for (`codim`, `i`) and advance `codim`, `i` static constexpr unsigned char nextValue(int& codim, int& i) { const auto result = F::evaluate(i, codim); i += 1; if (i >= subEnt(dim, codim)) { codim += 1; i = 0; } return result; } template static constexpr std::array computeValues(std::index_sequence) { int codim = 0, i = 0; return {{ ((void)I, nextValue(codim, i))... }}; } static constexpr std::array _offsets = computeOffsets(std::make_index_sequence{}); static constexpr std::array _values = computeValues(std::make_index_sequence{}); }; // functor for doing the actual entity shift calculation template struct calculate_entity_shift { static constexpr unsigned long long evaluate(int index, int cc) { auto result = 0ull; for (int d = dim; d>0; d--) { if (cc == d) return result; if (index < subEnt(d-1,cc)) result |= 1ull << (d-1); else { index = (index - subEnt(d-1, cc)) % subEnt(d-1,cc-1); cc--; } } return result; } }; /** \returns a shift vector as used by YGridComponent * \param index subentity index * \param cc the codimension * This maps a subentity, given by its codimension and index, to * a bitset which specifies the unit vectors which span the entity. * The implementation unravels the construction of the generic * reference elements. */ template std::bitset entityShift(int index, int cc) { return EntityShiftTable,dim>::evaluate(index,cc); } // functor for doing the actual entity move calculation template struct calculate_entity_move { static constexpr unsigned long long evaluate(int index, int cc) { auto result = 0ull; for (int d = dim; d>0; d--) { if (d == cc) { // result[d-1] = index & (1<<(d-1)); result &= ~(1ull << (d-1)); result |= index & (1ull << (d-1)); index &= ~(1<<(d-1)); } if (index >= subEnt(d-1,cc)) { if ((index - subEnt(d-1,cc)) / subEnt(d-1,cc-1) == 1) { result |= 1ull << (d-1); } index = (index - subEnt(d-1, cc)) % subEnt(d-1,cc-1); cc--; } } return result; } }; /** \returns a bitset telling in which direction to move a cell to get * the cell a given entity is living on. * \param index subentity index * \param cc the codimension * In Yasp, all entities live on a cell. Its those that lie on the lower * / left / ... part of the cell. */ template std::bitset entityMove(int index, int cc) { return EntityShiftTable,dim>::evaluate(index,cc); } #endif //DOXYGEN } // namespace Yasp. template class YaspEntity : public EntityDefaultImplementation { template friend class YaspLevelIterator; public: typedef typename GridImp::ctype ctype; typedef typename GridImp::template Codim::Geometry Geometry; typedef typename GridImp::Traits::template Codim::GeometryImpl GeometryImpl; typedef typename GridImp::template Codim::EntitySeed EntitySeed; //! level of this element int level () const { return _g->level(); } /** \brief Return the entity seed which contains sufficient information * to generate the entity again and uses as little memory as possible */ EntitySeed seed() const { return EntitySeed(YaspEntitySeed(_g->level(), _it.coord(), _it.which())); } //! geometry of this entity Geometry geometry () const { GeometryImpl _geometry(_it.lowerleft(),_it.upperright(),_it.shift()); return Geometry(_geometry); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ constexpr GeometryType type () const { return GeometryTypes::cube(Geometry::mydimension); } /*! Return number of subentities with codimension cc. * * That number is (dim over (dim-codim)) times 2^codim */ unsigned int subEntities (unsigned int cc) const { return Dune::Yasp::subEnt(dim-codim,cc-codim); } //! return partition type attribute PartitionType partitionType () const { if (_g->interior[codim].inside(_it.coord(),_it.shift())) return InteriorEntity; if (_g->interiorborder[codim].inside(_it.coord(),_it.shift())) return BorderEntity; if (_g->overlap[codim].inside(_it.coord(),_it.shift())) return OverlapEntity; if (_g->overlapfront[codim].inside(_it.coord(),_it.shift())) return FrontEntity; return GhostEntity; } typedef typename GridImp::YGridLevelIterator YGLI; typedef typename GridImp::YGrid::Iterator I; YaspEntity () {} YaspEntity (const YGLI& g, const I& it) : _it(it), _g(g) {} YaspEntity (YGLI&& g, const I&& it) : _it(std::move(it)), _g(std::move(g)) {} //! Return true when two iterators over the same grid are equal (!). bool equals (const YaspEntity& e) const { return _it == e._it && _g == e._g; } // IndexSets needs access to the private index methods friend class Dune::YaspIndexSet; friend class Dune::YaspIndexSet; friend class Dune::YaspGlobalIdSet; typedef typename GridImp::PersistentIndexType PersistentIndexType; //! globally unique, persistent index PersistentIndexType persistentIndex () const { // get size of global grid (in elements) std::array size; for (int i=0; img->levelSize(_g->level(), i); if (!_it.shift(i)) size[i]++; } // encode codim PersistentIndexType id(_it.shift().to_ulong()); // encode level id = id << yaspgrid_level_bits; id = id+PersistentIndexType(_g->level()); // encode coordinates for (int i=dim-1; i>=0; i--) { id = id << yaspgrid_dim_bits; id = id+PersistentIndexType(_it.coord(i)); } return id; } //! consecutive, codim-wise, level-wise index int compressedIndex () const { return _it.superindex(); } //! subentity compressed index int subCompressedIndex (int i, unsigned int cc) const { // get the shift of the entity and the subentity // the subentity shift is only available in the space spanned by the entity std::bitset subent_shift = Dune::Yasp::entityShift(i,cc-codim); std::bitset subent_move = Dune::Yasp::entityMove(i,cc-codim); std::bitset shift = _it.shift(); std::array coord = _it.coord(); for (int j=0, k=0; joverlapfront[cc].shiftmapping(shift); return _g->overlapfront[cc].superindex(coord,which); } public: const I& transformingsubiterator() const { return _it; } const YGLI& gridlevel() const { return _g; } I& transformingsubiterator() { return _it; } YGLI& gridlevel() { return _g; } const GridImp * yaspgrid() const { return _g->mg; } protected: I _it = {}; // position in the grid level YGLI _g = {}; // access to grid level }; // specialization for codim=0 template class YaspEntity<0,dim,GridImp> : public EntityDefaultImplementation <0,dim,GridImp,YaspEntity> { constexpr static int dimworld = GridImp::dimensionworld; typedef typename GridImp::Traits::template Codim< 0 >::GeometryImpl GeometryImpl; template friend class YaspLevelIterator; template friend class YaspHierarchicIterator; public: typedef typename GridImp::ctype ctype; typedef typename GridImp::YGridLevelIterator YGLI; typedef typename GridImp::YGrid::Iterator I; typedef typename GridImp::template Codim< 0 >::Geometry Geometry; typedef typename GridImp::template Codim< 0 >::LocalGeometry LocalGeometry; template struct Codim { typedef typename GridImp::template Codim::Entity Entity; }; typedef typename GridImp::template Codim<0>::Entity Entity; typedef typename GridImp::template Codim<0>::EntitySeed EntitySeed; typedef typename GridImp::LevelIntersectionIterator IntersectionIterator; typedef typename GridImp::LevelIntersectionIterator LevelIntersectionIterator; typedef typename GridImp::LeafIntersectionIterator LeafIntersectionIterator; typedef typename GridImp::HierarchicIterator HierarchicIterator; //! define the type used for persistent indices typedef typename GridImp::PersistentIndexType PersistentIndexType; //! define type used for coordinates in grid module typedef typename GridImp::YGrid::iTupel iTupel; // constructor YaspEntity () {} YaspEntity (const YGLI& g, const I& it) : _it(it), _g(g) {} YaspEntity (const YGLI& g, I&& it) : _it(std::move(it)), _g(g) {} YaspEntity (YGLI&& g, I&& it) : _it(std::move(it)), _g(std::move(g)) {} //! Return true when two iterators over the same grid are equal (!). bool equals (const YaspEntity& e) const { return _it == e._it && _g == e._g; } //! level of this element int level () const { return _g->level(); } /** \brief Return the entity seed which contains sufficient information * to generate the entity again and uses as little memory as possible */ EntitySeed seed () const { return EntitySeed(YaspEntitySeed<0,GridImp>(_g->level(), _it.coord())); } //! return partition type attribute PartitionType partitionType () const { if (_g->interior[0].inside(_it.coord(),_it.shift())) return InteriorEntity; if (_g->overlap[0].inside(_it.coord(),_it.shift())) return OverlapEntity; DUNE_THROW(GridError, "Impossible GhostEntity"); return GhostEntity; } //! geometry of this entity Geometry geometry () const { // the element geometry auto ll = _it.lowerleft(); auto ur = _it.upperright(); // If on periodic overlap, transform coordinates by domain size for (int i=0; img->isPeriodic(i)) { int coord = transformingsubiterator().coord(i); if (coord < 0) { auto size = _g->mg->domainSize()[i]; ll[i] += size; ur[i] += size; } else if (coord + 1 > gridlevel()->mg->levelSize(gridlevel()->level(),i)) { auto size = _g->mg->domainSize()[i]; ll[i] -= size; ur[i] -= size; } } } GeometryImpl _geometry(ll,ur); return Geometry( _geometry ); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ constexpr GeometryType type () const { return GeometryTypes::cube(Geometry::mydimension); } /*! Return number of subentities with codimension cc. * * That number is (dim over (dim-codim)) times 2^codim */ template int count () const { return Dune::Yasp::subEnt(dim,cc); } /*! Return number of subentities with codimension cc. * * That number is (dim over (dim-codim)) times 2^codim */ unsigned int subEntities (unsigned int codim) const { return Dune::Yasp::subEnt(dim,codim); } /*! Intra-element access to subentities of codimension cc > codim. */ template typename Codim::Entity subEntity (int i) const { // calculate move bitset std::bitset move = Dune::Yasp::entityMove(i,cc); // get the coordinate and modify it iTupel coord = _it.coord(); for (int j=0; joverlapfront[cc].shiftmapping(Dune::Yasp::entityShift(i,cc)); return typename Codim::Entity(YaspEntity(_g,_g->overlapfront[cc].begin(coord, which))); } //! Inter-level access to father element on coarser grid. Assumes that meshes are nested. Entity father () const { // check if coarse level exists if (_g->level()<=0) DUNE_THROW(GridError, "tried to call father on level 0"); // yes, get iterator to it YGLI cg(_g); --cg; // coordinates of the cell iTupel coord = _it.coord(); // get coordinates on next coarser level for (int k=0; k(cg,cg->overlap[0].begin(coord))); } //! returns true if father entity exists bool hasFather () const { return (_g->level()>0); } /*! Location of this element relative to the reference element of its father */ LocalGeometry geometryInFather () const { // configure one of the 2^dim transformations FieldVector ll(0.0),ur(0.5); for (int k=0; k(ll,ur) ); } const I& transformingsubiterator () const { return _it; } const YGLI& gridlevel () const { return _g; } I& transformingsubiterator() { return _it; } YGLI& gridlevel() { return _g; } const GridImp* yaspgrid () const { return _g->mg; } bool isLeaf() const { return (_g->level() == yaspgrid()->maxLevel()); } /**\brief Returns true, if the entity has been created during the last call to adapt() */ bool isNew () const { return yaspgrid()->adaptRefCount > 0 && yaspgrid()->maxLevel() < _g->level() + yaspgrid()->adaptRefCount; } /**\brief Returns true, if entity might disappear during the next call to adapt() */ bool mightVanish () const { return false; } //! returns intersection iterator for first intersection IntersectionIterator ibegin () const { return YaspIntersectionIterator(*this,false); } //! returns intersection iterator for first intersection LeafIntersectionIterator ileafbegin () const { // only if entity is leaf this iterator delivers intersections return YaspIntersectionIterator(*this, ! isLeaf() ); } //! returns intersection iterator for first intersection LevelIntersectionIterator ilevelbegin () const { return ibegin(); } //! Reference to one past the last neighbor IntersectionIterator iend () const { return YaspIntersectionIterator(*this,true); } //! Reference to one past the last neighbor LeafIntersectionIterator ileafend () const { return iend(); } //! Reference to one past the last neighbor LevelIntersectionIterator ilevelend () const { return iend(); } /*! Inter-level access to son elements on higher levels<=maxlevel. This is provided for sparsely stored nested unstructured meshes. Returns iterator to first son. */ HierarchicIterator hbegin (int maxlevel) const { return YaspHierarchicIterator(_g,_it,maxlevel); } //! Returns iterator to one past the last son HierarchicIterator hend (int /* maxlevel */) const { return YaspHierarchicIterator(_g,_it,_g->level()); } private: // IndexSets needs access to the private index methods friend class Dune::YaspIndexSet; friend class Dune::YaspIndexSet; friend class Dune::YaspGlobalIdSet; //! globally unique, persistent index PersistentIndexType persistentIndex () const { // encode codim PersistentIndexType id(_it.shift().to_ulong()); // encode level id = id << yaspgrid_level_bits; id = id+PersistentIndexType(_g->level()); // encode coordinates for (int i=dim-1; i>=0; i--) { id = id << yaspgrid_dim_bits; id = id+PersistentIndexType(_it.coord(i)); } return id; } //! consecutive, codim-wise, level-wise index int compressedIndex () const { return _it.superindex(); } //! subentity persistent index PersistentIndexType subPersistentIndex (int i, int cc) const { // calculate shift and move bitsets std::bitset shift = Dune::Yasp::entityShift(i,cc); std::bitset move = Dune::Yasp::entityMove(i,cc); int trailing = (cc == dim) ? 1000 : 0; std::array size = _g->mg->levelSize(_g->level()); std::array coord = _it.coord(); for (int j=0; jlevel(); k++) if (coord[j] & (1<level()-trailing); // encode coordinates for (int j=dim-1; j>=0; j--) { id = id << yaspgrid_dim_bits; id = id+PersistentIndexType(coord[j]>>trailing); } return id; } //! subentity compressed index int subCompressedIndex (int i, int cc) const { // get shift and move of the subentity in question std::bitset shift = Dune::Yasp::entityShift(i,cc); std::bitset move = Dune::Yasp::entityMove(i,cc); std::array coord = _it.coord(); for (int j=0; joverlapfront[cc].shiftmapping(shift); return _g->overlapfront[cc].superindex(coord,which); } I _it = {}; // position in the grid level YGLI _g = {}; // access to grid level }; // specialization for codim=dim (vertex) template class YaspEntity : public EntityDefaultImplementation { constexpr static int dimworld = GridImp::dimensionworld; template friend class YaspLevelIterator; typedef typename GridImp::Traits::template Codim::GeometryImpl GeometryImpl; public: typedef typename GridImp::ctype ctype; typedef typename GridImp::YGridLevelIterator YGLI; typedef typename GridImp::YGrid::Iterator I; typedef typename GridImp::template Codim::Geometry Geometry; typedef typename GridImp::template Codim::EntitySeed EntitySeed; //! define the type used for persistent indices typedef typename GridImp::PersistentIndexType PersistentIndexType; //! define type used for coordinates in grid module typedef typename GridImp::YGrid::iTupel iTupel; // constructor YaspEntity () {} YaspEntity (const YGLI& g, const I& it) : _it(it), _g(g) {} YaspEntity (YGLI&& g, I&& it) : _it(std::move(it)), _g(std::move(g)) {} //! Return true when two iterators over the same grid are equal (!). bool equals (const YaspEntity& e) const { return _it == e._it && _g == e._g; } //! level of this element int level () const {return _g->level();} /** \brief Return the entity seed which contains sufficient information * to generate the entity again and uses as little memory as possible */ EntitySeed seed () const { return EntitySeed(YaspEntitySeed(_g->level(), _it.coord(), _it.which())); } /*! Return number of subentities with codimension cc. * * That number is (dim over (dim-codim)) times 2^codim */ unsigned int subEntities (unsigned int cc) const { return Dune::Yasp::subEnt(dim-dim,cc-dim); } //! geometry of this entity Geometry geometry () const { GeometryImpl _geometry((_it).lowerleft()); return Geometry( _geometry ); } /** \brief Return the name of the reference element. The type can be used to access the Dune::ReferenceElement. */ constexpr GeometryType type () const { return GeometryTypes::cube(Geometry::mydimension); } //! return partition type attribute PartitionType partitionType () const { if (_g->interior[dim].inside(_it.coord(),_it.shift())) return InteriorEntity; if (_g->interiorborder[dim].inside(_it.coord(),_it.shift())) return BorderEntity; if (_g->overlap[dim].inside(_it.coord(),_it.shift())) return OverlapEntity; if (_g->overlapfront[dim].inside(_it.coord(),_it.shift())) return FrontEntity; return GhostEntity; } //! subentity compressed index simply returns compressedIndex int subCompressedIndex (int, unsigned int ) const { return compressedIndex(); } private: // IndexSets needs access to the private index methods friend class Dune::YaspIndexSet; friend class Dune::YaspIndexSet; friend class Dune::YaspGlobalIdSet; //! globally unique, persistent index PersistentIndexType persistentIndex () const { // get coordinate and size of global grid iTupel size = _g->mg->levelSize(_g->level()); for (int i=0; ilevel(); j++) if (_it.coord(i)&(1<level()-trailing; // encode codim: shift vector of vertices is 0. PersistentIndexType id(0); // encode level id = id << yaspgrid_level_bits; id = id+PersistentIndexType(level); // encode coordinates for (int i=dim-1; i>=0; i--) { id = id << yaspgrid_dim_bits; id = id+PersistentIndexType(_it.coord(i)>>trailing); } return id; } //! consecutive, codim-wise, level-wise index int compressedIndex () const { return _it.superindex();} public: const I& transformingsubiterator() const { return _it; } const YGLI& gridlevel() const { return _g; } I& transformingsubiterator() { return _it; } YGLI& gridlevel() { return _g; } const GridImp * yaspgrid() const { return _g->mg; } protected: I _it = {}; // position in the grid level YGLI _g = {}; // access to grid level }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDENTITY_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridentityseed.hh000066400000000000000000000030311511655130300234110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDENTITYSEED_HH #define DUNE_GRID_YASPGRIDENTITYSEED_HH /** \file * \brief The YaspEntitySeed class */ namespace Dune { /** \brief Describes the minimal information necessary to create a fully functional YaspEntity */ template class YaspEntitySeed { //! know your own dimension constexpr static int dim = GridImp::dimension; public: //! codimension of entity constexpr static int codimension = codim; //! default construct an invalid entity seed YaspEntitySeed () : _l(-1), _o(0) { std::fill(_c.begin(),_c.end(),0); } //! constructor YaspEntitySeed (int level, std::array coord, int o = 0) : _l(level), _c(coord), _o(o) {} //! check whether the EntitySeed refers to a valid Entity bool isValid() const { return _l != -1; } int level () const { return _l; } const std::array & coord() const { return _c; } int offset () const { return _o; } protected: int _l; // grid level std::array _c; // coord in the global grid int _o; // the offset: which YGridComponent, does the entity belong to }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDENTITYSEED_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridgeometry.hh000066400000000000000000000057631511655130300231050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDGEOMETRY_HH #define DUNE_GRID_YASPGRIDGEOMETRY_HH /** \file * \brief The YaspGeometry class and its specializations YaspGeometry realizes the concept of the geometric part of a mesh entity. We have specializations for dim == dimworld (elements) and dim == 0 (vertices). The general version implements all other codimensions. As of September 2014, the functionality of YaspGeometry is identical to that of AxisAlignedCubeGeometry. The latter cannot be used directly due to the grid interface facade construction (it isn't templated to the GridImp). As soon as template aliases are available, this header boils down to one line. */ namespace Dune { /** \brief The general version that handles all codimensions but 0 and dim. * \tparam mydim the codimension * \tparam cdim the coordinate dimension (NOT codim) */ template class YaspGeometry : public AxisAlignedCubeGeometry { public: //! define type used for coordinates in grid module typedef typename GridImp::ctype ctype; //! constructor from midpoint and extension and a bitset defining which unit vectors span the entity YaspGeometry (const FieldVector& ll, const FieldVector& ur, const std::bitset& shift) : AxisAlignedCubeGeometry(ll,ur,shift) { assert(mydim == shift.count()); } }; //! specialize for dim=dimworld, i.e. a volume element template class YaspGeometry : public AxisAlignedCubeGeometry { public: typedef typename GridImp::ctype ctype; //! constructor from midpoint and extension YaspGeometry (const FieldVector& ll, const FieldVector& ur) : AxisAlignedCubeGeometry(ll,ur) {} //! copy constructor (skipping temporary variables) YaspGeometry (const YaspGeometry& other) : AxisAlignedCubeGeometry(other) {} }; //! specialization for dim=0, this is a vertex template class YaspGeometry<0,cdim,GridImp> : public AxisAlignedCubeGeometry { public: typedef typename GridImp::ctype ctype; //! constructor explicit YaspGeometry ( const FieldVector< ctype, cdim > &p ) : AxisAlignedCubeGeometry( p ) {} YaspGeometry ( const FieldVector< ctype, cdim > &p, const FieldVector< ctype, cdim > &, const std::bitset &) : AxisAlignedCubeGeometry( p ) {} }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDGEOMETRY_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridhierarchiciterator.hh000066400000000000000000000106331511655130300251150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDHIERARCHICITERATOR_HH #define DUNE_GRID_YASPGRIDHIERARCHICITERATOR_HH /** \file * The YaspHierarchicIterator class * * Enables iteration over son entities of codim 0 */ namespace Dune { /** \brief YaspHierarchicIterator enables iteration over son entities of codim 0 */ template class YaspHierarchicIterator { constexpr static int dim = GridImp::dimension; typedef YaspEntity<0,GridImp::dimension,GridImp> YaspEntityImp; public: // types used from grids typedef typename GridImp::YGridLevelIterator YGLI; typedef typename GridImp::YGrid::Iterator I; typedef typename GridImp::template Codim<0>::Entity Entity; //! default constructor creating empty iterator YaspHierarchicIterator () : _entity(), _maxlevel(-1), stack() {} //! constructor YaspHierarchicIterator (const YGLI& g, const I& it, int maxlevel) : _entity(YaspEntity<0, dim, GridImp>(g,it)) { // store reference to entity implementation for better readability YaspEntityImp& entity = _entity.impl(); // now iterator points to current cell StackElem se(entity._g); std::copy(entity._it.coord().begin(), entity._it.coord().end(), se.coord.begin()); stack.push(se); // determine maximum level _maxlevel = std::min(maxlevel,entity._g->mg->maxLevel()); // if maxlevel not reached then push yourself and sons if (entity._g->level()<_maxlevel) { push_sons(); } // and make iterator point to first son if stack is not empty if (!stack.empty()) pop_tos(); } //! increment void increment () { // sanity check: do nothing when stack is empty if (stack.empty()) return; // if maxlevel not reached then push sons if (_entity.impl()._g->level()<_maxlevel) push_sons(); // in any case pop one element pop_tos(); } //! equality bool equals (const YaspHierarchicIterator& rhs) const { return (_entity == rhs._entity); } //! dereferencing const Entity& dereference() const { return _entity; } void print (std::ostream& s) const { // store reference to entity implementation for better readability YaspEntityImp& entity = _entity.impl(); s << "HIER: " << "level=" << entity._g.level() << " position=" << entity._it.coord() << " superindex=" << entity._it.superindex() << " maxlevel=" << entity._maxlevel << " stacksize=" << stack.size() << std::endl; } private: Entity _entity; //!< entity int _maxlevel; //!< maximum level of elements to be processed struct StackElem { YGLI g; // grid level of the element std::array coord; // and the coordinates StackElem(YGLI gg) : g(gg) {} }; std::stack stack; //!< stack holding elements to be processed // push sons of current element on the stack void push_sons () { // store reference to entity implementation for better readability YaspEntityImp& entity = _entity.impl(); // yes, process all 1<overlap[0].dataBegin()->origin(k)) || (se.coord[k] >= finer->overlap[0].dataBegin()->origin(k)+finer->overlap[0].dataBegin()->size(k))) exists = false; if (exists) stack.push(se); } } // make TOS the current element void pop_tos () { StackElem se = stack.top(); stack.pop(); YaspEntityImp& entity = _entity.impl(); entity._g = se.g; entity._it.reinit(entity._g->overlap[0],se.coord); } }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDHIERARCHICITERATOR_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgrididset.hh000066400000000000000000000041231511655130300223470ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDIDSET_HH #define DUNE_GRID_YASPGRIDIDSET_HH namespace Dune { //======================================================================== /*! \brief persistent, globally unique Ids */ //======================================================================== template class YaspGlobalIdSet : public IdSet, typename std::remove_const::type::PersistentIndexType > /* We used the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ { typedef YaspGlobalIdSet< GridImp > This; public: //! define the type used for persistent indices typedef typename std::remove_const::type::PersistentIndexType IdType; using IdSet::subId; //! Only default-constructible YaspGlobalIdSet() {} //! get id of an entity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ template IdType id (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { return e.impl().persistentIndex(); } //! get id of subentity /* We use the remove_const to extract the Type from the mutable class, because the const class is not instantiated yet. */ IdType subId (const typename std::remove_const::type::Traits::template Codim< 0 >::Entity &e, int i, unsigned int codim ) const { return e.impl().subPersistentIndex(i,codim); } }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDIDSET_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridindexsets.hh000066400000000000000000000060131511655130300232450ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDINDEXSET_HH #define DUNE_GRID_YASPGRIDINDEXSET_HH /** \file * \brief level-wise, non-persistent, consecutive indices for YaspGrid */ namespace Dune { /** \brief Implementation of Level- and LeafIndexSets for YaspGrid * * \tparam GridImp The YaspGrid class we are an index set for * \tparam isLeafIndexSet false: class functions as level index set, * true: class functions as leaf index set */ template class YaspIndexSet : public IndexSet< GridImp, YaspIndexSet< GridImp, isLeafIndexSet >, unsigned int, std::array > { typedef YaspIndexSet< GridImp, isLeafIndexSet > This; typedef IndexSet< GridImp, This, unsigned int, std::array > Base; public: typedef typename Base::IndexType IndexType; using Base::subIndex; /** \brief Level grid view constructor stores reference to a grid and level */ YaspIndexSet ( const GridImp &g, int l ) : grid( g ), level( l ) { assert(not isLeafIndexSet); } /** \brief Level grid view constructor stores reference to a grid and level */ YaspIndexSet ( const GridImp &g ) : grid( g ) { assert(isLeafIndexSet); } //! get index of an entity template IndexType index (const typename std::remove_const::type::Traits::template Codim::Entity& e) const { return e.impl().compressedIndex(); } //! get index of subentity of an entity template< int cc > IndexType subIndex ( const typename std::remove_const< GridImp >::type::Traits::template Codim< cc >::Entity &e, int i, unsigned int codim ) const { return e.impl().subCompressedIndex(i, codim); } //! get number of entities of given type and level (the level is known to the object) std::size_t size (GeometryType type) const { return (isLeafIndexSet) ? grid.size( type ) : grid.size( level, type ); } //! return size of set for a given codim std::size_t size (int codim) const { return (isLeafIndexSet) ? grid.size( codim ) : grid.size( level, codim ); } //! return true if the given entity is contained in \f$E\f$. template bool contains (const EntityType& e) const { return (isLeafIndexSet) ? e.level() == grid.maxLevel() : e.level() == level; } //! obtain all geometry types of entities in domain static constexpr std::array types (int codim) { return { GeometryTypes::cube(GridImp::dimension - codim) }; } private: const GridImp& grid; int level; }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDINDEXSET_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridintersection.hh000066400000000000000000000255271511655130300237600ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDINTERSECTION_HH #define DUNE_GRID_YASPGRIDINTERSECTION_HH /** \file * \brief The YaspIntersection class * YaspIntersection provides data about intersection with neighboring codim 0 entities. */ namespace Dune { /** \brief YaspIntersection provides data about intersection with neighboring codim 0 entities. */ template class YaspIntersection { constexpr static int dim = GridImp::dimension; constexpr static int dimworld = GridImp::dimensionworld; typedef typename GridImp::ctype ctype; typedef typename GridImp::Traits::template Codim< 1 >::GeometryImpl GeometryImpl; typedef typename GridImp::Traits::template Codim< 1 >::LocalGeometryImpl LocalGeometryImpl; friend class YaspIntersectionIterator; public: // types used from grids typedef typename GridImp::YGridLevelIterator YGLI; typedef typename GridImp::YGrid::Iterator I; typedef typename GridImp::template Codim<0>::Entity Entity; typedef typename GridImp::template Codim<1>::Geometry Geometry; typedef typename GridImp::template Codim<1>::LocalGeometry LocalGeometry; void update() { // vector with per-direction movements std::array dist{{0}}; // first move: back to center dist[_dir] = 1 - 2*_face; // update face info _dir = _count / 2; _face = _count % 2; // second move: to new neighbor dist[_dir] += -1 + 2*_face; // move transforming iterator _outside.transformingsubiterator().move(dist); } /*! return true if we are on the boundary of the domain unless we are periodic in that direction */ bool boundary () const { // Coordinate of intersection in its direction int coord = _inside.transformingsubiterator().coord(_dir) + _face; if (_inside.gridlevel()->mg->isPeriodic(_dir)) return false; else return coord == 0 || coord == _inside.gridlevel()->mg->levelSize(_inside.gridlevel()->level(),_dir); } //! return true if neighbor across intersection exists in this processor bool neighbor () const { // Coordinate of intersection in its direction int coord = _inside.transformingsubiterator().coord(_dir) + _face; return coord > _inside.gridlevel()->overlap[0].dataBegin()->min(_dir) && coord <= _inside.gridlevel()->overlap[0].dataBegin()->max(_dir); } //! Yasp is always conform bool conforming () const { return true; } //! return Entity on the inside of this intersection //! (that is the Entity where we started this Iterator) Entity inside() const { return Entity(_inside); } //! return Entity on the outside of this intersection Entity outside() const { return Entity(_outside); } //! identifier for boundary segment from macro grid //! (attach your boundary condition as needed) int boundarySegmentIndex() const { if(! boundary()) DUNE_THROW(GridError, "called boundarySegmentIndex while boundary() == false"); // size of local macro grid const std::array & size = _inside.gridlevel()->mg->begin()->overlap[0].dataBegin()->size(); const std::array & origin = _inside.gridlevel()->mg->begin()->overlap[0].dataBegin()->origin(); std::array sides; { for (int i=0; img->begin()->overlap[0].dataBegin()->origin(i) == 0)+ (_inside.gridlevel()->mg->begin()->overlap[0].dataBegin()->origin(i) + _inside.gridlevel()->mg->begin()->overlap[0].dataBegin()->size(i) == _inside.gridlevel()->mg->levelSize(0,i))); } } // global position of the cell on macro grid std::array pos = _inside.transformingsubiterator().coord(); for(int i=0; i fsize; { int vol = 1; for (int k=0; k=0; k--) { if (k == _dir) continue; index += (pos[k]) * localoffset; localoffset *= size[k]; } } // add unit-cube-face-offsets { for (int k=0; k<_dir; k++) index += sides[k] * fsize[k]; // add fsize if we are on the right face and there is a left-face-boundary on this processor index += _face * (sides[_dir]>1) * fsize[_dir]; } return index; } //! return unit outer normal, this should be dependent on local coordinates for higher order boundary FieldVector outerNormal (const FieldVector& /* local */) const { return centerUnitOuterNormal(); } //! return unit outer normal, this should be dependent on local coordinates for higher order boundary FieldVector unitOuterNormal (const FieldVector& /* local */) const { return centerUnitOuterNormal(); } //! return unit outer normal at center of intersection geometry FieldVector centerUnitOuterNormal () const { FieldVector normal(0); normal[_dir] = (_face==0) ? -1.0 : 1.0; return normal; } //! return unit outer normal, this should be dependent on //! local coordinates for higher order boundary //! the normal is scaled with the integration element of the intersection. FieldVector integrationOuterNormal ([[maybe_unused]] const FieldVector& local) const { return geometry().volume() * centerUnitOuterNormal(); } /*! intersection of codimension 1 of this neighbor with element where iteration started. Here returned element is in LOCAL coordinates of the element where iteration started. */ LocalGeometry geometryInInside () const { // set of dimensions that span the intersection std::bitset s; s.set(); s[_dir] = false; // lower-left and upper-right corners Dune::FieldVector ll(0.0); Dune::FieldVector ur(1.0); ll[_dir] = ur[_dir] = (_face==0) ? 0.0 : 1.0; return LocalGeometry(LocalGeometryImpl(ll,ur,s)); } /*! intersection of codimension 1 of this neighbor with element where iteration started. Here returned element is in LOCAL coordinates of neighbor */ LocalGeometry geometryInOutside () const { // set of dimensions that span the intersection std::bitset s; s.set(); s[_dir] = false; // lower-left and upper-right corners Dune::FieldVector ll(0.0); Dune::FieldVector ur(1.0); ll[_dir] = ur[_dir] = (_face==1) ? 0.0 : 1.0; return LocalGeometry(LocalGeometryImpl(ll,ur,s)); } /*! intersection of codimension 1 of this neighbor with element where iteration started. */ Geometry geometry () const { std::bitset shift; shift.set(); shift[_dir] = false; Dune::FieldVector ll, ur; for (int i=0; icoordinate(i,coord); if (i != _dir) coord++; ur[i] = _inside.transformingsubiterator().coordCont()->coordinate(i,coord); // If on periodic overlap, transform coordinates by domain size if (_inside.gridlevel()->mg->isPeriodic(i)) { int coordPeriodic = _inside.transformingsubiterator().coord(i); if (coordPeriodic < 0) { auto size = _inside.gridlevel()->mg->domainSize()[i]; ll[i] += size; ur[i] += size; } else if (coordPeriodic + 1 > _inside.gridlevel()->mg->levelSize(_inside.gridlevel()->level(),i)) { auto size = _inside.gridlevel()->mg->domainSize()[i]; ll[i] -= size; ur[i] -= size; } } } GeometryImpl _is_global(ll,ur,shift); return Geometry( _is_global ); } /** \brief obtain the type of reference element for this intersection */ GeometryType type () const { return GeometryTypes::cube(dim-1); } //! local index of codim 1 entity in self where intersection is contained in int indexInInside () const { return _count; } //! local index of codim 1 entity in neighbor where intersection is contained in int indexInOutside () const { // flip the last bit return _count^1; } YaspIntersection() : _count(~std::uint8_t(0)) // Use as marker for invalid intersection , _dir(0) , _face(0) {} //! make intersection iterator from entity, initialize to first neighbor YaspIntersection (const YaspEntity<0,dim,GridImp>& myself, bool toend) : _inside(myself.gridlevel(), myself.transformingsubiterator()), _outside(myself.gridlevel(), myself.transformingsubiterator()), // initialize to first neighbor _count(0), _dir(0), _face(0) { if (toend) { // initialize end iterator _count = 2*dim; return; } _count = 0; // move transforming iterator _outside.transformingsubiterator().move(_dir,-1); } //! copy constructor -- use default //! copy operator - use default void assign (const YaspIntersection& it) { *this = it; } bool equals(const YaspIntersection& other) const { // compare counts first -- that's cheaper if the test fails return _count == other._count && _inside.equals(other._inside); } private: /* The two entities that make up the intersection */ YaspEntity<0,GridImp::dimension,GridImp> _inside; //!< entity from which the intersection was created from YaspEntity<0,GridImp::dimension,GridImp> _outside; //!< outside entity /* current position */ std::uint8_t _count; //!< valid neighbor count in 0 .. 2*dim-1 std::uint8_t _dir; //!< count/2 std::uint8_t _face; //!< count%2 }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDINTERSECTION_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridintersectioniterator.hh000066400000000000000000000041301511655130300255150ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDINTERSECTIONITERATOR_HH #define DUNE_GRID_YASPGRIDINTERSECTIONITERATOR_HH /** \file * \brief The YaspIntersectionIterator class YaspIntersectionIterator enables iteration over intersections with neighboring codim 0 entities. */ namespace Dune { /** \brief YaspIntersectionIterator enables iteration over intersections with neighboring codim 0 entities. */ template class YaspIntersectionIterator { constexpr static int dim = GridImp::dimension; public: // types used from grids typedef Dune::YaspIntersection< GridImp > IntersectionImp; typedef Dune::Intersection< GridImp, IntersectionImp > Intersection; //! increment void increment() { intersection_.impl()._count += (intersection_.impl()._count < 2*dim); } //! equality bool equals (const YaspIntersectionIterator& other) const { return intersection_ == other.intersection_; } //! \brief dereferencing const Intersection & dereference() const { intersection_.impl().update(); return intersection_; } YaspIntersectionIterator() {} //! make intersection iterator from entity YaspIntersectionIterator (const YaspEntity<0,dim,GridImp>& myself, bool toend) : intersection_(IntersectionImp(myself, toend)) {} //! copy constructor YaspIntersectionIterator (const YaspIntersectionIterator& other) : intersection_(other.intersection_) {} //! assignment YaspIntersectionIterator & operator = (const YaspIntersectionIterator& other) { intersection_ = other.intersection_; return *this; } private: // The intersection this iterator points to mutable Intersection intersection_; }; } // namespace Dune #endif // DUNE_GRID_YASPGRIDINTERSECTIONITERATOR_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridleveliterator.hh000066400000000000000000000030721511655130300241220ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDLEVELITERATOR_HH #define DUNE_GRID_YASPGRIDLEVELITERATOR_HH /** \file * \brief The YaspLevelIterator class */ namespace Dune { /** \brief Iterates over entities of one grid level */ template class YaspLevelIterator { //! know your own dimension constexpr static int dim = GridImp::dimension; //! know your own dimension of world constexpr static int dimworld = GridImp::dimensionworld; typedef typename GridImp::ctype ctype; public: typedef typename GridImp::template Codim::Entity Entity; typedef typename GridImp::YGridLevelIterator YGLI; typedef typename GridImp::YGrid::Iterator I; //! default constructor YaspLevelIterator () {} //! constructor YaspLevelIterator (const YGLI & g, const I& it) : _entity(YaspEntity(g,it)) {} //! increment void increment() { ++(_entity.impl()._it); } //! equality bool equals (const YaspLevelIterator& rhs) const { return (_entity == rhs._entity); } //! dereferencing const Entity& dereference() const { return _entity; } protected: Entity _entity; //!< entity }; } #endif // DUNE_GRID_YASPGRIDLEVELITERATOR_HH dune-grid-2.11.0/dune/grid/yaspgrid/yaspgridpersistentcontainer.hh000066400000000000000000000076041511655130300253510ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRIDPERSISTENTCONTAINER_HH #define DUNE_GRID_YASPGRIDPERSISTENTCONTAINER_HH /** \file * \brief Specialization of the PersistentContainer for YaspGrid */ #include #include #include #include #include "../yaspgrid.hh" namespace Dune { /** \internal * \brief implement a consecutive index for all entities of given codim of a YaspGrid * * this class behaves similar to an IndexSet * * to make this work for a persistent vector we have to implement... * * indexSet.size( codim ) * indexSet.index( entity ); * indexSet.subIndex( entity, subEntity, codimension() ); */ template class YaspPersistentContainerIndex { public: YaspPersistentContainerIndex(const Grid & grid, int codim) : _grid(grid), _codim(codim) { recomputeOffsets(); } /** \copydoc IndexSet::IndexType */ typedef std::size_t IndexType; /** \copydoc IndexSet::index */ template IndexType index (const Entity& e) const { static const int cc = Entity::codimension; std::size_t level = e.level(); return _grid.indexsets[level]->template index(e) + _offsets[level]; } /** \copydoc IndexSet::subIndex */ template< class Entity > IndexType subIndex ( const Entity &e, int i, unsigned int codim ) const { static const int cc = Entity::codimension; std::size_t level = e.level(); return _grid.indexsets[level]->template subIndex(e,i,codim) + _offsets[level]; } /** \copydoc IndexSet::size */ std::size_t size (int /* codim */) const { if (_grid.indexsets.size()+1 != _offsets.size()) recomputeOffsets(); return _offsets.back(); } private: void recomputeOffsets() const { _offsets.resize(_grid.indexsets.size()+1,0); _offsets[0] = 0; for (std::size_t i=0; i<_grid.indexsets.size(); i++) _offsets[i+1] = _offsets[i] + _grid.indexsets[i]->size(_codim); } const Grid& _grid; int _codim; mutable std::vector _offsets; }; /** \brief Specialization of the PersistentContainer for YaspGrid */ /** \note questions regarding the interface of PersistentContainer: - is it allowed to access the container after grid modification, without calling resize? - which assumptions on the indexset doe the PersistentContainerVector have? */ template class PersistentContainer< YaspGrid, T > /* We have to pass the reference to the IndexSet to the constructor of the PersistentContainerVector. In order to have a valid indexset available, we inherit from a private indexset */ : private YaspPersistentContainerIndex< const YaspGrid >, public PersistentContainerVector< YaspGrid, YaspPersistentContainerIndex< const YaspGrid >, std::vector > { typedef YaspPersistentContainerIndex< const YaspGrid > IndexSet; typedef PersistentContainerVector< YaspGrid, IndexSet, std::vector > Base; public: typedef typename Base::Grid Grid; typedef typename Base::Value Value; using Base::size; PersistentContainer ( const Grid &grid, int codim, const Value &value = Value() ) : IndexSet(grid, codim), Base(*this, codim, value) {} }; } // end namespace Dune #endif // end DUNE_GRID_YASPGRIDPERSISTENTCONTAINER_HH dune-grid-2.11.0/dune/grid/yaspgrid/ygrid.hh000066400000000000000000000712321511655130300206170ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_YASPGRID_YGRID_HH #define DUNE_GRID_YASPGRID_YGRID_HH #include #include #include #include #include #include #include /** \file \brief This provides a YGrid, the elemental component of the yaspgrid implementation */ namespace Dune { namespace Yasp { /** @returns an array containing the sizes of the grids associated with vectors in given array. * Needed in this form due to the need of such functionality in class initializer lists. * @param v the array of vectors to examine */ template std::array sizeArray(const std::array,d>& v) { std::array tmp; for (int i=0; i class YGridComponent { public: //extract coordinate type and dimension from the coordinate container typedef typename Coordinates::ctype ct; static const int d = Coordinates::dimension; typedef std::array iTupel; typedef FieldVector fTupel; //! make uninitialized ygrid YGridComponent () : _shift(0ULL) { std::fill(_origin.begin(), _origin.end(), 0); std::fill(_offset.begin(), _offset.end(), 0); std::fill(_size.begin(), _size.end(), 0); } /** @brief make ygrid without coordinate information * @param origin origin of the grid in global coordinates * @param size size of the grid * Such grid has no coordinate information stored but can be * used to determine an intersection with a grid with coordinate * information. This avoids sending coordinates in the parallel case. */ YGridComponent(iTupel origin, iTupel size) : _origin(origin), _size(size) {} /** @brief make a subgrid by taking coordinates from a larger grid * @param origin origin of the grid to be constructed * @param size size of the grid to be constructed * @param enclosing the grid to take coordinates and shift vector from */ YGridComponent (iTupel origin, iTupel size, const YGridComponent& enclosing) : _origin(origin), _shift(enclosing.shift()), _coords(enclosing.getCoords()), _size(size), _supersize(enclosing.supersize()) { for (int i=0; i shift, Coordinates* coords, iTupel size, iTupel offset, iTupel supersize) : _origin(origin), _shift(shift), _coords(coords), _size(size), _offset(offset), _supersize(supersize) { // compute superincrements int inc = 1; for (int i=0; i& shift () const { return _shift; } Coordinates* getCoords() const { return _coords; } //! Return offset to origin of enclosing grid int offset (int i) const { return _offset[i]; } //! Return offset to origin of enclosing grid const iTupel & offset () const { return _offset; } //! return size of enclosing grid int supersize (int i) const { return _supersize[i]; } //! return size of enclosing grid const iTupel & supersize () const { return _supersize; } //! return size in direction i int size (int i) const { return _size[i]; } //! return size iTupel size () const { return _size; } //! Return total size of index set which is the product of all size per direction. int totalsize () const { int s=1; for (int i=0; i=_origin[i]+_size[i])) return false; } return true; } //! given a tuple compute its index in the lexicographic numbering int index (const iTupel& coord) const { int index = (coord[d-1]-_origin[d-1]); for (int i=d-2; i>=0; i--) index = index*_size[i] + (coord[i]-_origin[i]); return index; } //! return grid moved by the vector v YGridComponent move (iTupel v) const { for (int i=0; i(v,_size,*this); } //! Return YGridComponent of supergrid of self which is the intersection of self and another YGridComponent YGridComponent intersection (const YGridComponent& r) const { for (int i=0; i(); } iTupel neworigin; iTupel newsize; for (int i=0; i(neworigin,newsize,*this); } /** Iterator class allows one to run over all cells of a grid. * The cells of the grid to iterate over are numbered consecutively starting * with zero. Via the index() method the iterator provides a mapping of the * cells of the grid to a one-dimensional array. The number of entries * in this array must be the size of the grid. */ class Iterator { public: // default constructor Iterator () = default; //! Make iterator pointing to first cell in a grid. Iterator (const YGridComponent& r) : _grid(&r) { iTupel coord(r.origin()); reinit(r,coord); } //! Make iterator pointing to given cell in a grid. Iterator (const YGridComponent& r, const iTupel& coord) { reinit(r,coord); } //! reinitialize iterator to given position void reinit (const YGridComponent& r, const iTupel& coord) { // initialize to given position in index set for (int i=0; isuperincrement(i); } //! move this iterator dist cells in direction i void move (const iTupel& dist) { for (int i = 0; i < d; ++i) { _coord[i] += dist[i]; _superindex += dist[i]*_grid->superincrement(i); } } //! Increment iterator to next cell with position. Iterator& operator++ () { for (int i=0; isuperincrement(i); // move on cell in direction i if (++_coord[i] <= _grid->max(i)) return *this; else { _coord[i] = _grid->origin(i); // move back to origin in direction i _superindex -= _grid->size(i) * _grid->superincrement(i); } } // if we wrapped around, back to to begin(), we must put the iterator to end() if (_coord == _grid->origin()) { for (int i=0; isize(i)-1) * _grid->superincrement(i); _superindex += _grid->superincrement(0); } return *this; } //! Return ith component of lower left corner of the entity associated with the current coordinates and shift. ct lowerleft(int i) const { return _grid->getCoords()->coordinate(i,_coord[i]); } //! Return lower left corner of the entity associated with the current coordinates and shift. fTupel lowerleft() const { fTupel ll; for (int i=0; igetCoords()->coordinate(i,coord); } //! Return upper right corder of the entity associated with the current coordinates and shift. fTupel upperright() const { fTupel ur; for (int i=0; igetCoords()->meshsize(i,_coord[i]); } //! Return meshsize of current cell as reference. fTupel meshsize () const { fTupel h; for (int i=0; ishift(i); } std::bitset shift() const { return _grid->shift(); } Coordinates* coordCont() const { return _grid->getCoords(); } protected: iTupel _coord; //!< current position in index set int _superindex = 0; //!< consecutive index in enclosing grid const YGridComponent* _grid = nullptr; }; int superindex(iTupel coord) const { // move superindex to first cell in subgrid int si = 0; for (int i=0; i _shift; Coordinates* _coords; iTupel _size; iTupel _offset; //!< offset to origin of the enclosing grid iTupel _supersize; //!< size of the enclosing grid iTupel _superincrement; //!< moves consecutive index by one in this direction in supergrid }; //! Output operator for ygrids template inline std::ostream& operator<< (std::ostream& s, YGridComponent e) { s << "Printing YGridComponent structure:" << std::endl; s << "Origin: " << e.origin() << std::endl; s << "Shift: " << e.shift() << std::endl; s << "Size: " << e.size() << std::endl; s << "Offset: " << e.offset() << std::endl; s << "Supersize: " << e.supersize() << std::endl; return s; } //! Output operator for ygrids template inline std::ostream& operator<< (std::ostream& s, typename YGridComponent::Iterator& e) { s << "Printing YGridComponent Iterator:" << std::endl << "Iterator at " << e.coord() << " (index "; s << e.index() << "), position " << e.position(); return s; } /** \brief implements a collection of YGridComponents which form a codimension * Entities of given codimension c need to be represented by d choose c YgridComponents. * All entities in one such component share the same set of spanning unit vectors. * A YGrid is used to iterate over the entire set of components the codimension * consists of. It doesn't hold any data, but instead holds an iterator range into * an array of components (which is owned by YGridLevel). */ template class YGrid { public: static const int dim = Coordinates::dimension; // define data array iterator typedef YGridComponent* DAI; typedef typename std::array iTupel; //! set start iterator in the data array void setBegin(DAI begin) { _begin = begin; } //! get which component belongs to a given shift vector int shiftmapping(const std::bitset& shift) const { return _shiftmapping[shift.to_ulong()]; } //! get start iterator in the data array DAI dataBegin() const { return _begin; } //! get end iterator in the data array DAI dataEnd() const { return _end; } //! decide whether a coordinate is in the grid (depending on the component) bool inside(const iTupel& coord, const std::bitset& shift = std::bitset()) const { return (_begin+_shiftmapping[shift.to_ulong()])->inside(coord); } /** \brief Iterator over a collection o YGrids * A YGrid::Iterator is the heart of an entity in YaspGrid. */ class Iterator { public: //! default constructor Iterator () = default; //! construct an iterator from coordinates and component Iterator (const YGrid& yg, const std::array& coords, int which = 0) : _which(which), _yg(&yg) { _it = typename YGridComponent::Iterator(*(_yg->dataBegin()+which),coords); } //! create an iterator to start or end of the codimension Iterator (const YGrid& yg, bool end=false) : _yg(&yg) { if (end) { _it = _yg->_itends.back(); _which = _yg->_itends.size() - 1; } else { _it = _yg->_itbegins[0]; _which = 0; } } //! reinitializes an iterator, as if it was just constructed. void reinit(const YGrid& yg, const std::array& coords, int which = 0) { _yg = &yg; _which = which; _it = typename YGridComponent::Iterator(*(_yg->dataBegin()+which),coords); } //! return coordinate at the current position (direction i) int coord (int i) const { return _it.coord(i); } //! return coordinate array at the current position const std::array& coord () const { return _it.coord(); } typename Coordinates::ctype lowerleft(int i) const { return _it.lowerleft(i); } Dune::FieldVector lowerleft() const { return _it.lowerleft(); } typename Coordinates::ctype upperright(int i) const { return _it.upperright(i); } Dune::FieldVector upperright() const { return _it.upperright(); } //! return the current meshsize in direction i typename Coordinates::ctype meshsize (int i) const { return _it.meshsize(i); } //! return the current meshsize vector Dune::FieldVector meshsize() const { return _it.meshsize(); } //! return the shift in direction i bool shift (int i) const { return _it.shift(i); } //! return the shift vector std::bitset shift () const { return _it.shift(); } //! return the superindex int superindex() const { // the offset of the current component has to be taken into account return _yg->_indexOffset[_which] + _it.superindex(); } //! increment to the next entity jumping to next component if necessary Iterator& operator++ () { if ((++_it == _yg->_itends[_which]) && (_which < _yg->_itends.size()-1)) _it = _yg->_itbegins[++_which]; return *this; } //! compare two iterators: component has to match bool operator==(const Iterator& i) const { if (_which != i._which) return false; return _it == i._it; } //! compare two iterators: component has to match bool operator!=(const Iterator& i) const { if (_it != i._it) return true; return _which != i._which; } //! return the current component number int which() const { return _which; } //! move the grid, this is only done and needed for codim 0 void move(int i, int dist) { _it.move(i,dist); } void move(const iTupel& dist) { _it.move(dist); } Coordinates* coordCont() const { return _it.coordCont(); } private: unsigned int _which = 0; const YGrid* _yg = nullptr; typename YGridComponent::Iterator _it; }; //! return begin iterator for the codimension and partition the ygrid represents Iterator begin() const { return Iterator(*this); } //! return iterator pointint to a specified position Iterator begin(const std::array& coord, int which = 0) const { return Iterator(*this, coord, which); } //! return end iterator for the codimension and partition the ygrid represents Iterator end() const { return Iterator(*this,true); } int superindex(const iTupel& coord, int which) const { return _indexOffset[which] + (dataBegin()+which)->superindex(coord); } // finalize the ygrid construction by storing component iterators void finalize(const DAI& end, int artificialOffset = 0) { // set the end iterator in the ygrid component array _end = end; _indexOffset.push_back(artificialOffset); int k = 0; for (DAI i=_begin; i != _end; ++i, ++k) { //store begin and end iterators _itbegins.push_back(i->begin()); _itends.push_back(i->end()); // store index offset _indexOffset.push_back(_indexOffset.back() + i->totalsize()); // store shift to component mapping _shiftmapping[i->shift().to_ulong()] = k; } _indexOffset.resize(_itends.size()); } private: friend class YGrid::Iterator; DAI _begin; DAI _end; std::array _shiftmapping; std::vector::Iterator> _itbegins; std::vector::Iterator> _itends; std::vector _indexOffset; }; //! Output operator for ygrids template inline std::ostream& operator<< (std::ostream& s, const YGrid& e) { s << "Printing YGrid structure:" << std::endl; for (auto it = e.dataBegin(); it != e.dataEnd(); ++it) s << *it << std::endl; return s; } /** \brief implements a collection of multiple std::deque * Intersections with neighboring processors are stored as std::deque. * Eachsuch intersection only holds one YGridComponent. To do all communication * associated with one codimension, multiple such deques have to be concatenated. * YGridList manges this concatenation. As for YGrids, YGridList doesn't hold any * data, but an iterator range into a data array owned by YGridLevel. */ template class YGridList { public: static const int dim = Coordinates::dimension; /** \brief type describing an intersection with a neighboring processor */ struct Intersection { /** \brief The intersection as a subgrid of the local grid */ YGridComponent grid; /** \brief Rank of the process where the other grid is stored */ int rank; /** \brief Manhattan distance to the other grid */ int distance; /** \brief a YGrid stub, that acts wraps above YGrid Component and handles the index offset */ YGrid yg; }; // define data array iterator type typedef typename std::array, Dune::power(2,dim)>::iterator DAI; // iterator that allows to iterate over a concatenation of deques. namely those // that belong to the same codimension. class Iterator { public: //! return iterator to begin and end of the container Iterator(const YGridList& ygl, bool end=false) : _end(ygl.dataEnd()), _which(ygl.dataBegin()) { _it = _which->begin(); // advance the iterator to the first element that exists. // some deques might be empty and should be skipped while ((_which != _end) && (_it == _which->end())) { ++_which; if (_which != _end) _it = _which->begin(); } // the iterator is at the end if and only if _which==_end if (end) { _which = _end; } } //! increment iterator Iterator& operator++ () { ++_it; // advance the iterator to the next element that exists. // some deques might be empty and should be skipped while ((_which != _end) && (_it == _which->end())) { ++_which; if (_which != _end) _it = _which->begin(); } return *this; } //! dereference iterator typename std::deque::iterator operator->() const { return _it; } //! dereference iterator typename std::deque::iterator operator*() const { return _it; } //! compare two iterators bool operator== (const Iterator& i) const { if (_which != i._which) return false; if (_which == _end) return true; return _it == i._it; } //! compare two iterators bool operator!= (const Iterator& i) const { if (_which != i._which) return true; if (_which == _end) return false; return _it != i._it; } private: typename std::deque::iterator _it; DAI _end; DAI _which; }; //! return iterator pointing to the begin of the container Iterator begin() const { return Iterator(*this); } //! return iterator pointing to the end of the container Iterator end() const { return Iterator(*this,true); } //! set start iterator in the data array void setBegin(typename std::array, Dune::power(2,dim)>::iterator begin) { _begin = begin; } //! get start iterator in the data array DAI dataBegin() const { return _begin; } //! get end iterator in the data array DAI dataEnd() const { return _end; } //! return the size of the container, this is the sum of the sizes of all deques int size() const { int count = 0; for (DAI it = _begin; it != _end; ++it) count += it->size(); return count; } //! finalize the YGridLIst void finalize(DAI end, const YGrid& ygrid) { // Instead of directly iterating over the intersection deques, this code // iterates over the components of an associated ygrid and works its way // through the list of intersection deques in parallel. // The reason for this convoluted iteration technique is that there are not // necessarily intersections for all possible shifts, but we have to make // sure that we stop at each shift to update the per-component index shift. // This is ensured by iterating over the ygrid, which is guaranteed to have // a component for each shift vector. // set end iterator in the data array _end = end; //! set offsets allow the YGridComponents in the Intersctions to behave as YGrids int offset = 0; DAI i = _begin; // make sure that we have a valid deque (i.e. a non-empty one) while (i != _end && i->begin() == i->end()) ++i; for (auto yit = ygrid.dataBegin(); yit != ygrid.dataEnd(); ++yit) { if (i == _end) break; auto it = i->begin(); if (it->grid.shift() == yit->shift()) { // iterate over the intersections in the deque and set the offset for (; it != i->end(); ++it) { it->yg.setBegin(&(it->grid)); it->yg.finalize(&(it->grid)+1, offset); } // advance to next non-empty deque ++i; while (i != _end && i->begin() == i->end()) ++i; } // update the offset from the ygrid component int add = 1; for (int j=0; jsupersize(j); offset += add; } assert (i == end); } private: DAI _begin; DAI _end; }; } // namespace Dune #endif dune-grid-2.11.0/dune/python/000077500000000000000000000000001511655130300157255ustar00rootroot00000000000000dune-grid-2.11.0/dune/python/CMakeLists.txt000066400000000000000000000003331511655130300204640ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(grid) add_subdirectory(test) dune-grid-2.11.0/dune/python/grid/000077500000000000000000000000001511655130300166525ustar00rootroot00000000000000dune-grid-2.11.0/dune/python/grid/CMakeLists.txt000066400000000000000000000011041511655130300214060ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS capabilities.hh commops.hh entity.hh enums.hh factory.hh function.hh geometry.hh gridview.hh hierarchical.hh idset.hh indexset.hh intersection.hh localview.hh mapper.hh numpy.hh numpycommdatahandle.hh pygridfunction.hh object.hh range.hh simplegridfunction.hh vtk.hh ) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/python/grid) dune-grid-2.11.0/dune/python/grid/capabilities.hh000066400000000000000000000032121511655130300216220ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_CAPABILITIES_HH #define DUNE_PYTHON_GRID_CAPABILITIES_HH #include #include #include namespace Dune { // External Forward Declarations // ----------------------------- template< int dim, class Coordinates > class YaspGrid; namespace Python { namespace Capabilities { using namespace Dune::Capabilities; // HasGridFactory // -------------- template< class Grid > struct HasGridFactory : public std::integral_constant< bool, !isCartesian< Grid >::v > {}; // HasStructuredGridFactory // ------------------------ template< class Grid > struct HasStructuredGridFactory : public std::integral_constant< bool, HasGridFactory< Grid >::value && (Grid::dimension == Grid::dimensionworld) > {}; template< int dim, class Coordinates > struct HasStructuredGridFactory< YaspGrid< dim, Coordinates > > : public std::true_type {}; // canIterate // ---------- template< class Grid, int codim > struct canIterate : public std::integral_constant< bool, hasEntityIterator< Grid, codim >::v > {}; } // namespace Capabilities } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_CAPABILITIES_HH dune-grid-2.11.0/dune/python/grid/commops.hh000066400000000000000000000006241511655130300206520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_PYTHON_GRID_COMMOPTS_HH #define DUNE_PYTHON_GRID_COMMOPTS_HH namespace Dune { namespace Python { namespace detail { enum CommOp { add=0, set=1 }; } } } #endif // DUNE_PYTHON_GRID_COMMOPTS_HH dune-grid-2.11.0/dune/python/grid/entity.hh000066400000000000000000000234321511655130300205130ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_ENTITY_HH #define DUNE_PYTHON_GRID_ENTITY_HH #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // PyHierarchicIterator // -------------------- template struct PyHierarchicIterator { typedef typename Entity::HierarchicIterator HierarchicIterator; PyHierarchicIterator(const Entity& e, int maxLevel) : it_(e.hbegin(maxLevel)), end_(e.hend(maxLevel)) {} auto next() { if (it_ == end_) throw pybind11::stop_iteration(); return *it_++; } private: HierarchicIterator it_; HierarchicIterator end_; }; // registerPyHierarchicIterator // ---------------------------- template auto registerPyHierarchicIterator(pybind11::handle scope) { typedef PyHierarchicIterator Iterator; auto cls = insertClass(scope, "PyHierarchicIterator", GenerateTypeName("PyHierarchicIterator",MetaType()), IncludeFiles{"dune/python/entity.hh"}).first; cls.def("__iter__", [] (Iterator& it) -> Iterator& { return it; }); cls.def("__next__", &Iterator::next); } namespace detail { // makeSubEntity // ------------- template< class Entity, int codim > inline static auto makeSubEntity ( const Entity &entity, int i ) -> pybind11::object { const int size = entity.subEntities( codim ); if( (i < 0) || (i >= size) ) throw pybind11::value_error( "Invalid index: " + std::to_string( i ) + " (must be in [0, " + std::to_string( size ) + "))." ); return pybind11::cast( entity.template subEntity< codim >( i ) ); } // makeSubEntities // --------------- template< class Entity, int codim > inline static auto makeSubEntities ( const Entity &entity ) -> pybind11::tuple { const int size = entity.subEntities( codim ); pybind11::tuple subEntities( size ); for( int i = 0; i < size; ++i ) subEntities[ i ] = pybind11::cast( entity.template subEntity< codim >( i ) ); return subEntities; } // registerExtendedEntityInterface // ------------------------------- template< class Entity, class... options > inline static auto registerExtendedEntityInterface ( pybind11::class_< Entity, options... > cls, PriorityTag< 1 > ) -> std::enable_if_t< Entity::codimension == 0 > { const int dimension = Entity::dimension; const int mydimension = Entity::mydimension; const int codimension = Entity::codimension; static_assert( mydimension + codimension == dimension, "Entity exports incompatible dimensions" ); using pybind11::operator""_a; cls.def_property_readonly( "father", [] ( const Entity &self ) { return (self.hasFather() ? pybind11::cast( self.father() ) : pybind11::none()); } ); cls.def_property_readonly( "geometryInFather", [] ( const Entity &self ) { return (self.hasFather() ? pybind11::cast( self.geometryInFather() ) : pybind11::none()); } ); cls.def_property_readonly( "isLeaf", [] ( const Entity &self ) { return self.isLeaf(); } ); cls.def_property_readonly( "isRegular", [] ( const Entity &self ) { return self.isRegular(); } ); cls.def_property_readonly( "isNew", [] ( const Entity &self ) { return self.isNew(); } ); cls.def_property_readonly( "mightVanish", [] ( const Entity &self ) { return self.mightVanish(); } ); cls.def( "hasBoundaryIntersections", [] ( const Entity &self ) { return self.hasBoundaryIntersections(); } ); registerPyHierarchicIterator< Entity >( cls ); cls.def( "descendants", [] ( const Entity &self, int maxLevel ) { return PyHierarchicIterator< Entity >( self, maxLevel ); }, pybind11::keep_alive< 0, 1 >() ); std::array< pybind11::object (*) ( const Entity &, int ), dimension+1 > makeSubEntity; std::array< pybind11::tuple (*) ( const Entity & ), dimension+1 > makeSubEntities; Hybrid::forEach( std::make_integer_sequence< int, dimension+1 >(), [ &makeSubEntity, &makeSubEntities ] ( auto codim ) { makeSubEntity[ codim ] = detail::makeSubEntity< Entity, codim >; makeSubEntities[ codim ] = detail::makeSubEntities< Entity, codim >; } ); cls.def( "subEntity", [ makeSubEntity ] ( const Entity &self, int i, int c ) { if( (c < codimension) || (c > dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( codimension ) + ", " + std::to_string( dimension ) + "])" ); return makeSubEntity[ c ]( self, i ); }, "index"_a, "codim"_a ); cls.def( "subEntity", [ makeSubEntity ] ( const Entity &self, std::tuple< int, int > e ) { if( (std::get< 1 >( e ) < codimension) || (std::get< 1 >( e ) > dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( std::get< 1 >( e ) ) + " (must be in [" + std::to_string( codimension ) + ", " + std::to_string( dimension ) + "])" ); return makeSubEntity[ std::get< 1 >( e ) ]( self, std::get< 0 >( e ) ); } ); cls.def( "subEntities", [ makeSubEntities ] ( const Entity &self, int c ) { if( (c < codimension) || (c > dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( codimension ) + ", " + std::to_string( dimension ) + "])" ); return makeSubEntities[ c ]( self ); }, "codim"_a ); cls.def_property_readonly( "vertices", [] ( const Entity &self ) { return detail::makeSubEntities< Entity, dimension >( self ); } ); if( mydimension < dimension ) { cls.def_property_readonly( "edges", [] ( const Entity &self ) { return detail::makeSubEntities< Entity, (mydimension < dimension ? dimension-1 : dimension) >( self ); } ); cls.def_property_readonly( "facets", [] ( const Entity &self ) { return detail::makeSubEntities< Entity, (mydimension < dimension ? mydimension+1 : dimension) >( self ); } ); } } template< class Entity, class... options > inline static void registerExtendedEntityInterface ( pybind11::class_< Entity, options... > cls, PriorityTag< 0 > ) {} template< class Entity, class... options > inline static void registerExtendedEntityInterface ( pybind11::class_< Entity, options... > cls ) { return registerExtendedEntityInterface( cls, PriorityTag< 42 >() ); } // registerGridEntity // ------------------ template< class Entity, class... options > inline static void registerGridEntity ( pybind11::handle scope, pybind11::class_< Entity, options... > cls ) { cls.def_property_readonly_static( "codimension", [] ( pybind11::object ) -> int { return Entity::codimension; } ); cls.def_property_readonly_static( "dimension", [] ( pybind11::object ) -> int { return Entity::dimension; } ); cls.def_property_readonly_static( "mydimension", [] ( pybind11::object ) -> int { return Entity::mydimension; } ); cls.def_property_readonly( "geometry", [] ( const Entity &self ) { return self.geometry(); } ); cls.def_property_readonly( "level", [] ( const Entity &self ) { return self.level(); } ); cls.def_property_readonly( "type", [] ( const Entity &self ) { return self.type(); } ); cls.def_property_readonly( "partitionType", [] ( const Entity &self ) { return self.partitionType(); } ); cls.def_property_readonly( "referenceElement", [] ( const Entity &self ) { return referenceElement< double, Entity::dimension >( self.type() ); }, pybind11::keep_alive< 0, 1 >() ); cls.def( pybind11::self == pybind11::self ); cls.def( pybind11::self != pybind11::self ); registerExtendedEntityInterface( cls ); } } // namespace detail // registerGridEntity // ------------------ template< class Grid, int codim > auto registerGridEntity ( pybind11::handle scope ) { typedef typename Grid::template Codim< codim >::Entity Entity; auto entry = insertClass(scope, "Entity_" + std::to_string(codim), GenerateTypeName(MetaType(), "template Codim<" + std::to_string(codim) + ">::Entity")); if (entry.second) { detail::registerGridEntity< Entity >( scope, entry.first ); registerGridGeometry( entry.first ); } return entry.first; } // registerGridEntities // -------------------- template< class Grid, int... codim > inline static auto registerGridEntities ( pybind11::handle scope, std::integer_sequence< int, codim... > ) { return std::make_tuple( registerGridEntity< Grid, codim >( scope )... ); } template< class Grid > auto registerGridEntities ( pybind11::handle scope ) { return registerGridEntities< Grid >( scope, std::make_integer_sequence< int, Grid::dimension+1 >() ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_ENTITY_HH dune-grid-2.11.0/dune/python/grid/enums.hh000066400000000000000000000012401511655130300203170ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_ENUMS_HH #define DUNE_PYTHON_GRID_ENUMS_HH namespace Dune { namespace Python { enum class Reader { dgf, dgfString, gmsh, structured }; enum class VTKDataType { CellData, PointData, CellVector, PointVector }; enum class Marker { Coarsen = -1, Keep = 0, Refine = 1 }; } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_ENUMS_HH dune-grid-2.11.0/dune/python/grid/factory.hh000066400000000000000000000272131511655130300206470ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_FACTORY_HH #define DUNE_PYTHON_GRID_FACTORY_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // BoundarySegment // --------------- template< int dim, int dimworld > struct DUNE_PRIVATE BoundarySegment final : public Dune::BoundarySegment< dim, dimworld > { explicit BoundarySegment ( pybind11::function parametrization ) : parametrization_( std::move( parametrization ) ) {} FieldVector< double, dimworld > operator() ( const FieldVector< double, dim-1 > &local ) const { return parametrization_( local ).template cast< FieldVector< double, dimworld > >(); } private: pybind11::function parametrization_; }; namespace detail { namespace GridFactory { // insertVertices // -------------- template< class T, class Grid > inline static void insertVertices ( const pybind11::buffer_info &info, pybind11::format_descriptor< T >, Dune::GridFactory< Grid > &factory ) { const int dimWorld = Grid::dimensionworld; for( int i = 0; i < info.shape[ 0 ]; ++i ) { const std::size_t offset = i * (info.strides[ 0 ] / sizeof( T )); FieldVector< typename Grid::ctype, dimWorld > x; for( int j = 0; j < dimWorld; ++j ) x[ j ] = static_cast< T * >( info.ptr )[ offset + j * (info.strides[ 1 ] / sizeof( T )) ]; factory.insertVertex( x ); } } template< class Grid > inline static void insertVertices ( const pybind11::buffer_info &info, Dune::GridFactory< Grid > &factory ) { const int dimWorld = Grid::dimensionworld; if( (info.ndim != 2) || (info.shape[ 1 ] != dimWorld) ) throw std::invalid_argument( "vertex array must be of shape (*, " + std::to_string( dimWorld ) + ")" ); pybind11::handle_buffer_format(info, [ &info, &factory ] ( auto format ) { insertVertices( info, format, factory ); } ); } template< class Grid > inline static void insertVertices ( pybind11::list data, Dune::GridFactory< Grid > &factory ) { typedef FieldVector< typename Grid::ctype, Grid::dimensionworld > GlobalCoordinate; for( pybind11::handle item : data ) factory.insertVertex( item.template cast< GlobalCoordinate >() ); } template< class Grid > inline static void insertVertices ( pybind11::detail::item_accessor data, Dune::GridFactory< Grid > &factory ) { try { insertVertices( data.template cast< pybind11::buffer >().request(), factory ); return; } catch (const pybind11::type_error &) {} try { insertVertices( data.template cast< pybind11::list >(), factory ); return; } catch( const pybind11::cast_error & ) {} throw std::invalid_argument( "Incompatible array type for vertices." ); } // insertElements // -------------- template< class T, class Grid > inline static std::enable_if_t< std::is_integral< T >::value > insertElements ( GeometryType type, const pybind11::buffer_info &info, pybind11::format_descriptor< T >, Dune::GridFactory< Grid > &factory ) { const int dimGrid = Grid::dimension; const int numVertices = ReferenceElements< typename Grid::ctype, dimGrid >::general( type ).size( dimGrid ); if( (info.ndim != 2) || (info.shape[ 1 ] != numVertices) ) { std::ostringstream msg; msg << "buffer for geometry type " << type << " must be of shape (*, " << numVertices << ")\n"; if (info.ndim != 2) msg << " shape dimension is not 2 but " << info.ndim; else msg << " shape dimension is 2 but shape[1] is " << info.shape[ 1 ]; throw std::invalid_argument( msg.str() ); } std::vector< unsigned int > vertices( numVertices ); for( int i = 0; i < info.shape[ 0 ]; ++i ) { const std::size_t offset = i * (info.strides[ 0 ] / sizeof( T )); for( int j = 0; j < numVertices; ++j ) vertices[ j ] = static_cast< T * >( info.ptr )[ offset + j * (info.strides[ 1 ] / sizeof( T )) ]; factory.insertElement( type, vertices ); } } template< class T, class Grid > inline static std::enable_if_t< !std::is_integral< T >::value > insertElements ( GeometryType type, const pybind11::buffer_info &info, pybind11::format_descriptor< T >, Dune::GridFactory< Grid > &factory ) { std::ostringstream msg; msg << "Incompatible buffer format in array for geometry type " << type << ": '" << info.format << "'."; throw std::invalid_argument( msg.str() ); } template< class Grid > inline static void insertElements ( GeometryType type, const pybind11::buffer_info &info, Dune::GridFactory< Grid > &factory ) { pybind11::handle_buffer_format( info, [ type, &info, &factory ] ( auto format ) { insertElements( type, info, format, factory ); } ); } template< class Grid > inline static void insertElements ( GeometryType type, const pybind11::list &data, Dune::GridFactory< Grid > &factory ) { for( pybind11::handle item : data ) factory.insertElement( type, item.template cast< std::vector< unsigned int > >() ); } template< class Grid > inline static void insertElements ( GeometryType type, pybind11::detail::item_accessor data, Dune::GridFactory< Grid > &factory ) { try { insertElements( type, data.template cast< pybind11::buffer >().request(), factory ); return; } catch (const pybind11::type_error &) {} try { insertElements( type, data.template cast< pybind11::list >(), factory ); return; } catch( const pybind11::cast_error & ) {} std::ostringstream msg; msg << "Invalid array type for geometry type " << type << "."; throw std::invalid_argument( msg.str() ); } template< class Grid > inline static void insertElements ( pybind11::list data, Dune::GridFactory< Grid > &factory ) { for( pybind11::handle hItem : data ) { auto item = pybind11::reinterpret_borrow< pybind11::tuple >( hItem ); if( item.size() == 2 ) factory.insertElement( pybind11::cast< GeometryType >( item[ 0 ] ), pybind11::cast< std::vector< unsigned int > >( item[ 1 ] ) ); else throw std::invalid_argument( "Element tuple must be of length 2." ); } } template< class Grid > inline static void insertElements ( pybind11::detail::item_accessor data, Dune::GridFactory< Grid > &factory ) { insertElements( pybind11::cast< pybind11::list >( data ), factory ); } // insertBoundaries // ---------------- template< class Grid > inline static void insertBoundaries ( pybind11::list data, Dune::GridFactory< Grid > &factory ) { const int dimGrid = Grid::dimension; const int dimWorld = Grid::dimensionworld; for( pybind11::handle item : data ) { auto vertices = item.template cast< std::vector< unsigned int > >(); pybind11::function f; try { f = item.template cast< pybind11::function >(); } catch( const pybind11::cast_error & ) {} if( f ) factory.insertBoundarySegment( vertices, std::make_shared< BoundarySegment< dimGrid, dimWorld > >( f ) ); else factory.insertBoundarySegment( vertices ); } } template< class Grid > inline static void insertBoundaries ( pybind11::detail::item_accessor data, Dune::GridFactory< Grid > &factory ) { insertBoundaries( pybind11::cast< pybind11::list >( data ), factory ); } } // namespace GridFactory } // namespace detail // fillGridFactory // --------------- template< class Grid > inline void fillGridFactory ( const pybind11::dict &dict, Dune::GridFactory< Grid > &factory ) { const int dimGrid = Grid::dimension; if( dict.contains( "vertices" ) ) detail::GridFactory::insertVertices( dict[ "vertices" ], factory ); else throw std::invalid_argument( "Missing Key: 'vertices'" ); if( dict.contains( "elements" ) ) detail::GridFactory::insertElements( dict[ "elements" ], factory ); if( dict.contains( "lines" ) ) detail::GridFactory::insertElements( GeometryTypes::line, dict[ "lines" ], factory ); if( dict.contains( "line" ) ) detail::GridFactory::insertElements( GeometryTypes::line, dict[ "line" ], factory ); if( dict.contains( "triangles" ) ) detail::GridFactory::insertElements( GeometryTypes::triangle, dict[ "triangles" ], factory ); if( dict.contains( "triangle" ) ) detail::GridFactory::insertElements( GeometryTypes::triangle, dict[ "triangles" ], factory ); if( dict.contains( "tetrahedra" ) ) detail::GridFactory::insertElements( GeometryTypes::tetrahedron, dict[ "tetrahedra" ], factory ); if( dict.contains( "simplices" ) ) detail::GridFactory::insertElements( GeometryTypes::simplex( dimGrid ), dict[ "simplices" ], factory ); if( dict.contains( "tetra" ) ) { std::cout << "reading tetras\n"; detail::GridFactory::insertElements( GeometryTypes::simplex( dimGrid ), dict[ "tetra" ], factory ); } if( dict.contains( "quadrilaterals" ) ) detail::GridFactory::insertElements( GeometryTypes::quadrilateral, dict[ "quadrilaterals" ], factory ); if( dict.contains( "hexahedra" ) ) detail::GridFactory::insertElements( GeometryTypes::hexahedron, dict[ "hexahedra" ], factory ); if( dict.contains( "cubes" ) ) detail::GridFactory::insertElements( GeometryTypes::cube( dimGrid ), dict[ "cubes" ], factory ); if( dict.contains( "prisms" ) ) detail::GridFactory::insertElements( GeometryTypes::prism, dict[ "prisms" ], factory ); if( dict.contains( "pyramid" ) ) detail::GridFactory::insertElements( GeometryTypes::prism, dict[ "pyramids" ], factory ); if( dict.contains( "boundaries" ) ) detail::GridFactory::insertBoundaries( dict[ "boundaries" ], factory ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_FACTORY_HH dune-grid-2.11.0/dune/python/grid/function.hh000066400000000000000000000435161511655130300210310ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_FUNCTION_HH #define DUNE_PYTHON_GRID_FUNCTION_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_DUNE_VTK #include #endif #include #include namespace Dune { namespace Python { // GridFunctionTraits // ------------------ template< class GridFunction > struct GridFunctionTraits : public GridObjectTraits< GridFunction > { typedef typename GridObjectTraits< GridFunction >::LocalCoordinate LocalCoordinate; typedef std::decay_t< decltype( localFunction( std::declval< const GridFunction & >() ) ) > LocalFunction; typedef std::decay_t< decltype( std::declval< LocalFunction & >()( std::declval< const LocalCoordinate & >() ) ) > Range; typedef typename GridFunction::GridView GridView; }; namespace detail { template< class LocalCoordinate, class LocalFunction, class X > inline static auto callLocalFunction ( LocalFunction &&f, const X &x, PriorityTag< 2 > ) -> decltype( f( x ) ) { return f( x ); } template< class LocalCoordinate, class LocalFunction > inline static pybind11::object callLocalFunction ( LocalFunction &&f, pybind11::array_t< typename FieldTraits< LocalCoordinate >::field_type > x, PriorityTag< 1 > ) { return vectorize( [ &f ] ( const LocalCoordinate &x ) { return f( x ); }, x ); } template< class LocalCoordinate, class LocalFunction, class X > inline static auto callLocalFunction ( LocalFunction &&f, const X &x, PriorityTag<0> ) -> std::enable_if_t< !std::is_const< std::remove_reference_t< LocalFunction > >::value, pybind11::object > { return callLocalFunction< LocalCoordinate >( std::forward< LocalFunction >( f ), x, PriorityTag< 42 >() ); } template< class GridFunction, class... options > void registerGridFunction ( pybind11::handle scope, pybind11::class_< GridFunction, options... > cls ) { using pybind11::operator""_a; typedef typename GridFunctionTraits< GridFunction >::Range Range; cls.def_property_readonly( "grid", [] ( const GridFunction &self ) -> pybind11::handle { return pybind11::cast(Dune::Python::gridView( self )); } ); cls.def_property_readonly( "gridView", [] ( const GridFunction &self ) -> pybind11::handle { return pybind11::cast(Dune::Python::gridView( self )); } ); cls.def_property_readonly( "dimRange", [] ( pybind11::object self ) { return pybind11::int_( DimRange< Range >::value ); } ); cls.def( "addToVTKWriter", &addToVTKWriter< GridFunction >, pybind11::keep_alive< 3, 1 >(), "name"_a, "writer"_a, "dataType"_a ); cls.def( "cellData", [] ( const GridFunction &self, int level ) { return cellData( self, level ); }, "level"_a = 0 ); cls.def( "pointData", [] ( const GridFunction &self, int level ) { return pointData( self, level ); }, "level"_a = 0 ); auto dataWithPartition = [&cls](auto &part) { cls.def( "cellData", [] ( const GridFunction &self, int level, decltype(part) partition ) { return cellData( self, level, partition ); }, "level"_a = 0, pybind11::kw_only(), "partition"_a ); cls.def( "pointData", [] ( const GridFunction &self, int level, decltype(part) partition ) { return pointData( self, level, partition ); }, "level"_a = 0, pybind11::kw_only(), "partition"_a ); }; dataWithPartition(Dune::Partitions::interior); dataWithPartition(Dune::Partitions::ghost); dataWithPartition(Dune::Partitions::all); dataWithPartition(Dune::Partitions::interiorBorder); dataWithPartition(Dune::Partitions::interiorBorderOverlap); dataWithPartition(Dune::Partitions::interiorBorderOverlapFront); cls.def( "polygonData", [] ( const GridFunction &self ) { return polygonData( self ); }, R"doc( Store the grid with piecewise constant data in numpy arrays. Returns: pair with coordinate array storing the vertex coordinate of each polygon in the grid and an array with a range type for each polygon. )doc" ); } } // namespace detail // registerGridFunction // -------------------- template< class GridFunction, class... options > void registerGridFunction ( pybind11::handle scope, pybind11::class_< GridFunction, options... > cls ) { using pybind11::operator""_a; typedef typename GridFunctionTraits< GridFunction >::Element Element; typedef typename GridFunctionTraits< GridFunction >::LocalCoordinate LocalCoordinate; typedef typename GridFunctionTraits< GridFunction >::LocalFunction LocalFunction; typedef typename GridFunctionTraits< GridFunction >::Range Range; typedef pybind11::array_t< typename FieldTraits< LocalCoordinate >::field_type > Array; // TODO subclassing from a non registered traits class not covered by TypeRegistry pybind11::class_< LocalFunction > clsLocalFunction( cls, "LocalFunction", pybind11::dynamic_attr() ); registerLocalView< Element >( clsLocalFunction ); clsLocalFunction.def( "__call__", [] ( LocalFunction &self, const LocalCoordinate &x ) { return detail::callLocalFunction< LocalCoordinate >( self, x, PriorityTag<2>() ); }, "x"_a ); clsLocalFunction.def( "__call__", [] ( LocalFunction &self, Array x ) { return detail::callLocalFunction< LocalCoordinate >( self, x, PriorityTag<2>() ); }, "x"_a ); clsLocalFunction.def_property_readonly( "dimRange", [] ( pybind11::object self ) { return pybind11::int_( DimRange< Range >::value ); } ); cls.def( "localFunction", [] ( const GridFunction &self ) { return localFunction( self ); }, pybind11::keep_alive< 0, 1 >() ); cls.def( "localFunction", [] ( const GridFunction &self, const Element &element ) { auto lf = localFunction(self); lf.bind(element); return lf; }, pybind11::keep_alive< 0, 1 >(), pybind11::keep_alive< 0, 2 >() ); cls.def( "__call__", [] ( const GridFunction &self, const Element &element, LocalCoordinate &x ) { auto lf = localFunction(self); lf.bind(element); auto y = detail::callLocalFunction< LocalCoordinate >( lf, x, PriorityTag<2>() ); lf.unbind(); return y; }, "element"_a, "x"_a ); cls.def( "__call__", [] ( const GridFunction &self, const Element &element, Array x ) { auto lf = localFunction(self); lf.bind(element); auto y = detail::callLocalFunction< LocalCoordinate >( lf, x, PriorityTag<2>() ); lf.unbind(); return y; }, "element"_a, "x"_a ); detail::registerGridFunction(scope,cls); #if HAVE_DUNE_VTK typedef typename GridFunctionTraits< GridFunction >::GridView GridView; using VirtualizedGF = Dune::Vtk::GridFunction; // register the Function class if not already available auto vgfClass = Python::insertClass(scope,"VtkFunction", Python::GenerateTypeName("Dune::Vtk::GridFunction",MetaType()), Python::IncludeFiles{"dune/vtk/gridfunctions/gridfunction.hh"}); vgfClass.first.def( pybind11::init( [] ( GridFunction &gf ) { // TODO: perhaps grid functions should just have a name attribute in general return new VirtualizedGF( gf, Dune::Vtk::FieldInfo{"tmp"} ); } ) ); pybind11::implicitly_convertible(); #endif } template struct stdFunction { static const unsigned int dimRange = (dimR ==0 ? 1 : dimR); typedef typename GridView::template Codim< 0 >::Entity Entity; typedef typename Entity::Geometry::LocalCoordinate Coordinate; typedef typename std::conditional< dimR == 0, double, Dune::FieldVector< double, dimRange > >::type Value; typedef std::function type; }; template struct EvaluateType { typedef typename GridView::template Codim< 0 >::Entity Entity; typedef typename Entity::Geometry::LocalCoordinate Coordinate; typedef typename std::conditional< dimR == 0, double, Dune::FieldVector< double, dimR > >::type Value; static std::string name() { std::string entity = findInTypeRegistry().first->second.name; std::string coord = findInTypeRegistry().first->second.name; std::string value; if (dimR==0) value = "double"; else { auto found = findInTypeRegistry(); assert(!found.second); value = found.first->second.name; } return "std::function<"+value+"(const "+entity+"&,const "+coord+"&)>"; } }; template struct EvaluateType { static std::string name() { return "pybind11::function"; } }; namespace detail { // PyGridFunctionEvaluator // ----------------------- template struct DUNE_PRIVATE PyGridFunctionEvaluator {}; template struct DUNE_PRIVATE PyGridFunctionEvaluator { static const unsigned int dimRange = (dimR ==0 ? 1 : dimR); typedef typename GridView::template Codim< 0 >::Entity Entity; typedef typename Entity::Geometry::LocalCoordinate Coordinate; typedef typename std::conditional< dimR == 0, double, Dune::FieldVector< double, dimRange > >::type Value; explicit PyGridFunctionEvaluator ( pybind11::function evaluate ) : evaluate_( evaluate ) {} Value operator() ( const Entity &entity, const Coordinate &x ) const { pybind11::gil_scoped_acquire acq; return pybind11::cast< Value >( evaluate_( entity, x ) ); } pybind11::array_t< double > operator() ( const Entity &entity, const pybind11::array_t x ) const { pybind11::gil_scoped_acquire acq; return pybind11::cast< pybind11::array_t< double > >( evaluate_( entity, x ) ); } pybind11::function evaluate() const { return evaluate_; } private: pybind11::function evaluate_; }; template struct DUNE_PRIVATE PyGridFunctionEvaluator::type > { static const unsigned int dimRange = (dimR ==0 ? 1 : dimR); typedef typename GridView::template Codim< 0 >::Entity Entity; typedef typename Entity::Geometry::LocalCoordinate Coordinate; typedef typename std::conditional< dimR == 0, double, Dune::FieldVector< double, dimRange > >::type Value; typedef typename stdFunction::type Evaluate; explicit PyGridFunctionEvaluator ( Evaluate evaluate ) : evaluate_( evaluate ) {} Value operator() ( const Entity &entity, const Coordinate &x ) const { return evaluate_( entity, x ); } Evaluate evaluate() const { return evaluate_; } private: Evaluate evaluate_; }; // registerPyGridFunction // ---------------------- template< class GridView, class Evaluate, unsigned int dimRange > auto registerPyGridFunction ( pybind11::handle scope, const std::string &name, bool scalar, std::integral_constant< unsigned int, dimRange > ) { using pybind11::operator""_a; typedef typename GridView::template Codim<0>::Entity Entity; typedef typename Entity::Geometry::LocalCoordinate LocalCoordinate; typedef PyGridFunctionEvaluator Evaluator; typedef SimpleGridFunction< GridView, Evaluator > GridFunction; if (dimRange>0) Dune::Python::registerFieldVector(scope); addToTypeRegistry(GenerateTypeName("Dune::Python::detail::PyGridFunctionEvaluator", MetaType(),dimRange, EvaluateType::name() ), IncludeFiles{"dune/python/grid/function.hh"}); std::string clsName = name + std::to_string( dimRange ); auto gf = insertClass< GridFunction >( scope, clsName, pybind11::dynamic_attr(), GenerateTypeName("Dune::Python::SimpleGridFunction", MetaType(), Dune::MetaType()), IncludeFiles{"dune/python/grid/function.hh"}); gf.first.def(pybind11::init([](GridView &gridView, Evaluate callable) { return new GridFunction( gridView, PyGridFunctionEvaluator(callable) ); }), "gridView"_a, "callable"_a, pybind11::keep_alive<1,2>() ); gf.first.def( pybind11::pickle( [](const pybind11::object &self) { // __getstate__ GridFunction& gv = self.cast(); /* Return a tuple that fully encodes the state of the object */ pybind11::dict d; if (pybind11::hasattr(self, "__dict__")) { d = self.attr("__dict__"); } return pybind11::make_tuple(gv.gridView(),gv.localEvaluator().evaluate(),d); }, [](pybind11::tuple t) { // __setstate__ if (t.size() != 3) throw std::runtime_error("Invalid state in GridFunction::setstate with "+std::to_string(t.size())+"arguments!"); pybind11::handle pygv = t[0]; GridView& gv = pygv.cast(); pybind11::handle pyeval = t[1]; Evaluate callable = pyeval.cast(); /* Create a new C++ instance */ auto py_state = t[2].cast(); return std::make_pair( new GridFunction(gv,PyGridFunctionEvaluator(callable)), py_state); } ),pybind11::keep_alive<1,2>()); if (gf.second) { Dune::Python::registerGridFunction( scope, gf.first ); gf.first.def_property_readonly( "scalar", [scalar] ( pybind11::object self ) { return scalar; } ); if constexpr (dimRange>0) { typedef typename Dune::Python::stdFunction::type Evaluate0; detail::registerPyGridFunction< GridView, Evaluate0, 0 > ( scope, name, true, std::integral_constant< unsigned int, 0 >() ); gf.first.def( "__getitem__", [] ( const GridFunction &self, std::size_t c ) { Evaluate0 eval0 = [&self,c](const Entity &e, const LocalCoordinate &x) -> double { auto lf = localFunction(self); lf.bind(e); auto y = detail::callLocalFunction< LocalCoordinate >( lf, x, PriorityTag<2>() ); lf.unbind(); return y[0]; }; auto gridFunction = simpleGridFunction( gridView(self), detail::PyGridFunctionEvaluator< GridView, 0, Evaluate0 >( std::move( eval0 ) ) ); return gridFunction; // return pybind11::cast( std::move( gridFunction ) ); }, pybind11::keep_alive< 0, 1 >() ); } } return gf; } } // namespace detail template< class GridView, class Evaluate, int dimRange > auto registerGridFunction ( pybind11::handle scope, std::string name, bool scalar ) { detail::registerPyGridFunction< GridView, Evaluate, dimRange >( scope, name, scalar, std::integral_constant< unsigned int, dimRange >() ); } template struct FunctionRange { static constexpr int value() { if constexpr (std::is_convertible_v) return 0; else return Value::dimension; } }; template< class GridView, class Eval > auto registerGridFunction ( pybind11::handle scope, pybind11::object gp, std::string name, Eval eval ) { typedef typename GridView::template Codim<0>::Entity Entity; typedef typename Entity::Geometry::LocalCoordinate LocalCoordinate; typedef decltype(eval(std::declval(),std::declval())) Value; static constexpr int dimRange = FunctionRange::value(); typedef typename Dune::Python::stdFunction::type Evaluate; registerGridFunction< GridView, Evaluate, dimRange >( scope, name, dimRange==0 ); Evaluate evaluate(eval); const GridView &gridView = gp.cast< const GridView & >(); auto gridFunction = simpleGridFunction( gridView, detail::PyGridFunctionEvaluator< GridView, dimRange, Evaluate >( std::move( evaluate ) ) ); return pybind11::cast( std::move( gridFunction ), pybind11::return_value_policy::move, gp ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_FUNCTION_HH dune-grid-2.11.0/dune/python/grid/geometry.hh000066400000000000000000000353331511655130300210350ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_GEOMETRY_HH #define DUNE_PYTHON_GRID_GEOMETRY_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { namespace detail { // registerGridGeometry // -------------------- template< class Geometry, class Array > inline static pybind11::array_t< double > pushForwardGradients ( const Geometry &geo, Array xVec, pybind11::array_t< double > gVec ) { typedef typename Geometry::LocalCoordinate LocalCoordinate; typedef typename Geometry::GlobalCoordinate GlobalCoordinate; // x = (localCoord,nofQuad) auto x = xVec.unchecked(); // g = (dimRange,localCoord,nofQuad) auto g = gVec.unchecked(); // ret = (dimRange,globalCoord,nofQuad) pybind11::array_t< double > ret( std::array< ssize_t, 3 >{{ g.shape( 0 ), static_cast< ssize_t >( Geometry::GlobalCoordinate::size() ), g.shape( 2 ) }} ); auto y = ret.template mutable_unchecked< 3 >(); if( x.shape( 1 ) != g.shape( 2 ) ) std::cout << x.shape( 1 ) << " " << g.shape( 2 ) << std::endl; if( x.shape( 0 ) != ssize_t(LocalCoordinate::size()) ) std::cout << x.shape( 0 ) << " " << Geometry::LocalCoordinate::size() << std::endl; for( ssize_t p = 0; p < g.shape( 2 ); ++p ) { LocalCoordinate xLocal; for( std::size_t l = 0; l < LocalCoordinate::size(); ++l ) xLocal[ l ] = x( l, p ); const auto jit = geo.jacobianInverseTransposed( xLocal ); for( ssize_t range = 0; range < g.shape( 0 ); ++range ) { // Performance Issue: // The copies gradLocal and gradGlobal can be avoided by providing // a DenseVector implementation based on a single axis of the // pybind11::array accessor, because the `jit.mv` method is required // to take arbitrary implementations of the dense vector interface. LocalCoordinate gradLocal; for( std::size_t l = 0; l < LocalCoordinate::size(); ++l ) gradLocal[ l ] = g(range, l, p ); GlobalCoordinate gradGlobal; jit.mv( gradLocal, gradGlobal ); for( std::size_t r = 0; r < GlobalCoordinate::size(); ++r ) y( range, r, p ) = gradGlobal[ r ]; } } return ret; } template< class Geometry, class... options > void registerGridGeometry ( pybind11::handle scope, pybind11::class_ cls ) { const int mydimension = Geometry::mydimension; const int coorddimension = Geometry::coorddimension; typedef typename Geometry::ctype ctype; typedef FieldVector< ctype, mydimension > LocalCoordinate; typedef FieldVector< ctype, coorddimension > GlobalCoordinate; typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian; typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed; typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianInverse; typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed; registerFieldVecMat::apply(); registerFieldVecMat::apply(); registerFieldVecMat::apply(); registerFieldVecMat::apply(); registerFieldVecMat::apply(); registerFieldVecMat::apply(); typedef pybind11::array_t< ctype > Array; using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.doc() = R"doc( A geometry describes a map from the reference domain into a Euclidean space, where the reference domain is given by the reference element. The mapping is required to be one-to-one. We refer to points within the reference domain as "local" points. The image of a local point is called its (global) position. Note: The image of the mapping may be a submanifold of the Euclidean space. )doc"; cls.def( "corner", [] ( const Geometry &self, int i ) { const int size = self.corners(); if( (i < 0) || (i >= size) ) throw pybind11::value_error( "Invalid index: " + std::to_string( i ) + " (must be in [0, " + std::to_string( size ) + "))." ); return self.corner( i ); }, "index"_a, R"doc( get global position a reference corner Args: index: index of the reference corner Returns: global position of the reference corner Note: If the argument "index" is omitted, this method returns a NumPy array containing the global position of all corners. This version may be used to vectorize the code. )doc" ); cls.def( "corner", [] ( const Geometry &self ) { const int size = self.corners(); pybind11::array_t< ctype > cornersArray( { static_cast< ssize_t >( coorddimension ), static_cast< ssize_t >( size ) } ); auto corners = cornersArray.template mutable_unchecked< 2 >(); for( int i = 0; i < size; ++i ) { const auto corner = self.corner( i ); for( int j = 0; j < coorddimension; ++j ) corners( j, i ) = corner[ j ]; } return cornersArray; } ); cls.def_property_readonly( "corners", [] ( const Geometry &self ) { const int size = self.corners(); pybind11::tuple corners( size ); for( int i = 0; i < size; ++i ) corners[ i ] = pybind11::cast( self.corner( i ) ); return corners; }, R"doc( get global positions of all reference corners Note: This function differs from the vectorized version of 'corner' in the way the corners are returned. This method returns a tuple of global positions of type FieldVector. Returns: tuple of global positions, in the order given by the reference element )doc" ); cls.def_property_readonly( "center", [] ( const Geometry &self ) { return self.center(); }, R"doc( global position of the barycenter of the reference element )doc" ); cls.def_property_readonly( "volume", [] ( const Geometry &self ) { return self.volume(); }, R"doc( volume of the map's image The volume is measured using the Hausdorff measure of the corresponding dimension. )doc" ); cls.def_property_readonly( "affine", [] ( const Geometry &self ) { return self.affine(); }, R"doc( True, if the map is affine-linear, False otherwise )doc" ); cls.def_property_readonly( "referenceElement", []( const Geometry &self ) { return referenceElement< double, mydimension >( self.type() ); }, pybind11::keep_alive< 0, 1 >(), R"doc( corresponding reference element, describing the domain of the map )doc" ); cls.def( "toGlobal", [] ( const Geometry &self, const LocalCoordinate &x ) { return self.global( x ); }, "x"_a, R"doc( obtain global position of a local point Args: x: local point Returns: global position of x Note: This method may be used in vectorized form by passing in a NumPy array for 'x'. )doc" ); cls.def( "toGlobal", [] ( const Geometry &self, Array x ) { return vectorize( [ &self ] ( const LocalCoordinate &x ) { return self.global( x ); }, x ); } ); cls.def( "toLocal", [] ( const Geometry &self, const GlobalCoordinate &y ) { return self.local( y ); }, "y"_a, R"doc( obtain local point mapped to a global position Args: y: global position Returns: local point mapped to y Note: This method may be used in vectorized form by passing in a NumPy array for 'y'. )doc" ); cls.def( "toLocal", [] ( const Geometry &self, Array y ) { return vectorize( [ &self ] ( const GlobalCoordinate &y ) { return self.local( y ); }, y ); } ); cls.def( "integrationElement", [] ( const Geometry &self, const LocalCoordinate &x ) { return self.integrationElement( x ); }, "x"_a, R"doc( obtain integration element in a local point The integration element is the factor appearing in the integral transformation formula. It describes the weight factor when transforming a quadrature rule on the reference element into a quadrature rule on the image of this map. Args: x: local point Returns: integration element in x Note: This method may be used in vectorized form by passing in a NumPy array for 'x'. )doc" ); cls.def( "integrationElement", [] ( const Geometry &self, Array x ) { return vectorize( [ &self ] ( const LocalCoordinate &x ) { return self.integrationElement( x ); }, x ); } ); cls.def( "jacobian", [] ( const Geometry &self, const LocalCoordinate &x ) { return static_cast< Jacobian >( self.jacobian( x ) ); }, "x"_a, R"doc( obtain the Jacobian of this mapping in a local point The Jacobian describes the push-forward for tangential vectors from the reference domain to the image of this map. Args: x: local point Returns: Jacobian matrix in x Note: This method may be used in vectorized form by passing in a NumPy array for 'x'. )doc" ); cls.def( "jacobian", [] ( const Geometry &self, Array x ) { return vectorize( [ &self ] ( const LocalCoordinate &x ) { return static_cast< Jacobian >( self.jacobian( x ) ); }, x ); } ); cls.def( "jacobianTransposed", [] ( const Geometry &self, const LocalCoordinate &x ) { return static_cast< JacobianTransposed >( self.jacobianTransposed( x ) ); }, "x"_a, R"doc( obtain transposed of the Jacobian of this mapping in a local point The rows of the returned matrix describe the tangential vectors in the global position of the local point. The Jacobian itself describes the push-forward for tangential vectors from the reference domain to the image of this map. Args: x: local point Returns: transposed of the Jacobian matrix in x Note: This method may be used in vectorized form by passing in a NumPy array for 'x'. )doc" ); cls.def( "jacobianTransposed", [] ( const Geometry &self, Array x ) { return vectorize( [ &self ] ( const LocalCoordinate &x ) { return static_cast< JacobianTransposed >( self.jacobianTransposed( x ) ); }, x ); } ); cls.def( "jacobianInverse", [] ( const Geometry &self, const LocalCoordinate &x ) { return static_cast< JacobianInverse >( self.jacobianInverse( x ) ); }, "x"_a, R"doc( obtain inverse Jacobian of this mapping in a local point The inverse Jacobian describes the push-forward of cotangential vectors from the reference domain to the image of this map. Args: x: local point Returns: Inverse Jacobian matrix in x Note: This method may be used in vectorized form by passing in a NumPy array for 'x'. )doc" ); cls.def( "jacobianInverse", [] ( const Geometry &self, Array x ) { return vectorize( [ &self ] ( const LocalCoordinate &x ) { return static_cast< JacobianInverse >( self.jacobianInverse( x ) ); }, x ); } ); cls.def( "jacobianInverseTransposed", [] ( const Geometry &self, const LocalCoordinate &x ) { return static_cast< JacobianInverseTransposed >( self.jacobianInverseTransposed( x ) ); }, "x"_a, R"doc( obtain transposed of the inverse Jacobian of this mapping in a local point This matrix describes the push-forward for local function gradients to the image of this map. The inverse Jacobian itself describes the push-forward of cotangential vectors from the reference domain to the image of this map. Args: x: local point Returns: transposed of the Jacobian matrix in x Note: This method may be used in vectorized form by passing in a NumPy array for 'x'. )doc" ); cls.def( "jacobianInverseTransposed", [] ( const Geometry &self, Array x ) { return vectorize( [ &self ] ( const LocalCoordinate &x ) { return static_cast< JacobianInverseTransposed >( self.jacobianInverseTransposed( x ) ); }, x ); } ); cls.def( "pushForwardGradients", [] ( const Geometry &self, Array x, pybind11::array_t g ) { return pushForwardGradients(self,x,g); } ); } } // namespace detail // registerGridGeometry // -------------------- template< class Base, class Geometry = typename Base::Geometry > inline static pybind11::class_< Geometry > registerGridGeometry ( pybind11::handle scope ) { auto entry = insertClass< Geometry >( scope, "Geometry", GenerateTypeName( scope, "Geometry" ) ); if ( entry.second ) detail::registerGridGeometry( scope, entry.first ); return entry.first; } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_GEOMETRY_HH dune-grid-2.11.0/dune/python/grid/gridview.hh000066400000000000000000000575101511655130300210230ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_GRIDPART_HH #define DUNE_PYTHON_GRID_GRIDPART_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_DUNE_VTK #include #endif namespace Dune { namespace Python { // ProxyDataHandle for parallel communication // ------------------------------------------ struct DUNE_PRIVATE ProxyDataHandle : public Dune::CommDataHandleIF< ProxyDataHandle, double > { ProxyDataHandle ( pybind11::object dataHandle ) : contains_( method( dataHandle, "contains" ) ), fixedSze_( method( dataHandle, "fixedSize" ) ), size_( method( dataHandle, "size" ) ), gather_( method( dataHandle, "gather" ) ), scatter_( method( dataHandle, "scatter" ) ) {} bool contains ( int dim, int codim ) const { return contains_( dim, codim ).cast< bool >(); } bool fixedSize ( int dim, int codim ) const { return fixedSze_( dim, codim ).cast< bool >(); } template< class Entity > std::size_t size ( const Entity &entity ) const { return size_( entity ).template cast< std::size_t >(); } template< class Buffer, class Entity > void gather ( Buffer &buffer, const Entity &entity ) const { pybind11::list data = gather_( entity ); for( const pybind11::handle &x : data ) buffer.write( x.template cast< double >() ); } template< class Buffer, class Entity > void scatter ( Buffer &buffer, const Entity &entity, std::size_t n ) { pybind11::list data; for( std::size_t i = 0; i < n; ++i ) { double x; buffer.read( x ); data.append( pybind11::cast( x ) ); } scatter_( entity, data ); } private: pybind11::object method ( pybind11::handle dataHandle, const char *name ) { pybind11::object method = dataHandle.attr( name ); if( !method ) throw std::invalid_argument( std::string( "Method \"" ) + name + std::string( "\" missing from data handle." ) ); return method; } pybind11::object contains_, fixedSze_; pybind11::object size_, gather_, scatter_; }; namespace detail { // registerGridViewConstructorFromGrid // ----------------------------------- template< class GridView, class... options, std::enable_if_t< std::is_same< GridView, typename GridView::Grid::LeafGridView >::value, int > = 0 > void registerGridViewConstructorFromGrid ( pybind11::class_< GridView, options... > &cls, PriorityTag< 2 > ) { cls.def( pybind11::init( [] ( typename GridView::Grid &grid ) { return new GridView( grid.leafGridView() ); } ), pybind11::keep_alive< 1, 2 >() ); cls.def( pybind11::pickle( [](const pybind11::object &self) { // __getstate__ GridView& gv = self.cast(); /* Return a tuple that fully encodes the state of the object */ pybind11::dict d; if (pybind11::hasattr(self, "__dict__")) { d = self.attr("__dict__"); } return pybind11::make_tuple(gv.grid(),d); }, [](pybind11::tuple t) { // __setstate__ if (t.size() != 2) throw std::runtime_error("Invalid state in GridView::setstate with "+std::to_string(t.size())+"arguments!"); pybind11::handle pyHg = t[0]; typename GridView::Grid& hg = pyHg.cast(); /* Create a new C++ instance */ auto py_state = t[1].cast(); return std::make_pair(new GridView(hg.leafGridView()), py_state); } ),pybind11::keep_alive<1,2>()); } template< class GridView, class... options, std::enable_if_t< std::is_constructible< GridView, typename GridView::Grid & >::value, int > = 0 > void registerGridViewConstructorFromGrid ( pybind11::class_< GridView, options... > &cls, PriorityTag< 1 > ) { cls.def( pybind11::init( [] ( typename GridView::Grid &grid ) { return new GridView( grid ); } ), pybind11::keep_alive< 1, 2 >() ); cls.def( pybind11::pickle( [](const pybind11::object &self) { // __getstate__ GridView& gv = self.cast(); /* Return a tuple that fully encodes the state of the object */ pybind11::dict d; if (pybind11::hasattr(self, "__dict__")) { d = self.attr("__dict__"); } return pybind11::make_tuple(gv.grid(),d); }, [](pybind11::tuple t) { // __setstate__ if (t.size() != 2) throw std::runtime_error("Invalid state in GridView::setstate with "+std::to_string(t.size())+"arguments!"); pybind11::handle pyHg = t[0]; typename GridView::Grid& hg = pyHg.cast(); /* Create a new C++ instance */ auto py_state = t[1].cast(); return std::make_pair(new GridView(hg), py_state); } ),pybind11::keep_alive<1,2>()); } template< class GridView, class... options > void registerGridViewConstructorFromGrid ( pybind11::class_< GridView, options... > &, PriorityTag< 0 > ) {} } // namespace detail // registerGridView // ---------------- template< class GridView, class... options > inline static void registerGridView ( pybind11::handle scope, pybind11::class_< GridView, options... > cls ) { typedef typename GridView::Grid Grid; typedef PyGridViewIterator< GridView, 0 > PyElementIterator; using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); detail::registerGridViewConstructorFromGrid( cls, PriorityTag< 42 >() ); cls.attr( "dimGrid" ) = pybind11::int_( static_cast< int >( GridView::dimension ) ); cls.attr( "dimWorld" ) = pybind11::int_( static_cast< int >( GridView::dimensionworld ) ); registerGridEntities< GridView >( cls ); registerGridIntersection< GridView >( cls ); cls.def( "_mapper", [] ( GridView &self, pybind11::object layout ) { return makeMultipleCodimMultipleGeomTypeMapper( self, layout ); }, pybind11::keep_alive< 0, 1 >(), "layout"_a, R"doc( Set up a mapper to attach data to the grid. The layout argument defines how many degrees of freedom to assign to each subentity of a geometry type. Args: layout: function, dict, tuple, or list defining the number of indices to reserve for each geometry type. If layout is a dict, is must map geometry types to integers. All types not mentioned in the dictionary are assumed to be zero. If layout is a tuple or a list, it must contain exactly dimension+1 integers, one for each codimension in the grid. if layout is a function it maps a geometry type to the number of degrees of freedom to reserve. Here a return value of 0 or `False` indicates that no data is to be attach, `True` can be used instead of 1. Returns: the mapper )doc" ); // register iterators Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [] ( auto codim ) { registerPyGridViewIterator< GridView, codim >(); } ); if( Capabilities::canIterate< Grid, 0 >::value ) cls.def_property_readonly( "elements", [] ( pybind11::object self ) { return makePyGridViewIterator< GridView, 0 >( self ); }, R"doc( sequence of all elements (i.e., entities of codimension 0) )doc" ); if( Capabilities::canIterate< Grid, 1 >::value ) cls.def_property_readonly( "facets", [] ( pybind11::object self ) { return makePyGridViewIterator< GridView, 1 >( self ); }, R"doc( range of all facets (i.e., entities of codimension 1) )doc" ); if( Capabilities::canIterate< Grid, GridView::dimension-1 >::value ) cls.def_property_readonly( "edges", [] ( pybind11::object self ) { return makePyGridViewIterator< GridView, GridView::dimension-1 >( self ); }, R"doc( range of all edges (i.e., entities of dimension 1) )doc" ); if( Capabilities::canIterate< Grid, GridView::dimension >::value ) cls.def_property_readonly( "vertices", [] ( pybind11::object self ) { return makePyGridViewIterator< GridView, GridView::dimension >( self ); }, R"doc( range of all vertices (i.e., entities of dimension 0) )doc" ); std::array< pybind11::object (*) ( pybind11::object ), GridView::dimension+1 > makePyGridViewIterators; Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [ &makePyGridViewIterators ] ( auto codim ) { makePyGridViewIterators[ codim ] = makePyGridViewIterator< GridView, codim >; } ); cls.def( "entities", [ makePyGridViewIterators ] ( pybind11::object self, int codim ) { if( (codim < 0) || (codim > GridView::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( GridView::dimension ) + "])." ); return makePyGridViewIterators[ codim ]( self ); }, "codim"_a, R"doc( get range of entities for a codimension Args: codim: Codimension to obtain range of entities for )doc" ); registerPyIntersectionIterator< GridView >(); cls.def( "intersections", [] ( const GridView &self, const typename GridView::template Codim< 0 >::Entity &e ) { return PyIntersectionIterator< GridView >( self.ibegin( e ), self.iend( e ) ); }, pybind11::keep_alive< 0, 1 >(), "element"_a, R"doc( get range of all codim-1 intersections for an element Args: element: Element of obtain intersections for )doc" ); registerPyBoundaryIntersectionIterator< GridView, PyElementIterator >(); cls.def_property_readonly( "boundaryIntersections", [] ( const GridView &self ) { return PyBoundaryIntersectionIterator< GridView, PyElementIterator >( self, PyElementIterator( self.template begin< 0 >(), self.template end< 0 >() ) ); }, pybind11::keep_alive< 0, 1 >(), R"doc( range of all codim-1 boundary intersections of the grid )doc" ); // register partitions registerGridViewPartition< GridView, Interior_Partition >(); registerGridViewPartition< GridView, InteriorBorder_Partition >(); registerGridViewPartition< GridView, Overlap_Partition >(); registerGridViewPartition< GridView, OverlapFront_Partition >(); registerGridViewPartition< GridView, All_Partition >(); registerGridViewPartition< GridView, Ghost_Partition >(); cls.def_property_readonly( "interiorPartition", [] ( pybind11::object self ) { return GridViewPartition< GridView, Interior_Partition >( self ); }, R"doc( Partition containing only interior entities. )doc" ); cls.def_property_readonly( "interiorBorderPartition", [] ( pybind11::object self ) { return GridViewPartition< GridView, InteriorBorder_Partition >( self ); }, R"doc( Partition containing only interior and border entities. )doc" ); cls.def_property_readonly( "overlapPartition", [] ( pybind11::object self ) { return GridViewPartition< GridView, Overlap_Partition >( self ); }, R"doc( Partition containing only interior, border and overlap entities. )doc" ); cls.def_property_readonly( "overlapFrontPartition", [] ( pybind11::object self ) { return GridViewPartition< GridView, OverlapFront_Partition >( self ); }, R"doc( Partition containing only interior, border, overlap, and front entities. )doc" ); cls.def_property_readonly( "allPartition", [] ( pybind11::object self ) { return GridViewPartition< GridView, All_Partition >( self ); }, R"doc( Partition containing all entities. )doc" ); cls.def_property_readonly( "ghostPartition", [] ( pybind11::object self ) { return GridViewPartition< GridView, Ghost_Partition >( self ); }, R"doc( Partition containing only ghost entities. )doc" ); cls.def("__repr__", [] (const GridView &gridView) -> std::string { return "LeafGrid with " + std::to_string(gridView.indexSet().size(0)) + " elements"; }); cls.def_property_readonly( "hierarchicalGrid", [] ( const GridView &self ) -> const Grid & { return self.grid(); }, R"doc( associated hierarchical grid )doc" ); cls.def_property_readonly( "grid", [] ( const GridView &self ) -> const Grid & { return self.grid(); }, R"doc( associated hierarchical grid )doc" ); cls.def_property_readonly_static( "dimension", [] ( pybind11::object ) { return int(GridView::dimension); } ); cls.def_property_readonly_static( "dimensionworld", [] ( pybind11::object ) { return int(GridView::dimensionworld); } ); cls.def( "size", [] ( const GridView &self, int codim ) { if( (codim < 0) || (codim > GridView::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( GridView::dimension ) + "])." ); return self.size( codim ); }, "codim"_a, R"doc( Args: codim: required codimension Returns: number of subentities of codimension `codim` )doc" ); cls.def( "size", [] ( const GridView &self, Dune::GeometryType gt ) { if( (gt.dim() < 0) || (gt.dim() > GridView::dimension) ) throw pybind11::value_error( "Invalid geometry type (dimension must be in [0, " + std::to_string( GridView::dimension ) + "])." ); return self.size( gt ); }, "gt"_a, R"doc( Args: gt: a geometry type Returns: number of subentities of the given geometry type )doc" ); registerVTKWriter< GridView >( cls ); cls.def( "vtkWriter", [] ( const GridView &self, const bool nonconforming = false ) { const VTK::DataMode dm = nonconforming ? VTK::nonconforming : VTK::conforming; return new VTKWriter< GridView >( self, dm ); }, pybind11::keep_alive< 0, 1 >() ); cls.def( "vtkWriter", [] ( const GridView &self, int subsampling ) { return new SubsamplingVTKWriter< GridView >( self, Dune::refinementIntervals(1<(), "subsampling"_a ); cls.def( "overlapSize", [] ( const GridView &self, int codim ) { if( (codim < 0) || (codim > GridView::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( GridView::dimension ) + "])." ); return self.overlapSize( codim ); }, "codim"_a ); cls.def( "ghostSize", [] ( const GridView &self, int codim ) { if( (codim < 0) || (codim > GridView::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( GridView::dimension ) + "])." ); return self.ghostSize( codim ); }, "codim"_a ); cls.def_property_readonly( "_indexSet", [] ( const GridView &self ) -> const typename GridView::IndexSet & { return self.indexSet(); }, pybind11::return_value_policy::reference, pybind11::keep_alive< 0, 1 >(), R"doc( index set for the grid )doc" ); cls.def_property_readonly( "comm", [] ( const GridView &gridView ) -> const typename Grid::Communication & { return gridView.grid().comm(); }, pybind11::return_value_policy::reference, pybind11::keep_alive< 0, 1 >(), R"doc( collective communication for the grid Note: For collective (or global) operations, all processes in this collective communication must call the corresponding method. )doc" ); typedef NumPyCommDataHandle< MultipleCodimMultipleGeomTypeMapper< GridView >, double, std::function< double ( double, double ) > > CommDataHandle; cls.def( "communicate", [] ( const GridView &gridView, CommDataHandle &dataHandle, InterfaceType iftype, CommunicationDirection dir ) { gridView.communicate( dataHandle, iftype, dir ); } ); cls.def( "communicate", [] ( const GridView &gridView, pybind11::object dataHandle, InterfaceType iftype, CommunicationDirection dir ) { ProxyDataHandle proxyDataHandle( std::move( dataHandle ) ); gridView.communicate( proxyDataHandle, iftype, dir ); }); // export grid capabilities cls.def_property_readonly( "conforming", [] ( pybind11::object ) { return static_cast< bool >( GridView::conforming ); } ); if( Capabilities::hasSingleGeometryType< Grid >::v ) cls.def_property_readonly_static( "type", [] ( pybind11::object ) { return GeometryType( Capabilities::hasSingleGeometryType< Grid >::topologyId, Grid::dimension ); } ); cls.def_property_readonly_static( "isCartesian", [] ( pybind11::object ) { return Capabilities::isCartesian< Grid >::v; } ); cls.def_property_readonly_static( "canCommunicate", [] ( pybind11::object ) { pybind11::tuple canCommunicate( Grid::dimension+1 ); Hybrid::forEach( std::make_integer_sequence< int, Grid::dimension+1 >(), [ &canCommunicate ] ( auto codim ) { canCommunicate[ codim ] = pybind11::cast( bool( Capabilities::canCommunicate< Grid, codim >::v ) ); } ); return canCommunicate; } ); cls.def_property_readonly_static( "threadSafe", [] ( pybind11::object ) { return Capabilities::viewThreadSafe< Grid >::v; } ); // export utility methods cls.def( "coordinates", [] ( const GridView &self, int dimworld ) { return coordinates( self, dimworld ); }, "dimworld"_a=GridView::dimensionworld, R"doc( Returns: `numpy` array with the coordinates of all vertices in the grid in the format `[ [x_1,y_1], [x_2,y_2], ..., [x_N,y_N] ]` for example in 2d (will be filled up by zeros if dimworld is larger than the world dimension of the view. )doc" ); cls.def( "tessellate", [] ( const GridView &self, int level, int dimworld) { return tessellate( self, level, dimworld ); }, "level"_a = 0, pybind11::kw_only(), "dimworld"_a=GridView::dimensionworld, R"doc( Generated a possibly refined tessellation using only simplices. Args: level: virtual refinement level to use to generate the tessellation Returns: (coordinates,simplices) where coordinates is a `numpy` array of the vertex coordinates (padded by to `dimworld` is needed) (e.g. in 2d `[ [x_1,y_1,0], [x_2,y_2,0], ..., [x_N,y_N],0 ]` if `dimworld` is set to 3 - default is no padding, `dimworld` less than actual world dimension of grid is ignored) and simplices is a `numpy` array of the vertices of the simplices (e.g. in 2d `[s_11,s_12,s_13], [s_21,s_22,s_23], ..., [s_N1,s_N2,s_N3] ]` ) )doc" ); auto tessellateWithPartition = [&cls](auto &part) { cls.def( "tessellate", [] ( const GridView &self, int level, decltype(part) partition, int dimworld) { return tessellate( self, level, partition, dimworld ); }, "level"_a = 0, pybind11::kw_only(), "partition"_a, "dimworld"_a=GridView::dimensionworld, R"doc( Generated a possibly refined tessellation using only simplices. Args: level: virtual refinement level to use to generate the tessellation Returns: (coordinates,simplices) where coordinates is a `numpy` array of the vertex coordinates (padded by to `dimworld` is needed) (e.g. in 2d `[ [x_1,y_1,0], [x_2,y_2,0], ..., [x_N,y_N],0 ]` if `dimworld` is set to 3 - default is no padding, `dimworld` less than actual world dimension of grid is ignored) and simplices is a `numpy` array of the vertices of the simplices (e.g. in 2d `[s_11,s_12,s_13], [s_21,s_22,s_23], ..., [s_N1,s_N2,s_N3] ]` ) )doc" ); }; tessellateWithPartition(Dune::Partitions::interior); tessellateWithPartition(Dune::Partitions::ghost); tessellateWithPartition(Dune::Partitions::all); tessellateWithPartition(Dune::Partitions::interiorBorder); tessellateWithPartition(Dune::Partitions::interiorBorderOverlap); tessellateWithPartition(Dune::Partitions::interiorBorderOverlapFront); cls.def( "polygons", [] ( const GridView &self ) { return polygons( self ); }, R"doc( Store the grid in numpy arrays. Returns: coordinate array storing the vertex coordinate of each polygon in the grid. )doc" ); cls.def( "contains", [] ( GridView &self, pybind11::object entity ) { bool found = false, contained = false; Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [ &self, entity, &found, &contained ] ( auto codim ) { typedef typename GridView::template Codim< decltype( codim )::value >::Entity Entity; if( pybind11::isinstance< Entity >( entity ) ) { found = true; contained = self.contains( pybind11::cast< const Entity & >( entity ) ); } } ); if( found ) return contained; else throw pybind11::value_error( "Argument 'entity' is not a valid entity for this grid." ); }, "entity"_a, R"doc( Check whether an entity is contained in the grid instance Args: entity: entity to check Note: - The entity must be contained in the corresponding hierarchical grid. )doc" ); #if HAVE_DUNE_VTK using VirtualizedGF = Dune::Vtk::GridFunction; auto vgfClass = Python::insertClass(scope,"VtkFunction", Python::GenerateTypeName("Dune::Vtk::GridFunction", MetaType()), Python::IncludeFiles{"dune/vtk/gridfunctions/gridfunction.hh"}); if( vgfClass.second ) { vgfClass.first.def("name",[](VirtualizedGF &self) { return self.name(); }); } #endif auto addAttr = pybind11::module::import( "dune.grid.grid_generator" ).attr("addAttr"); addAttr(scope, cls); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_GRIDPART_HH dune-grid-2.11.0/dune/python/grid/hierarchical.hh000066400000000000000000000470601511655130300216200ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_HIERARCHICAL_HH #define DUNE_PYTHON_GRID_HIERARCHICAL_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // GridModificationListener // ------------------------ template< class Grid > struct GridModificationListener { virtual ~GridModificationListener () {} virtual void preModification ( const Grid &grid ) {} virtual void postModification ( const Grid &grid ) {} }; namespace detail { template< class Grid > using GridModificationListeners = std::vector< GridModificationListener< Grid > * >; template< class Grid > inline GridModificationListeners &gridModificationListeners (const Grid &grid) { pybind11::handle pygrid = pybind11::detail::get_object_handle( &grid, pybind11::detail::get_type_info( typeid( Grid ) ) ); if (!pybind11::hasattr(pygrid, "listeners_")) { auto ptr = new detail::GridModificationListeners; pybind11::cpp_function cleanup( [ptr](pybind11::handle weakref) { for (auto l : *ptr) delete l; delete ptr; weakref.dec_ref(); }); (void) pybind11::weakref(pygrid, cleanup).release(); pygrid.attr("listeners_") = (void*)(ptr); } pybind11::handle l = pygrid.attr("listeners_"); return *static_cast< detail::GridModificationListeners* >(l.cast()); } template< class Grid > inline static IteratorRange< typename GridModificationListeners::const_iterator > gridModificationListenersRange ( const Grid &grid ) { typedef typename GridModificationListeners::const_iterator Iterator; const auto& listeners = gridModificationListeners(grid); return IteratorRange< Iterator >(listeners.begin(), listeners.end()); } template< class Grid > inline static void addGridModificationListener ( const Grid &grid, GridModificationListener* listener, pybind11::handle nurse = pybind11::handle() ) { auto &listeners = gridModificationListeners< Grid >(grid); listeners.push_back( listener ); } } // namespace detail // registerHierarchicalGridPicklingSupport // --------------------------------------- template< class Grid, class... options > inline static std::enable_if_t< Capabilities::hasBackupRestoreFacilities< Grid >::v > registerHierarchicalGridPicklingSupport ( pybind11::class_< Grid, options... > cls, PriorityTag< 1 > ) { cls.def( pybind11::pickle( [](const pybind11::object &self) { // __getstate__ Grid& grid = self.cast(); std::ostringstream stream; BackupRestoreFacility< Grid >::backup( grid, stream ); /* pybind11::dict d; if (pybind11::hasattr(self, "__dict__")) { d = self.attr("__dict__"); } return pybind11::make_tuple(pybind11::bytes(stream.str()),d); */ return pybind11::make_tuple(pybind11::bytes(stream.str())); }, [] ( pybind11::tuple t) { // __setstate__ if (t.size() != 1) throw std::runtime_error("Invalid state in HGrid::setstate with "+std::to_string(t.size())+"arguments!"); pybind11::bytes state = t[0]; std::istringstream stream( state ); /* auto py_state = t[1].cast(); return std::make_pair( std::shared_ptr< Grid >( BackupRestoreFacility< Grid >::restore( stream ) ), py_state); */ return std::shared_ptr< Grid >( BackupRestoreFacility< Grid >::restore( stream ) ); } ) ); } template< class Grid, class... options > inline static void registerHierarchicalGridPicklingSupport ( pybind11::class_< Grid, options... > cls, PriorityTag< 0 > ) {} template< class Grid, class... options > inline static void registerHierarchicalGridPicklingSupport ( pybind11::class_< Grid, options... > cls ) { registerHierarchicalGridPicklingSupport( cls, PriorityTag< 42 >() ); } // readDGF (input can be either an filename string or an input stream) // ------- template< class Grid, typename In > inline static std::shared_ptr< Grid > readDGF ( In &input ) { DGFGridFactory< Grid > dgfFactory( input ); std::shared_ptr< Grid > grid( dgfFactory.grid() ); grid->loadBalance(); return grid; } // readGmsh // -------- template< class Grid, std::enable_if_t< Capabilities::HasGridFactory< Grid >::value, int > = 0 > inline static std::shared_ptr< Grid > readGmsh ( const std::string &fileName ) { Dune::GridFactory< Grid > gridFactory; Dune::GmshReader< Grid >::read( gridFactory, fileName, false ); return std::shared_ptr< Grid >( gridFactory.createGrid() ); } template< class Grid, std::enable_if_t< !Capabilities::HasGridFactory< Grid >::value, int > = 0 > inline static std::shared_ptr< Grid > readGmsh ( const std::string &fileName ) { throw std::invalid_argument( "Can only read Gmsh files into grids supporting the GridFactory concept." ); } // reader // ------ template< class Grid > inline static std::shared_ptr< Grid > reader ( const std::tuple< Reader, std::string > &args ) { switch( std::get< 0 >( args ) ) { case Reader::dgf: return readDGF< Grid >( std::get< 1 >( args ) ); case Reader::dgfString: { std::istringstream input( std::get< 1 >( args ) ); return readDGF< Grid >( input ); } case Reader::gmsh: return readGmsh< Grid >( std::get< 1 >( args ) ); default: return nullptr; } } template< typename Grid > using StructuredReader = std::tuple< Reader, std::string, FieldVector< typename Grid::ctype, Grid::dimensionworld >, FieldVector< typename Grid::ctype, Grid::dimensionworld >, std::array< unsigned int, Grid::dimension > >; template< class Grid > inline static auto reader ( const StructuredReader< Grid > &args, PriorityTag< 1 > ) -> std::enable_if_t< Capabilities::HasStructuredGridFactory< Grid >::value, std::shared_ptr< Grid > > { using std::get; if( get< 0 >( args ) != Reader::structured ) throw pybind11::value_error( "This overload only supports the 'structured' grid reader." ); if( get< 1 >( args ) == "cube" ) return StructuredGridFactory< Grid >::createCubeGrid( get< 2 >( args ), get< 3 >( args ), get< 4 >( args ) ); else if( get< 1 >( args ) == "simplex" ) return StructuredGridFactory< Grid >::createSimplexGrid( get< 2 >( args ), get< 3 >( args ), get< 4 >( args ) ); else throw pybind11::value_error( "Unknown grid element type." ); } template< class Grid > inline static std::shared_ptr< Grid > reader ( const StructuredReader< Grid > &args, PriorityTag< 0 > ) { throw pybind11::value_error( "Can only create structured grids for grids supporting the GridFactory concept." ); } template< class Grid > inline static std::shared_ptr< Grid > reader ( const StructuredReader< Grid > &args ) { return reader< Grid >( args, PriorityTag< 42 >() ); } template< class Grid > inline static auto reader ( const pybind11::dict &args, PriorityTag< 1 > ) -> std::enable_if_t< Capabilities::HasGridFactory< Grid >::value, std::shared_ptr< Grid > > { GridFactory< Grid > factory; fillGridFactory( args, factory ); return std::shared_ptr< Grid >( factory.createGrid() ); } template< class Grid > inline static std::shared_ptr< Grid > reader ( const pybind11::dict &args, PriorityTag< 0 > ) { throw pybind11::value_error( "Can only read Python dictionaries into grids supporting the GridFactory concept." ); } template< class Grid > inline static std::shared_ptr< Grid > reader ( const pybind11::dict &args ) { return reader< Grid >( args, PriorityTag< 42 >() ); } namespace detail { // Variable template that checks if a grid has refineStepsForHalf or not template struct has_refine_steps_for_half : public std::false_type{}; // specialization for grids that have template struct has_refine_steps_for_half().refineStepsForHalf() )> > : public std::true_type {}; } // registerHierarchicalGrid // ------------------------ template< class Grid, class... options > void registerHierarchicalGrid ( pybind11::module module, pybind11::class_< Grid, options... > cls ) { pybind11::module::import( "dune.geometry" ); pybind11::module::import( "dune.grid" ); using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); auto clsLeafView = insertClass< typename Grid::LeafGridView >( module, "LeafGrid", GenerateTypeName( cls, "LeafGridView" ) ); if( clsLeafView.second ) registerGridView( module, clsLeafView.first ); module.def( "reader", [] ( const std::tuple< Reader, std::string > &args ) { return reader< Grid >( args ); } ); module.def( "reader", [] ( const std::string &args ) { return reader< Grid >( std::make_tuple( Reader::dgf,args ) ); } ); module.def( "reader", [] ( const StructuredReader &args ) { return reader< Grid >( args ); } ); module.def( "reader", [] ( const pybind11::dict &args ) { return reader< Grid >( args ); } ); registerHierarchicalGridPicklingSupport( cls ); registerHierarchicalGridIdSets( cls ); cls.def_property_readonly( "leafView", pybind11::cpp_function( [] ( const Grid &self ) { return self.leafGridView(); }, pybind11::keep_alive< 0, 1 >() ), R"doc( Obtain leaf view of the grid Returns: leaf grid view )doc" ); cls.def( "_levelView", [] ( const Grid &self, int level ) { return self.levelGridView( level ); }, pybind11::keep_alive< 0, 1 >(), "level"_a, R"doc( Obtain level view of the grid Args: level: level to obtain view for Returns: level grid view )doc" ); typedef typename Grid::template Codim< 0 >::Entity Element; cls.def( "mark", [] ( Grid &self, const Element &element, Marker marker ) { self.mark( static_cast< int >( marker ), element ); }, "element"_a, "marker"_a, R"doc()doc" ); cls.def( "mark", [] ( Grid &self, const std::function< Marker( const Element &e ) > &marking ) { std::pair< int, int > marked; for( const Element &element : elements( self.leafGridView() ) ) { Marker marker = marking( element ); marked.first += static_cast< int >( marker == Marker::Refine ); marked.second += static_cast< int >( marker == Marker::Coarsen ); self.mark( static_cast< int >( marker ), element ); } return marked; }, "marking"_a, R"doc( Set the grid's adaptation markers Args: marking: callback returning a dune.grid.Marker for each leaf element in the grid )doc" ); cls.def( "adapt", [] ( Grid &self ) { const auto &range = detail::gridModificationListenersRange(self); for( const auto &listener : range ) listener->preModification( self ); self.preAdapt(); self.adapt(); self.postAdapt(); for( const auto &listener : range ) listener->postModification( self ); }, R"doc( Refine or coarsen the hierarchical grid to match the current marking All elements marked for refinement will be refined by this operation. However, due to closure rules, additional elements might be refined. Similarly, not all elements marked for coarsening are necessarily coarsened. Note: - This is a collective operation. - The grid implementation defines the rule by which elements are split. )doc" ); cls.def( "adapt", [] ( Grid &self, const std::function< Marker( const Element &e ) > &marking ) { std::pair< int, int > marked; for( const Element &element : elements( self.leafGridView() ) ) { Marker marker = marking( element ); marked.first += static_cast< int >( marker == Marker::Refine ); marked.second += static_cast< int >( marker == Marker::Coarsen ); self.mark( static_cast< int >( marker ), element ); } if (marked.first + marked.second) { const auto &range = detail::gridModificationListenersRange(self); for( const auto &listener : range ) listener->preModification( self ); self.preAdapt(); self.adapt(); self.postAdapt(); for( const auto &listener : range ) listener->postModification( self ); } return marked; }, R"doc( Refine or coarsen the hierarchical grid to match the provided marking function. Args: marking: callback returning a dune.grid.Marker for each leaf element in the grid All elements for which are marked for refinement by the callback function will be refined by this operation. However, due to closure rules, additional elements might be refined. Similarly, not all elements marked for coarsening are necessarily coarsened. Note: - This is a collective operation. - The grid implementation defines the rule by which elements are split. )doc" ); cls.def( "globalRefine", [] ( Grid &self, int level ) { const auto &range = detail::gridModificationListenersRange(self); for( const auto &listener : range ) listener->preModification( self ); self.globalRefine( level ); for( const auto &listener : range ) listener->postModification( self ); }, "iterations"_a = 1, R"doc( Refine each leaf element of the grid. Args: iterations: Number of global refinement iterations to perform (defaults to 1) Note: - This is a collective operation. - The grid implementation defines the rule by which elements are split. )doc" ); cls.def( "loadBalance", [] ( Grid &self ) { const auto &range = detail::gridModificationListenersRange(self); for( const auto &listener : range ) listener->preModification( self ); self.loadBalance(); for( const auto &listener : range ) listener->postModification( self ); }, R"doc( Redistribute the grid to equilibrate the work load on each process. Note: - This is a collective operation. - The redistribution strategy is chosen by the grid implementation. )doc" ); cls.def_property_readonly( "maxLevel", [] ( const Grid &self ) -> int { return self.maxLevel(); } ); cls.def_property_readonly_static( "dimension", [] ( pybind11::object ) { return int(Grid::dimension); } ); cls.def_property_readonly_static( "dimensionworld", [] ( pybind11::object ) { return int(Grid::dimensionworld); } ); // if the grid implements a method refineStepsForHalf then use that to evaluate needed refine steps if constexpr ( detail::has_refine_steps_for_half< Grid >::value ) { cls.def_property_readonly( "refineStepsForHalf", [] ( const Grid& self ) -> int { return self.refineStepsForHalf(); } ); } else { // default implementation based on DGFGridInfo cls.def_property_readonly_static( "refineStepsForHalf", [] ( pybind11::object ) { return int(DGFGridInfo< Grid >::refineStepsForHalf()); } ); } // export grid capabilities if( Capabilities::hasSingleGeometryType< Grid >::v ) { cls.def_property_readonly_static( "type", [] ( pybind11::object ) { return GeometryType( Capabilities::hasSingleGeometryType< Grid >::topologyId, Grid::dimension ); }, R"doc( "All elements in this grid have this geometry type" )doc" ); } cls.def_property_readonly_static( "isCartesian", [] ( pybind11::object ) { return Capabilities::isCartesian< Grid >::v; } ); cls.def_property_readonly_static( "canCommunicate", [] ( pybind11::object ) { pybind11::tuple canCommunicate( Grid::dimension+1 ); Hybrid::forEach( std::make_integer_sequence< int, Grid::dimension+1 >(), [ &canCommunicate ] ( auto codim ) { canCommunicate[ codim ] = pybind11::cast( bool( Capabilities::canCommunicate< Grid, codim >::v ) ); } ); return canCommunicate; } ); cls.def_property_readonly_static( "threadSafe", [] ( pybind11::object ) { return Capabilities::threadSafe< Grid >::v; } ); cls.def_property_readonly_static( "viewThreadSafe", [] ( pybind11::object ) { return Capabilities::viewThreadSafe< Grid >::v; } ); auto [ clsComm, notRegistered ] = insertClass< typename Grid::Communication >( cls, "Communication", GenerateTypeName( cls, "Communication" ) ); if( notRegistered ) registerCommunication( clsComm ); cls.def_property_readonly( "comm", [] ( const Grid &grid ) -> const typename Grid::Communication & { return grid.comm(); }, pybind11::return_value_policy::reference, pybind11::keep_alive< 0, 1 >(), R"doc( collective communication for the grid Note: For collective (or global) operations, all processes in this collective communication must call the corresponding method. )doc" ); auto addHAttr = pybind11::module::import( "dune.grid.grid_generator" ).attr("addHAttr"); addHAttr(module); } //! \brief export the C++ type used for the structuredGrid template using StructuredGrid = Dune::YaspGrid>; } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_HIERARCHICAL_HH dune-grid-2.11.0/dune/python/grid/idset.hh000066400000000000000000000204601511655130300203050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_IDSET_HH #define DUNE_PYTHON_GRID_IDSET_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { namespace detail { // GridId // ------ template< class Id > struct GridId { Id id; }; // Comparison Operators // -------------------- template< class Id > inline static bool operator== ( const GridId< Id > &a, const GridId< Id > &b ) { return (a.id == b.id); } template< class Id > inline static bool operator!= ( const GridId< Id > &a, const GridId< Id > &b ) { return !(a == b); } template< class Id > inline static bool operator< ( const GridId< Id > &a, const GridId< Id > &b ) { return (a.id < b.id); } template< class Id > inline static bool operator>= ( const GridId< Id > &a, const GridId< Id > &b ) { return !(a.id < b.id); } template< class Id > inline static auto operator<= ( const GridId< Id > &a, const GridId< Id > &b ) -> std::enable_if_t< std::is_same< decltype( a.id <= b.id ), bool >::value, bool > { return (a.id <= b.id); } template< class Id > inline static auto operator<= ( const GridId< Id > &a, const GridId< Id > &b ) -> std::enable_if_t< !std::is_same< decltype( a.id <= b.id ), bool >::value, bool > { return (a.id < b.id) || (a.id == b.id); } template< class Id > inline static bool operator> ( const GridId< Id > &a, const GridId< Id > &b ) { return !(a.id <= b.id); } // to_string // --------- template< class Id > inline static auto to_string ( const GridId< Id > &id, PriorityTag< 2 > ) -> decltype( static_cast< std::string >( id.id ) ) { return static_cast< std::string >( id.id ); } template< class Id > inline static auto to_string ( const GridId< Id > &id, PriorityTag< 1 > ) -> decltype( to_string( id.id ) ) { return to_string( id.id ); } template< class Id > inline static std::string to_string ( const GridId< Id > &id, PriorityTag< 0 > ) { std::ostringstream s; s << id.id; return s.str(); } template< class Id > inline static std::string to_string ( const GridId< Id > &id ) { return to_string( id, PriorityTag< 42 >() ); } // idSetSubId // ---------- template< class IdSet, class Entity > inline static typename IdSet::IdType idSetSubId ( const IdSet &idSet, const Entity &entity, int i, int c ) { if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); const int size = entity.subEntities( c ); if( (i < 0) || (i >= size) ) throw pybind11::value_error( "Invalid index: " + std::to_string( i ) + " (must be in [0, " + std::to_string( size ) + "))." ); return idSet.subId( entity, i, c ); } // registerSubId // ------------- template< class Entity, class IdSet, class... options > inline static auto registerSubId ( pybind11::class_< IdSet, options... > cls, PriorityTag< 1 > ) -> std::enable_if_t< Entity::codimension == 0 > { using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.def( "subId", [] ( const IdSet &self, const Entity &entity, int i, int codim ) { return detail::idSetSubId( self, entity, i, codim ); } ); cls.def( "subId", [] ( const IdSet &self, const Entity &entity, std::tuple< int, int > e ) { return detail::idSetSubId( self, entity, std::get< 0 >( e ), std::get< 1 >( e ) ); } ); cls.def( "subIds", [] ( const IdSet &self, const Entity &entity, int c ) { if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); const int size = entity.subEntities( c ); pybind11::tuple subIds( size ); for( int i = 0; i < size; ++i ) subIds[ i ] = pybind11::cast( self.subId( entity, i, c ) ); return subIds; }, "entity"_a, "codim"_a ); } template< class Entity, class IdSet, class... options > inline static void registerSubId ( pybind11::class_< IdSet, options... >, PriorityTag< 0 > ) {} template< class Entity, class IdSet, class... options > inline static void registerSubId ( pybind11::class_< IdSet, options... > cls ) { return registerSubId< Entity >( cls, PriorityTag< 42 >() ); } } // namespace detail // registerGridIdSet // ----------------- template< class Grid, class IdSet, class... options > inline static void registerGridIdSet ( pybind11::handle scope, pybind11::class_< IdSet, options... > cls ) { typedef detail::GridId< typename IdSet::IdType > Id; auto id = insertClass< Id >( cls, "Id", GenerateTypeName( "Dune::Python::detail::GridId", GenerateTypeName( cls, "IdType" ) ) ); if( id.second ) { pybind11::options opts; opts.disable_function_signatures(); id.first.def( pybind11::self == pybind11::self ); id.first.def( pybind11::self != pybind11::self ); id.first.def( pybind11::self < pybind11::self ); id.first.def( pybind11::self <= pybind11::self ); id.first.def( pybind11::self > pybind11::self ); id.first.def( pybind11::self >= pybind11::self ); std::hash< typename IdSet::IdType > hash; id.first.def( "__hash__", [ hash ] ( const Id &self ) { return pybind11::int_( hash( self.id ) ); } ); id.first.def( "__str__", [] ( const Id &self ) { return to_string( self ); } ); } Hybrid::forEach( std::make_integer_sequence< int, Grid::dimension+1 >(), [ &cls ] ( auto codim ) { typedef typename Grid::template Codim< codim >::Entity Entity; using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.def( "id", [] ( const IdSet &self, const Entity &entity ) { return self.id( entity ); }, "entity"_a ); detail::registerSubId< Entity >( cls ); } ); } // registerGridIdSets // ------------------ template< class Grid, class... options > inline static void registerHierarchicalGridIdSets ( pybind11::class_< Grid, options... > cls ) { pybind11::options opts; opts.disable_function_signatures(); typedef typename Grid::LocalIdSet LocalIdSet; auto local = insertClass< LocalIdSet >( cls, "LocalIdSet", GenerateTypeName( cls, "LocalIdSet" ) ); if( local.second ) registerGridIdSet< Grid >( cls, local.first ); cls.def_property_readonly( "localIdSet", [] ( const Grid &self ) -> const LocalIdSet & { return self.localIdSet(); }, pybind11::keep_alive< 0, 1 >() ); typedef typename Grid::GlobalIdSet GlobalIdSet; auto global = insertClass< GlobalIdSet >( cls, "GlobalIdSet", GenerateTypeName( cls, "GlobalIdSet" ) ); if( global.second ) registerGridIdSet< Grid >( cls, global.first ); cls.def_property_readonly( "globalIdSet", [] ( const Grid &self ) -> const GlobalIdSet & { return self.globalIdSet(); }, pybind11::keep_alive< 0, 1 >() ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_IDSET_HH dune-grid-2.11.0/dune/python/grid/indexset.hh000066400000000000000000000333521511655130300210240ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_INDEXSET_HH #define DUNE_PYTHON_GRID_INDEXSET_HH #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { namespace detail { // indexSetSubIndex // ---------------- template< class IndexSet, class Entity > inline static int indexSetSubIndex ( const IndexSet &indexSet, const Entity &entity, int i, int c ) { if( !indexSet.contains( entity ) ) pybind11::value_error( "Entity not contained in index set." ); if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); const int size = entity.subEntities( c ); if( (i < 0) || (i >= size) ) throw pybind11::value_error( "Invalid index: " + std::to_string( i ) + " (must be in [0, " + std::to_string( size ) + "))." ); return static_cast< int >( indexSet.subIndex( entity, i, c ) ); } // registerSubIndex // ---------------- template< class Entity, class IndexSet, class... options > inline static std::enable_if_t< Entity::codimension == 0 > registerSubIndex ( pybind11::class_< IndexSet, options... > cls, PriorityTag< 1 > ) { using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.def( "subIndex", [] ( const IndexSet &self, const Entity &entity, int i, int c ) { return detail::indexSetSubIndex( self, entity, i, c ); }, "entity"_a, "index"_a, "codim"_a, R"doc( get index of a subentity Numerical codes frequently require only the index of a subentity, not the subentity itself. This method directly provides the index. The subentity is described by a local index and a codimension. The exact interpretation of the local index is defined by the reference element. Calling this method is semantically equivalent to self.index(entity.subEntity(index, codim)) Note: This method is implemented even if the grid does not implement entities of the corresponding codimension. Args: entity: entity containing the subentity index: number of the subentity codim: codimension of the subentity (wrt. the grid dimension) Returns: Index of the subentity )doc" ); cls.def( "subIndex", [] ( const IndexSet &self, const Entity &entity, std::tuple< int, int > e ) { return detail::indexSetSubIndex( self, entity, std::get< 0 >( e ), std::get< 1 >( e ) ); }, "entity"_a, "subentity"_a, R"doc( Args: entity: entity containing the subentity subentity: (index, codim) tuple Returns: Index of the subentity )doc" ); cls.def( "subIndices", [] ( const IndexSet &self, const Entity &entity, int c ) { if( !self.contains( entity ) ) pybind11::value_error( "Entity not contained in index set." ); if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); const int size = entity.subEntities( c ); pybind11::tuple subIndices( size ); for( int i = 0; i < size; ++i ) subIndices[ i ] = pybind11::cast( self.subIndex( entity, i, c ) ); return subIndices; }, "entity"_a, "codim"_a, R"doc( get indices of all subentities in a codimension Numerical codes frequently require all subindices of a codimension, e.g., all vertex indices. This convenience method provides them in a single call. Note: This method is implemented even if the grid does not implement entities of the corresponding codimension. Args: entity: entity containing the subentities codim: codimension of the subentities (wrt. the grid dimension) Returns: Tuple of indices, in the order given by the reference element )doc" ); cls.def( "subIndices", [] ( const IndexSet &self, const Entity &entity, int i, int c, int cc ) { if( !self.contains( entity ) ) pybind11::value_error( "Entity not contained in index set." ); if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); if( (cc < c) || (cc > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( cc ) + " (must be in [" + std::to_string( c ) + ", " + std::to_string( Entity::dimension ) + "])" ); const auto reference = referenceElement< double, Entity::dimension >( entity.type() ); const int size = reference.size( i, c, cc ); pybind11::tuple subIndices( size ); for( int ii = 0; ii < size; ++ii ) subIndices[ ii ] = pybind11::cast( self.subIndex( entity, reference.subEntity(i, c, ii, cc), cc ) ); return subIndices; }, "entity"_a, "index"_a, "codim"_a, "codim"_a, R"doc( get indices of all subentities in a codimension Numerical codes frequently require all subindices of a subentity of a codimension, e.g., all vertex indices of a edge. This convenience method provides them in a single call. Note: This method is implemented even if the grid does not implement entities of the corresponding codimension. Args: entity: entity containing the subentities index: index of the subentity of entity codim: codimension of the subentity of entity codim: codimension of the subentities (wrt. the grid dimension) Returns: Tuple of indices, in the order given by the reference element )doc" ); cls.def( "subIndices", [] ( const IndexSet &self, const Entity &entity, std::pair< int, int > ic, int cc ) { int i = ic.first; int c = ic.second; if( !self.contains( entity ) ) pybind11::value_error( "Entity not contained in index set." ); if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); if( (cc < c) || (cc > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( cc ) + " (must be in [" + std::to_string( c ) + ", " + std::to_string( Entity::dimension ) + "])" ); const auto reference = referenceElement< double, Entity::dimension >( entity.type() ); const int size = reference.size( i, c, cc ); pybind11::tuple subIndices( size ); for( int ii = 0; ii < size; ++ii ) subIndices[ ii ] = pybind11::cast( self.subIndex( entity, reference.subEntity(i, c, ii, cc), cc ) ); return subIndices; }, "entity"_a, "subentity"_a, "codim"_a, R"doc( get indices of all subentities in a codimension Numerical codes frequently require all subindices of a subentity of a codimension, e.g., all vertex indices of a edge. This convenience method provides them in a single call. Note: This method is implemented even if the grid does not implement entities of the corresponding codimension. Args: entity: entity containing the subentities subentity: (index, codim) tuple codim: codimension of the subentities (wrt. the grid dimension) Returns: Tuple of indices, in the order given by the reference element )doc" ); } template< class Entity, class IndexSet, class... options > inline static void registerSubIndex ( pybind11::class_< IndexSet, options... > cls, PriorityTag< 0 > ) {} template< class Entity, class IndexSet, class... options > inline static void registerSubIndex ( pybind11::class_< IndexSet, options... > cls ) { registerSubIndex< Entity >( cls, PriorityTag< 42 >() ); } } // namespace detail // registerGridViewIndexSet // ------------------------ template< class IndexSet, class... options > inline static void registerGridViewIndexSet ( pybind11::handle scope, pybind11::class_< IndexSet, options... > cls ) { using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.doc() = R"doc( The index set maps all entities in a grid view to natural numbers (including 0). Denoting by E(g) the entities of geometry type g, this map has the following properties: - It is injective on each E(g). - The image of E(g) is consecutive and zero-starting, i.e., { 0, ..., N-1 } for some integer N Index sets are used to assign user-defined data (e.g., degrees of freedom of a discretization) to entities in the grid view. For efficiency reasons, the preferred data structure for user data is an array. In order to access the data from associated to an entity, its index (wrt. an index set) is evaluated and used to access the array element. Usually, the index set is not used directly. Instead, a mapper is used to compute the array index from the index provided by an index set. Note: The index assigned to an entity may change during grid modification (e.g., refinement of dynamic load balancing). The user is responsible for reorganizing the information stored in the external arrays. In order to do this, the concepts of id sets and persistent containers are provided. )doc"; cls.def( "size", [] ( IndexSet &self, Dune::GeometryType type ) { return self.size( type ); } ); cls.def( "size", [] ( IndexSet &self, int codim ) { if( (codim < 0) || (codim > IndexSet::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( IndexSet::dimension ) + "])" ); return self.size( codim ); } ); cls.def( "types", [] ( const IndexSet &self, int codim ) { pybind11::list types; for( GeometryType type : self.types( codim ) ) types.append( pybind11::cast( type ) ); return types; }, "codim"_a, R"doc( obtain list of geometry types in the domain of the index set. Args: codim: codimension to obtain geometry types for Returns: List of all geometry types of given codimension in the domain of the index set )doc" ); Hybrid::forEach( std::make_integer_sequence< int, IndexSet::dimension+1 >(), [ &cls ] ( auto codim ) { typedef typename IndexSet::template Codim< codim >::Entity Entity; using pybind11::operator""_a; cls.def( "index", [] ( const IndexSet &self, const Entity &entity ) { if( !self.contains( entity ) ) pybind11::value_error( "Entity not contained in index set." ); return static_cast< int >( self.index( entity ) ); }, "entity"_a, R"doc( get index of an entity Args: entity: entity to obtain index for Returns: Index assigned to the entity )doc" ); cls.def( "contains", [] ( const IndexSet &self, const Entity &entity ) { return self.contains( entity ); }, "entity"_a, R"doc( check whether an entity is in the domain of the index set Args: entity: entity to check for Returns: True, if the entity is in the domain, False otherwise )doc" ); detail::registerSubIndex< Entity >( cls ); } ); } // registerGridViewIndexSet // ------------------------ template< class GridView > inline static pybind11::class_< typename GridView::IndexSet > registerGridViewIndexSet ( pybind11::handle scope ) { typedef typename GridView::IndexSet IndexSet; auto cls = insertClass< IndexSet >( scope, "IndexSet", GenerateTypeName( MetaType< GridView >(), "IndexSet" ) ).first; registerGridViewIndexSet( scope, cls ); return cls; } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_INDEXSET_HH dune-grid-2.11.0/dune/python/grid/intersection.hh000066400000000000000000000074151511655130300217100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_INTERSECTION_HH #define DUNE_PYTHON_GRID_INTERSECTION_HH #include #include #include #include #include namespace Dune { namespace Python { namespace detail { // registerGridIntersection // ------------------------ template< class Intersection > void registerGridIntersection ( pybind11::handle scope, pybind11::class_ cls ) { const int mydimension = Intersection::mydimension; // information on boundary intersections cls.def_property_readonly( "boundary", &Intersection::boundary ); cls.def_property_readonly( "boundarySegmentIndex", [] ( const Intersection &i ) { return (i.boundary() ? pybind11::cast( i.boundarySegmentIndex() ) : pybind11::none()); } ); // conformity cls.def_property_readonly( "conforming", &Intersection::conforming ); // geometric information cls.def_property_readonly( "geometry", &Intersection::geometry ); cls.def_property_readonly( "type", &Intersection::type ); cls.def_property_readonly( "referenceElement", []( const Intersection &self ) { return referenceElement< double, mydimension >( self.type() ); }, pybind11::keep_alive< 0, 1 >(), R"doc( corresponding reference element, describing the domain of the map )doc" ); // information on inside entity cls.def_property_readonly( "inside", &Intersection::inside ); cls.def_property_readonly( "geometryInInside", &Intersection::geometryInInside ); cls.def_property_readonly( "indexInInside", &Intersection::indexInInside ); // information on outside entity cls.def_property_readonly( "outside", [] ( const Intersection &i ) { return (i.neighbor() ? pybind11::cast( i.outside() ) : pybind11::none()); } ); cls.def_property_readonly( "geometryInOutside", [] ( const Intersection &i ) { return (i.neighbor() ? pybind11::cast( i.geometryInOutside() ) : pybind11::none()); } ); cls.def_property_readonly( "indexInOutside", [] ( const Intersection &i ) { return (i.neighbor() ? pybind11::cast( i.indexInOutside() ) : pybind11::none()); } ); // outer normals cls.def_property_readonly( "centerUnitOuterNormal", &Intersection::centerUnitOuterNormal); cls.def( "outerNormal", &Intersection::outerNormal ); cls.def( "integrationOuterNormal", &Intersection::integrationOuterNormal ); cls.def( "unitOuterNormal", &Intersection::unitOuterNormal ); // comparison cls.def( pybind11::self == pybind11::self ); cls.def( pybind11::self != pybind11::self ); } } // namespace detail // registerGridIntersection // ------------------------ template< class GridView > auto registerGridIntersection ( pybind11::handle scope ) { typedef typename GridView::Intersection Intersection; pybind11::class_< Intersection > cls = insertClass(scope, "Intersection", GenerateTypeName(scope,"Intersection")).first; detail::registerGridIntersection( scope, cls ); registerGridGeometry( cls ); return cls; } } // namespace Python } // namespace Dune #endif //#ifndef DUNE_PYTHON_GRID_INTERSECTION_HH dune-grid-2.11.0/dune/python/grid/localview.hh000066400000000000000000000063451511655130300211700ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_PYTHON_GRID_LOCALVIEW_HH #define DUNE_PYTHON_GRID_LOCALVIEW_HH #include #include #include namespace Dune { namespace Python { namespace detail { // LocalViewRegistry // ----------------- template< class LocalView > struct DUNE_PRIVATE LocalViewRegistry { ~LocalViewRegistry() { for (auto i = binds_.begin(), last = binds_.end(); i != last; ++i) i->second = pybind11::object(); binds_.clear(); } template void bind ( pybind11::handle localView, pybind11::object context ) { localView.template cast< LocalView & >().bind( context.template cast< const Context & >() ); find( localView ) = context; } void unbind ( pybind11::handle localView ) { localView.template cast< LocalView & >().unbind(); find( localView ) = pybind11::object(); } private: pybind11::object &find ( pybind11::handle localView ) { auto result = binds_.emplace( localView.ptr(), pybind11::object() ); const auto pos = result.first; if( result.second ) { pybind11::cpp_function remove_bind( [ this, pos ] ( pybind11::handle weakref ) { binds_.erase( pos ); weakref.dec_ref(); } ); pybind11::weakref weakref( localView, remove_bind ); weakref.release(); } return pos->second; } std::map< void *, pybind11::object > binds_; }; // localViewRegsitry // ----------------- template< class LocalView > inline LocalViewRegistry< LocalView > &localViewRegistry (pybind11::handle self) { if (!pybind11::hasattr(self, "registry_")) { auto ptr = new LocalViewRegistry(); pybind11::cpp_function storage_cleanup( [ptr](pybind11::handle weakref) { delete ptr; weakref.dec_ref(); }); (void) pybind11::weakref(self, storage_cleanup).release(); self.attr("registry_") = (void*)ptr; } pybind11::handle l = self.attr("registry_"); return *static_cast< LocalViewRegistry* >(l.cast()); } } // namespace detail // registerLocalView // ----------------- template< class Context, class LocalView, class... options > void registerLocalView ( pybind11::class_< LocalView, options... > cls ) { using pybind11::operator""_a; cls.def( "bind", [ ] ( pybind11::handle self, pybind11::object context ) { detail::localViewRegistry(self).template bind( self, context ); }, "context"_a ); cls.def( "unbind", [ ] ( pybind11::handle self ) { detail::localViewRegistry(self).unbind( self ); } ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_LOCALVIEW_HH dune-grid-2.11.0/dune/python/grid/mapper.hh000066400000000000000000000462341511655130300204700ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_MAPPER_HH #define DUNE_PYTHON_GRID_MAPPER_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { namespace detail { // mapperSubIndex // -------------- template< class Mapper, class Entity > inline static pybind11::object mapperSubIndex ( const Mapper &mapper, const Entity &entity, int i, int c ) { if( (c < Entity::codimension) || (c > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( c ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); const int size = entity.subEntities( c ); if( (i < 0) || (i >= size) ) throw pybind11::value_error( "Invalid index: " + std::to_string( i ) + " (must be in [0, " + std::to_string( size ) + "))." ); typename Mapper::Index index; return (mapper.contains( entity, i, c, index ) ? pybind11::cast( index ) : pybind11::none()); } // registerMapperSubIndex // ---------------------- template< class Entity, class Mapper, class... options > inline static std::enable_if_t< Entity::codimension == 0 > registerMapperSubIndex ( pybind11::class_< Mapper, options... > cls, PriorityTag< 1 > ) { using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.def( "subIndex", [] ( const Mapper &self, const Entity &entity, int i, int c ) { return detail::mapperSubIndex( self, entity, i, c ); }, "entity"_a, "i"_a, "c"_a, R"doc( Args: entity: an entity of the grid i: number of subentity of `entity` c: codimension of the subentity Returns: the starting index of the dofs attached to the `ith` subentity of codimension `c` of the given entity. )doc" ); cls.def( "subIndex", [] ( const Mapper &self, const Entity &entity, std::tuple< int, int > subEntity ) { return detail::mapperSubIndex( self, entity, std::get< 0 >( subEntity ), std::get< 1 >( subEntity ) ); }, "entity"_a, "subEntity"_a, R"doc( Args: entity: an entity of the grid (i,c): number and codimension of a subentity of `entity` Returns: the starting index of the dofs attached to the `ith` subentity of codimension `c` of the given entity. )doc" ); cls.def( "subIndices", [] ( const Mapper &self, const Entity &entity, int codim ) { if( (codim < Entity::codimension) || (codim > Entity::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [" + std::to_string( Entity::codimension ) + ", " + std::to_string( Entity::dimension ) + "])" ); const int size = entity.subEntities( codim ); pybind11::tuple subIndices( size ); for( int i = 0; i < size; ++i ) { typename Mapper::Index index; subIndices[ i ] = (self.contains( entity, i, codim, index ) ? pybind11::cast( index ) : pybind11::none()); } return subIndices; }, "entity"_a, "codim"_a, R"doc( Args: entity: an entity of the grid codim: codimension of a subentity of `entity` Returns: indices of dofs attached to all subentity of codimension `codim` of the given entity. )doc" ); } template< class Entity, class Mapper, class... options > inline static void registerMapperSubIndex ( pybind11::class_< Mapper, options... > cls, PriorityTag< 0 > ) {} template< class Entity, class Mapper, class... options > inline static void registerMapperSubIndex ( pybind11::class_< Mapper, options... > cls ) { registerMapperSubIndex< Entity >( cls, PriorityTag< 42 >() ); } template void mapperCommunicate(const Mapper &mapper, CommOp commOp, std::vector> data, InterfaceType iftype, CommunicationDirection dir ) { switch (commOp) { case add: { auto dataHandle = numPyCommDataHandle( mapper, data, [] (double local, double remote) {return remote+local;}); mapper.gridView().communicate( dataHandle, iftype, dir ); } case set: { auto dataHandle = numPyCommDataHandle( mapper, data, [] (double local, double remote) {return remote;}); mapper.gridView().communicate( dataHandle, iftype, dir ); } } } } // namespace detail // makeMultipleCodimMultipleGeomTypeMapper // --------------------------------------- template< class GridView > MultipleCodimMultipleGeomTypeMapper< GridView > *makeMultipleCodimMultipleGeomTypeMapper ( const GridView &gridView, pybind11::object layout ) { typedef MultipleCodimMultipleGeomTypeMapper< GridView > MCMGMapper; if( pybind11::isinstance< pybind11::function >( layout ) ) { const auto function = pybind11::cast< pybind11::function >( layout ); return new MCMGMapper( gridView, [ function ] ( Dune::GeometryType gt, int griddim ) -> unsigned int { return pybind11::cast< int >( function( gt ) ); } ); } if( pybind11::isinstance< pybind11::dict >( layout ) ) { typedef Dune::GlobalGeometryTypeIndex GTI; std::array< unsigned int, GTI::size( GridView::dimension ) > count; std::fill( count.begin(), count.end(), 0 ); for( auto entry : pybind11::cast< pybind11::dict >( layout ) ) count[ GTI::index( pybind11::cast< Dune::GeometryType >( entry.first ) ) ] = pybind11::cast< int >( entry.second ); return new MCMGMapper( gridView, [ count ] ( Dune::GeometryType gt, int griddim ) { return count[ Dune::GlobalGeometryTypeIndex::index( gt ) ]; } ); } if( pybind11::isinstance< pybind11::tuple >( layout ) ) { std::array< unsigned int, GridView::dimension+1 > count; const auto tuple = pybind11::cast< pybind11::tuple >( layout ); if( pybind11::len( tuple ) != GridView::dimension+1 ) throw pybind11::value_error( "len(layout) must be " + std::to_string( GridView::dimension ) + "." ); for( int d = 0; d <= GridView::dimension; ++d ) count[ d ] = pybind11::cast< int >( tuple[ GridView::dimension - d ] ); return new MCMGMapper( gridView, [ count ] ( Dune::GeometryType gt, int griddim ) { return count[ gt.dim() ]; } ); } if( pybind11::isinstance< pybind11::list >( layout ) ) { std::array< unsigned int, GridView::dimension+1 > count; const auto list = pybind11::cast< pybind11::list >( layout ); if( pybind11::len( list ) != GridView::dimension+1 ) throw pybind11::value_error( "len(layout) must be " + std::to_string( GridView::dimension ) + "." ); for( int d = 0; d <= GridView::dimension; ++d ) count[ d ] = pybind11::cast< int >( list[ GridView::dimension - d ] ); return new MCMGMapper( gridView, [ count ] ( Dune::GeometryType gt, int griddim ) { return count[ gt.dim() ]; } ); } throw pybind11::value_error( "Argument 'layout' must be either a function, a dict, a tuple, or a list." ); } // registerMapperCommunicate // ------------------------- template < Dune::PartitionIteratorType fromType, Dune::PartitionIteratorType toType, Dune::InterfaceType interfaceType, class Mapper > inline static void registerMapperCommunicate(pybind11::class_ cls) { using pybind11::operator""_a; typedef typename Mapper::GridView GridView; cls.def( "communicate", [] ( const Mapper &self, GridViewPartition< GridView, fromType > from, GridViewPartition< GridView, toType > to, detail::CommOp commOp, pybind11::args args ) { std::vector> data(args.size()); for (unsigned int i=0;i(args[i]); mapperCommunicate(self,commOp, data, interfaceType, ForwardCommunication); }, "from"_a, "to"_a, "commOp"_a); cls.def( "communicate", [] ( const Mapper &self, GridViewPartition< GridView, fromType > from, GridViewPartition< GridView, toType > to, pybind11::function operation, pybind11::args args ) { std::vector> data(args.size()); for (unsigned int i=0;i(args[i]); auto dataHandle = numPyCommDataHandle( self, data, operation.template cast>()); self.gridView().communicate( dataHandle, interfaceType, ForwardCommunication); }, "from"_a, "to"_a, "operation"_a ); if (fromType != toType) { cls.def( "communicate", [] ( const Mapper &self, GridViewPartition< GridView, fromType > from, GridViewPartition< GridView, toType > to, detail::CommOp commOp, pybind11::args args ) { std::vector> data(args.size()); for (unsigned int i=0;i(args[i]); mapperCommunicate(self,commOp, data, interfaceType, BackwardCommunication); }, "from"_a, "to"_a, "commOp"_a ); cls.def( "communicate", [] ( const Mapper &self, GridViewPartition< GridView, fromType > from, GridViewPartition< GridView, toType > to, pybind11::function operation, pybind11::args args ) { std::vector> data(args.size()); for (unsigned int i=0;i(args[i]); auto dataHandle = numPyCommDataHandle( self, data, operation.template cast>()); self.gridView().communicate( dataHandle, interfaceType, BackwardCommunication); }, "from"_a, "to"_a, "operation"_a ); } } // registerMapper // -------------- template< class GridView, class Mapper, class... options > inline static void registerMapper ( pybind11::class_< Mapper, options... > cls ) { using pybind11::operator""_a; pybind11::options opts; opts.disable_function_signatures(); cls.def( "__len__", [] ( const Mapper &self ) { return self.size(); }, R"doc( Returns the maximum index plus 1 returns by the mapper. Use to set the number of entries in the dof vector. Note: corresponds to the `size()` method on the MCMGMapper. )doc" ); cls.def_property_readonly( "size", [] ( const Mapper &self ) { return self.size(); }, R"doc( Returns the maximum index plus 1 returns by the mapper. Use to set the number of entries in the dof vector. )doc" ); cls.def( "types", [] ( const Mapper &self, int codim ) { pybind11::list types; for( GeometryType type : self.types( codim ) ) types.append( pybind11::cast( type ) ); return types; }, "codim"_a, R"doc( Args: codim: codimension Returns: list of geometry types of the given codimension with attached data )doc" ); Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [ &cls ] ( auto codim ) { typedef typename GridView::template Codim< codim >::Entity Entity; using pybind11::operator""_a; cls.def( "index", [] ( const Mapper &self, const Entity &e ) -> pybind11::object { typename Mapper::Index index; if( self.contains( e, index ) ) return pybind11::cast( index ); else return pybind11::none(); }, "entity"_a, R"doc( Args: entity: entity in the grid Returns: the first index for dofs stored on the given entity if no dofs are stored on this entity the return value is `None` )doc" ); cls.def( "contains", [] ( const Mapper &self, const Entity &entity ) { typename Mapper::Index index; return self.contains( entity, index ); }, "entity"_a, R"doc( Args: entity: entity in the grid Returns: `True` if the data is stored on this entity )doc" ); detail::registerMapperSubIndex< Entity >( cls ); } ); // see comment added to __init__ method for some details on reference counting cls.def( "update", [] ( Mapper &self, GridView &grid ) { self.update(grid); }, R"doc( Update the mapper after a grid modification. Note: after grid modification the mapper is not valid anymore and needs to be updated! )doc" ); cls.def( "__call__", [] ( const Mapper &self, const typename GridView::template Codim< 0 >::Entity &element ) { // need a cache gt(cdim=0) -> nof indices then we could store directly in retArray std::vector< typename Mapper::Index > indices; for( int c = GridView::dimension; c>=0; --c ) for( auto se : range( element.subEntities( c ) ) ) { const auto &i = self.indices( element, se, c ); indices.insert( indices.end(), i.begin(), i.end() ); } pybind11::array_t< std::size_t > retArray( indices.size() ); auto y = retArray.template mutable_unchecked< 1 >(); std::size_t idx = 0; for ( auto i : indices ) y[idx++] = i; return retArray; }, "element"_a, R"doc( Args: element: codim zero entity in the grid Returns: list of all degrees of freedom attached to the given and all subentities of the given entity. )doc" ); registerMapperCommunicate(cls); registerMapperCommunicate(cls); registerMapperCommunicate(cls); registerMapperCommunicate(cls); registerMapperCommunicate(cls); cls.def( "communicate", [] ( const Mapper &self, pybind11::object from, pybind11::object to, pybind11::object, pybind11::args args ) { throw pybind11::value_error("Combination of 'to' and 'from' partition not legal"); }, "from"_a, "to"_a, "commOp"_a, R"doc( Communicate data stored in `numpy` arrays attached using the given mapper Args: from: partition used on sending processor to: partition used on receiving processor commOp: function (local,remote)->result defining how to combine received with locally stored data on receiving process *args: data vectors to communicate Returns: None Note: - At the moment only double numpy vectors are supported - Not all combinations of `from` and `to` partitions are valid. Possible combinations are - from=interiorBorder and to=interiorBorder|all - from=overlap and to=overlapFront|all - from=overlapFront and to=overlap - from=all and to=interiorBorder|overlap|all, )doc" ); } // registerMultipleCodimMultipleGeomTypeMapper // ------------------------------------------- template< class MCMGMapper, class... options > inline static auto registerMultipleCodimMultipleGeomTypeMapper( pybind11::handle scope, pybind11::class_< MCMGMapper, options... > cls ) { typedef typename MCMGMapper::GridView GridView; using pybind11::operator""_a; registerMapper(cls); // Remark: the gridView is kept alive although the Mapper stores a // copy - this is done to keep the underlying hierarchical grid alive // during the whole life time of the mapper. For this reason the // 'update(GV)' method does not add a keep_alive reference to the GV. // If the update method is called with a GV belonging to a different // HGrid this will cause havoc... cls.def( pybind11::init( [] ( const GridView &gridView, pybind11::object layout ) { return makeMultipleCodimMultipleGeomTypeMapper( gridView, layout ); } ), pybind11::keep_alive< 1, 2 >(), "grid"_a, "layout"_a, R"doc( Set up a mapper to attach data to a grid. The layout argument defines how many degrees of freedom to assign to each subentity of a geometry type. Args: gridView: grid view to set the mapper up for layout: function, dict, tuple, or list defining the number of indices to reserve for each geometry type. 0 or `False`: do not attach any, `True` can be used instead of 1. If layout is a dict, is must map geometry types to integers. All types not mentioned in the dictionary are assumed to be zero. If layout is a tuple or a list, it must contain exactly dimension+1 integers, one for each codimension in the grid. )doc" ); return cls; } template auto registerMultipleCodimMultipleGeomTypeMapper(pybind11::handle scope) { typedef MultipleCodimMultipleGeomTypeMapper MCMGMapper; auto cls = insertClass(scope, "MultipleCodimMultipleGeomTypeMapper", GenerateTypeName("Dune::MultipleCodimMultipleGeomTypeMapper", MetaType()), IncludeFiles{"dune/grid/common/mcmgmapper.hh","dune/python/grid/mapper.hh"}).first; registerMultipleCodimMultipleGeomTypeMapper(scope,cls); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_MAPPER_HH dune-grid-2.11.0/dune/python/grid/numpy.hh000066400000000000000000000372701511655130300203540ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_PYTHON_GRID_NUMPY_HH #define DUNE_PYTHON_GRID_NUMPY_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // External Forward Declarations // ----------------------------- template< class GridFunction > struct GridFunctionTraits; // coordinates // ----------- template< class GridView, class Mapper > inline static pybind11::array_t< typename GridView::ctype > coordinates ( const GridView &gridView, const Mapper &mapper, size_t dimworld ) { typedef typename GridView::ctype ctype; const std::vector< std::size_t > shape{ static_cast< std::size_t >( mapper.size() ), static_cast< std::size_t >( dimworld ) }; const std::vector< std::size_t > stride{ dimworld * sizeof( ctype ), sizeof( ctype ) }; pybind11::array_t< ctype > coords( pybind11::buffer_info( nullptr, sizeof( ctype ), pybind11::format_descriptor< ctype >::value, 2, shape, stride ) ); pybind11::buffer_info info = coords.request( true ); auto ret = [&info,dimworld](const typename Mapper::Index &idx) { return static_cast< ctype * >( info.ptr ) + dimworld * idx; }; for( const auto &vertex : vertices( gridView, Partitions::all ) ) { typename Mapper::Index index; if( !mapper.contains( vertex, index ) ) continue; const auto x = vertex.geometry().center(); std::copy( x.begin(), x.end(), ret(index) ); std::fill( ret(index) + GridView::dimensionworld, ret(index) + dimworld, 0 ); } return coords; } template< class GridView > inline static pybind11::array_t< typename GridView::ctype > coordinates ( const GridView &gridView, size_t dimworld=GridView::dimensionworld ) { MultipleCodimMultipleGeomTypeMapper< GridView > mapper( gridView, mcmgVertexLayout() ); return coordinates( gridView, mapper, dimworld ); } // flatCopy // -------- template< class In, class T, class = std::enable_if_t< std::is_convertible< In, T >::value > > T *flatCopy ( const In &in, T *out ) { *out = in; return ++out; } template< class In, class T, class = decltype( std::declval< const In & >().begin() ), class = std::enable_if_t< !std::is_convertible< In, T >::value > > T *flatCopy ( const In &in, T *out ) { for( auto it = in.begin(), end = in.end(); it != end; ++it ) out = flatCopy( *it, out ); return out; } // makeNumPyArray // -------------- template< class T, class In > pybind11::array_t< T > makeNumPyArray ( const In &in, const std::vector< std::size_t > &shape ) { const std::size_t dim = shape.size(); std::size_t size = sizeof( T ); std::vector< std::size_t > stride( dim ); for( std::size_t i = dim; i-- > 0; ) { stride[ i ] = size; size *= shape[ i ]; } pybind11::array_t< T > result( pybind11::buffer_info( nullptr, sizeof( T ), pybind11::format_descriptor< T >::value, dim, shape, stride ) ); pybind11::buffer_info info = result.request( true ); flatCopy( in, static_cast< T * >( info.ptr ) ); return result; } // tessellate // ---------- template< class GridView, unsigned int partitions > inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tessellate ( const GridView &gridView, RefinementIntervals intervals, PartitionSet< partitions > ps, size_t dimworld) { typedef typename GridView::ctype ctype; const std::size_t dimGrid = GridView::dimension; std::vector< std::vector< ctype > > coords; std::vector< std::array< int, dimGrid+1 > > simplices; for( const auto &element : elements( gridView, ps ) ) { const auto &refinement = buildRefinement< dimGrid, double >( element.type(), GeometryTypes::simplex( dimGrid ) ); const std::size_t offset = coords.size(); // get coordinates const auto geometry = element.geometry(); for( auto it = refinement.vBegin( intervals ), end = refinement.vEnd( intervals ); it != end; ++it ) { auto point = geometry.global( it.coords() ); coords.push_back( std::vector(std::max((int)dimworld,GridView::dimensionworld), 0) ); std::copy(point.begin(),point.end(), coords[coords.size()-1].begin()); } // get simplices for( auto it = refinement.eBegin( intervals ), end = refinement.eEnd( intervals ); it != end; ++it ) { std::array< int, dimGrid+1 > simplex; auto indices = it.vertexIndices(); assert( indices.size() == simplex.size() ); std::transform( indices.begin(), indices.end(), simplex.begin(), [ offset ] ( std::size_t i ) { return (i + offset); } ); simplices.push_back( simplex ); } } return std::make_pair( makeNumPyArray< ctype >( coords, { coords.size(), dimworld } ), makeNumPyArray< int >( simplices, { simplices.size(), dimGrid+1 } ) ); } template< class GridView, unsigned int partitions > inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tessellate ( const GridView &gridView, int level, PartitionSet< partitions > ps, size_t dimworld=GridView::dimensionworld ) { return tessellate( gridView, refinementLevels( level ), ps, dimworld ); } template< class GridView, unsigned int partitions > inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tessellate ( const GridView &gridView, PartitionSet< partitions > ps, size_t dimworld=GridView::dimensionworld ) { return tessellate( gridView, 0, ps, dimworld ); } template< class GridView > inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tessellate ( const GridView &gridView, int level = 0, size_t dimworld=GridView::dimensionworld ) { return tessellate( gridView, level, Partitions::all, dimworld ); } template< class GridView, unsigned int partitions > inline static std::vector< pybind11::array_t< typename GridView::ctype > > polygons ( const GridView &gridView, PartitionSet< partitions > ps ) { typedef typename GridView::ctype ctype; const std::size_t dimWorld = GridView::dimensionworld; std::map< std::size_t, std::vector< std::vector< FieldVector< ctype, dimWorld > > > > coords; for( const auto &element : elements( gridView, ps ) ) { // get coordinates const auto geometry = element.geometry(); const std::size_t corners = geometry.corners(); std::vector< FieldVector< ctype, dimWorld > > poly( corners ); for( std::size_t i = 0; i != corners; ++i ) poly[ i ] = geometry.corner( i ); // Martin: This seems to be limited to two spatial dimensions. if( element.type().isCube() ) std::swap( poly[ 0 ], poly[ 1 ] ); coords[ corners ].push_back( poly ); } std::vector< pybind11::array_t< typename GridView::ctype > > ret; for( const auto &entry : coords ) ret.push_back( makeNumPyArray< ctype >( entry.second, { entry.second.size(), entry.first, dimWorld } ) ); return ret; } template< class GridFunction, unsigned int partitions > inline static // std::pair< // std::vector< pybind11::array_t< typename GridFunction::GridView::ctype > >, // pybind11::array_t< typename GridFunction::GridView::ctype > // > auto polygonData ( const GridFunction &gridFunction, PartitionSet< partitions > ps ) { typedef typename GridFunction::GridView GridView; typedef typename GridView::ctype ctype; const std::size_t dimWorld = GridView::dimensionworld; typedef typename GridFunctionTraits< GridFunction >::Range Range; std::map< std::size_t, std::pair< std::vector< std::vector< FieldVector< ctype, dimWorld > > >, std::vector< Range > > > coords; const auto &gv = gridView( gridFunction ); auto lf = localFunction( gridFunction ); for( const auto &element : elements( gv, ps ) ) { // get coordinates const auto geometry = element.geometry(); const std::size_t corners = geometry.corners(); std::vector< FieldVector< ctype, dimWorld > > poly( corners ); for( std::size_t i = 0; i != corners; ++i ) poly[ i ] = geometry.corner( i ); // Martin: This seems to be limited to two spatial dimensions. if( element.type().isCube() ) std::swap( poly[ 0 ], poly[ 1 ] ); lf.bind(element); coords[ corners ].first.push_back( poly ); // for polygons we can't use a reference element but one could use // the following for elements with type not none: // auto ref = ReferenceElements< typename GridView::ctype, dimGrid >::general( element.type() ); // coords[ corners ].second.push_back( lf( ref.position(0,0) ) ); coords[ corners ].second.push_back( lf( geometry.local( geometry.center() ) ) ); lf.unbind(); } std::vector< pybind11::array_t< typename GridView::ctype > > ret; std::vector< pybind11::array_t< typename GridView::ctype > > values; for( const auto &entry : coords ) { ret.push_back( makeNumPyArray< ctype >( entry.second.first, { entry.second.first.size(), entry.first, dimWorld } ) ); values.push_back( Python::makeNumPyArray< typename FieldTraits< Range >::field_type >( entry.second.second, { entry.second.second.size(), GetDimension::value } ) ); } return std::make_pair(ret, values); } template< class GridView > inline static std::vector< pybind11::array_t< typename GridView::ctype > > polygons ( const GridView &gridView ) { return polygons( gridView, Partitions::all ); } template< class GridFunction > inline static // std::pair< // std::vector< pybind11::array_t< typename GridFunction::GridView::ctype > >, // pybind11::array_t< typename GridFunction::GridView::ctype > // > auto polygonData ( const GridFunction &gridFunction ) { return polygonData( gridFunction, Partitions::all ); } // pointData // --------- template< class GridFunction, unsigned int partitions > inline static auto pointData ( const GridFunction &gridFunction, int level, PartitionSet< partitions > ps ) { typedef typename GridFunctionTraits< GridFunction >::Element Element; typedef typename GridFunctionTraits< GridFunction >::LocalCoordinate LocalCoordinate; typedef typename GridFunctionTraits< GridFunction >::Range Range; typedef typename FieldTraits< LocalCoordinate >::field_type ctype; const auto &gv = gridView( gridFunction ); auto lf = localFunction( gridFunction ); std::vector< Range > values; auto refLevel = refinementLevels(level); for( const auto &element : elements( gv, ps ) ) { lf.bind( element ); const auto &refinement = buildRefinement< Element::mydimension, ctype >( element.type(), GeometryTypes::simplex( Element::dimension ) ); for( auto it = refinement.vBegin( refLevel ), end = refinement.vEnd( refLevel ); it != end; ++it ) values.push_back( lf( it.coords() ) ); lf.unbind(); } return Python::makeNumPyArray< typename FieldTraits< Range >::field_type >( values, { values.size(), GetDimension::value } ); } template< class GridFunction, unsigned int partitions > inline static auto pointData ( const GridFunction &gridFunction, PartitionSet< partitions > ps ) { return pointData( gridFunction, 0, ps ); } template< class GridFunction > inline static auto pointData ( const GridFunction &gridFunction, int level = 0 ) { return pointData( gridFunction, level, Partitions::all ); } // cellData // -------- template< class GridFunction, unsigned int partitions > inline static auto cellData ( const GridFunction &gridFunction, int level, PartitionSet< partitions > ps ) { typedef typename GridFunctionTraits< GridFunction >::Element Element; typedef typename GridFunctionTraits< GridFunction >::LocalCoordinate LocalCoordinate; typedef typename GridFunctionTraits< GridFunction >::Range Range; typedef typename FieldTraits< LocalCoordinate >::field_type ctype; const auto &gv = gridView( gridFunction ); auto lf = localFunction( gridFunction ); std::vector< Range > values; auto refLevel = refinementLevels(level); for( const Element &element : entities( gv, Dune::Codim< Element::codimension >(), ps ) ) { lf.bind( element ); const auto &refinement = buildRefinement< Element::mydimension, ctype >( element.type(), GeometryTypes::simplex( Element::mydimension ) ); for( auto it = refinement.eBegin( refLevel ), end = refinement.eEnd( refLevel ); it != end; ++it ) values.push_back( lf( it.coords() ) ); lf.unbind(); } return Python::makeNumPyArray< typename FieldTraits< Range >::field_type >( values, { values.size(), GetDimension::value } ); } template< class GridFunction, unsigned int partitions > inline static auto cellData ( const GridFunction &gridFunction, PartitionSet< partitions > ps ) { return cellData( gridFunction, 0, ps ); } template< class GridFunction > inline static auto cellData ( const GridFunction &gridFunction, int level = 0 ) { return cellData( gridFunction, level, Partitions::all ); } // deprecated tesselate (note spelling) functions template< class GridView, unsigned int partitions > [[deprecated("use 'tessellate' (note spelling)")]] inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tesselate ( const GridView &gridView, RefinementIntervals intervals, PartitionSet< partitions > ps ) { return tessellate( gridView, intervals, ps); } template< class GridView, unsigned int partitions > [[deprecated("use 'tessellate' (note spelling)")]] inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tesselate ( const GridView &gridView, int level, PartitionSet< partitions > ps ) { return tessellate( gridView, level, ps); } template< class GridView, unsigned int partitions > [[deprecated("use 'tessellate' (note spelling)")]] inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tesselate ( const GridView &gridView, PartitionSet< partitions > ps ) { return tessellate( gridView, ps); } template< class GridView > [[deprecated("use 'tessellate' (note spelling)")]] inline static std::pair< pybind11::array_t< typename GridView::ctype >, pybind11::array_t< int > > tesselate ( const GridView &gridView, int level = 0 ) { tessellate(gridView, level); } } // namespace FemPy } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_NUMPY_HH dune-grid-2.11.0/dune/python/grid/numpycommdatahandle.hh000066400000000000000000000146311511655130300232320ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_PYTHON_UTILITY_VECTORCOMMDATAHANDLE_HH #define DUNE_PYTHON_UTILITY_VECTORCOMMDATAHANDLE_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { // External Forward Declarations // ----------------------------- template< class > class MultipleCodimMultipleGeomTypeMapper; namespace Python { // NumPyCommDataHandle // ------------------- template< class Mapper, class T, class Function > class NumPyCommDataHandle; template< class GV, class T, class Function > class DUNE_PRIVATE NumPyCommDataHandle< MultipleCodimMultipleGeomTypeMapper< GV >, T, Function > : public CommDataHandleIF< NumPyCommDataHandle< MultipleCodimMultipleGeomTypeMapper< GV >, T, Function >, T > { typedef NumPyCommDataHandle< MultipleCodimMultipleGeomTypeMapper< GV >, T, Function > This; typedef MultipleCodimMultipleGeomTypeMapper< GV > Mapper; public: NumPyCommDataHandle ( const Mapper &mapper, std::vector< pybind11::array_t< T > > arrays, Function function = Function() ) : mapper_( mapper ), buffers_( arrays.size() ), function_( function ) { std::transform( arrays.begin(), arrays.end(), buffers_.begin(), [] ( pybind11::array_t< T > &a ) { return a.request(); } ); itemSize_ = 0; for( const pybind11::buffer_info &buffer : buffers_ ) { if( static_cast< std::size_t >( buffer.shape[ 0 ] ) != mapper_.size() ) pybind11::value_error( "Array does not match mapper in construction of NumPyCommDataHandle." ); itemSize_ += std::accumulate( buffer.shape.begin()+1, buffer.shape.end(), std::size_t( 1 ), std::multiplies< std::size_t >() ); } } NumPyCommDataHandle ( const Mapper &mapper, pybind11::array_t< T > array, Function function = Function() ) : NumPyCommDataHandle( mapper, std::vector< pybind11::array_t< T > >{ array }, function ) {} bool contains ( int dim, int codim ) const { const auto &types = mapper_.types( codim ); return std::any_of( types.begin(), types.end(), [ this ] ( GeometryType gt ) { return mapper_.size( gt ) > 0; } ); } bool fixedSize ( int dim, int codim ) const { const auto &types = mapper_.types( codim ); return (std::adjacent_find( types.begin(), types.end(), [ this ] ( GeometryType a, GeometryType b ) { return mapper_.size( a ) != mapper_.size( b ); } ) == types.end()); } template< class Entity > std::size_t size ( const Entity &entity ) const { return mapper_.size( entity.type() ) * itemSize_; } template< class CommBuffer, class Entity > void gather ( CommBuffer &commBuffer, const Entity &entity ) const { for( const pybind11::buffer_info &buffer : buffers_ ) for( const auto index : mapper_.indices( entity ) ) gather( commBuffer, buffer, 1, index*buffer.strides[ 0 ] ); } template< class CommBuffer, class Entity > void scatter ( CommBuffer &commBuffer, const Entity &entity, std::size_t n ) { assert( n == size( entity ) ); for( const pybind11::buffer_info &buffer : buffers_ ) for( const auto index : mapper_.indices( entity ) ) scatter( commBuffer, buffer, 1, index*buffer.strides[ 0 ] ); } private: template< class CommBuffer > void gather ( CommBuffer &commBuffer, const pybind11::buffer_info &buffer, ssize_t dim, ssize_t pos ) const { if( dim < buffer.ndim ) { for( ssize_t i = 0; i < buffer.shape[ dim ]; ++i ) gather( commBuffer, buffer, dim+1, pos + i*buffer.strides[ dim ] ); } else commBuffer.write( *reinterpret_cast< T * >( static_cast< char * >( buffer.ptr ) + pos ) ); } template< class CommBuffer > void scatter ( CommBuffer &commBuffer, const pybind11::buffer_info &buffer, ssize_t dim, ssize_t pos ) { if( dim < buffer.ndim ) { for( ssize_t i = 0; i < buffer.shape[ dim ]; ++i ) scatter( commBuffer, buffer, dim+1, pos + i*buffer.strides[ dim ] ); } else { T &local = *reinterpret_cast< T * >( static_cast< char * >( buffer.ptr ) + pos ); T remote; commBuffer.read( remote ); local = function_( local, remote ); } } const Mapper &mapper_; std::vector< pybind11::buffer_info > buffers_; std::size_t itemSize_; Function function_; }; // vectorCommDataHandle // -------------------- template< class Mapper, class T, class Function > inline static NumPyCommDataHandle< Mapper, T, Function > numPyCommDataHandle ( const Mapper &mapper, pybind11::array_t< T > array, Function function ) { return NumPyCommDataHandle< Mapper, T, Function >( mapper, std::move( array ), std::move( function ) ); } template< class Mapper, class T, class Function > inline static NumPyCommDataHandle< Mapper, T, Function > numPyCommDataHandle( const Mapper &mapper, std::vector> array, Function function ) { return NumPyCommDataHandle< Mapper, T, Function >( mapper, std::move( array ), std::move( function ) ); } template< class Mapper, class T, class Function, class... options > void registerDataHandle ( pybind11::handle module, pybind11::class_< NumPyCommDataHandle< Mapper, T, Function >, options... > cls ) { cls.def( pybind11::init( [] ( Mapper &mapper, pybind11::array_t< T > array, Function function ) { return NumPyCommDataHandle< Mapper, T, Function >( mapper, array, function ); } ), pybind11::keep_alive< 1, 2 >() ); cls.def( pybind11::init( [] ( Mapper &mapper, std::vector< pybind11::array_t< T > > arrays, Function function ) { return NumPyCommDataHandle< Mapper, T, Function >( mapper, arrays, function ); } ), pybind11::keep_alive< 1, 2 >() ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_UTILITY_VECTORCOMMDATAHANDLE_HH dune-grid-2.11.0/dune/python/grid/object.hh000066400000000000000000000054551511655130300204520ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_PYTHON_GRID_OBJECT_HH #define DUNE_PYTHON_GRID_OBJECT_HH #include #include #include namespace Dune { namespace Python { namespace detail { template< class GridObject > inline static const decltype( std::declval< const GridObject & >().gridView() )& gridView ( const GridObject &gridObject, PriorityTag< 3 > ) { return gridObject.gridView(); } template< class GridObject > inline static const decltype( std::declval< const GridObject & >().entitySet().gridView() )& gridView ( const GridObject &gridObject, PriorityTag< 2 > ) { return gridObject.entitySet().gridView(); } template< class GridObject > inline static const decltype( std::declval< const typename GridObject::GridPartType::GridViewType & >() )& gridView ( const GridObject &gridObject, PriorityTag< 1 > ) { return gridObject.gridPart(); } } // namespace detail // gridView // -------- template< class GridObject > inline static const auto& gridView ( const GridObject &gridObject ) { return detail::gridView( gridObject, PriorityTag< 42 >() ); } namespace detail { namespace GridObjectTraits { using Dune::Python::gridView; template< class GridObject > using GridView = std::decay_t< decltype( gridView( std::declval< const GridObject & >() ) ) >; template< class GridObject > typename GridObject::EntitySet::Element element ( const GridObject &, PriorityTag< 1 > ); template< class GridObject > typename GridView< GridObject >::template Codim< 0 >::Entity element ( const GridObject &, PriorityTag< 0 > ); template< class GridObject > typename GridObject::EntitySet::LocalCoordinate localCoordinate ( const GridObject &, PriorityTag< 1 > ); template< class GridObject > typename GridView< GridObject >::template Codim< 0 >::Geometry::LocalCoordinate localCoordinate ( const GridObject &, PriorityTag< 0 > ); } // namespace GridObjectTraits } // namespace detail // GridObjectTraits // ---------------- template< class GridObject > struct GridObjectTraits { typedef decltype( detail::GridObjectTraits::element( std::declval< const GridObject & >(), PriorityTag< 42 >() ) ) Element; typedef decltype( detail::GridObjectTraits::localCoordinate( std::declval< const GridObject & >(), PriorityTag< 42 >() ) ) LocalCoordinate; }; } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_OBJECT_HH dune-grid-2.11.0/dune/python/grid/persistentcontainer.hh000066400000000000000000000026331511655130300233020ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_PERSISTENTCONTAINER_HH #define DUNE_PYTHON_GRID_PERSISTENTCONTAINER_HH #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // registerPersistentContainer // --------------------------- template< class PersistentContainer, class... options > inline static void registerPersistentContainer ( pybind11::handle scope, pybind11::class_< PersistentContainer, options... > cls ) { typedef typename PersistentContainer::Grid Grid; cls.def( pybind11::init( [] ( Grid &grid, int codim ) { return new PersistentContainer( grid, codim ); } ), pybind11::keep_alive< 1, 2 >() ); cls.def_property_readonly( "size", [] ( const PersistentContainer &self ) -> int { return self.size(); }, R"doc( return the size of the given persistent container )doc" ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_PERSISTENTCONTAINER_HH dune-grid-2.11.0/dune/python/grid/pygridfunction.hh000066400000000000000000000042441511655130300222430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_GRID_PY_PYFUNCTION_HH #define DUNE_GRID_PY_PYFUNCTION_HH #warning "The header is deprecated." #include #include #include #include namespace Dune { namespace Python { // PyGridFunction // -------------- template< class GridFunction > class DUNE_PRIVATE [[deprecated]] PyGridFunction { public: PyGridFunction ( const GridFunction &impl, pybind11::object pyObj ) : pyObj_( std::move( pyObj ) ), lf_(impl) {} PyGridFunction ( const GridFunction &impl ) : pyObj_( pybind11::reinterpret_borrow( pybind11::detail::get_object_handle( &impl, pybind11::detail::get_type_info( typeid( GridFunction ) ) ) ) ), lf_(impl) {} template< class Point > auto evaluate ( const Point &x ) const { return lf_( x ); } template< class Point > auto operator() ( const Point &x ) const { return lf_( x ); } template void bind(const Entity &entity) { lf_.bind(entity); } void unbind() { lf_.unbind(); } // friend PyGridFunction localFunction ( const PyGridFunction &gf ) { return PyGridFunction( gf ); } protected: pybind11::object pyObj_; typename GridFunction::LocalFunction lf_; }; // pyGridFunction // -------------- template< class GridFunction > inline static PyGridFunction< GridFunction > pyGridFunction ( const GridFunction &gridFunction ) noexcept { return PyGridFunction< GridFunction >( gridFunction ); } template< class GridFunction > inline static PyGridFunction< GridFunction > pyGridFunction ( const GridFunction &gridFunction, pybind11::object pyObj ) noexcept { return PyGridFunction< GridFunction >( gridFunction, std::move( pyObj ) ); } } // namespace Python } // namespace Dune #endif // DUNE_GRID_PY_PYFUNCTION_HH dune-grid-2.11.0/dune/python/grid/range.hh000066400000000000000000000421431511655130300202730ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_RANGE_HH #define DUNE_PYTHON_GRID_RANGE_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // PyIterator // ---------- template< class Iterator, class Entity > struct PyIterator { PyIterator ( Iterator begin, Iterator end ) : it_( std::move( begin ) ), end_( std::move( end ) ) {} Entity next () { if( it_ == end_ ) throw pybind11::stop_iteration(); Entity entity = *it_; ++it_; return entity; } private: Iterator it_, end_; }; // registerPyIterator // ------------------ template< class Iterator > void registerPyIterator( pybind11::handle scope, pybind11::class_< Iterator > cls ) { cls.def( "__iter__", [] ( Iterator &self ) -> Iterator & { return self; } ); cls.def( "__next__", [] ( Iterator &self ) { return self.next(); } ); } // PyGridViewIterator // ------------------ template< class GridView, int codim > using PyGridViewIterator = PyIterator< typename GridView::template Codim< codim >::Iterator, typename GridView::template Codim< codim >::Entity >; // PyGridViewPartitionIterator // --------------------------- template< class GridView, int codim, PartitionIteratorType partition > using PyGridViewPartitionIterator = PyIterator< typename GridView::template Codim< codim >::template Partition< partition >::Iterator, typename GridView::template Codim< codim >::Entity >; // PyIntersectionIterator // ---------------------- template< class GridView > using PyIntersectionIterator = PyIterator< typename GridView::IntersectionIterator, typename GridView::Intersection >; // PyBoundaryIntersectionIterator // ------------------------------ template< class GridView, class PyElementIterator > struct PyBoundaryIntersectionIterator { typedef typename GridView::Intersection Intersection; PyBoundaryIntersectionIterator ( const GridView &gridView, PyElementIterator it ) : gridView_( gridView ), elementIt_( std::move( it ) ) {} Intersection next () { while( true ) { if( intersectionIt_ != intersectionEnd_ ) { Intersection intersection = *intersectionIt_; ++intersectionIt_; if( intersection.boundary() ) return intersection; } else { auto element = elementIt_.next(); while( !element.hasBoundaryIntersections() ) element = elementIt_.next(); intersectionIt_ = gridView_.ibegin( element ); intersectionEnd_ = gridView_.iend( element ); } } } private: const GridView &gridView_; PyElementIterator elementIt_; typename GridView::IntersectionIterator intersectionIt_, intersectionEnd_; }; #if 0 // PyGridViewPartitionIntersectionIterator // --------------------------------------- template< class GridView, PartitionIteratorType partition > struct PyGridViewPartitionIntersectionIterator { typedef typename GridView::Intersection Intersection; PyGridViewPartitionIntersectionIterator ( const GridView &gridView ) : gridView_( gridView ), mapper_( gridView_, mcmgElementLayout() ), elementIt_( gridView_.template begin< 0, partition >(), gridView_.template end< 0, partition >() ) {} Intersection next () { while( true ) { if( intersectionIt_ != intersectionEnd_ ) { Intersection intersection = *intersectionIt_; ++intersectionIt_; if( !intersection.neighbor() ) return intersection; auto outside = intersection.outside(); if( !partitionSet< partition >().contains( outside.partitionType() ) || (insideIndex_ < mapper_.index( outside )) ) return intersection; } else { auto element = elementIt_.next(); insideIndex_ = mapper_.index( element ); intersectionIt_ = gridView_.ibegin( element ); intersectionEnd_ = gridView_.iend( element ); } } } private: typedef MultipleCodimMultipleGeomTypeMapper< GridView > Mapper; const GridView &gridView_; Mapper mapper_; PyGridViewPartitionIterator< GridView, 0, partition > elementIt_; typename Mapper::Index insideIndex_; typename GridView::IntersectionIterator intersectionIt_, intersectionEnd_; }; #endif // registerPyGridViewIterator // -------------------------- template< class GridView, int codim > inline static auto registerPyGridViewIterator ( pybind11::handle scope, PriorityTag< 1 > ) -> std::enable_if_t< Capabilities::canIterate< typename GridView::Grid, codim >::value > { typedef PyGridViewIterator< GridView, codim > Iterator; auto typeName = GenerateTypeName( "PyGridViewIterator", MetaType< GridView >(), codim ); auto entry = insertClass< Iterator >( scope, "EntityIterator", typeName, IncludeFiles{ "dune/python/grid/range.hh" } ); if( entry.second ) { registerPyIterator( scope, entry.first ); Logger logger( "dune.grid" ); entry.first.def( "__call__", [ logger ] ( pybind11::object self ) { logger.warning( "The methods elements, facets, edges, and vertices have been converted to properties." ); logger.warning( "Please remove the trailing parenthesis." ); return self; } ); entry.first.def( "__call__", [ logger ] ( pybind11::object self, PartitionIteratorType pitype ) { logger.error( "The methods elements, facets, edges, and vertices have been converted to properties." ); switch( pitype ) { case Interior_Partition: logger.error( "The parallel versions can be obtained from the corresponding partition, i.e., interiorPartition." ); break; case InteriorBorder_Partition: logger.error( "The parallel versions can be obtained from the corresponding partition, i.e., interiorBorderPartition." ); break; case Overlap_Partition: logger.error( "The parallel versions can be obtained from the corresponding partition, i.e., overlapPartition." ); break; case OverlapFront_Partition: logger.error( "The parallel versions can be obtained from the corresponding partition, i.e., overlapFrontPartition." ); break; case All_Partition: logger.error( "The parallel versions can be obtained from the corresponding partition, i.e., allPartition." ); break; case Ghost_Partition: logger.error( "The parallel versions can be obtained from the corresponding partition, i.e., ghostPartition." ); break; } throw pybind11::value_error( "The methods elements, facets, edges, and vertices have been converted to properties." ); } ); } } template< class GridView, int codim > inline static void registerPyGridViewIterator ( pybind11::handle scope, PriorityTag< 0 > ) {} template< class GridView, int codim > inline static void registerPyGridViewIterator ( pybind11::handle scope = {} ) { return registerPyGridViewIterator< GridView, codim >( scope, PriorityTag< 42 >() ); } // makePyGridViewIterator // ---------------------- template< class GridView, int codim > inline static auto makePyGridViewIterator ( pybind11::object obj ) -> std::enable_if_t< Capabilities::canIterate< typename GridView::Grid, codim >::value, pybind11::object > { const GridView &gridView = pybind11::cast< const GridView & >( obj ); pybind11::object iterator = pybind11::cast( new PyGridViewIterator< GridView, codim >( gridView.template begin< codim >(), gridView.template end< codim >() ) ); pybind11::detail::keep_alive_impl( iterator, obj ); return iterator; } template< class GridView, int codim > inline static auto makePyGridViewIterator ( pybind11::object ) -> std::enable_if_t< !Capabilities::canIterate< typename GridView::Grid, codim >::value, pybind11::object > { throw pybind11::value_error( "Iterators for codimension " + std::to_string( codim ) + " are not implemented." ); } // registerPyIntersectionIterator // ------------------------------ template< class GridView > inline static void registerPyIntersectionIterator ( pybind11::handle scope = {} ) { typedef PyIntersectionIterator< GridView > Iterator; auto typeName = GenerateTypeName( "Dune::Python::PyIntersectionIterator", MetaType< GridView >() ); auto entry = insertClass< Iterator >( scope, "IntersectionIterator", typeName, IncludeFiles{ "dune/python/range.hh" } ); if( entry.second ) registerPyIterator< Iterator >( scope, entry.first ); } // registerPyBoundaryIntersectionIterator // -------------------------------------- template< class GridView, class PyElementIterator > inline static void registerPyBoundaryIntersectionIterator ( pybind11::handle scope = {} ) { typedef PyBoundaryIntersectionIterator< GridView, PyElementIterator > Iterator; auto typeName = GenerateTypeName( "Dune::Python::PyBoundaryIntersectionIterator", MetaType< GridView >(), MetaType< PyElementIterator >() ); auto entry = insertClass< Iterator >( scope, "BoundaryIntersectionIterator", typeName, IncludeFiles{ "dune/python/range.hh" } ); if( entry.second ) registerPyIterator< Iterator >( scope, entry.first ); } #if 0 // registerPyGridViewPartitionIntersectionIterator // ----------------------------------------------- template< class GridView, PartitionIteratorType partition > inline static void registerPyGridViewPartitionIntersectionIterator ( pybind11::handle scope = {} ) { typedef PyGridViewPartitionIntersectionIterator< GridView, partition > Iterator; auto typeName = GenerateTypeName( "Dune::Python::PyGridViewPartitionIntersectionIterator", MetaType< GridView >(), static_cast< int >( partition ) ); auto entry = insertClass< Iterator >( scope, "PartitionIntersectionIterator", typeName, IncludeFiles{ "dune/python/range.hh" } ); if( entry.second ) registerPyIterator< Iterator >( scope, entry.first ); } #endif // GridViewPartition // ----------------- template< class GridView, PartitionIteratorType partition > struct DUNE_PRIVATE GridViewPartition { explicit GridViewPartition ( pybind11::object o ) : gridView( pybind11::cast< const GridView & >( o ) ), obj( std::move( o ) ) {} const GridView &gridView; pybind11::object obj; }; // registerPyGridViewPartitionIterator // ----------------------------------- template< class GridView, int codim, PartitionIteratorType partition > inline static auto registerPyGridViewPartitionIterator ( pybind11::handle scope, PriorityTag< 1 > ) -> std::enable_if_t< Capabilities::canIterate< typename GridView::Grid, codim >::value > { typedef PyGridViewPartitionIterator< GridView, codim, partition > Iterator; auto typeName = GenerateTypeName( "Dune::Python::PyGridViewPartitionIterator", MetaType< GridView >(), codim, static_cast< int >( partition ) ); auto entry = insertClass< Iterator >( scope, "EntityIterator", typeName, IncludeFiles{ "dune/python/grid/range.hh" } ); if( entry.second ) registerPyIterator( scope, entry.first ); } template< class GridView, int codim, PartitionIteratorType partition > inline static void registerPyGridViewPartitionIterator ( pybind11::handle scope, PriorityTag< 0 > ) {} template< class GridView, int codim, PartitionIteratorType partition > inline static void registerPyGridViewPartitionIterator ( pybind11::handle scope = {} ) { return registerPyGridViewPartitionIterator< GridView, codim, partition >( scope, PriorityTag< 42 >() ); } // makePyGridViewPartitionIterator // ------------------------------- template< class GridView, int codim, PartitionIteratorType partition > inline static auto makePyGridViewPartitionIterator ( pybind11::object obj ) -> std::enable_if_t< Capabilities::canIterate< typename GridView::Grid, codim >::value, pybind11::object > { typedef GridViewPartition< GridView, partition > Partition; const GridView &gridView = pybind11::cast< const Partition & >( obj ).gridView; pybind11::object iterator = pybind11::cast( new PyGridViewPartitionIterator< GridView, codim, partition >( gridView.template begin< codim, partition >(), gridView.template end< codim, partition >() ) ); pybind11::detail::keep_alive_impl( iterator, obj ); return iterator; } template< class GridView, int codim, PartitionIteratorType partition > inline static auto makePyGridViewPartitionIterator ( pybind11::object ) -> std::enable_if_t< !Capabilities::canIterate< typename GridView::Grid, codim >::value, pybind11::object > { throw pybind11::value_error( "Iterators for codimension " + std::to_string( codim ) + " are not implemented." ); } // registerGridViewPartition // ------------------------- template< class GridView, PartitionIteratorType partition > inline static void registerGridViewPartition ( pybind11::handle scope = {} ) { typedef GridViewPartition< GridView, partition > Partition; typedef typename GridView::Grid Grid; typedef PyGridViewPartitionIterator< GridView, 0, partition > PyElementIterator; using pybind11::operator""_a; Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [] ( auto codim ) { registerPyGridViewPartitionIterator< GridView, codim, partition >(); } ); if( !pybind11::already_registered< Partition >() ) { pybind11::class_< Partition > cls( scope, "Partition" ); if( Capabilities::canIterate< Grid, 0 >::value ) cls.def_property_readonly( "elements", [] ( pybind11::object self ) { return makePyGridViewPartitionIterator< GridView, 0, partition >( self ); } ); if( Capabilities::canIterate< Grid, 1 >::value ) cls.def_property_readonly( "facets", [] ( pybind11::object self ) { return makePyGridViewPartitionIterator< GridView, 1, partition >( self ); } ); if( Capabilities::canIterate< Grid, GridView::dimension-1 >::value ) cls.def_property_readonly( "edges", [] ( pybind11::object self ) { return makePyGridViewPartitionIterator< GridView, GridView::dimension-1, partition >( self ); } ); if( Capabilities::canIterate< Grid, GridView::dimension >::value ) cls.def_property_readonly( "vertices", [] ( pybind11::object self ) { return makePyGridViewPartitionIterator< GridView, GridView::dimension, partition >( self ); } ); std::array< pybind11::object (*) ( pybind11::object ), GridView::dimension+1 > makePyIterators; Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [ &makePyIterators ] ( auto codim ) { makePyIterators[ codim ] = makePyGridViewPartitionIterator< GridView, codim, partition >; } ); cls.def( "entities", [ makePyIterators ] ( pybind11::object self, int codim ) { if( (codim < 0) || (codim > GridView::dimension) ) throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( GridView::dimension ) + "])." ); return makePyIterators[ codim ]( self ); }, "codim"_a ); registerPyBoundaryIntersectionIterator< GridView, PyElementIterator >(); cls.def_property_readonly( "boundaryIntersections", [] ( const Partition &self ) { const GridView &gv = self.gridView; return PyBoundaryIntersectionIterator< GridView, PyElementIterator >( gv, PyElementIterator( gv.template begin< 0, partition >(), gv.template end< 0, partition >() ) ); }, pybind11::keep_alive< 0, 1 >() ); } #if 0 registerPyGridViewPartitionIntersectionIterator< GridView, partition >(); cls.def_property_readonly( "intersections", [] ( const Partition &self ) { return PyGridViewPartitionIntersectionIterator< GridView, partition >( self.gridView ); }, pybind11::keep_alive< 0, 1 >() ); #endif } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_RANGE_HH dune-grid-2.11.0/dune/python/grid/simplegridfunction.hh000066400000000000000000000136421511655130300231060ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_PYTHON_FUNCTION_SIMPLEGRIDFUNCTION_HH #define DUNE_PYTHON_FUNCTION_SIMPLEGRIDFUNCTION_HH #include #include #include #include #include namespace Dune { namespace Python { // SimpleLocalFunction // ------------------- template< class GridView, class LocalEvaluator > class SimpleLocalFunction { typedef SimpleLocalFunction< GridView, LocalEvaluator > This; public: typedef typename GridView::template Codim< 0 >::Entity Element; typedef typename Element::Geometry::LocalCoordinate LocalCoordinate; typedef std::decay_t< std::invoke_result_t< LocalEvaluator, Element, LocalCoordinate > > Value; explicit SimpleLocalFunction ( LocalEvaluator localEvaluator ) : localEvaluator_( std::move( localEvaluator ) ) {} ~SimpleLocalFunction() { unbind(); } template explicit SimpleLocalFunction ( const GF &gf ) : SimpleLocalFunction(gf.localEvaluator()) {} void bind ( const Element &element ) { element_ = element; } void unbind () { element_.reset(); } template< class X > auto operator() ( const X &x ) const -> decltype( std::declval< const LocalEvaluator & >()( std::declval< const Element & >(), x ) ) { return localEvaluator_( element(), x ); } const Element &element () const { assert( element_ ); return *element_; } private: std::optional element_; LocalEvaluator localEvaluator_; }; // SimpleGridFunction // ------------------ template< class GV, class LocalEval > class SimpleGridFunction { typedef SimpleGridFunction< GV, LocalEval > This; public: typedef LocalEval LocalEvaluator; static const unsigned int dimRange = LocalEvaluator::dimRange; typedef GV GridView; typedef SimpleLocalFunction< GridView, LocalEvaluator > LocalFunction; typedef typename LocalFunction::Element Element; typedef typename LocalFunction::Value Value; SimpleGridFunction ( const GridView &gridView, LocalEvaluator localEvaluator ) : gridView_( gridView ), localEvaluator_( std::move( localEvaluator ) ) {} const GridView &gridView () const { return gridView_; } const LocalEvaluator &localEvaluator () const { return localEvaluator_; } friend LocalFunction localFunction ( const This &gf ) { return LocalFunction( gf.localEvaluator_ ); } protected: const GridView &gridView_; LocalEvaluator localEvaluator_; }; // LocalEvaluatorAdapter // --------------------- template< class Element, class Evaluator > struct LocalEvaluatorAdapter { static const unsigned int dimRange = Evaluator::dimRange; typedef typename Element::Geometry::GlobalCoordinate GlobalCoordinate; typedef typename Element::Geometry::LocalCoordinate LocalCoordinate; typedef decltype( std::declval< Evaluator >()( std::declval< GlobalCoordinate >() ) ) Value; LocalEvaluatorAdapter ( Evaluator evaluator ) : evaluator_( std::move( evaluator ) ) {} Value operator () ( const GlobalCoordinate &x ) const { return evaluator_( x ); } Value operator () ( const Element &element, const LocalCoordinate &x ) const { return evaluator_( element.geometry().global( x ) ); } private: Evaluator evaluator_; }; // SimpleGlobalGridFunction // ------------------------ template< class GV, class Evaluator > class SimpleGlobalGridFunction : public SimpleGridFunction< GV, LocalEvaluatorAdapter< typename GV::template Codim< 0 >::Entity, Evaluator > > { typedef SimpleGlobalGridFunction< GV, Evaluator > This; typedef SimpleGridFunction< GV, LocalEvaluatorAdapter< typename GV::template Codim< 0 >::Entity, Evaluator > > Base; public: typedef typename Base::GridView GridView; typedef typename Base::Value Value; typedef typename GridView::template Codim< 0 >::Geometry::GlobalCoordinate GlobalCoordinate; SimpleGlobalGridFunction ( const GridView &gridView, Evaluator evaluator ) : Base( gridView, std::move( evaluator ) ) {} Value operator() ( const GlobalCoordinate &x ) const { return localEvaluator_( x ); } protected: using Base::localEvaluator_; }; // simpleGridFunction // ------------------ template< class GV, class LE, class = std::invoke_result_t< std::decay_t< LE >, typename GV::template Codim< 0 >::Entity, typename GV::template Codim< 0 >::Geometry::LocalCoordinate > > inline static auto simpleGridFunction ( const GV &gridView, LE &&localEvaluator, PriorityTag< 1 > ) -> SimpleGridFunction< GV, std::decay_t< LE > > { return SimpleGridFunction< GV, std::decay_t< LE > >( gridView, std::forward< LE >( localEvaluator ) ); } template< class GV, class E, class = std::invoke_result_t< std::decay_t< E >, typename GV::template Codim< 0 >::Geometry::GlobalCoordinate > > inline static auto simpleGridFunction ( const GV &gridView, E &&evaluator, PriorityTag< 0 > ) -> SimpleGlobalGridFunction< GV, std::decay_t< E > > { return SimpleGlobalGridFunction< GV, std::decay_t< E > >( gridView, std::forward< E >( evaluator ) ); } template< class GridView, class Evaluator > inline static auto simpleGridFunction ( const GridView &gridView, Evaluator &&evaluator ) -> decltype( simpleGridFunction( gridView, std::forward< Evaluator >( evaluator ), PriorityTag< 42 >() ) ) { return simpleGridFunction( gridView, std::forward< Evaluator >( evaluator ), PriorityTag< 42 >() ); } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_FUNCTION_SIMPLEGRIDFUNCTION_HH dune-grid-2.11.0/dune/python/grid/vtk.hh000066400000000000000000000111111511655130300177720ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PYTHON_GRID_VTK_HH #define DUNE_PYTHON_GRID_VTK_HH #include #include #include #include #include #include #include #include #include namespace Dune { namespace Python { // External Forward Declarations // ----------------------------- template< class GridFunction > struct GridFunctionTraits; // addToVTKWriter // -------------- template< class GridFunction, class Writer = VTKWriter< std::decay_t< decltype( gridView( std::declval< const GridFunction & >() ) ) > > > void addToVTKWriter ( const GridFunction &gf, std::string name, Writer &vtkWriter, VTKDataType dataType ) { typedef typename GridFunctionTraits< GridFunction >::Range Range; switch( dataType ) { case VTKDataType::CellData: { VTK::FieldInfo info( std::move( name ), VTK::FieldInfo::Type::scalar, GetDimension::value ); vtkWriter.addCellData( gf, info ); break; } case VTKDataType::PointData: { VTK::FieldInfo info( std::move( name ), VTK::FieldInfo::Type::scalar, GetDimension::value ); vtkWriter.addVertexData( gf, info ); break; } case VTKDataType::CellVector: { VTK::FieldInfo info( std::move( name ), VTK::FieldInfo::Type::vector, GetDimension::value ); vtkWriter.addCellData( gf, info ); break; } case VTKDataType::PointVector: { VTK::FieldInfo info( std::move( name ), VTK::FieldInfo::Type::vector, GetDimension::value ); vtkWriter.addVertexData( gf, info ); break; } default: DUNE_THROW( InvalidStateException, "Invalid vtk data type" ); } } // registerVTKWriter // ----------------- template void registerVTKWriter(pybind11::handle scope) { { typedef VTKWriter< GridView > Writer; auto cls = insertClass(scope, "VTKWriter", GenerateTypeName("VTKWriter", MetaType()) ).first; cls.def( "write", [] ( Writer &writer, const std::string &name, Dune::VTK::OutputType outputType ) { writer.write( name, outputType ); }, pybind11::arg("name"), pybind11::arg("outputType")=VTK::appendedraw ); cls.def( "write", [] ( Writer &writer, const std::string &name, int number, Dune::VTK::OutputType outputType ) { std::stringstream s; s << name << std::setw(5) << std::setfill('0') << number; writer.write( s.str(), outputType ); }, pybind11::arg("name"), pybind11::arg("number"), pybind11::arg("outputType")=VTK::appendedraw ); } { typedef SubsamplingVTKWriter< GridView > Writer; auto cls = insertClass< Writer, VTKWriter >(scope, "SubsamplingVTKWriter", GenerateTypeName("SubsamplingVTKWriter", MetaType()) ).first; cls.def( "write", [] ( Writer &writer, const std::string &name, Dune::VTK::OutputType outputType ) { writer.write( name, outputType ); }, pybind11::arg("name"), pybind11::arg("outputType")=VTK::appendedraw ); cls.def( "write", [] ( Writer &writer, const std::string &name, int number ) { std::stringstream s; s << name << std::setw(5) << std::setfill('0') << number; writer.write( s.str() ); }, pybind11::arg("name"), pybind11::arg("number") ); cls.def( "write", [] ( Writer &writer, const std::string &name, int number, Dune::VTK::OutputType outputType ) { std::stringstream s; s << name << std::setw(5) << std::setfill('0') << number; writer.write( s.str(), outputType ); }, pybind11::arg("name"), pybind11::arg("number"), pybind11::arg("outputType")=VTK::appendedraw ); } } } // namespace Python } // namespace Dune #endif // #ifndef DUNE_PYTHON_GRID_VTK_HH dune-grid-2.11.0/dune/python/test/000077500000000000000000000000001511655130300167045ustar00rootroot00000000000000dune-grid-2.11.0/dune/python/test/CMakeLists.txt000066400000000000000000000027031511655130300214460ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception dune_python_add_test(NAME pytest_gf1 SCRIPT test_gf1.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) dune_python_add_test(NAME pytest_gf2 SCRIPT test_gf2.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) dune_python_add_test(NAME pytest_indexset SCRIPT test_indexset.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) dune_python_add_test(NAME pyinterpolate SCRIPT interpolate.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) dune_python_add_test(NAME pybackrest1 SCRIPT backrest1.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) if(dune-uggrid_FOUND) dune_python_add_test(NAME pytestug SCRIPT test-ug.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) dune_python_add_test(NAME pyugfromfile SCRIPT ugfromfile.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) endif() dune-grid-2.11.0/dune/python/test/backrest1.py000066400000000000000000000030251511655130300211350ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import pickle, numpy import dune.generator def backup(): from dune.grid import structuredGrid grid = structuredGrid([0,0],[1,1],[2,2]) grid.hierarchicalGrid.globalRefine(2) a = numpy.array([1,2,3]) pickle.dump([a,"hallo",grid.hierarchicalGrid,10], open("dumpA",'wb')) return grid def restore(): return pickle.load(open("dumpA","rb")) class Test: def __init__(self,g,og): # note: only classes containing HGrids can be pickeled self.hg = g.hierarchicalGrid self.hog = og.hierarchicalGrid def run(self): return self.hg.leafView.size(0) == self.hog.leafView.size(0) if __name__ == "__main__": grid = backup() [b,string,otherHGrid,value] = restore() otherGrid = otherHGrid.leafView print("leaf after refine", grid.size(0),otherGrid.size(0)) print("level 1 after refine", grid.hierarchicalGrid.levelView(1).size(0), otherGrid.hierarchicalGrid.levelView(1).size(0)) otherGrid.hierarchicalGrid.globalRefine(-2) print("coarsen other", grid.size(0),otherGrid.size(0)) grid.hierarchicalGrid.globalRefine(-2) print("coarsen original", grid.size(0),otherGrid.size(0)) test = Test(grid,otherGrid) print("test:",test.run()) pickle.dump(test,open("dumpB","wb")) del test, grid, otherGrid test = pickle.load(open("dumpB","rb")) print("test:",test.run()) dune-grid-2.11.0/dune/python/test/backrest2.py000066400000000000000000000013011511655130300211310ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import pickle import dune.generator # needed to set path to 'dune.generated' - could be moved to 'import dune' [a,string,otherHGrid,value] = pickle.load(open("dumpA","rb")) otherGrid = otherHGrid.leafView otherGrid.plot() print("leaf after refine", otherGrid.size(0)) print("level 1 after refine", otherGrid.hierarchicalGrid.levelView(1).size(0)) otherGrid.hierarchicalGrid.globalRefine(-2) print("coarsen other", otherGrid.size(0)) print("numpy vector",a) test = pickle.load(open("dumpB","rb")) print("test:",test.run()) dune-grid-2.11.0/dune/python/test/interpolate.py000066400000000000000000000073511511655130300216120ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import time, math, numpy, io import dune from dune.generator import algorithm import dune.geometry from dune.grid import cartesianDomain from dune.grid import yaspGrid as gridView def testPyQuad(view,rules,error): start = time.time() l2norm2 = 0 for e in view.elements: hatxs, hatws = rules(e.type).get() weights = hatws * e.geometry.integrationElement(hatxs) l2norm2 += numpy.sum(error(e, hatxs)**2 * weights, axis=-1) # print("Python:",math.sqrt(l2norm2),flush=True) # print("time used:", round(time.time()-start,2),flush=True) return l2norm2 code=""" #include #include #include #include #include template< class GridView, class Rules, class GF > double l2norm2 ( const GridView &gridView, const Rules &rules, const GF& gf ) { auto lf = localFunction( gf ); double l2norm2 = 0; for( const auto &entity : elements( gridView ) ) { const auto geo = entity.geometry(); typedef typename decltype(geo)::LocalCoordinate LocalCoordinate; lf.bind( entity ); pybind11::object pyrule = rules( geo.type() ); pybind11::object pyPW = pyrule.attr("get")(); auto pointsWeights = pyPW.template cast< std::pair, pybind11::array_t> >(); const auto &valuesArray = lf( pointsWeights.first ).template cast< pybind11::array_t< double > >(); // check shape here... auto values = valuesArray.template unchecked< 1 >(); for( std::size_t i = 0, sz = pointsWeights.second.size(); i < sz; ++i ) { LocalCoordinate hatx(0); for (std::size_t c=0;c #include #include template auto myFunction(double a) { return [a](const auto& en,const auto& x) -> auto { auto y = en.geometry().global(x); return std::sin(a*Dune::MathematicalConstants::pi()*(y[0]+y[1])); }; } """ codeVecFunc = """ #include template auto myVecFunction(Dune::FieldVector &a, const GF &gf) { return [&a,lgf=localFunction(gf)](const auto& en,const auto& x) mutable -> auto { lgf.bind(en); auto v = lgf(x); auto y = en.geometry().global(x); return Dune::FieldVector{v[0],(y[0]-0.5)*a[0]}; }; } """ def testGF_second(gridView): gf1 = gridView.function(lambda e,x:\ math.sin(math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1]))) if True: a = 2. gf1 = gridView.function(lambda e,x:\ math.sin(a*math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1])), name="gf1") lgf1 = gf1.localFunction() average1 = 0 for e in gridView.elements: lgf1.bind(e) average1 += lgf1([0.5,0.5])*e.geometry.volume # print(average1) # gf1.plot() gf2 = gridView.function("myFunction",StringIO(codeFunc),a,name="gf2") lgf2 = gf2.localFunction() average2 = 0 for e in gridView.elements: lgf2.bind(e) average2 += lgf2([0.5,0.5])*e.geometry.volume # print(average2) # gf2.plot() # assert abs(average1-average2)<1e-12 diff = 0 for e in gridView.elements: lgf1.bind(e) lgf2.bind(e) diff += abs(lgf1([0.5,0.5])-lgf2([0.5,0.5])) assert diff<1e-12 if True: gf1 = gridView.function(lambda e,x:\ [math.sin(2*math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1])),\ (e.geometry.toGlobal(x)[0]-0.5)*2], name="gf1") lgf1 = gf1.localFunction() average1 = 0 for e in gridView.elements: lgf1.bind(e) average1 += sum(lgf1([0.5,0.5]))*e.geometry.volume # print(average1) # gf1.plot() a = FieldVector([2]) gf2 = gridView.function("myVecFunction",StringIO(codeVecFunc),a,gf1,name="gf2") lgf2 = gf2.localFunction() average2 = 0 for e in gridView.elements: lgf2.bind(e) average2 += sum(lgf2([0.5,0.5]))*e.geometry.volume # print(average2) # gf2.plot() assert abs(average1-average2)<1e-12 diff = 0 for e in gridView.elements: lgf1.bind(e) lgf2.bind(e) diff += abs(lgf1([0.5,0.5]).two_norm-lgf2([0.5,0.5]).two_norm) assert diff<1e-12 a[0] = 3 diff = 0 for e in gridView.elements: lgf1.bind(e) lgf2.bind(e) v = lgf1([0.5,0.5]) v[1] *= 3./2. diff += abs(v.two_norm-lgf2([0.5,0.5]).two_norm) assert diff<1e-12 gridView.writeVTK("test_gf",pointdata=[gf1,gf2]) if False: a = 2. @gridFunction(gridView) def gf1(e,x): return math.sin(a*math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1])) lgf1 = gf1.localFunction() average1 = 0 for e in gridView.elements: lgf1.bind(e) average1 += lgf1([0.5,0.5])*e.geometry.volume # print(average1) # gf1.plot() @gridFunction(gridView) def gf2(x): return math.sin(a*math.pi*(x[0]+x[1])) gf2 = gridView.function("myFunction",StringIO(codeFunc),a,name="gf2") lgf2 = gf2.localFunction() average2 = 0 for e in gridView.elements: lgf2.bind(e) average2 += lgf2([0.5,0.5])*e.geometry.volume # print(average2) # gf2.plot() assert abs(average1-average2)<1e-12 diff = 0 for e in gridView.elements: lgf1.bind(e) lgf2.bind(e) diff += abs(lgf1([0.5,0.5])-lgf2([0.5,0.5])) assert diff<1e-12 if __name__ == "__main__": gridView = structuredGrid([0,0],[1,1],[10,10]) testGF_second(gridView) dune-grid-2.11.0/dune/python/test/test_indexset.py000066400000000000000000000016201511655130300221370ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception from dune.grid import structuredGrid def test_subIndices(gridView): indexSet = gridView.indexSet for intersection in gridView.boundaryIntersections: entity = intersection.inside subentity = (intersection.indexInInside, 1) indices_global = indexSet.subIndices(entity, subentity, 2) indices_reference = entity.referenceElement.subEntities(subentity, 2) indices_lookup = indexSet.subIndices(entity, 2) assert len(indices_global) == len(indices_reference) for i, j in zip(indices_global, indices_reference): assert i == indices_lookup[j] if __name__ == "__main__": gridView = structuredGrid([0,0],[1,1],[10,10]) test_subIndices(gridView) dune-grid-2.11.0/dune/python/test/ugfromfile.py000066400000000000000000000005111511655130300214120ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import dune.grid mshfile = "../../../doc/grids/gmsh/circle1storder.msh" unstructuredGrid = dune.grid.ugGrid( (dune.grid.reader.gmsh, mshfile), dimgrid=2 ) dune-grid-2.11.0/pyproject.toml000066400000000000000000000006211511655130300163640ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception [build-system] requires = ['dune-geometry@git+https://gitlab.dune-project.org/core/dune-geometry.git', 'numpy', 'pip', 'setuptools', 'wheel', 'scikit-build', 'cmake', 'ninja', 'requests'] build-backend = 'setuptools.build_meta' dune-grid-2.11.0/python/000077500000000000000000000000001511655130300147725ustar00rootroot00000000000000dune-grid-2.11.0/python/CMakeLists.txt000066400000000000000000000004661511655130300175400ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(dune) dune_python_configure_bindings( PATH "." CMAKE_METADATA_FLAGS DUNE_OPTS_FILE HAVE_ALBERTA HAVE_DUNE_UGGRID ) dune-grid-2.11.0/python/dune/000077500000000000000000000000001511655130300157255ustar00rootroot00000000000000dune-grid-2.11.0/python/dune/CMakeLists.txt000066400000000000000000000003041511655130300204620ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(grid) dune-grid-2.11.0/python/dune/grid/000077500000000000000000000000001511655130300166525ustar00rootroot00000000000000dune-grid-2.11.0/python/dune/grid/CMakeLists.txt000066400000000000000000000007501511655130300214140ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(tutorial) add_python_targets(grid __init__ __main__ _grids grid_generator core map datahandle ) dune_add_pybind11_module(NAME _grid) set_property(TARGET _grid PROPERTY LINK_LIBRARIES Dune::Grid APPEND) if(SKBUILD) install(TARGETS _grid LIBRARY DESTINATION python/dune/grid) endif() dune-grid-2.11.0/python/dune/grid/__init__.py000066400000000000000000000037321511655130300207700ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception from ._grid import * from .core import * from ._grids import * from dune.common import FieldVector from dune.common.utility import getNumberOfParameters registry = dict() registry["grid"] = grid_registry def gridFunction(view,name=None,order=None,dimRange=None): assert hasattr(view, "dimension"), "did you forget to pass in the grid view to the gridFunction decorator" def gridFunction_decorator(func): return view.function(func,name=name,order=order,dimRange=dimRange) return gridFunction_decorator gridFunction._counter = 0 def GridFunction(view, name=None,order=None): assert hasattr(view, "dimension"), "did you forget to pass in the grid view to the gridFunction decorator" def GridFunction_decorator(cls): if not hasattr(cls,"__call__"): raise TypeError("Class has no call method") class Wrapper(cls): def __init__(self, *args, **kwargs): cls.__init__(self,*args,**kwargs) if getNumberOfParameters(cls.__call__) == 2: # global case self.gf = view.function(lambda x: cls.__call__(self,x),name=name) elif getNumberOfParameters(cls.__call__) == 3: # local case self.gf = view.function(lambda e,x: cls.__call__(self,e,x),name=name) else: raise TypeError("__call__ method needed with 2 or 3 arguments, not %d " %getNumberOfParameters(cls.__call__)) if not hasattr(self,"order"): self.order = order # note: any magic methods on gf will not be picked up! def __getattr__(self, name): return getattr(self.gf, name) def __call__(self,element,point): return self.gf(element,point) return Wrapper return GridFunction_decorator dune-grid-2.11.0/python/dune/grid/__main__.py000066400000000000000000000013331511655130300207440ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import os path = os.path.join( os.path.dirname(__file__), "tutorial" ) execute = "cp -RL " + path + " " execute += "grid_tutorial" status = os.system(execute) if status != 0: raise RuntimeError(status) print("##################################################################") print("## An example script is now located in the 'grid_tutorial' folder.") try: import matplotlib except ImportError: print("## Note: the examples requires the installation of 'matplotlib'.") print("##################################################################") dune-grid-2.11.0/python/dune/grid/_grid.cc000066400000000000000000000110151511655130300202430ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 PYBIND11_MODULE( _grid, module ) { // enumeration types from dune-grid pybind11::enum_< Dune::PartitionType > partitionType( module, "PartitionType" ); partitionType.value( "Interior", Dune::InteriorEntity ); partitionType.value( "Border", Dune::BorderEntity ); partitionType.value( "Overlap", Dune::OverlapEntity ); partitionType.value( "Front", Dune::FrontEntity ); partitionType.value( "Ghost", Dune::GhostEntity ); pybind11::enum_< Dune::InterfaceType > interfaceType( module, "InterfaceType" ); interfaceType.value( "InteriorBorder_InteriorBorder", Dune::InteriorBorder_InteriorBorder_Interface ); interfaceType.value( "InteriorBorder_All", Dune::InteriorBorder_All_Interface ); interfaceType.value( "Overlap_OverlapFront", Dune::Overlap_OverlapFront_Interface ); interfaceType.value( "Overlap_All", Dune::Overlap_All_Interface ); interfaceType.value( "All_All", Dune::All_All_Interface ); auto addPartition = [](auto &module, auto partition, std::string name) { std::string className = name; className[0] = std::toupper(name[0]); pybind11::class_(module, className.c_str()); module.attr( name.c_str() ) = pybind11::cast( partition ); }; auto partitions = module.def_submodule("Partitions"); addPartition(partitions, Dune::Partitions::interior, "interior"); addPartition(partitions, Dune::Partitions::overlap, "overlap"); addPartition(partitions, Dune::Partitions::ghost, "ghost"); addPartition(partitions, Dune::Partitions::all, "all"); addPartition(partitions, Dune::Partitions::interiorBorder, "interiorBorder"); addPartition(partitions, Dune::Partitions::interiorBorderOverlap, "interiorBorderOverlap"); addPartition(partitions, Dune::Partitions::interiorBorderOverlapFront, "interiorBorderOverlapFront"); /* pybind11::enum_< Dune::PartitionIteratorType > partIterType( module, "PartitionIteratorType" ); partIterType.value( "Interior", Dune::Interior_Partition ); partIterType.value( "InteriorBorder", Dune::InteriorBorder_Partition ); partIterType.value( "Overlap", Dune::Overlap_Partition ); partIterType.value( "OverlapFront", Dune::OverlapFront_Partition ); partIterType.value( "All", Dune::All_Partition ); partIterType.value( "Ghost", Dune::Ghost_Partition ); */ pybind11::enum_< Dune::CommunicationDirection > communicationDirection( module, "CommunicationDirection" ); communicationDirection.value( "Forward", Dune::ForwardCommunication ); communicationDirection.value( "Backward", Dune::BackwardCommunication ); pybind11::enum_< Dune::VTK::OutputType > vtkOutputType( module, "OutputType" ); vtkOutputType.value( "ascii", Dune::VTK::OutputType::ascii ); vtkOutputType.value( "base64", Dune::VTK::OutputType::base64 ); vtkOutputType.value( "appendedraw", Dune::VTK::OutputType::appendedraw ); vtkOutputType.value( "appendedbase64", Dune::VTK::OutputType::appendedbase64 ); // enumeration types added by dune-python pybind11::enum_< Dune::Python::detail::CommOp > commOps( module, "CommOp" ); commOps.value( "set", Dune::Python::detail::CommOp::set ); commOps.value( "add", Dune::Python::detail::CommOp::add ); pybind11::enum_< Dune::Python::Marker > marker( module, "Marker" ); marker.value( "coarsen", Dune::Python::Marker::Coarsen ); marker.value( "keep", Dune::Python::Marker::Keep ); marker.value( "refine", Dune::Python::Marker::Refine ); pybind11::enum_< Dune::Python::VTKDataType > vtkDataType( module, "DataType" ); vtkDataType.value( "CellData", Dune::Python::VTKDataType::CellData ); vtkDataType.value( "PointData", Dune::Python::VTKDataType::PointData ); vtkDataType.value( "CellVector", Dune::Python::VTKDataType::CellVector ); vtkDataType.value( "PointVector", Dune::Python::VTKDataType::PointVector ); pybind11::enum_< Dune::Python::Reader > reader( module, "reader" ); reader.value( "dgf", Dune::Python::Reader::dgf ); reader.value( "dgfString", Dune::Python::Reader::dgfString ); reader.value( "gmsh", Dune::Python::Reader::gmsh ); reader.value( "structured", Dune::Python::Reader::structured ); } dune-grid-2.11.0/python/dune/grid/_grids.py000066400000000000000000000365541511655130300205100ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception from dune.typeregistry import generateTypeName class CartesianDomain(tuple): @staticmethod def bndDomain(lower, upper, division, tol = 1e-4 ): bnd = "" lower = list(lower) upper = list(upper) dim = len(lower) for i in range(dim): # compute epsilon eps = tol * abs(upper[i] - lower[i]) / division[i] l = lower.copy() u = upper.copy() l[i] -= 1e2 * eps u[i] = lower[i] bnd += str(2*i+1) + " " + " ".join(str((x-eps)) for x in l) +\ " " + " ".join(str((x+eps)) for x in u) + "\n" l = lower.copy() u = upper.copy() l[i] = upper[i] u[i] = upper[i] + 1e2 * eps bnd += str(2*i+2) + " " + " ".join(str(x-eps) for x in l) +\ " " + " ".join(str(x+eps) for x in u) + "\n" return bnd def __new__ (cls, lower,upper,division,boundary=True,**parameters): from ._grid import reader dgf = "DGF\n" dgf += "INTERVAL\n" dgf += " ".join([str(x) for x in lower]) + "\n" dgf += " ".join([str(x) for x in upper]) + "\n" dgf += " ".join([str(x) for x in division]) + "\n" dgf += "#\n" if boundary: dgf += "BOUNDARYDOMAIN\n" dgf += CartesianDomain.bndDomain(lower,upper, division) dgf += "#\n" dgf += "GRIDPARAMETER\n" foundRefEdge = False for key in parameters: if key.lower() == 'refinementedge': foundRefEdge = True dgf += key + " " + str(parameters[key]) + "\n" # set default value for refinementedge if not provided to avoid warning if not foundRefEdge: dgf += "REFINEMENTEDGE ARBITRARY\n" # simplex grids built from interval blocks are bisection compatible dgf += "BISECTIONCOMPATIBILITY 1\n" dgf += "#\n" try: periodic = parameters["periodic"] if any(periodic): dim = len(lower) # create identity matrix in comma separated rows eye = "" for i in range(dim): for j in range(dim): eye += " 1" if i == j else " 0" eye += " + " if i == dim-1 else ", " dgf += "PERIODICFACETRANSFORMATION\n" for i,p in enumerate(periodic): if p: dgf += eye dgf += " ".join([str(upper[i]-lower[i]) if i==j else "0" for j in range(dim)]) dgf += "\n" dgf += "#\n" except KeyError: pass # print dgf file if verbosity was enabled if "verbose" in parameters: if parameters["verbose"]: print(dgf) return super(CartesianDomain, cls).__new__(cls, tuple( (reader.dgfString, dgf) ) ) def __init__(self,lower,upper,division,boundary=True,**parameters): self.dimgrid = len(lower) self.lower = lower self.upper = upper self.division = division self.param = parameters self.boundaryWasSet = boundary def dimgrid(self): return self.dimgrid def onedGrid(constructor): from .grid_generator import module, getDimgrid typeName = "Dune::OneDGrid" includes = ["dune/grid/onedgrid.hh", "dune/grid/io/file/dgfparser/dgfoned.hh"] gridModule = module(includes, typeName) return gridModule.reader(constructor).leafView def moduleYaspCoordinates(dim, ctype="double"): moduleName = "yaspcoordinates_dim{dim}_ct{ct}".format(ct = ctype, dim = dim) source = """ #include #include #include #include #include #include #include using namespace Dune; using namespace Dune::Python; namespace py = pybind11; template auto registerCoords(py::module module, std::string name) {{ auto includes = IncludeFiles{{"dune/grid/yaspgrid/coordinates.hh"}}; std::string nspace("Dune::"); auto typeName = GenerateTypeName(nspace+name, MetaType<{ct}>(), "{dim}"); auto cls = insertClass(module, name, typeName, includes); if (cls.second) {{ // cls.first.def("name", [name](const T & self) cls.first.def_static("name", [name]() {{ return name; }}); cls.first.def_property_readonly_static("typeName", [typeName](py::object) {{ return typeName.name(); }}); cls.first.def_property_readonly_static("dimgrid", [](py::object) {{ return {dim}; }}); cls.first.def_property_readonly_static("numpy_ctype", [](py::object) {{ return py::dtype::of<{ct}>(); }}); cls.first.def_property_readonly_static("ctype", [](py::object) {{ return "{ct}"; }}); }} return cls.first; }} PYBIND11_MODULE({moduleName}, module) {{ // make sure FieldVector is known to pybind11 addToTypeRegistry<{ct}>(GenerateTypeName("{ct}")); registerFieldVector<{ct},{dim}>(module); // EquidistantCoordinates(const Dune::FieldVector& upperRight, const std::array& s) //py::class_>(module, "EquidistantCoordinates") registerCoords>(module, "EquidistantCoordinates") .def(py::init, std::array>()); // EquidistantOffsetCoordinates(const Dune::FieldVector& lowerLeft, const Dune::FieldVector& upperRight, const std::array& s) registerCoords>(module, "EquidistantOffsetCoordinates") .def(py::init, Dune::FieldVector<{ct},{dim}>, std::array>()); //.def(py::init( [] (std::array, std::array, std::array) {{ return static_cast*>(0); }} )); // TensorProductCoordinates(const std::array,dim>& c, const std::array& offset) registerCoords>(module, "TensorProductCoordinates") .def(py::init,{dim}>, std::array>()); }} """.format(moduleName = moduleName, ct = ctype, dim = dim) from dune.generator import builder module = builder.load(moduleName, source, "yasp coordinates dim={dim} ctype={ct}".format(ct = ctype, dim = dim)) return module def equidistantOffsetCoordinates(lowerleft, upperright, elements, ctype='double'): import numpy as np dim = len(elements) mod = moduleYaspCoordinates(dim,ctype) coords_ = mod.EquidistantOffsetCoordinates # make sure we have float values dtype = coords_.numpy_ctype lowerleft = np.array(lowerleft, dtype=dtype) upperright = np.array(upperright, dtype=dtype) assert(len(lowerleft) == dim) assert(len(upperright) == dim) return coords_(lowerleft, upperright, elements) def equidistantCoordinates(upperright, elements): import numpy as np dim = len(elements) mod = moduleYaspCoordinates(dim,ctype) coords_ = mod.EquidistantCoordinates # make sure we have float values dtype = coords_.numpy_ctype upperright = np.array(upperright, dtype=dtype) assert(len(upperright) == dim) return coords_(upperright, elements) def tensorProductCoordinates(coords, offset=None, ctype='double'): import numpy as np dim = len(coords) mod = moduleYaspCoordinates(dim,ctype) coords_ = mod.TensorProductCoordinates if offset is None: offset = [0,]*dim if len(offset) != dim: raise ValueError("tensorProductCoordinates: offset parameter has wrong size") dtype = coords_.numpy_ctype ## to get the right dtype we use coords = [ np.array(c,dtype=dtype) for c in coords] return coords_(coords,offset) def yaspGrid(constructor, dimgrid=None, coordinates="equidistant", ctype=None, periodic=None, overlap=None, **param): """create a Dune::YaspGrid constructor: a Yaspgrod coordinates object (created via equidistantCoordinates, equidistantOffsetCoordinates or tensorProductCoordinates) or CartesianDomain or a reader object that can be called via gridModule.reader(constructor) dimgrid: explicitly specify the dimension of the grid (should only be set if using a reader) coordinates: explicitly specify coordinates template parameter (deprecated, and ignored) ctype: explicitly specify grids C++ ctype template parameter (should only be set if using a reader, default: double) periodic: boolean list specifying periodicity per dimension (default: no periodicity) overlap: size of overlap for periodic or parallel grids (default: 1) parameters coordinates and ctype are deprecated and will in future be deduced from the constructor parameter. """ from dune.generator import Constructor from .grid_generator import module, getDimgrid # we have to keep track whether we create the grid via a constructor call or via a reader useReader = False #### we try to guess what kind of "constructor" we are using now # CartesianDomain if isinstance(constructor, CartesianDomain): # retrieve parameters from constructor.param, explicit parameters take precedence ctype_ = constructor.param.get("ctype", ctype) if not ctype: ctype = ctype_ else: if ctype != ctype_: print("WARNING: yaspGrid: ctype Parameter of CartesianDomain overwritten by explicit parameter") if not ctype: ctype = "double" # default is double # --- periodic_ = constructor.param.get("periodic", periodic) if not periodic: periodic = periodic_ # if periodic is not gieven on the command line, we use the parameter from CartesianDomain else: if periodic != periodic_: print("WARNING: yaspGrid: periodic Parameter of CartesianDomain overwritten by explicit parameter") # --- overlap_ = constructor.param.get("overlap", overlap) if not overlap: overlap = overlap_ # if overlap is not gieven on the command line, we use the parameter from CartesianDomain else: if overlap != overlap_: print("WARNING: yaspGrid: overlap Parameter of CartesianDomain overwritten by explicit parameter") # --- constructor = equidistantOffsetCoordinates( lowerleft = constructor.lower, upperright = constructor.upper, elements = constructor.division, ctype = ctype ) from dune.grid import reader # Coordinate object if (not isinstance(constructor, tuple)): dimgrid_ = getDimgrid(constructor) if dimgrid: if dimgrid != dimgrid_: raise ValueError("yaspGrid: parameter dimgrid can only be specified, when using a reader") else: dimgrid = dimgrid_ if ctype: if ctype != constructor.ctype: raise ValueError("yaspGrid: ctype is specified via coordinate object and can not be overwritten") ctype = constructor.ctype coordinates_type = constructor.typeName dimgrid = getDimgrid(constructor) if periodic is None: periodic = [False,]*dimgrid if overlap is None: overlap = 1 # Reader elif isinstance(constructor, tuple) and isinstance(constructor[0], reader): if not ctype: ctype = "double" if not dimgrid: raise ValueError("yaspGrid: parameter dimgrid must be specified, when using a reader") mod = moduleYaspCoordinates(dimgrid,ctype) # reader only works with EquidistantOffsetCoordinates or EquidistantCoordinates coords = mod.EquidistantOffsetCoordinates coordinates_type = coords.typeName useReader = True # periodic and overlap are (if required) defined by the DGF reader periodic = None overlap = None else: raise ValueError("yaspGrid: unsupported constructor parameter " + str(constructor)) # compile YaspGrid for a given dimension & coordinate type includes = ["dune/grid/yaspgrid.hh", "dune/grid/io/file/dgfparser/dgfyasp.hh"] gridTypeName, _ = generateTypeName("Dune::YaspGrid", str(dimgrid), coordinates_type) ctor = Constructor( [ "const " + coordinates_type + "& coordinates", 'std::array periodic', 'int overlap' ], [ 'std::bitset<'+str(dimgrid)+'> periodic_;', 'for (int i=0;i<'+str(dimgrid)+';++i) periodic_.set(i,periodic[i]);', 'return new DuneType(coordinates,periodic_,overlap);' ], [ '"coordinates"_a', '"periodic"_a', '"overlap"_a' ]) gridModule = module(includes, gridTypeName, ctor) # read the grid either via reader or create it directly... if useReader: return gridModule.reader(constructor).leafView else: return gridModule.HierarchicalGrid(constructor,periodic,overlap).leafView grid_registry = { "OneD" : onedGrid, "Yasp" : yaspGrid, } from dune.packagemetadata import getCMakeFlags try: if not getCMakeFlags()["HAVE_ALBERTA"]: raise KeyError def albertaGrid(constructor, dimgrid=None, dimworld=None): from .grid_generator import module, getDimgrid if not dimgrid: dimgrid = getDimgrid(constructor) if dimworld is None: dimworld = dimgrid typeName = "Dune::AlbertaGrid< " + str(dimgrid) + " >" includes = ["dune/grid/albertagrid.hh", "dune/grid/albertagrid/dgfparser.hh"] extraCMake = ["add_dune_alberta_flags(TARGET WORLDDIM {})".format(str(dimworld))] gridModule = module(includes, typeName) # , extraCMake=extraCMake) return gridModule.reader(constructor).leafView except KeyError: def albertaGrid(constructor, dimgrid=None, dimworld=None): print(""" Alberta was not found during the configuration of dune-grid. To use 'albertaGrid' install the alberta package first and then reinstall the dune-grid package. """) grid_registry["Alberta"] = albertaGrid from dune.packagemetadata import getCMakeFlags try: if not getCMakeFlags()["HAVE_DUNE_UGGRID"]: raise KeyError def ugGrid(constructor, dimgrid=None, **parameters): from .grid_generator import module, getDimgrid if not dimgrid: dimgrid = getDimgrid(constructor) typeName = "Dune::UGGrid< " + str(dimgrid) + " >" includes = ["dune/grid/uggrid.hh", "dune/grid/io/file/dgfparser/dgfug.hh"] gridModule = module(includes, typeName) return gridModule.reader(constructor).leafView except KeyError: def ugGrid(constructor, dimgrid=None, **parameters): print(""" UGGrid was not found during the configuration of dune-grid. To use 'ugGrid' install the dune-uggrid package first and then reinstall the dune-grid package. """) grid_registry["UG"] = ugGrid if __name__ == "__main__": import doctest dune-grid-2.11.0/python/dune/grid/core.py000066400000000000000000000023151511655130300201550ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception from ._grids import CartesianDomain from .map import MultipleCodimMultipleGeomTypeMapper as Mapper def cartesianDomain(lower, upper, division, **parameters): return CartesianDomain(lower,upper,division,**parameters) def structuredGrid(lower,upper,division,**parameters): from ._grids import yaspGrid domain = cartesianDomain(lower, upper, division, **parameters) return yaspGrid(domain, dimgrid=len(lower), coordinates="equidistantoffset") def string2dgf(dgf): from ._grid import reader return (reader.dgfString,"DGF\n" + dgf) class P1VTKFunction: def __init__(self, module, gridView, container): self.module = module self.mapper = Mapper(gridView, lambda gt: gt.dim == 0) self.v = container def evaluate(self, e, xi): dim = e.dimension nVertices = e.subEntities(dim) cornerValues = [self.v[self.mapper.subIndex(e, i, dim)] for i in range(nVertices)] interpolation = self.module.MultiLinearGeometry(e.type, cornerValues) return interpolation.toGlobal(xi) dune-grid-2.11.0/python/dune/grid/datahandle.py000066400000000000000000000014751511655130300213200ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception from dune.generator.generator import SimpleGenerator from dune.common.hashit import hashIt generator = SimpleGenerator("DataHandle", "Dune::Python") def load(includes, typeName, *args): includes = includes + ["dune/python/common/numpycommdatahandle.hh"] moduleName = "numpycommdatahandle_" + hashIt(typeName) return generator.load(includes, typeName, moduleName, *args) def dataHandle(mapper,array,function): typeName = "Dune::Python::NumPyCommDataHandle< " + mapper.cppTypeName + ", double, std::function >" includes = mapper.cppIncludes return load(includes, typeName).DataHandle(mapper,array,function) dune-grid-2.11.0/python/dune/grid/grid_generator.py000066400000000000000000000400041511655130300222150ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import os, inspect from ..generator.generator import SimpleGenerator from dune.common.hashit import hashIt from dune.common import FieldVector from dune.common.utility import isString from dune.deprecate import deprecated from dune.grid import gridFunction, DataType, Partitions from dune.grid import OutputType from dune.generator.algorithm import cppType from dune.generator import builder from dune.deprecate import deprecated def getDimgrid(constructor): dimgrid = None if not dimgrid: try: dimgrid = constructor.dimgrid except AttributeError: pass if not dimgrid: try: dimgrid = len(constructor["vertices"][0]) except KeyError: pass if not dimgrid: raise ValueError("Couldn't extract dimension of grid from constructor arguments, added dimgrid parameter") return dimgrid def triangulation(grid, level=0, *, partition=Partitions.all): if grid.dimGrid != 2: raise Exception("Grid must be 2-dimensional for use as matplotlib triangulation.") from matplotlib.tri import Triangulation x, triangles = grid.tessellate(level, partition=partition) if len(triangles) == 0: # no elements in this partition set return None return Triangulation(x[:,0], x[:,1], triangles) _writeVTKDispatcher = [] def _writeVTK(vtk,grid,f,name,dataTag): done = False try: f.addToVTKWriter(name, vtk, dataTag) done = True except AttributeError: pass if not done: for dispatch in _writeVTKDispatcher: try: func = dispatch(grid,f) except: func = None if func is not None: func.addToVTKWriter(name,vtk,dataTag) done = True break if not done: gridFunction(grid)(f).addToVTKWriter(name, vtk, dataTag) def writeVTK(grid, name, celldata=None, pointdata=None, cellvector=None, pointvector=None, number=None, subsampling=None,outputType=OutputType.appendedraw, write=True, nonconforming=False): vtk = grid.vtkWriter(nonconforming) if subsampling is None else grid.vtkWriter(subsampling) def addDataToVTKWriter(dataFunctions, dataName, dataTag): if dataFunctions is None: return if isinstance(dataFunctions, dict): for n, f in dataFunctions.items(): if f is None: continue _writeVTK(vtk,grid,f,n,dataTag) elif isinstance(dataFunctions, list): for f in dataFunctions: if f is None: continue try: _writeVTK(vtk,grid,f,f.name,dataTag) except AttributeError: try: _writeVTK(vtk,grid,f[0],f[1],dataTag) except IndexError: raise TypeError(""" Did you try to pass in a function without a name attribute? Try using a dictionary with name:function instead.""") elif dataFunctions is not None: raise TypeError("Argument '" + dataName + "' must be a dict or list instance.") addDataToVTKWriter(celldata, 'celldata', DataType.CellData) addDataToVTKWriter(pointdata, 'pointdata', DataType.PointData) addDataToVTKWriter(cellvector, 'cellvector', DataType.CellVector) addDataToVTKWriter(pointvector, 'pointvector', DataType.PointVector) assert isinstance(outputType,OutputType) if write: if number is None: vtk.write(name, outputType) else: vtk.write(name, number, outputType) else: return vtk class SequencedVTK: def __init__(self, grid, name, number, celldata, pointdata, cellvector, pointvector, subsampling, outputType=OutputType.appendedraw): self.number = number self.name = name self.vtk = grid.writeVTK(name,celldata=celldata,pointdata=pointdata,cellvector=cellvector,pointvector=pointvector,subsampling=subsampling,write=False) self.outputType = outputType def __call__(self): self.vtk.write(self.name, self.number, self.outputType) self.number += 1 def sequencedVTK(grid, name, celldata=None, pointdata=None, cellvector=None, pointvector=None, number=0, subsampling=None, outputType=OutputType.appendedraw): return SequencedVTK(grid,name,number, celldata=celldata,pointdata=pointdata, cellvector=cellvector,pointvector=pointvector, subsampling=subsampling,outputType=outputType) def plot(self, function=None, *args, **kwargs): import dune.plotting if not function: dune.plotting.plotGrid(self, *args, **kwargs) else: if not hasattr(function,"grid"): function = self.function(function) dune.plotting.plot(solution=function,*args,**kwargs) isGenerator = SimpleGenerator("GridViewIndexSet", "Dune::Python") def indexSet(gv): try: return gv._indexSet except TypeError: includes = gv.cppIncludes + ["dune/python/grid/indexset.hh"] typeName = gv.cppTypeName+"::IndexSet" moduleName = "indexset_" + hashIt(typeName) module = isGenerator.load(includes, typeName, moduleName) return gv._indexSet mcmgGenerator = SimpleGenerator("MultipleCodimMultipleGeomTypeMapper", "Dune::Python") def mapper(gv,layout): includes = gv.cppIncludes + ["dune/python/grid/mapper.hh"] typeName = "Dune::MultipleCodimMultipleGeomTypeMapper< "+gv.cppTypeName+" >" moduleName = "mcmgmapper_" + hashIt(typeName) module = mcmgGenerator.load(includes, typeName, moduleName) return gv._mapper(layout) import functools def gfPlot(gf, *args, **kwargs): gf.gridView.plot(gf,*args,**kwargs) def callbackFunction(callback_,e,x): return callback_(e.geometry.toGlobal(x)) def function(gv,callback,includeFiles=None,*args,name=None,order=None,dimRange=None): if name is None: name = "tmp"+str(gv._gfCounter) gv.__class__._gfCounter += 1 if isString(callback): if includeFiles is None: raise ValueError("""if `callback` is the name of a C++ function then at least one include file containing that function must be provided""") # unique header guard is added further down source = '#include \n\n' source += '#define USING_DUNE_PYTHON 1\n\n' includes = [] if isString(includeFiles): if not os.path.dirname(includeFiles): with open(includeFiles, "r") as include: source += include.read() source += "\n" else: source += "#include <"+includeFiles+">\n" includes += [includeFiles] elif hasattr(includeFiles,"readable"): # for IOString with includeFiles as include: source += include.read() source += "\n" elif isinstance(includeFiles, list): for includefile in includeFiles: if not os.path.dirname(includefile): with open(includefile, "r") as include: source += include.read() source += "\n" else: source += "#include <"+includefile+">\n" includes += [includefile] includes += gv.cppIncludes argTypes = [] for arg in args: t,i = cppType(arg) argTypes.append(t) includes += i signature = callback + "( " + ", ".join(argTypes) + " )" moduleName = "gf_" + hashIt(signature) + "_" + hashIt(source) # add unique header guard with moduleName source = '#ifndef Guard_'+moduleName+'\n' + \ '#define Guard_'+moduleName+'\n\n' + \ source includes = sorted(set(includes)) source += "".join(["#include <" + i + ">\n" for i in includes]) source += "\n" source += '#include \n' source += '#include \n' source += '\n' source += "PYBIND11_MODULE( " + moduleName + ", module )\n" source += "{\n" source += " module.def( \"gf\", [module] ( "+gv.cppTypeName + " &gv"+"".join([", "+argTypes[i] + " arg" + str(i) for i in range(len(argTypes))]) + " ) {\n" source += " auto callback="+callback+"<"+gv.cppTypeName+">( "+",".join(["arg"+str(i) for i in range(len(argTypes))]) +"); \n" source += " return Dune::Python::registerGridFunction<"+gv.cppTypeName+",decltype(callback)>(module,pybind11::cast(gv),\"tmp\",callback);\n" source += " }," source += " "+",".join(["pybind11::keep_alive<0,"+str(i+1)+">()" for i in range(len(argTypes)+1)]) source += ");\n" source += "}\n" source += "#endif\n" gf = builder.load(moduleName, source, signature).gf(gv,*args) else: if len(inspect.signature(callback).parameters) == 1: # global function, turn into a local function callback_ = callback # callback = lambda e,x: callback_(e.geometry.toGlobal(x)) callback = functools.partial(callbackFunction, callback_) else: callback_ = None if dimRange is None: # if no `dimRange` attribute is set on the callback, # try to evaluate the function to determine the dimension of # the return value. This can fail if the function is singular in # the computational domain in which case an exception is raised e = gv.elements.__iter__().__next__() try: y = callback(e,e.referenceElement.position(0,0)) except ArithmeticError: try: y = callback(e,e.referenceElement.position(0,2)) except ArithmeticError: raise TypeError("Cannot determine dimension of range of "+ "given grid function due to arithmetic exceptions being "+ "raised. Add a `dimRange` parameter to the grid function to "+ "solve this issue - set `dimRange`=0 for a scalar function.") try: dimRange = len(y) except TypeError: dimRange = 0 if dimRange > 0: scalar = "false" else: scalar = "true" FieldVector(dimRange*[0]) # register FieldVector for the return value if not dimRange in gv.__class__._functions.keys(): # unique header key is added further down source = '#include \n\n' source += '#define USING_DUNE_PYTHON 1\n\n' includes = gv.cppIncludes signature = gv.cppTypeName+"::gf<"+str(dimRange)+">" moduleName = "gf_" + hashIt(signature) + "_" + hashIt(source) # add unique header guard with moduleName source = '#ifndef Guard_'+moduleName+'\n' + \ '#define Guard_'+moduleName+'\n\n' + \ source includes = sorted(set(includes)) source += "".join(["#include <" + i + ">\n" for i in includes]) source += "\n" source += '#include \n' source += '#include \n' source += '\n' source += "PYBIND11_MODULE( " + moduleName + ", module )\n" source += "{\n" source += " typedef pybind11::function Evaluate;\n"; source += " Dune::Python::registerGridFunction< "+gv.cppTypeName+", Evaluate, "+str(dimRange)+" >( module, \"gf\", "+scalar+" );\n" source += "}\n" source += "#endif\n" gfModule = builder.load(moduleName, source, signature) gfFunc = getattr(gfModule,"gf"+str(dimRange)) """ if callback_ is not None: gfFunc.localCall = gfFunc.__call__ gfFunc.globalCall = lambda self,x: callback_(x) feval = lambda self,e,x=None: self.globalCall(e) if x is None else self.localCall(e,x) subclass = type(gfFunc.__name__, (gfFunc,), {"__call__": feval}) gv.__class__._functions[dimRange] = subclass else: gv.__class__._functions[dimRange] = gfFunc """ gfFunc._localCall = gfFunc.__call__ def gfCall(self,e,x=None): if x is None: if not hasattr(self,"_globalCall"): raise AttributeError("this grid function can not be called with a global coordinate") return self._globalCall(e) else: return self._localCall(e,x) gfFunc.__call__ = gfCall gv.__class__._functions[dimRange] = gfFunc gf = gv.__class__._functions[dimRange](gv,callback) if callback_ is not None: # allow to still call with only global coordinate gf._globalCall = callback_ gf.plot = functools.partial(gfPlot, gf) gf.name = name gf.order = order return gf def addAttr(module, cls): setattr(cls, "_module", module) setattr(cls, "writeVTK", writeVTK) setattr(cls, "sequencedVTK", sequencedVTK) setattr(cls, "_functions", {}) @deprecated(name="dune.grid.GridView.tesselate", msg="Use 'tessellate' (note spelling)") def tesselate(gv, *args,**kwargs): return gv.tessellate(*args,**kwargs) setattr(cls,"tesselate", tesselate) [[deprecated("use 'tessellate' (note spelling)")]] if cls.dimension == 2: setattr(cls, "plot", plot) setattr(cls, "triangulation", triangulation) else: def throwFunc(msg): def throw(*args, **kwargs): raise AttributeError(msg) return throw setattr(cls, "plot", throwFunc("plot(...) only implemented on 2D grids")) setattr(cls, "triangulation", throwFunc("triangulation(...) only implemented on 2d grid")) cls.indexSet = property(indexSet) setattr(cls,"mapper",mapper) setattr(cls,"function",function) setattr(cls,"_gfCounter",0) def addHAttr(module): # register reference element for this grid import dune.geometry for d in range(module.LeafGrid.dimension+1): dune.geometry.module(d) setattr(module.HierarchicalGrid,"levelView",levelView) setattr(module.HierarchicalGrid,"persistentContainer",persistentContainer) gvGenerator = SimpleGenerator("GridView", "Dune::Python") def viewModule(includes, typeName, *args, **kwargs): includes = includes + ["dune/python/grid/gridview.hh"] moduleName = "view_" + hashIt(typeName) module = gvGenerator.load(includes, typeName, moduleName, *args, **kwargs) return module def levelView(hgrid,level): includes = hgrid.cppIncludes typeName = "typename "+hgrid.cppTypeName+"::LevelGridView" viewModule(includes, typeName) return hgrid._levelView(level) pcGenerator = SimpleGenerator("PersistentContainer", "Dune::Python") def persistentContainer(hgrid,codim,dimension): includes = hgrid.cppIncludes + ["dune/python/grid/persistentcontainer.hh"] typeName = "Dune::PersistentContainer<"+hgrid.cppTypeName+", Dune::FieldVector>" moduleName = "persistentcontainer_" + hashIt(typeName) module = pcGenerator.load(includes, typeName, moduleName) return module.PersistentContainer(hgrid,codim) def module(includes, typeName, *args, **kwargs): try: generator = kwargs.pop("generator") except KeyError: generator = SimpleGenerator("HierarchicalGrid", "Dune::Python") includes = includes + ["dune/python/grid/hierarchical.hh"] typeHash = "hierarchicalgrid_" + hashIt(typeName) kwargs["dynamicAttr"] = True kwargs["holder"] = "std::shared_ptr" module = generator.load(includes, typeName, typeHash, *args, **kwargs) return module if __name__ == "__main__": import doctest doctest.testmod(optionflags=doctest.ELLIPSIS) dune-grid-2.11.0/python/dune/grid/map.py000066400000000000000000000004131511655130300177770ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception def MultipleCodimMultipleGeomTypeMapper(gridView, layout): return gridView.mapper(layout) dune-grid-2.11.0/python/dune/grid/tutorial/000077500000000000000000000000001511655130300205155ustar00rootroot00000000000000dune-grid-2.11.0/python/dune/grid/tutorial/CMakeLists.txt000066400000000000000000000012261511655130300232560ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # make sure the example works and run in during tests dune_python_add_test(NAME pyexample SCRIPT example.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} LABELS quick) dune_symlink_to_source_files(FILES example.py test2d_offset.dgf circle1storder.msh) if(SKBUILD) install(FILES ../../../../doc/grids/dgf/test2d_offset.dgf ../../../../doc/grids/gmsh/circle1storder.msh DESTINATION python/dune/grid/tutorial) endif() dune-grid-2.11.0/python/dune/grid/tutorial/circle1storder.msh000077700000000000000000000000001511655130300334732../../../../doc/grids/gmsh/circle1storder.mshustar00rootroot00000000000000dune-grid-2.11.0/python/dune/grid/tutorial/dunereader.py000066400000000000000000000335641511655130300232200ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception ############################################################################### # This paraview reader adds support for 'dune binary format' # files (dbf). # The file is assumed to be written using 'dune.common.pickle.dump'. It # therefore consists of two parts (the required jit module source code and # a pickled list of objects). This list is searched for objects containing # a 'gridView' attribute - these are all assumed to be grid functions # over the same grid view and with a 'pointData' attribute. # If no entry in the list with a 'gridView' attribute is found the first # entry is assumed to be a grid view and only the grid is plotted. # # Additional features: # -------------------- # - Only pointdata is extracted at the moment - cell data could be nice. # - We always use the dune subsampler so that a non-connected simplex grid is produced. # An option of working on the actual grid would be nice to have # - Add a indicator based grid refinement (or refinement is some part of the domain only) # - General file reader, i.e., dgf or using GMshReader - issue is figuring out the right dim/dimw ############################################################################### import numpy as np import os,sys,vtk,importlib,glob,json from importlib.util import spec_from_loader, module_from_spec from importlib.machinery import SourceFileLoader from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase from paraview.util.vtkAlgorithm import smdomain, smhint, smproperty, smproxy from vtkmodules.numpy_interface import dataset_adapter as dsa from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid # In paraview (older versions?) there is no way to set the # virtual environment to use - use a environment variable # to set it before starting paraview. # This should be improved to take other usages into account. # This finds all 'egg-link' files in a given folder structure. # These correspond to packages installed 'editable' and need to # be added by hand to the Python search path: def find_egglinks(directory_name): dune_found = [] for path, subdirs, files in os.walk(directory_name): if not path.endswith("site-packages"): continue dune_found.append(path) for name in files: if not "dune" in name: continue ext = os.path.splitext(name)[1] if ext == ".egg-link": file_path = os.path.join(path,name) with open(file_path,"r") as f: dune_found.append(f.read().split()[0]) return dune_found # We find an active virtual env by checking if the environment variable # 'VIRTUAL_ENV' is set - this work at least with activated environments # setup with 'venv' on Linux: def setDuneModulePaths(): try: envdir = os.path.realpath(os.environ['VIRTUAL_ENV']) dunePaths = find_egglinks(os.path.join(envdir,"lib")) sys.path += dunePaths if not "DUNE_PY_DIR" in os.environ: os.environ["DUNE_PY_DIR"] = os.path.join(envdir,".cache") sys.path += os.path.join(os.environ["DUNE_PY_DIR"],"python","dune","generated") # print(os.environ["DUNE_PY_DIR"], dunePaths) except KeyError: # print("no virtual env path found!") pass ############################################ # Actual reader # ------------- # Some documentation # https://kitware.github.io/paraview-docs/latest/python/paraview.util.vtkAlgorithm.html # https://github.com/Kitware/ParaView/blob/master/Examples/Plugins/PythonAlgorithm/PythonAlgorithmExamples.py dune_extensions = ["dbf"] # ,"dgf"] @smproxy.reader( label="Dune Reader", extensions=dune_extensions, file_description="dune binary format files", ) class DuneReader(VTKPythonAlgorithmBase): def __init__(self): VTKPythonAlgorithmBase.__init__( self, nInputPorts=0, nOutputPorts=1, outputType="vtkUnstructuredGrid" ) self._filename = None self._filenameSeries = None self._level = 0 self._transform = None self._transformFcts = [] self._transformFct = "" self._dataFcts = [] self._dataFct = 0 self._timeSteps = None self._currentTime = None self._gridView = None setDuneModulePaths() try: import dune.common.pickle import dune.common.utility except ImportError: raise ImportError("could not import dune.common") self.load = dune.common.pickle.load self.reload = dune.common.utility.reload_module @smproperty.stringvector(name="FileName") @smdomain.filelist() @smhint.filechooser( extensions=dune_extensions, file_description="dune binary file format" ) def SetFileName(self, filename): if (self._filename != filename): self._filename = filename if self._filename != "None": filepart = filename.split(".") if len(filepart)>=3 and filepart[-1] == "dbf": if filepart[-2] == "series": with open(filename,"r") as f: self._filenameSeries = json.load(f) self._timeSteps = [float(v["time"]) for v in self._filenameSeries.values()] self._currentTime = self._timeSteps[0] else: # see if a file of the form 'base.0000.dbf' and # there are others of the same type available: self._filenameSeries = [ f for f in glob.glob(".".join(filepart[0:-2]) + ".*.dbf") if f.split(".")[-2].isnumeric() ] if len(self._filenameSeries) > 1 and filename in self._filenameSeries: # we seem to have a series: self._timeSteps = list(range(len(self._filenameSeries))) self._filenameSeries.sort() self._timeSteps = list(range(len(self._filenameSeries))) self._currentTime = self._filenameSeries.index(filename) else: self._filenameSeries = None self.loadData() self.Modified() def _get_timesteps(self): return self._timeSteps @smproperty.doublevector(name="TimestepValues", information_only="1", si_class="vtkSITimeStepsProperty") def GetTimestepValues(self): return self._get_timesteps() def _get_update_time(self, outInfo): executive = self.GetExecutive() timesteps = self._get_timesteps() if timesteps is None or len(timesteps) == 0: return None elif outInfo.Has(executive.UPDATE_TIME_STEP()) and len(timesteps) > 0: utime = outInfo.Get(executive.UPDATE_TIME_STEP()) dtime = timesteps[0] for atime in timesteps: if atime > utime: return dtime else: dtime = atime return dtime else: assert(len(timesteps) > 0) return timesteps[0] @smproperty.stringvector(name="DataFct", information_only="1") def getDataFcts(self): return self._dataFcts @smproperty.stringvector(name="Datafct", number_of_elements="1") @smdomain.xml(\ """ """) def setDataFcts(self, value): if value in self.getDataFcts(): self._dataFct = self.getDataFcts().index(value) self.Modified() @smproperty.stringvector(name="Transform", default_values="") # , panel_visibility="never") @smdomain.filelist() @smhint.filechooser( extensions=["py"], file_description="Python script" ) def SetTransform(self, transformPath): if transformPath is None: return try: mod = sys.modules.get(transformPath) if mod is None: mod = importlib.import_module(transformPath) else: mod = self.reload(mod) except ImportError: try: spec = spec_from_loader("transform", SourceFileLoader("transform", transformPath)) mod = module_from_spec(spec) spec.loader.exec_module(mod) except FileNotFoundError: print("Failed to import script",transformPath) return if not hasattr(mod,"register"): print("Script",transformPath,"does not have a 'register' attribute - import cancelled") return transformFcts = [m.__name__ for m in mod.register] transformFcts[:0] = ["None"] transformFct = transformFcts[0] self._transform = mod self._transformFcts = transformFcts self._transformFct = transformFct self.Modified() @smproperty.stringvector(name="TransformFct", information_only="1") def getTransformFcts(self): return self._transformFcts @smproperty.stringvector(name="Transfct", number_of_elements="1") @smdomain.xml(\ """ """) def setTransformFcts(self, value): self._transformFct = value self.Modified() @smproperty.intvector(name="Level", default_values="0") @smdomain.intrange(min=0, max=5) def SetLevel(self, level): self._level = level self.Modified() def loadData(self): ext = os.path.splitext(self._filename)[1] if ext == ".dgf": print("Still need to implement dgf reading") print("Which grid to use with which dimensions?") else: if self._filenameSeries is not None: if type(self._filenameSeries) is dict: idx = self._timeSteps.index(self._currentTime) with open(self._filenameSeries[str(idx)]["dumpFileName"],"rb") as f: df = self.load(f) else: with open(self._filenameSeries[self._currentTime],"rb") as f: df = self.load(f) else: with open(self._filename,"rb") as f: df = self.load(f) self._df = [d for d in df if hasattr(d,"gridView")] if len(self._df) > 0: self._gridView = self._df[0].gridView else: self._gridView = df[0] # make some checks: assert hasattr(self._gridView,"dimension"), "file read contains no valid grid view" assert all( [hasattr(d,"pointData") for d in self._df] ), "found a non valid grid function (no 'pointData' attribute" assert all( [self._gridView == d.gridView for d in self._df] ), "all grid function must be over the same gridView" self._dataFcts = [df.name for df in self._df] def RequestInformation(self, request, inInfo, outInfo): executive = self.GetExecutive() outInfo = outInfo.GetInformationObject(0) outInfo.Remove(executive.TIME_STEPS()) outInfo.Remove(executive.TIME_RANGE()) timesteps = self._get_timesteps() if timesteps is not None: for t in timesteps: outInfo.Append(executive.TIME_STEPS(), t) outInfo.Append(executive.TIME_RANGE(), timesteps[0]) outInfo.Append(executive.TIME_RANGE(), timesteps[-1]) return 1 def RequestData(self, request, inInfo, outInfo): cTime = self._get_update_time(outInfo.GetInformationObject(0)) if self._currentTime != cTime: self._currentTime = cTime self.loadData() # data if ( (self._transform is not None) and (not self._transformFct in ["","None"]) and (not self._transformFct is None) ): assert self._dataFct >= 0 gfs = getattr(self._transform,self._transformFct)\ (self._gridView, self._currentTime, self._df[self._dataFct], self._df) else: gfs = self._df points, cells = self._gridView.tessellate(self._level) output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfo)) # points need to be 3d: if self._gridView.dimWorld == 2: vtk_type = vtk.VTK_TRIANGLE points = np.hstack([points, np.zeros((len(points), 1))]) elif self._gridView.dimWorld == 3: if self._gridView.dimGrid == 2: vtk_type = vtk.VTK_TRIANGLE else: vtk_type = vtk.VTK_TETRA output.SetPoints(points) cell_types = np.array([], dtype=np.ubyte) cell_offsets = np.array([], dtype=int) cell_conn = np.array([], dtype=int) ncells, npoints = cells.shape cell_types = np.hstack( [cell_types, np.full(ncells, vtk_type, dtype=np.ubyte)] ) offsets = len(cell_conn) + (1 + npoints) * np.arange(ncells, dtype=int) cell_offsets = np.hstack([cell_offsets, offsets]) conn = np.hstack( [npoints * np.ones((ncells, 1), dtype=int), cells] ).flatten() cell_conn = np.hstack([cell_conn, conn]) output.SetCells(cell_types, cell_offsets, cell_conn) # cell connectivities for df in gfs: array = df.pointData(self._level) output.PointData.append(array, df.name) # point data # output.CellData.append(array, df.name) # cell data # output.FieldData.append(array, name) # field data return 1 dune-grid-2.11.0/python/dune/grid/tutorial/example.py000066400000000000000000000055171511655130300225320ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import math import sys, os # find grid files relative to example.py script griddir = os.path.dirname(sys.argv[0]) # example of how to perform operations on a given grid def runOnGrid(grid): # define a grid function and visualize from dune.grid import gridFunction @gridFunction(grid) def f(x): return math.cos(2.*math.pi/(1+abs(x[0]*x[1]))) f.plot() grid.writeVTK("example", pointdata={"gf":f}) # integrate the grid function using a quadrature rule from dune.geometry from dune.geometry import quadratureRules rules = quadratureRules(5) l2norm2 = 0 for e in grid.elements: geo = e.geometry for qp in rules(e.type): x,w = qp.position, qp.weight l2norm2 += f(e,x)**2*w*geo.integrationElement(x) print("integral of grid function=",math.sqrt(l2norm2)) # construct ugGrid and yaspGrid via file reader from dune.grid import ugGrid, reader print ("construct an unstructured Grid (ugGrid) via file reader") mshfile = os.path.join(griddir, "circle1storder.msh") unstructuredGrid = ugGrid( (reader.gmsh, mshfile), dimgrid=2 ) if not unstructuredGrid: print ("WARNING: skipped ugGrid example, as dune-uggrid is not installed") else: unstructuredGrid.plot() runOnGrid(unstructuredGrid) print ("construct a Grid via file reader") from dune.grid import yaspGrid, reader mshfile = os.path.join(griddir, "test2d_offset.dgf") print(mshfile) dgfgrid = yaspGrid( (reader.dgf, mshfile), dimgrid=2 ) dgfgrid.plot() runOnGrid(dgfgrid) # construct a Cartesian grid print ("construct a Cartesian grid") from dune.grid import structuredGrid grid = structuredGrid([-1,-1],[1,1],[10,10]) print("number of elements of Cartesian grid:",grid.size(0)) grid.plot() runOnGrid(grid) # construct YaspGrids with different coordinate types # yaspGrid allows to specify the coordinate type print ("construct a YaspGrid with tensor product coordinate type") from dune.grid import yaspGrid, tensorProductCoordinates import numpy as np coords = tensorProductCoordinates([np.array([1,2,3,4]), np.array([10,11,33,44])], ctype='float') ygrid = yaspGrid(coords) print("number of elements of tensor YaspGrid grid:",ygrid.size(0)) ygrid.plot() runOnGrid(ygrid) # create a YaspGrid for a cartesian domain with non-standard overlap and periodicity print ("construct a YaspGrid as a CartesianDomain with non-standard overlap and periodicity") from dune.grid import yaspGrid, cartesianDomain dim = 2 cartDomain = cartesianDomain([-10]*dim,[10]*dim, [20]*dim, periodic=[True]*dim, overlap=2) p_grid = yaspGrid( cartDomain, dimgrid=dim) #, ctype='float' ) print("number of elements of periodic YaspGrid grid:",p_grid.size(0)) p_grid.plot() runOnGrid(p_grid) dune-grid-2.11.0/python/dune/grid/tutorial/picklefunc.py000066400000000000000000000011441511655130300232120ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import numpy def globalF(x): x -= [0.1,0.1,0.1] return numpy.sin( (x[0]*x[1]*x[2])*numpy.pi ) def localF(e,y): x = e.geometry.toGlobal(y) x -= [0.1,0.1,0.1] return numpy.sin( (x[0]*x[1]*x[2])*numpy.pi ) class TimeDependent: def __init__(self): self.t = 0 def __call__(self,e,y): x = e.geometry.toGlobal(y) x -= [0.1,0.1,0.1] return numpy.sin( (x[0]*x[1]+self.t*x[1])*numpy.pi ) dune-grid-2.11.0/python/dune/grid/tutorial/pickletrans.py000066400000000000000000000011651511655130300234110ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception from dune.grid import gridFunction from picklefunc import localF, TimeDependent func = TimeDependent() def error(gv,t,df,dfs): if t is None: return [ gridFunction(gv, name="error", order=3)( lambda e,x: abs(df(e,x)-localF(e,x)) )] else: func.t = t return [ gridFunction(gv, name="error", order=3)( lambda e,x: abs(df(e,x)-func(e,x)) )] register = [error] dune-grid-2.11.0/python/dune/grid/tutorial/test2d_offset.dgf000077700000000000000000000000001511655130300326732../../../../doc/grids/dgf/test2d_offset.dgfustar00rootroot00000000000000dune-grid-2.11.0/python/dune/grid/tutorial/testpickle.py000066400000000000000000000036251511655130300232440ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import sys, numpy import dune.common.pickle try: from dune.alugrid import aluConformGrid as view from dune.grid import Marker except ImportError: from dune.grid import yaspGrid as view Marker = None from dune.grid import cartesianDomain, gridFunction def test(fileName): # at the moment only locally defined gridfunctions can be pickled also # function needs to be defined outside of 'main' for unpickling from picklefunc import globalF, localF, TimeDependent grid = view( cartesianDomain([-2,-2,-2],[2,2,2],[3,3,3]) ) grid.hierarchicalGrid.globalRefine(2) if Marker is not None: def indicator(e,y): x = e.geometry.toGlobal(y) return numpy.exp( -(x*x-1)**2 ) for i in range(5): grid.hierarchicalGrid.mark(lambda e: Marker.refine if indicator(e,[1./3.,1./3.]) > 0.9 else Marker.coarsen) grid.hierarchicalGrid.adapt() print("size of adapted grid:", grid.size(0)) # make localF into a gridFunction gf = gridFunction(grid, name="gf", order=3)(localF) # glabal version does not work: gf = gridFunction(grid, name="gf", order=3)(globalF) with open(fileName+".dbf","wb") as f: dune.common.pickle.dump([gf],f) func = TimeDependent() timeGf = gridFunction(grid, name="gf", order=3)(func.__call__) series = dune.common.pickle.SeriesPickler(fileName+"_ts", [timeGf]) tsps = [0,0.1,0.4,0.8,2,4] for i,tsp in enumerate(tsps): func.t = tsp series.dump({"time":tsp}) fbase = "dump.test" if len(sys.argv)<2 or (not sys.argv[1] == 'load'): test(fbase) else: with open(fbase+".dbf","rb") as f: dump = dune.common.pickle.load(f) dump[0].plot() dune-grid-2.11.0/setup.py000066400000000000000000000005351511655130300151660ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception import os, sys try: from dune.packagemetadata import metaData except ImportError: from packagemetadata import metaData from skbuild import setup setup(**metaData()[1]) dune-grid-2.11.0/src/000077500000000000000000000000001511655130300142405ustar00rootroot00000000000000dune-grid-2.11.0/src/CMakeLists.txt000066400000000000000000000003151511655130300167770ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception add_subdirectory(gridinfo-gmsh) dune-grid-2.11.0/src/gridinfo-gmsh/000077500000000000000000000000001511655130300167755ustar00rootroot00000000000000dune-grid-2.11.0/src/gridinfo-gmsh/CMakeLists.txt000066400000000000000000000025621511655130300215420ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception if(ALBERTA_2D_LIB_FOUND AND ENABLE_GRID_EXTRA_UTILS) add_executable(dune-gridinfo-gmsh-alberta-2d gridinfo-gmsh-alberta-2d.cc) target_link_libraries(dune-gridinfo-gmsh-alberta-2d PRIVATE dunegrid) add_dune_alberta_flags(dune-gridinfo-gmsh-alberta-2d GRIDDIM 2) set(PROGRAMS ${PROGRAMS} dune-gridinfo-gmsh-alberta-2d) endif(ALBERTA_2D_LIB_FOUND AND ENABLE_GRID_EXTRA_UTILS) if(ALBERTA_3D_LIB_FOUND AND ENABLE_GRID_EXTRA_UTILS) add_executable(dune-gridinfo-gmsh-alberta-3d gridinfo-gmsh-alberta-3d.cc) target_link_libraries(dune-gridinfo-gmsh-alberta-3d PRIVATE dunegrid) add_dune_alberta_flags(dune-gridinfo-gmsh-alberta-3d GRIDDIM 3) set(PROGRAMS ${PROGRAMS} dune-gridinfo-gmsh-alberta-3d) endif(ALBERTA_3D_LIB_FOUND AND ENABLE_GRID_EXTRA_UTILS) if(dune-uggrid_FOUND AND ENABLE_GRID_EXTRA_UTILS) add_executable(dune-gridinfo-gmsh-ug-2d gridinfo-gmsh-ug-2d.cc) add_dune_ug_flags(dune-gridinfo-gmsh-ug-2d) add_executable(dune-gridinfo-gmsh-ug-3d gridinfo-gmsh-ug-3d.cc) add_dune_ug_flags(dune-gridinfo-gmsh-ug-3d) set(PROGRAMS ${PROGRAMS} dune-gridinfo-gmsh-ug-2d dune-gridinfo-gmsh-ug-3d) endif() if(PROGRAMS) install(TARGETS ${PROGRAMS} DESTINATION ${CMAKE_INSTALL_BINDIR}) endif(PROGRAMS) dune-grid-2.11.0/src/gridinfo-gmsh/gridinfo-gmsh-alberta-2d.cc000066400000000000000000000007401511655130300237550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file COPYING in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include const std::string programName = "dune-gridinfo-gmsh-alberta-2d"; typedef Dune::AlbertaGrid<2, 2> Grid; #include dune-grid-2.11.0/src/gridinfo-gmsh/gridinfo-gmsh-alberta-3d.cc000066400000000000000000000007401511655130300237560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file COPYING in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include const std::string programName = "dune-gridinfo-gmsh-alberta-3d"; typedef Dune::AlbertaGrid<3, 3> Grid; #include dune-grid-2.11.0/src/gridinfo-gmsh/gridinfo-gmsh-ug-2d.cc000066400000000000000000000007161511655130300227610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file COPYING in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include const std::string programName = "dune-gridinfo-gmsh-ug-2d"; typedef Dune::UGGrid<2> Grid; #include dune-grid-2.11.0/src/gridinfo-gmsh/gridinfo-gmsh-ug-3d.cc000066400000000000000000000007161511655130300227620ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file COPYING in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include const std::string programName = "dune-gridinfo-gmsh-ug-3d"; typedef Dune::UGGrid<3> Grid; #include

%eERI֝Հ1OևFKrmy!֗8{%VG`14:Ο"YV0zGLuYK7:Ҡ\e„)F@^ګQPPS+ſd1³4"d>߸n҅Tw&Sșvto:Q-39De(Y+*UsA\:8L۫] *%L1q]_gʔui)>bmV&%fK𚖻Pث.݄+ݭdþPk)ZiH;#d#A<AB.鳊z>lЕ&<Øwz4~/SYޓ^O):W_}G< c1ǨVW^[?G' $|_`L7՛ڥEtia`Su6'(N|VriϮ JroHu_ku#)^bty;AsǙUԓe{FU㡵++3c12: [0`0g~:1x,Yb(*f0c?pk{GNΧt9EFLN<!Rz@QdV5q>D{C{" '6ٻw:g\ZRͪ)R atcnQm2􇟁MoGi0Ϫxs3:~PDV? O}Oae꫽:TtyH*Ip>"aWZe,C_G?-p3<&Y U;ƖgK%&Rz] nH7gIaЕF@ZV١L O{ppUߗ}/^=w8^Q5)Eq]f}E_g99wkq2/ jB˪Pt~G8*axz!#^D{,-_O ч)F{ S.+V|Kc OMc#M3$NaG>S3!v2J_ۈ Xch-TESX! !M#0ڦ1^)2Hn!1[vBViMDI;51@E}6p#^iv}^&?Ծ,U7!x#o>ؗygax̔¥`Wԝ>WK03j g8$?2;a PEYiik{s0ϓ>c87R76w^&?}n[vHoU&/&EMhG/ݹYUmtmCe^V_]ۀWv1B1]O mF-*ՙaRP[]T{J6fDbMVh=wLO~61:&L1x8e%!ᰡeeNו- bfCRe*ղ#w7[ۘuX ;`E#UȽ==piqJű_Sk-Skã|3#@6iuA ƣ\aiE7,${Cګ ~"!()(yI(:jYr'!x8IX_+B[;OFjoK ;,$?^POO9Fs8'Ӯ E`0!0̅0KiI8bj~ΦJ1M ;)@Y)LQGG9zR{E=i6]9S S6d>}ͦ %aQ0RV;Rzͯ/ vep(Di,0 /q6~TFG90DF:Ϟ|މ-y-w1!L=86)5{֌OmyަXZY l"S?ֵS2)όD'fCk kJYD5UUmVSq(s'O.SݧJ05WԾbbr'O8PiJr[`p@k8bqͯx3gS39]˖j~1_`~eȵ SUρ1cRңJ9 ?,Ff٧4WbzbJ'':4G< )u/li\3AtC>#:ңgrzW>^3/33vv{ c\홙7o| 7O.Ry#oC_xL2tbR\G,Ȥa3l·X\8'WOjt٣nwQI5='J!F$LqR  Wq-tj#,݄K($Kk_SRSxf=Kz5`Y*.P !1ORvɵ e?̧b{CN10T>!gђ{BYY^fe' Y,kŔR8Jm@ y U΍U--CCߣzK۩Ǣ&$#(*d0W[$&ԎZ'欧}->yCj>[ۯ'jdg҃b(PW[g9QUd1P샍NO nouӫ쇟OHVkRmʇap(FHb-fBΧ1gzNSCϠ[[Aty x L7+W+IQJAbrNNEE{QKȥP1zC cm RL_OBr1L񰕯CH10K|H4h3[gr=_^[kW$uY GT8{@n\>赮p|rS=gϬQ,zse'I'1N@\Y ]rmN gާ^Yzb#b:Ih)fS(2.50xB[JESmN&zw a"M s]0Eg7C-we%nB?G%rJUuylbK21skԃ}mcwxP!1B(,R_ yGSd|ezPG'sx0Z 2I0v!]ZK*UԱHFp-Ql(N]1inR:8)NKP^QReܚ7vU~^ƻ EIʕnEQ/] Sj s !Laqoc{/R y8TU,2772Fvԕ 4h!$,#`Lify9L)B.9S<wx={{'t~ '9T$ b^ ܨ<4iuu0Fuĸ9PIZTdj#:Lak13mzod DK"70#hA|q~?}J|;@űjuĕOyKE53(dܮ}vxQUxw:|6aj]`fl+@ \,I t:2-CD)QL2\(_ Ոw%`'xoõ х.<pmNvF0oa6kSZ!=)c3b. >lv:}³c3ncܮIAZ X2?'*~,"_Dzk/] 6 hGv>X1'bM&Y0 M'xseѫ3/,{o>G'ECϒe5K0M#!LQ4Q)8! 7ngl^4dVN{C@ϥyIa}56,vsAڥ7ó<KGh d7[|ݼEwd]OюkТzexgG}tT0>t&5`QHc}KO_58*V  S4M*|J~>{Peݢo q[?ˈ _GhFRe"R QR>oeqoַ ߸h`}ʧ|Pb hGDR#tU|Pabʻ*jA~'4x)dž*P,Tq'ƨuァ'-k(S/? GR'-C=3hGTsi B'ЎUіK()Sګ fc1Sx(gҗ66L-ld>qX,#*Swr_jkݝKpa郺t&%+`u$Oop[{BpV7X=aA\ 2}>ҬurXnWk..e R#6_zMeҪFe8&҉CӧD98);aܐ-=u[*; 5eG.g5ָXF؆륊}%"#sO>?Ss@ի7JGL#&Qx QKNU<~c;) CJ L'jTqxO[ߩk5;h v+f_!=a(kB;nŒ1lMNJ9k%&yxaSXn?T |*X(-P)rgu-ck݄0_~jo`Y5L+@ISq^ntH(G'x8jdeHSzK"mGiqoU):,L)}?W^w.͒ʲ2=Mʵ ,Jx M~W~.o Vp n6b(savM>=5;-]f@34 {Y/* TO+0ErWPw|1o}dS͎|0(^EAX`?'G` @/պA?7N1L,\6}W\eG X]XQ#]FFG&㸧v5,+pTk؞(j*M~(f,TX*ࣛ(Ѐe2p~P%&̗=NV]7)]12RԨꋼR? !DΥOqTGUE ǥ3#d8jpFS mgri?X KSe>JA5}q\n?[%T|pP믵7n]-@0m# ]#c\H5+ &rwiq쵛۟+a@R _͝EC:ԺRHj] o8C4(fbMũB]I]7Jj;qP^`F޸}PV4#RˬzPHFpin2~ސ70*TY{_._[lԺ QM#yԺ^@tm#39zQ2;1TRy z#7o-2Jz~pEJxӣW Mŋpf9 6omVJU#L>8v,ReuRA E+'iڍ޸߬U{R&졻׺Յ4ɖoB&%gn~Ik{ .oEMkw8P\^z5`(i<{-_ߺ} o{CcbY}J`5H Lbzw`<>Yd6SR\ ^],؏HӴ^>;F*H_*kQK_39:uucɔ%{.xz;;;8LLN,9fJjfR xôKa벩3;}- uӆ툄i u{ f?:^N/'WPit.+3Yxd$IjՄZiIƮ~]QGdYP'P6Dž4]pe=0{|#%Bń!|af=ńdBf(09p!\xt˜RBK3짿G}]"XNy:+e⃧ 6p*gF QIWN/zsnB6vmĺY"*CI;a pWVŒvxYX<nT٤;c¼@ k]1aRf{@eg(BкC#]HӍfTsB_/FJVUڹx/ƒSE 0oR=r.*:3FS4Ϭ&DF,[Q a/Ow_]e٤l$k(ǤD C83~v)D 0G:$S8xc!`y99,%έ<vrugy\Fb)ύTr,\dv }Sծ=hSlb;g@s4yvJ3Dx5K%T_}Ed0K)4yj&G^y u2G_x|/_#6GTL:}E~0$.׋C)83kSx裹{C\Q݄?25Y,d7$x/Up8@7~XH`0+MF1& Gg ><ҷ F "Lq^;Vj~ѳ8:~<ѼGUJ7 }7 -Gu[*K qS;<*-S4Ժ^θPFWg9y$Zf -xx[ŷ)պ4EJL>'w#B#ދ+aIIy#њN/I4&0ZT,Tq37K%ʶY[HK_ɦ(P1%}u}dy>8ɤ}tgG޺GA䵮,7AJtv&UUۭBD'VصP4f@gZ(Ůc︡HZtB9^Ql[x)U$&d*)L!ΧȲ?8b,l/`pu2OiB I@#΀TWw⼃7Y̻H&NP e~WURX{qaqK_"t|5LeI8QƇd(tjq= A4fe챣}%PJ;dYsjb~'a$f≩eKb9B_Бt4VFBnĄZKix. MrgQg"@IĂN0þIe%+_>(;kjZ(UU[Cd,ѩ8Rȸ{KQƞSƲhl&\&/rwl5za-+ϐgaVkWOCHڔ^NǹF.Hl@nW̧fPQ†ʗ=;@tî@mv*B4ώLyNnEYuRm<(fd>r{n={0q1ST!MzŎVL>wמr½{LX`FYqF_1s8ګŞXa_z2H鵮w{/ Сπ( 4:QL"\ 4Y(i 3`rɑ5JJ41((Uұj D|K%>Ϟ{,5HDžu{0/] ѮKLq 0EG0/6D5GDދT9sHf@!+Z66wUm@:%u; hEa%)3`e0p?#Lmd<{;8ÔZ꫷ݣFˬB[ Rqjc6UMnGB>~4[MQȖr>JR[ـCu,>P,HEoEUm#'jF4=W`1ɘkҖH:KK𞋾w2lqqOf@OBF0aL8;\JIv,~7mTv7;m @>䳗3FE:,.EHvmA^ֽ[Boߏ!XBr#Q o~AF' DMuxAajm$itYNCtt):PBT GQ◖ {>+/|Z&RCVw{\,hкn{S j{b/ʢ$Bם=YQRhA?.ڑO=tswy^f@^>SG/X E? 0$PȢDRrVҗ$<7ҘN o(%DpK{ٛ(Q`oE߽I`Q6ooi0Y,R+kOyw^f@:6viy٤qOg@Ovb\N%ZTs+s|j 0KLfzޭeݔ"SXJ.e{ea8z QGlwN Ak/IsϜ=e+cxچr1y0Y-{^-7>UL'Md hGLSF7392wւQT)Z*.PEQ8Y,S/,f8mXßq-qgG-%Kk [24Oc#j=|C}\j>աcסdY5= !!\HP?Qn3eD247HkJ+c,:+ob,&!sg%,U4*c7ŷf EC=fd*N{a=0yO,$zSLGtzݙ?JL)#&/#M#F*M>?1a݁tMNПyyd>@w_0iO_Ib)?_,G,֗)/0|p"0xk+Sg{wFv9߼h9X4LchGGńҔ:3(dugMX&:U,=R,YSa ;?DD:0w6냊 \{a֟f {TdMU1^+:L ' #gv3ە)" ^eIp0mwNqbZX׺`ЎMd1؅AyW,P8 'y&D=ʍo|0kTSe=\ !RH5TE.R?M 쁛and֤( tfr'_պ:E3(~Wj!ϼ^uP+Pv֚-Nr@׽2h 0 %=9F,н%t:Fɽ]gC8EӱgIqz#=. ]8nd f &x8?;­9k7.\ZD =Q3c,֖:́ew20}ѬK&zsP;#җe4%YZIpm{/*a98=F'[8Q,_<=׵k8dYNB0_`>> ͜}~QffyX7ԛ[YA7dE0VΕ}ȣ|NgTVg܂<&y1LQ> d;$f&'b(¹K_5&8KQJ:qNgS9[& cst[X.k8P=ƄnK9nH05K6k<|!f@5IߵL[W MWJΕGxN{b^&;º**V9Sp0 *}C _Zu&&R&*ςuʊ:5G'}ys95鑝xXW"Pc{>.RX~ щrAE W$FحdfEQqfVT\q:$m|~Ӗgv9~8d]6O*lxZwʊaFmB+?'mԋz##>`idv-g/.TpK$ `[5tiqҦxZ s H6zu]%qRQ_^ӒtxnwlKM3O_؏ Qvuʗńg@zG4LSZyb?  C;`Z8 tL$H`G!g=8ސnXQf&}40MPE'['W(`݄Sw^H2ޫ {XHBQB~lWH\  N%Et !2Z&I_z qN8 aD'D %7;oלLc`Re-# ̧|Ͱ;\i_b]LB^P;BfE|#,6Es*Vu/Zב0FrqγMs 14t>35mN}_$)uD1a'g2=0pk WXu 2ژ#0e罡m:T[h5>R: [E}i y&4C\|Ǔf.,T//TW_?#e/ֵ`R;A yh(PEшF!P̰,S4=WqO#ıR}P%w-,/L| ԄityJq~gͻtq^0xE lm;B*b??C`X4-CcLXDž |T h ѴZ[/jS6OVe^a=Kޝ/SP>(;DNb3NZ?#X`Ҋۼ+*U,Q⋹B8 fIc$t7L 0@41Hkc0W:Ue,nGFlUQ;}woTfkx&f ^I} W@0 .7ṙ1-p x}lB^Oi%^m`yFgNnO?_߿}.M ,14ͳt:Ҟ bE/q_n$`EVkxJi?/,fSxmL5 hG觷?Tڝ0iUT Z.g\R@yKMqjsˋKF߭e!MUIB,sŸ@~oLw:PbUB%x*[O<|eW4_msE;L1an`FHZץ/)FJM3s>+8B5=:.48;iyA=[/J ]PVgg_X_???mB#vOdi. b^MQBƄH\B M`@^{tU=:&+cv ,S*6:0/d2oUBH)3xzM,:XpRl.7 30jQÍJMc" 3ގgS39݉qf@x<TbDS8ү5>EU-tb N )qo$8Oő;@{0_Z|qd>}9]iiJ4y#$¢{]Ϻ^= &7o,nvF%AS/gDZ{ u9@xht١\H%LJ|>jMI[m/cBq4 F8:Bp*n(YkzXB|1_Jd B,rc E/]bH\ s7VfCZ=JBIn_7zLXZ6;{<K\XJcULՀbh:s}t3 񎘙z㢊OQ 7#=QI_R褎ðǝ^ο^~.<đԺfsکzkeẀԓ; 6QtIńy(W3?~drzE_T}f&|0;ܨXƄ\|Vm  &CMnjs+]w]|PQ R#JRpټ}{w7i3e--yw{;x|M,ŢP 9qlG8WA9Ч3n#B]@MNઝ2T1HWs,Yt)M+>xQ&QxAaTIv! BV/=v3)Rc+K3?'Y Eg+XTw2v,0J|=W011>Wkẓƞҗ}"Iˡŏg4Y>.R~lWekԛ#qBA*LCӴ {;1B mEr+YW7$IctfzO,`g! =-bNib%YA7;&9J_J.[8U9va:G3n>/0?@w` 'DJHk @!w~<mxXſgoX|S%aKb٧ }Їq6skCὗrZKi,9B¦qL<2E4q^f@OkjZ c!X|Jw7!0M2y%$xTs|goXn|OTL8Bbnӵ;jqEs Y-öawy ]pbϼCJ_ScRcզt˽}R#L(A1gVǤiMhȁXL{aK`G8 >0 qދ1/#mcnhu9Ҁ?aI//0G::@o5Zއ>^H;Bq&D̫Lme %xyGeC6*WwDՄj70@X*ѾqKG C{=@$n1PtwL2.]It@V48M sk {IU}_­yМePAmb{Xg0M|u&\(s[ۚ(Jsدm`>gQoBp 5gԺ"q3B6E^XV罶LuǨ΀s0sĈ2*iZE;#8n`f}97Y,dw_ẃW+ (D  A?CL @kcU;0Fr~v%A2,f#(k=νxC{E%|#ce&} &82%A,-oU&o,$+Ro&緛8J˼}ou}ʐsDNo};nu5k[mJ\օKSL%NS<'㘦΀Tq! 65`7{sPR|4xRL !.߼B2Ǡ7FXJϋG/CI+僃:g,ie>{9mT/nU4Yq5+70M+}EXN=H%r#`H_S75L=L}߬]"r6@ G7ݪiD/1N"酢8(J<|KgIos(.6Y|/g{^gM#)0t.yXTd605<0n{ 2K:*5 }:zad>QxTU\GUxKk/\pJR:Ƅ_{8s_[AU:FG1ES}aIn?,wvj-h3j,=M *{$ o>(:{kaIzݭQdb0?|X$~g= wl ރ`ث%Bci'P` 0*1NT|Ԏ6ӽ!V#u6/zDbmCf0^~qѝ2A!ͳT6IχW+y EOEz#>64 ^"qOż ۶2Iەm!Pc*lW4Jqz^qX%%@P 1& |iJDDj >xrG2 6'dA>X!=/F6;;֡vȲq χ7c+y†1~aX1a~^.)_|]A]+Anj$<2B>5h!DK_F"\`\Y ƽ"x|ԫ7 tw>{LUy2_PA={SS9W'& P{^6qD}pdiuJ5KS=1y*#S4-'î%A 0`)>ܣ̥ (MC, QC1DH4=ro/q ܻ ,&*ZMrhՙV( E܃, PVa AEtZ(xu팰WSGꌠz@U gO+׺s 08,k]zNYYpL&fbL }$& ,\kOYF`}ѬJb E.akˠGzm6* qO%_8;4mǜџyhqZS4ʳ"}G) />}_^*A`wՇӕri~Ͻ,e4RoXCщ5w_xGFK_DÊ1 pƼlTo6Qfחϱ%v~勺!] /p گ7i!RZ1#R}c f2ts~q>N{k:́-^<6&y\N[v-.ZL=q >vf-UXfRZҵ&'0j{m%@/L7-}Z:~H|\_&`6y'==ag2]`cB#"e݃:zx] Bte8u裥Tq'y&lv5i%aX؏KXRSpV)V,KKs Uxˀ-C3MQN-3+Ч(ʐitG(φjSwGKE]L: Mŷ<}R2?g^Bvz e =8j-& Ѻ}qSh];8KQcg&" hGLbݪhKF0ۑXU%&`f !2u YRQa(7:8SIJ쳱لӵ mqE/ڡ-1aޕEaDyd3AhZ왟z_rRKTGCV8|L{1G:MDt&%cl\S1* #Lmdt`:o vZ([cu-Rdj3G#,2@|ShGFF\^߼ f6!]_ 'opZL(" t@gJcm{M9Kŭ*4!n67f9N1+d>-w7߱S.f#tq׵J+=ν{LX`F8 1֥/¸P> ?Qh:.΀6 +ZoTk7ߚ/ec 3^HD=½&ʚ,+S10itVtgYN{O M:Ti&9M=no\\[-!M1O"qO?3u<^TF6jdeH_2NudEۉBkS4rF}Pvթ#*M!GCIvHL PcꍑbAC-җ1a9'Y,d7j?Wr JUB9Ea ˥T)Gk|ߊ, ^~@e%_!1H zS;={R)eń`3(qQb"$Cu踲B-7T}ovpcBnnX>b.3-җnq\NJ3eri?\1 x#4a),?LG{b4Z7dr24+ -#J\QQcL&x:.ЅYvLu .ΧI¬N0B]>,~:N%IJ,fޥ+ղnBK3;\{pdG$f|?{  15&G%*)p|V`x8f9J_;X ()0E$wS ŌaKο#:}-}裢_7Rqvp4(u EMtuk~X,I NtrsyЀT$L~GH壤?Y/!Zױ50&YP-׃}꠆HP& M# OQehw4ҟx |Q_04=9S>@`BU=7rll>K ؛ʍT vA")Ut D3L柜t= ZABԅ_gyXNG0g# ϞY7YZr]\ R4UQ!k+3/aw%s(` Æ}=q?Fs P|׮ǹPtâ20͐ǵ.%]TDǟhB.b{4 ct-SԇMݨBIDAT̀7>%0w&nȊa~QG'YZ{EMk_Y;IG%bt&{k=q!P.zǹƻԺ6vO4I`## PʐY2M {L![`dI[=3#oAZ!+3c3s>79GQܷ\M+U(z^)UUE-e٤%xͧ~Qﳌ.uxEa0{ʳxGֲֽm֘hx8#1*]sVooV1^FGNxG~gD5ˑETP1J>sc TKRF 1飶]M΍Fcˬ1ͮԊWbL z``·{+yxj_޼*&̥ c¦ֺΧ1}'Y@ WS@YN#yX^NR{X E+l6d>rҒraaMP0WhV Je;F&dX: ]vH?yxc=x" sB< fH -z M%9 Gƣ/E]̰w[۰]rG/d2~=Q:7&:=VhIaRci ' _7̵n֝ B9;dR$ \l0/FUN=-z$M LNQ` I PXjM w-0C!:&L| s7!N*棢|H4Bd1K^\`[i*Oo|`9Bd$\{MXΥ?sB__nT.1aQ17oT σ\NCE {##Tb짷 ZeT<)gGk_205X;bEZzbիX CI5bGwnBwLB6M;l)[.r|o1=TWHuQ׌Kv"V*4(L&KDmT9ve#,h372F(}3\ʺE{itGW1e(Bnkf@nBw$Iy)0U.h`j#tLMS5벓l,t=/ö-:% }YiwQyH\/9F/w荌1Ew74S[ wzI(Jnvid4k>^^qkLXHXzn©pOTԗ\V |*#tLgwPt {o5F#Ɋ tUq|52{iM? 4m̗pk4p/]fd`Xjk(rXb¦2=Q DK14[HӹTF0җ 72$u-BVQўY×n-W`O\Z 8q'ń9‹w2dqC>iQ,&d1_݄;LGAG#N&bN%fR'KіZQDBF^|P!!x6it@`*`L'N.ܬ?`|@RN(Qyb(Z((z;jz/:>B|`(ތ~^ Z!fT!C8_ͻA-CG9hG#H¥X+211Ϣ vLN0Ýҗ^LZQ{OMP}Y2nZ> M8QtDVp76;/YBK(wFp_fga_/:סiR7.J}J~$%6 Rq2d1K7\5)4]C4/Tyz$B&Z0oF b1L3Q4E;}GY~$f6}jUyn={$;7M:Fٯjg }J1N04 ́.Ece2_n݄Tz/mURE?BcWXB/}~m/?m+7Ysa"#( ѻXx _#@wmt5l^0FIt, DH<(5v]RQcKerKXn\*.2mo)K,Gu76& >ȥPkW|T8ˋzCzSR߬Цv"}ϥ0GYmѸf 6p+*p6I=;@]hPY|q~߼;mVFBQ\,v4[ĿCN >f{ǾOi9bbce@`H7f4h >H3 dN! 'Ab‚yQ MXMŘGG]\QfKFQ̀6B8l;f [U6ڭEOqOЎB.aܢ`2Lv*ߠiD!@@C3|!US4}yulVf:C4P+”B`=v(1#J%IR1ۀ$i4ajVL4Wԁ'@*.'0GxDZhgVOl.1BN8Gq9 CVa ѭ,*"D5NwI2AVj|_qO3'!L#rڲKi=:rl>;;"R= REG6Sv>WO}o1afhwَhc/ZO^ۈ %eSZy0td%^AMevPi%DQeݢgĄM t GĄi- %d>wT7KRo&5z⨓ 9 !ԺIjkՃa.PwG{\`kd~-=iAIVkRmʇa?#qa=nRk[}(L./n>sa6^a $fRiL##Ӷ<%_҅F(UȖ2 1#,JYd6Pq)>6t c!7W*h4h ah:)7O-DP^zbH:U+שI>HAQ$Y/b{:#)4ĸn~S|\+ƻmRР߉oQńY_S[ݾn >lR>d Y LRe\+U"}H:)Y %)DWVxIA6|y}nGώntљKMyD{tσ_Kի׵J+=΅`<&̽ w"}'!* l+*'2*Ng \^htY 8lE 6e#̇c6?Bzo^P~DŽy!,DŽ A ] ,: &}B,1aEqQ80—\k# |QɄ@..J Eq0Dbn+,p>S@ _a;}X잟4Fwno܈&) ACM{J?>Sc&6!7 Ӵ &,#OՋK ˆbh@4_>|FLNUkt42SUt#sa륫*jYDVTJ%*ֺIG!RHT0ahV3X%L%T=q?>c݄c +~Mm`ov σ]W&ﮤb&1Yo%yO'ycN(lG$X MѠC1mEqx.lЎ` KE6sPLv5q,bOƺ|gmt9Džxf٧8GdjY_nO>xbL 0F+<~s+anG^<ö@u}52R!03tF:h}uai#!Y04E'cdfRxzEzHP{7;,nL o2{5Z&LƘB |~bS XwkW 8}w c!!e\~aB糐DFCuz@BH\GUe)^#žzi zn<5? =$^:[(vj[(#m(205P,,7.`SUG׺,C\JQov9㹜tYL qC7BWAϬQل[ο9"}P"db}IE_RW@}f)|m}CF0Pk ƅL ΀w{\`O8jdj[b>(,zgs~xZ,"!'1VV 6J`6?Ҽ c7xIPtI^pR-_ |K_1>NpK ]H3{idt.qG8uA#82xqJrw`?䑟ZZ]H%B } Ne2o1_/4]^1RQ+d~_-cꩽ=o7舨t]3tFhu,U(}zPb5Χ}WNxBIqb7T^yWkpFFGs,0RjcXV( Q0knU|_"G3RXK .dt/iZSR%@YnB+ޯO6nIVK_h IJb-fT*鹂'Fp24Saž(dE{H\Sh8P}E'b{9MaE_p,f⛯.Һ|,tfKKZұLTY.Vfs'ςuZwĉ4Z7Z#zC{ĩ}jS6O^8.ѼSw}PQ!|nD65Pr{Re(O ## 66*57Yo7!`zkK&cbGY ı e/\`̵n?;#-C ~5.,ôH\L Dxz)VU&(gcB,2Iʯ EcEmU ,@[c.g.U*M~(fV \ H[A\Q\b¢bs#c6>m) ,.,I.N: tއߴ1>NIi8w5<({E}2O#Nc^N{2eʴ|:.,/d5V>j}> 8ދ17 #PEZACC֥8׋sZ,MG˅@QկG`Vj >7D#vO(%n3/K/@+M>XPApma SOh/Zs;9F'[Gxr£ا K ++u LmG P`3x ß`}SR@:8p:|_#Nl|y'mG2I[˖W6Z8,}&Y*K qG7#dYT& ua\l3!d<ųL&y8q(t>h]w{TB $NCϯ mt%=$#p,z9j@$Y2t̻tq^0˞9>J<|b?Sxu lIR6Ə IA *T =;d5=ܽJv?~w|i sj&U )C} `tiuGI\F*3c|2>絛Ў+6}d{ |")U Ȑ]>܏}oG  u0‡vp]L4S؇FI9^8&,@kO,z1rZNYKr!PTp食Kksƪ[oSHͧ\/8*`#cPΗZ\Mb &1e{s.,ra˟51 hGX#%d.EL$siijE̓$'_H r_?hٟA*/VX)H#U`3 T RoK-Wz0_ZM=ΑKJ>HSQZ.jS7cp.Wm|:+rWoXݟ~>Fǩ3d>sx.I20(|mBoz/}XC[3Y'fr'[KV _o0X\_ ]H3p2x// I&_MѴ`EFGTF(eJc1Ov*MYc^z2,-:aC!:BR@TJ+c,=^yV@%n©,ƥ;W/3rOto>1~jο,?vLKBAm׺Χt@P 5Hǀ-& ^.cQ<7˔ʟ" SCiMi2Mz3,v,G,V\zOj xK~UP/\@%f>-C x>K:ֺqI,xhfۡx<*# ia>F;:n&,gZfe~Dzub ]zi9O溿R">㾪I݄S%YL%_t1 rШu-YiЎ`Vn[\H_^bKp&1!<ʦhCY:Hn;TZ?Ӊ*m=L&tǤd1IM_ԙCمA_zM/.@d1{^ШT[LXHF{ZjaʹTx+@@/ o`p\ <4Fk4|5bPj,_~>zW eK.݄Sa_N][|q1-(LJIhK&)(ϙ?;s$aCsu̇7Lō> )߿b's$nT9y/jh#q],I;e8Vj[.S_(O(5!g@{k#sB:Ŷ]: f.UiZ.d1.l73c0Bc,5BBfBQ\*ߖ?}/"ɱ}@f4CZm!ܩ~\?E-IL75ݢJ^JKɿx977*V"Z #LZ4ǦXMƘd,}w!`߼K6q$"ғ>0wS$BNep).d*0B>?MDfE#4g}m7OtWS}PΧ7U:L EQQ4C8J>zRGX*9|~|Yxgc$^>Ro}? D NUMeN%4LwzGFp2ԟ{_X ݅ 8PN|J1al2T#ǘ09 0?9f̪Cd1݄Tm/UK&̻gG [AElj1ׯ썌;E #}u 8;zDŽa9: :;}h<2V^1aA2d// r෦#I;8%栮VMq(>qkP@ih1+Q r5"j}R^MثgEі{/H`{;}BKDUD$}yu 8R'xSE8@ouzC?TkvȲfD*it`f[NJ MK%$uf(4,f-s2?6`Gh@Av>#,@Z]{/ bcO|:{#+LB3T&5wԢ5mv#i` hAZ+Qd1TdwR{{)y5zsceY|0@# 5-p$_k˥V!=L%IƘDP?w*`V uaim*@3eEБf`-JM2 8=Zt 0 %=IXd.-g |<# ~Qu xoG0& /mQ&\\%Bgy8eGfQnn;nO%J5ڞ|'wT$`42L\Q\N0h8w8/MG찦\kbզhj]|BSceYIg*~/Z& P %)̽O,pzo|]eha7#|cSiwSaiP*֢ r"Ǘ 5 䨥Tǟ+.T//ס~GGDOPP#&Zt;TU#4ˆ&(sDnlͫb_SeQ,"S>B28aʞ {g#uWj}Hm%lZVrDKNl"9H`_|Y.9ĀHCqD!/==oPbͫUェ!3;كpyO\)N{'ѸԹDz#`A 24ie$4vN%bUn8dߒg2Hҩf"t~0)1༥koz90ͷJ : ,$KŒ ;@pϸpuSuR~"/3W+bAgsGk.ܑպRc=E5뺶"uYҴqge`0&p/lskg~um:=M"Q6f@۩!_6)QM-x^;a7`r~O?y2o*QYRT1|&2tj:| §0LvHqUzԺ$ ۶('dJ) 1޿8V`m¼qO#XPk9s#qF&둦I&r9>⺅ 0W4g|2\y'!ʦ(Z\7%KS/@ZHsvh~K&uc`P'نER5A9g)Seތ~ +`6a$8ӝͿVGX*f dZTl(s!ƥ?3A'?Ke~VU~#/Fd%$`aպފSRͦ"$L' LjN90̚Vۢ; 0GS$"#A&LE'&Juyi#U(oE[b̥f^QuP n\ zۄT+Hӹ rlkoNZ_6`MfLȸ|/t>+ smQQi+Cwz%{t"OVojh0I6/Qx^|:Zlj$=*Z:*LN~B  *?0Mwօ<y E RQPC~7d>_.dj0ItD~?7^UMX6aފF49>J$g]m܏Y-6k䭯S4RGX\ڸuwRMp1+cN HWZ"b4;u*1[\ɠqO *]=?ɝ NB\X x(?7VWBKO ٤jaS2It4h`l:v+΢}L+ӻ6I ݧ/%qᆹs.b莭8eSj4ZqB(`"]+ކ |Tb6EtCkЕWAhi+nWg+Je躎$gʠPjn>Ic;<ϟ9O 7 "n4uMk5cyYNلqiƼ2kꌉ|ȁ׷jTOx?7'bջrZOh&c7EX)ltQ hlx SM*)fSc/E: BJA7ϺrC|sDG&'V7S{>,a*G뫛MXy" dD2L>:|PYUڔ!&s96wSO$o&u3o~V {we5>_BJp\U7k셨:*MCM+K|GDyȵ 8l<zu3-+be.mVVU?mnW59JܹMM4ۄcϾ0{^-)[rSןo7ŀwoKBbF:smM/<KʼnHk]+C SjaQUZfGyȈPmܦ] Gw2O,(HwPn~;G "HmkCnJqV|feP\GeMyd)}hlf e3 iSbwn&%GT45/pYۄY@(/l\DAxl֚Sw|򑁌M|*ͥae**tUœ`&6 oK~O{&yDG" EaDy`L}|V6j"_E2G;"՗A15tSwezÍjzzy+h Uqw[BMS%x /fN=s3SJBpEkίpYQ"<|砂+ueQ\>15_F%Y_v0?ķX-,|75X҅;/}e @`V}Yl2"g)Msh8}OeƦ ]i8[_CF}1Pȉ31> ?1 hno8$80Xdt?ofX|PK"x\o,-\_dľH${"M'& 51Guac騹tk88u׾_ YTʕ[׮߾4kh:=7=!bDMpk]"8EOp9YC^ KB&̀vK@}S&ۄި_Dֶ;DUk *D%Ibum8e #T9)@_ȈBo&YCCvg @ Wxs$`)k]b~cZ'x(V9|nRQ1ce@wwtd/t97="{P}exk~Kg?g?YMltΐ "Q6o"sJH< 1hmA2܍ }tz~B^=64[YlO6} @p+} 8Xi Mr aoTV#j-=EYN(_kI&Cd>Nޝͤs_:OYQY/;醀|a ؊T3So a?FЁMZ a['XfG&woT|GX^N`Oƈc)H[ވ-c b:{eK! X!Xxv4# ѥ\wQ)6ږ7)?! |柛{t@1脒,r QabN"ءd@vLÌ5"hAQXx+G4"<9>WA~hUTʕR/ɰ# :EFgJ33&{WBAx6ajr;mhg[o= 8پ:_HG,PB6agQ糚!1 h7f];p?4/2 Z$2yh]7{?ZzU@F }]d&}"*##bzVUꥤov0PR羴 xx({g$Ǯí3Oum^= ۱aqN~kXCIDATxikus|1"@Ӌ7˗́dJ$EJd.VrUUer.n%[dy$K. -k0")23;{q$#3wqqp󝽿c__zc;7?xJ s:B\?=刧))LJu&1kssr<%^BR~g})G<Ň=on|>۷ooڵJ?!PJ]qs9=_{OqxJ ȿW;~bo(-)G<ŇOIaBC?k &SxOIalT+W~4WKYϿmۦ"ٮS߼!2B/FL>#k##븦e ׵ǰg{?b2ƛ[czoG<o~տ;ŤGCq˕/mT~oY<%>{k)`#~ ;bH2`80h -1צz5A9'8<%SV*? 0 |[z8A)aaپt, 6dLQ8W#X5Vj^79!@?Bs͋FRKGȊ]#[Y:67s<@݈<Ɇgn wm8 v׾SW)p\ٟw݉˙oî-~w5>xJ -"+vdxuZ7nL?LX&߶+?ID,xncj47Ol<B_{\mgV(֞f<%/~X;TPqceEoԻe$\ ƕG\T_|I ,!#|s_}qTxJ 82QA!Tv'Ag¿8< va\( > R32:#W=]k޿c`g~қWRԫH·/)++v zoGR}?MwP1ˬa S<PfI@ʠS| n.$:iUap2䬸}uO?r)k&iLpnR0XLk;%=.Zx8ňud™lk7*kvhpy/sQx{_o/RXVBKt|K]]:08HVO;r%_Xn\, #:0FEoV/XH/}?޵~:· )t1xQ81)b{K5$̚ȅAL q5Ip-pҌecw3A*_LT1xWϿy ᅤ:;~^ſ_Iډ%ң,4#r_1rQn g<]8#˕)9[k-גחu_-~}5K1B\S>L Ӓ_bKebVnI(+ ^Z#Q~BP'\8>e{цT~8A5GsFXփ_{ur>|pķ&) w[=:`pё˥/+pG<"RKo8cƒR3vc_)XF/x{pg[¶`!}^k?$u{̾}8[t[=( kF#~ :VCGwTP;pp\hҗ#0xZ>߼rm0!Vσv> dhteC" rWpw1-V? &:[fi{7}F4h6խz "~DŽ-6_[?3+Kݤ3?;ooRmܤpѲbN߃A]qh9kN1\8ܚUOץ+)7Fȴ 8! L*n۟fr_0}~nI^RЀᣏ')3 C4'kzՙ !fȲ.Bg^خ>FJs'-9,ro?èle^~8|@;r< gkLy\;# >=/tF.?+lfObfcNh/#L-fҬZݛF9biigZw}[:)YdU&l=ǀVz7o_]wHhp#$;aNA ɼgr.v:Ѵ"-}v3Zb/JDqjD<0yi3Ge;"s?G뫵pז߂Ѕ7סL99'KL0q/܉0଄3pB'vG.-3>zM+pf,uiʟ4}|g8n. ޼fx{BAa2e;xT^V%Nwo&Rx筻>9w2#reZi\^7 )Q~Fϴ_ʼn(h*8-εϨezTA_mָhY] Y݃>+]n0yĉЎ\w=r*C# {.4B3t}G rM7rpwtp4Dnm}Ӑ (+[rM#:-ּc\?M +y.܉r0Y1G;rAX30f83 :#wO^7y], l oT3S_9zg8ܭK _Z Qcom@`.o-G 8c2T 5&NwS}8!\K?sPD.a7y^8ѩů7yYO 5P=/;x* "պ4:R۟sB{&+#vnD% rJXOsa\VtӂzDPk5ͫ(tSǩlb?licE "VwgL+tǍ\if9@[>E,'ȶڙBR?ՙ7keuq,VeS\S<' m a1Hg }<#w\$Gt @콟y$nj}ەQ&] C* ="L+A0Fd.,3rX8YS!ȶ^g#Q>a!m_{lˉ܅X* Hqtx4sfc+]\O Vnby;.˗ܘ4yI6OOYmfUf}+[A52xc1Qv\s"08|IDw jZ =rT™%9l9.™ŝ{oxV+v׾zemHD|\}(8P[_q5_R J;fBX9*YX ϭSaI ),}] `Rq*坑KgOǛ!UYncp{>\\4Hjp6]Ƥ0r# W\g̐q yxq[Pp\VvQ@Aygǖ4E(P(TJ![bʱF Kŀc zhJUa :T }N+\t@LABGx?y5e΄+!An& v%c45M#s^[v.˖Yq1ŻǮe+.2m ry287L+;$&Rp+ubt=;"*Cy] t\((.v An% e/'!eɛjY@(~뱐-ԝ"G4t{vfU@DEv cJ/k$?k֬E9Vz/Ǵz#?l@Sg:#}Do8Ori9FytqM CV;+_E2t»U. 8Ϫ̔Nql Kin6퓻Z.l%.6݋ɡ)\ `{s:raSuLg⸸ۥ7B-)*pu|f \*) w[m nd _:$׵g5w%Ys.RͰ*DK&cL%sB 9T&-PiwT7qOuŇeksxi04g/"\hUpk!.nks{#])CÛ8WPP!Y|E_Q@aEYXƳ1nkq`V C;ylǒDNr6{F ?}*s-KeŹteʼnJ }VR׼J]L"tJ[3a0'p*E yl۔3=F爠E )Xf K3@f3x<' 'cOzÙbXFٛGh}.ɏ/~hD;QR ӝ; /LtCCBh[JAlj&>,~VXHg I@Qﺆ$)GtBZ$ 爦q:'= ZOK3<9] +/a+rUɚ}vc@\-I=0HLYS%4T!S$6\~u+> 7@Hr,w g~[Ga2|ea9׾n4Sn1$( YbY1:n+)7 ڋ7Wna5xh7luF- H9+wG~U @٦ 3іyɥ XXj\YO~ LCPt4x/m,zzaXI ~bJlE\9˟rwo?Q3xQO]]+\G0*ZųQ$PLͰZʓ/jnǢ6㙨<=QȅrDf։-+tTK_zpwa,q#+%EdAʯXLn?5R8m0몃s'wʊIk{Y¹mGQL^Yƕs3޺oI"QCćGb8uawsPK ;|m"hc~s0;!" !QhZ}`Xi߯GLjr'-NieSŅ)Y = -F}ԍf3+ ?¸bױkNބ ar56DZum/i^2ZD!r\Ҟܶgҳ~^PO&Sӻp`!Ɩ,d-j8I`ga#ӊGY]q*8M, 8 2Fj/oe=NE.yfuSlWzooڙbyKL9Jy8K Jo;r&CGT{'l4'cԶ 溶4׊.TV$UdWoj!S$x#y?/t64 յ`cX,0 DOCՅ^ 0S.wH(С ].OHawrn$Ҍ?ɆkU8E ̟/ EkںL/F"2v7r"J)/YDž^|%MS/rllZ,2x疖C s\ް;#+c\]yȷ/oO7״/s~c5?\\ dE?Iq$.vbrRd0.v~!f]<=YYKfVR‹7y14P]"\;@$ȤkQs&Jl5M-truMs~-a̜1{E ho?ϵ{AO\|sH^[^dI_\ZŁGź;1;!>%u\'׵ma>Xm< q=4LOGon ʍy-vSǝpN!r[,z&!5_eQڭ#W6-ֻJeDESA_x牛)~w-Ҷx(:о~t3;W︣id&nGUvZԙCpN-y=voV6Tu5C΅^S'ȥ_.AQ\ dś٠S\݈i Ra'r_kqEPY1cqZ ^[W9xt$ﻸ8)+vO%g~j)-/xUGdo;ۋ8p\aaj5"G}*ط:Љ{b5LvX\8hǿ' +Cw-B/F l%ѕ=؉QIaZb\LEPt[ȍCᰩfl 0-?K"47 wz}9,s9.O'IւiѽKSPAvGb3<Ϲ!Ѧ9n,rDDEnzuU9dby>('y%䈶n9B54 : v\a;G4T_]JH3EfdE~ ApM VσO m/" gvt/Xk_3lZnQ';eNq™;W8 z?\Up^~%_{_<q<(5dRIsU^%l &x4[̛+C,ʶ }"h%"ܹ*Ã0V Cl+kZ9 uZ_N-iURf&t[$.}. 7-1 9'( t8{9a?wDn̗;ÙBMx UҾJ-׼ެd_R|&)eK7;"+Ӊ:p_BaR*y3Ԛ(vv/ Ss]=@זGy/+ur:޾p˲Z3+ڂ$YA*kPGh\Mx3y]p<^JO{3g! ;̯ ;BI14I܀p&5O"*(wc-͘xxψg7N2 }L .ZWtYXk\ЉÚ/1(+SV|Ym #b٦ah&Ia)XύzL kKGl(lnT֤ zV3ĦηSgE^Du]~! \"}\z`Z:,RE! AeKW*A:(.hlkE^~/܆o?yG;v]:UQ񢣆4!0ϳ=oueI!_ s<8l7Ŷ+l/˟}e;g9^z"gDzUg@bӐPmr}Uuijjv̖UW$gZ91bJIUꠒJ]n}zr+w:}j c(ivUꊽ8ga(țKG(%n`TEVtlͲTܺB:'ßxMCD4O, mLGLtU!` " ܹ*uNfW꥛VRJ)u!}oǴ" + A™`H8<&u}v#)'zV#7 3̔Ś[%A1 j(zT#O2a*KLQi7SG*X3#jv}5>J5(=c!!1E-@ Dҹd}j"p)u CX9 noIg9pxA+&]dXRĴ̗qIcǮ۫J|̄ݵKy]Yp2^XI \450f8$+9(J q-x f$zVɌ4hu#rXG6sbׯp+yZ}'C~'cTH"›6˗t(z10N_Z!uqg|@p@!o.Ipk=5-&k`;n]* rwlg(VnSs0u=- 3!#iœ9u0a**O Dג"pJltPgc 3'-;6bWVB(BJR3p}K?oBɔ0QdQ3j-KPk,-;m<0fS#r}93*i'\GTL{x$!ښ$)U4 ;3wb!"v#.VQ@<>vQW>~FURSJ,е0cBp$qY/r=R ҳֲ q q9C29"Dۏu2Į5nWQj#TWnHxwW(0A+Ϲ/lDèTH<8b![l~QY̾to77jeEDžVq"a,[6VEm ^[ #%wf_qqH%q5*^U Y gbTÂxV^f# [K$N2$l #,ۭ4r<:J3!3f bXiSL*Ubl%"+p.#U$¸"̨] o=Awմr2d&Ī7S|ӽ.3B!EKs@tb3e}g$C*)+^.z#W1pƹϔ)rre篽{:ĘϘpZNI0=, 82MpcPvܓ, ,Ҝ M?0Ɯas\ԯ.EbZ鹖im.ΤzٶM'."L+0rLStUN<ǃsgA(bl99# ̜/~xRĐ"ĈaepX-+Śc$Btqܙ71(gsTg?mӐ b٨ikwR \[^o9(NDJ5)8պw6FAӭltʓGG9@DqyElFع3/}w=Je '~>=__9ZO}{xXUͥا>K8yXu5T 6ʼGP&TO%5â [.w[7\vوv$j>z;D9ޔya6R8j83zo]l_D׮r8&={=8pVr4..7t.hDO/z{?Wn?Gg /O?ɸǮ>xRڏZCLT]]ClK+qXBd+10, ɏ^YQ6]p s)6(jpɩK™\(,PjMDz]-NOנC !@| JXȼMyV'ؖ#v(wwPnЋ^=TE'ҰՇ]o.Wi#8QzQ0&__Tq#0A\̰$)> _ G$Z=**ڬn)ay[<7qHqs1a{}tUqNV]Y"/##cWh:T]b&WZ^[m-s1o6\(}J#{{SJ8եJ:Q]pLT́ ?̑Ͼ2;p8.(raW{;fl_M*[J]{]JĢə_P$b9`9T>f9p=-+ź !Ӗ6L00"Ś*?a6 G.W&[% @)%6hTP!TНm)i=rJXOsq~-9Al$e/mANj=/{&L~? ki-8m.u߷Z Nq45#w2fفp_4r\ qJzyR`&9js,SJC^1t]qe(#?>`4}M9ML&+vc+D)nO¢g,-$! }= *ZF}}[6)TZ)̄,\HO|*V-tQm q*{q|44Lyj:W l.Ԍ[R4$?ݺs~8;L3>F4s\=~N| K74 AyXp=\B+4B"2m#xu!]F-)0 a̍[6kGϿRQi8%QRD.9q2fjftܚ pU2/]BɅrݹHJ)0F,ijdR^H DB|}T_pvXca\JJXk][㮮**Ϗ.ʱ`9|0>o-w 0+6lwHpdJ.GpOyr)-D*{!ܟjjU|;V<# 85#.Ŧ5=Դa<[-V-J٭%J;8!pT #{LvØJi9scM"ƕ瘖QQWyl<~t4Y ?Ҫ++7* 4A gDtRV}x/Rm粥vwQǝڤb"Sxuݵu u\zT }8bqW ɸs&OnߖCrZC35'kMblo,F:\8:#(q-ڬ3X" Sȅ<\9 g2Fm[ss.N,2=LӦa8.g#cˊz\UE\o!py.2%UOQ9yf܈Y`n)%x*9Qc#Qŕ|(4=ɸMld\Ls1~6ϼ3CJYxHԍْnXQHD%U5[Ve{#JuT*ϳ)$LBTWQ4Cdfڜ!<$bDJ3-d\L2Urw"%+7U^0ۋDxD~|FCܫwbiCN%ԃXnЛf4BOްT(q[bx\-Np]}Sqqs*7G̛.5%с^Bʲ}6V 4MrQcViaޜ;.yg︓=:0 \@=~p '#.?0, krU q|D֟ˊ'&mD|9lQ0K~LZIIqE_P𨲓1]ˆ4 nP%r!LׂZ)p}+)+ 3mm"WSE{'[mr^GV㸵$KbE#y:I B=&5;sFK2GE="4ȼ}*Gdq''15yRsF|h$`.֨1纮tʖCٲaQUzydre[󅃣!囸P2% _-%ᥛ4 gVR S eޓCz,^X #;WA֓с6èAN~y_Gax{l<9YYxfKD(4tw,4`) k /-=gspn6qAN㘄s[K0j># tY Eh Ԁ]x5lQ}XCBH=j'_}xJO9HD 2 #q#Q3 -$6nlt頽[[Rqz e*iMɖ#3XڊHP4E lM6@hgX u+csD`0Í"wy*lI8fֹ[E+)gp}XN.f#~}ZDE_Vi0nv(yDg@\\M53"pV%eP=EE J5mTJ}yѱ0BQU+!knj[mʤB8c X$lt /L稊0M/`9nXvrfaIomMבjp\[s))u.dv6u S^Ã`RS5zK"za 1b^!̰=#[0d937`Pn˭2`$H"e ᙃ۾^HBHvau(;9J0eݬ^kdh^J)GM6ECHQӠD~їEFk1P2E;_q5P}!' :9c<yTm8I5:ɘ1?j%e'(cB ׵>271v2%8q&} t#  VRbAWc?""^Ys/'}tBxNQQCae OJ݉79n{(@X(T\z!bHf"w8YCgTe[=9ɸ!n./M8A C͔g_!f4{uʗLшp]GzP,?&t 5 cj^($I-6k H :H'X(7"~b/(e~6Ƙ唰6UT캮ocE4="PDӴ%.X-G8#+)ZYoׇ}C(*sR>^}b>cd̨ rFf[{n&$b<~ .bk bNJuBPG ȃa;OT8esbl zof'*@a1U}ji^(՜Jӣ6i԰v}O Ȋ[ TtQ ` 5U]ts$` *);kGHV2.Foo<~ks'"QLDvSp H<*)k;{ox}oXxx|:]q*#:ge\]#U;Ӱ(ŪkNXDӳ30#\B<5 Zs9<0fPJjHcC۫ǟ|M7: v)\ZϺn bI" ʍp0MsuHF`O6X [5%='C-xEB| 3)8(tfu;2fIA` WDre)|ًA0jA%[FU乎)sTll/!! -^pQA#4[ Ex`mzatqO+%F.MitpV0# mM75^er֨FDb+Q97YW=,(\]!1c(x0l&Y fqx*VPdtnc!3EbK)ie^}C8QT@V+)o Ūhڮ7ŕz}th/8]i?NJ˹P>b$ ~mGX# ECl$eCl8LQ\쨤li~d`jg,<:UѼQ2[U{*!D.'W@(aZ_qIoDAi͕#jG+_6*-Z8K.G"n &0zw]',}%s,۶^;ˮ#JJgU τ;-29 y9ƜtMwzV^砅pqүx>^%}q{R3R4dZE6X D5ۅ#fC56PwLy6F57WseJaX1qiEBKj67He}F/^'+_j}) /\hhW+0k3ϳUi#Ebc%F*8C-q PW4ӡ8t{pfy26?(4S0}jo>w_ԉ,TbY{ǎ㸾QzV_Ft )bH@/#"zZ?*NF7z IY7qJav}-}ѧ#jVH'rwN0Fw o3V3/3z0h+FwkZfm tzmQU xt4{xٟcZ"[͚(0ɍԅŝBq BKTkzyW3Z c svh@fɏIQyνv@rfm'k6435cpJP\~/Z?O'ُh;fP'\jT<I"'+[ ʏXw~t&vʊ5y >./|J^N:Cpf'NP"a,mGx15 aXK,g'#@x{Փe atF~T"ۡV E5q$oDB:u@jzp2TG篁Â~pl><0ba@Q} ʼ||kDGP;d\)XG󽝺_ʤe\Cu {N5/.fV:i󅚼WxPiwLJ <l+)- D,ϕɘ aK&_ue+,YIٹZQLƪh1IA3IEeEгe/{+Ms(s qu{u ݝ,%Տ߹uRLyDǥx}3)+us4J=W׼ :Myz|4K7]CR~ŪyӜ5d*]=" NgKF3eF:D5<0 Qh6z?Ojs[<$vZp7 jS{m9o|^9=0[ںkf;{Ś qf>|N sc gV`ޕIUqYAw\L[G AW\-wlgƢBo9|3Q-"kזy/R Q,7J527bʇ[T̯|~-ұOxf4)~qlvRՔӕIH3l J@T(Ԍ"*7ÑrG8n -Fha6>*߮rPVe"pr{9p& U)Se %M7iTRǠ (?Ո\h@@Nӄ!bJyf%c|ry02;sh Lf>dûP5PK[jKңw> H|]wu_ĎK;/rnI7vq3_637#`Lǿ45%.%QX&:1Kk,=K&0z}֒8%_l b_ ~i qqHw\ZlݒG1q%8?OkX߇||~=0o| =sAH9H]sEX5Dye95,ظT8EsL[t hP,  .hʹB]HʆrUTY7f:;bP"Mp=wL:/XR%vu Et~Y!T^ (D 2 !n}dEOr M9T zdkH~! !lYd /i?vVUV敉uj!I.Ol}=_1"JSBȍIlT/\Bkys7cD Z[3c 0Ӗ̝,9J ZX5># ;V*)lIaFޙ}ds[z2/̏'/mw|!2&KQ~<>* R@eBs*qi(`&\{jY{{, tq.)MW"?~,8(V흌N"͓}k\jDe)ܗ$p U4{xN>qƘo4_Mjݻ;ת/C_;nQlw ɸbllP\/,sl?j\HDH|4|:Fh5}ECHSj`'E~}qS3W)U JϱvS<^Y8I6lu1[-RnLΞGӄbW\t[O~Γy_\\NVM[Ra0l%#{_ߑzNN\*ս'i]н''U'p#GzY?n˦帑P%p}=K)Ե8ԅspOsXVf 7"I}L:/G4ĵt}Z9*ŊȪZnI2KO-AqźZ+9PrX\br^0I't]n}eEw]H(~җGD)2+K5IpAD#oT.#=ǵP2EqB=(olM)&UR ߯ʹtm7'oJ}5[Yp>$"JcbA[Fl#h&lbXOd2t>qw-4 seJ!(1 8l:Sb)y st-;N6lMUىL<*j<ͤRe>T"][GEiGBWOG<ŪM8|#zPzVˆ7 _[\2S_,s1NlPP" lt=!SNJ<>$$sj p.cc7M|uYnv0n~!WeOyzp2~v@)9#B{ٙ|U +v0L[XPv2f= q'+z#QAc76o1}+)k;,$LUl<>ԛ)|fȧ__F'JJs?SVLIԛ "4̥VRȰb [,e/fV^!"SuƽAKתtkg֗#u O2Sƚj D:  Gyij<ba~}&@i%18QD"t_)CgR'c,Grո?[Kް{ZM1A,оsSנ _[m+Yal\YzTĭBIs )m/ϔ}NZHyN\ Jy+.;wBjg8* 5ZifLAK ʐ xS++?jh&7  q f&N~ w5nE.+uTkP$n}}Ғ*iX :ȁ .CȊե-/Q* Xr%k+)m ((Ɛ*RD E*0H a];)'}qjQ]}UR} ;TH!_i.AWzVTYlu D(BE3prJ[.ڃBAlE8$ 4ÜXWRL\[P?~{ԆW >p|0>a.iF@)vrAy^LgN!5H,Y5Szs@Z ]-˕TGECLU,[`dJ F$Ǝw!& ǝL0&an*>j*}݈f淐쪌ncC US<.9G0dKT{fbki2^|f@ڿg"x#0uÄ9C:3vf:|aޖJzZ`^9-ْ)Z|q}19Ұsy"ۅJJ:HQ !zc`:[R 5TGZa կmJ#cXsxI8fn䢡Q}lWzﴸhu0JNGĶ xWREɥ;5Q͸7֧srD6!:cqDߏXSqg_ ,s3*,fL}:~B༴Oxyx%|_ZYm "gJhUk Rl0Wb ɐNJ9xNPX #W^qP,w0J]d| "7)6Pbs?Sƽ9j;b3/&ΟY'(154u-V݆A2ETw ̤ZJB)"1Z%ʔ̉$`Bn/:*ScajD~mcqy=<*{_'΃JIbpXlHWNXI$& EnI!y"R\ȳ//_9:\ +TSDg G05ǥ ihZ ©g6cR0i1zS&rXŹ 9gq+rDۺ/4t^[ǪMVYҙ|jj÷}ndΏhEp]痄 W=qIM_9jY-U&k L__΅+)~%PM_`pC?o$s\" îk+)GiQ Y}nlqXϬmn[sov'_H]N6cRCje{-Q\h)T,#CM1ӝ5@C2.&gc}{H8N[U:NvC`Tv3ATDddJs|>2/'Al,-u-f#zE+p k痄E9.ؖ3̖"ppu ҳ޸FA((t;a{p" o,Iol0;F0?h=W\]g3+)c7K'? &O!n9ݽWs4_&oO4daxW(p[V9 xWBteY\Ӷ;y- #4$^ċs! jN#8,0q'nJWMflc u V_so-.^Z92e>536G8.caV[ )h{-''_ *)aٕ#>@b|wGxnk#p 9 .prT+.zեA S[T;^D'#@/)/QQ:r\*/ ZZ0@^ ]}XK,Ä.-0S%@܀l<>L۲JUS ֽ%ό!2 FcIitY^psL-72(!^g&Uj]Y&}<)+vWbt=^" (XãWZ;'p5̐J^A<)\h7 >{'=+"g;G0:#g>SNk]oqP, $ǦaW2@ƒyIgAfڱPӜC03aOdҫ@c|Zqo[3W,`ۈķȓBQR`x4|k+ E,?(e&wR=ne?nh]tRWO|`TQoƻrI]FtSe/pj<-OtG.f-qLBחWፒqaj޽=)F.wuX]jrfHP)ŶI)a,  э R3H; LYdoI{YD)9=.&ḘFBVig%#W]!J}eG$_ yaYńc - .f;rXI.o8gr=]0 xeͳmʃwRoO{ySQ.Flk8ȩzV,] c3rw#r-fX JXp=wzNCmvA |h.!(ƄX3 T ˪Áմp؁ 4u1AZ*UoB)8.u0V 0庩Zn$`'|d$se)> PQL"s#U˜6U``0#>7 QKm>~W$t\0,[ef+c <˩10ed 4Ұ5ݴEd9i SCp^_L)$[+&\mt* ]i5!経KJVmA H:^ g5љFIᠠH#u)p8.y~6RCDw1ZÝ "}.ma.EOvnwtRmK&nJ)ITRJ0 "ۥ3q4x5&:9]dL, vamUbY˯tu>֒4vZiO \nC*LjJ,&hsK+mc.n:Gxvn ]}߻ԝn}5~\M[ʀᎊ7W乃C7- b<`BًyL""$"6?QѺ;[O;;YZdۆB]cـecGT~>P~pN6m|pi`|V"զ p JK ;մaOSpܛ_KZ1l]!`kXV0O mUTPD;ERP 8 E(i#4:hc۪%f"}J5"kD8]'Q%N_# @^kx5BB촒DEMr}[N1YI-+ g)!W$bWS*2򞊗o6k D)p,:sמi0@Rޚ_Y,yj,iVp 4Vۥ8<8>L[0>۪}RT5+6ضEKDp$8RMEoJW줜 p,MP[qz]U׊qǎx-q,p[؛Lbeh70rZTajmR\,7X.TmĴo)WfuE.R$>6WD\0,*LFvRNV@(QڲasQMSkk_͍#P;buߕlWږV⑋'-x\uGOp^Fô!OPn^{ecRD[JϿabjVn[W p YƄ"0 Jń^$'0K;3=5B7)À,2E2W . ϳ^ !4 I0o^(I>;)m_KFT[R4`1z", Vhy\Of:)gtQǔj?uYʳ8ږ|.潭[M{)2a$:)R\r7F'B D +3h9@hk8W6j-vm0 ccBH/[Yzd5jKr !^|]y ƹvfnw#[,+ij(栄A }7ƫ^|SOF[n@Rz$y3 A3LX@+:.cTd޴ 8{kF<|2S'eߙd9 핋⒗i{|rkrqvO.GHh~@GurUմ_mKi$6Ɉ)!_\, +\{>DcNM%X6~~ii:U p< Y3EQ1CsldЌ^P4%#H䙖JYhdYM*:KN~V1v*&|^">9I|:t 2,OJр0݁>F_\(3H7(9d:0<{R^RMEl'ӝLlg3t|=zhVFڮxE:EVn8G jyZ>x U<3ܛыOA%t4*F<jt1̼q/z[:ohm#Oہմ O]28RL|p>;ӒQnkC<-XG3/˴- L7:b%"h Jrzy8;)}PFM Bv[a6˱+ӄ~rqsi,ӊtz'葋o(1 * զed˄LB]](ぷ,%Y8#[kL^0O  qվc/I5J&Tj,7:gE[%\$^ۋ +v'HΏAswMmfcbxbC8 >v40"..a~; 8=VJKȓ`-g%9FdCSEռy>f&j7I 3n0~0 8Iip>8r>I<-Z/{Y9bxdQJ^ 9<5"&.!> yYti4UQB'%'AǶcyå EmFRb-q`BBJ]˲9g_z&( DX'8[ v\TlZTܝ,_mi${vH=2$.E UeZӤ  "쯖#oRf2@'%&,&̇š?zg_|RҰ GF5hGSXD0FR]PT\=PmeᎲ=u 7Y?OQEV.ՖgZ? ՟0"Q (Ի sMk#jT2)!ț/o]q[5,._5qܕ$ *TG]cpǘ`4G'j0Atu$ (c)0D(Há (i;XFN*^8r7褴\yb$8ϱ`0ka$Wͮs`;:P;Ykp4@P$F3{"Ӗ&!DrʒpKN fZ6H Y[R^ޕCTP[#T_!,bї: e_<]Acٗ7GK"ZI Z`9PkնvS'\Lv̷w\t#[b*0ঢQ^Yd5`VMd[IаdFbEUEJTR&Z]KG _`R"$GR.6S~ܼ(tu\jóZ8HuZ>Hݙ;Ltuat <%v|EH=)tfƲx_]D$0UnMGTt[iZ\'0(}ΡAhh OϬ?M#i|M)7z$g% bankZI^CNv<vPs 58E*JFl%a&{0 1 <=X/kdb#߾WI.z 9B[}zXCљB}~퇱%yVa@^50@t8Kygs>&t;Q^_!HыbVJl퓒ypާ woDIkPQ ld!E-wn )1'jvL%Nt= WLFpmB(gm!wD5mA4(1ԥ eJbÓ %OW.ۙb پMW")<{XON % սLaP/5԰K \A)ig3tR^= :n49䝔CA[/ >Z :)c4`ey< 0MlJkJ57lgo'h<=U"ҭ,>o|Ef@jTv_cJè͇m}&p jbeR`- ho}зvMzE( HJMmhzSHBJoP ņ_aBt ˃ۗPrQ8`d(}o8O^ɿ?ifr0zBk|7_{ӉnJ};:ed/ ww+}:QX95l^V$WOhs,;ŚCX袀n k0Ӥ\nv`JUPuAv\!ކi!Իȫ73lPBr%? @.wR#}k ~q7E|L?Z(&,:Piu\0OKäq~DM4`7{ý R EA`SjFLUfiF@XmrU$VZgYb  _ Β#kDExm, `bü4zWR͊;)|+C_{\CCi8rm%O)=N37^ػo>e$1؋!QcpV۪YeG3~HRmR#[0zidzgs=ë?F^fJ2'tGy־;' ץNPu]݌~Rr Q>K堭W#:Ft rT05rKӯ<|9n%sҊWeHڒR!Z`x!92ӄ?0A0 qu7~w˗}Fq(8i[&D;GG6ρW~|N=-OFsd%>,eJУ;S:Nfq,6RF&0l&C3+Śk9ڲ⾵b6v1q\L?} ٗZ[+E㬌Vj˪4o>I6^IZP `(0LDXzmݢj, Su1 lý"(7b設DCbM" j`t?fikk:j캅{\5GKl,xt"~t[nqQmUF=̛vo" +vC9J)? |ZQbHmQiIqNVzz~{d"DTqfad0mOtڀi, )"$a^+53AwK5°RWspĵi4P SQ6V ro+UiG'a /qTv u  VYK۞ SAJcE,.FCu9֤[sY0ʚ.V-OdI%!&P=PଗΦU[R *[C㞗o>U:C$_Ê E`Leg`zӄrqmu\b=hfY1A~Z6եYo,VRAw^%foI9{tgMȕZ<jkתA!wR:8$;<]bt1"<@.N#S{m/Ea~oM3dզCaErUnv0{>>B [3l)b;~(/ ш"6>-ꥺLWZ @*F PJ.,8Z/p'дqM׵x2`!GqyvɘƠm{#Vu, n@F66,[X2փ%O !=󅞘"ouP?8 RG:NK.tRF61ȳ8ѱ0X#8Rbl7?}"NwnإQ驆wL??Sݶ]XFĽF&XkCDZ:mbˡM 3;lrkYƧ%UӻGg%)iAȺ}a0~'F|.`\w(SKqWzƙޯ\̹o[30!`&l\/VW#.c'DS)yYqg`'F<yoavnziZNjSH8 x$R=D(sKtbV3y8> yvֵjX<g9VĔa?GȽ-LNq\T+ņ`'B&_ۖ}4I {+o%ɲax [e/:զqbj~noZI"C0J&"$Qn[Ck+ 3_m9*:6[d|kL ̄di-. ԻR2z$ln[Pyp1K(锡Wp櫦j*i;͕r"<3 .b@hW#^xZQcA`N;Gp"*"ˁ{{Ai>}Rm2Ֆt^pJZ<-w?6i:)|;s\hiR_?+dV'@)tHx`p"_BMZ"L#g ܫ=9:))PalW2Xv[ȵO+K|K["4׀RiajGYVQմaU競]KU'_5:ZtSbmBuo+RäFnԅ1C׸qZ+دE=ww%kOhp P̂O+FL{A&Y-ɩo"FWw]TnMN g0 \,6$H.zәx_.6bSqn(fmIjí& Sֈ/~45Ŭj ˘qhw<;W[f;FXWnj˾}x5RvMye#Jé6ZX5!:~{bL+SjЀ̅vt4kTcXY%Pj {pn~|Jǘxx2~"bzy@l\jJt4fVSi-&M+s7n1MN 'H'=T'BLd٤m'Wpil6Sk3#h6Elu1yB:^Z$csRP[%JxLqxv&(%'d͕ΪVt tVd^2M>}Z1l]-Aq@)IDrMNG'Iƥ JF`+Sa= 1F$NʝZ:r%u':גQ8^ISy wL4_EnނӢJb1GJ)-? $"|'PLV=z" Vts9M_KR@6)J0a;+%|onWF vm~)5:@jNt4:JE@L1,D2,#GØf~2ڪsRT-9-z=1^M$"5a"09 vm#FDrk,G+bB><ۜ"RBb,Z&;)SkkiNJ?}bm!|s4h 1Z`䵝ýZH_%qz;Ңj@ދA(<]ü\G (.H5 +*t5lX2 ukHGfS44rt\6f C\<$̴mՈ5_}z[ s+IV䙶yGC,E1!ntUh6e]K卵V%.pm}-)̰1BOc vRNH0(8DW7_GEe2qoſàIA+7gFu9Y"vJ1 0Ƶ8F7pqMՖkdbp|U˕ͮfI'fwHpʜ#}I.xXokY 2S.6%=1v >^9b.hŝz:R>rUzFa'+fSz_K " ^S|M[~zw1 [+:l%GH&L_<(D_{hg+U~*Uy"Lff}t/h|d'HkGଶ򗣗zgןrE+ m9-je=D$J/ťyHZ!1tw`4yglI%TwWذ''Vm%QrKo?g=Ggl#_:5dx MR1)͕o<>?ғj&sLqQKUd9^h yDhMxQK $}[ -m+Glٖά. ˅WA$BC Xt'HΔraTq^8P%2`2 ys/}m~3Ët  +)A{5"(3 %]Xg9V8 $ciHȉtze\ d4>-DB;>!9 wR.W?CJ}( H\`pKu:x ;|5[>o\JQoM(]ݴ7#oOd_қ èn&1X#lC<7(ulZx''iiw! NfeSz's\P[spfj$^fd9^ֻzk|iEmuַJ%2 KCm=u2q±d';XL;Z {XL&' 'Vf=8#B$#;nQ5We0 gfҌZKMFĎvuT6Bv)H[臾=E[Y6.7q ;EC=qɑL* |-p̋QX6>kQTvׂȚ>)s"|Br.̰ӕs;blٔ<'u3Z3^93qw1d99sp}YPRMd4%YPw%0AB&G״uKܖ*^ܳبupr:)'k~iQy5ĹضXB7ynځ`1 :ȇ`{G.{|'Ȁ䩣śM\YqCGF &HDI`=ݎf==Ui;krT e?,Vn>MzGi5M_EIIYMG.J2wH""J]ƚ{0~* ~c[-}UI?EALֲsQAouaàV6M6HvWeLstO<}fJF.;7 LC_bfsźRnZ}w;+k%Op19TbBDR'Gp'a1/mG1zUJ \iR u-Rj{퉪 K"\jqQuWe&!l? E, ϦFn1m_,|$ KOjGM^%ˑNvv}e/29z+x%*쳟6h@!# mABG}m yrփh[9r%BItJx-r{oRVazr&N|=呋~Pg{j|֭6u_JF{FHR"ܒ4I0jH IOkN;C;a߷Fc.DI=hORu`' ?S7qZT#AWf7\nL\|}19j&g^A3rin]Iw6|$;A%O(n[׻a68RTi}rq'cPmZRt>#!.jmxz],۴1a5-6AO4e99ۻ|RMhcDZ#Aݵ (qR7dxJXAz5"A]UD@*bLYI횫if{E/ւZt%x4{HDȴ4KT?3_[K}c(9mw:¯&褤4¡^G#edӡOJZGCXG.#$GxE!_uڸ,rO^/a o<''q| kn'jzJUpki;ˉ%V`۽EClsT#t Dx]ccӶ=N2Xx,60 V%~mERELͻ}mՐܚeLgH)iEWӟ~8rуejbqA㼙\nyʫit= %"D^׈TҚ)3הgjckdT0,a 杵^lPS AQ=zoNLointI9+;`وR0 -7F]#.{lO0#1v:ƼykR7mYvL)4@$6`4N'a ۂE!7+3[8 qA3L0o_jYvheC|d,JHONjԃ p-p7~.Õ`~(H׈Jêz}|ێM ઒ !  APk:nu$ bO?f8ӃR# .$o?dN΢L2z_H'%G0 lSѩ< !uRUӍϱd؏E!O<#܃svKR-䶲L`Z#г Ă9-R=M(f^2@jJ|2E51QhNm;J*QW=Z:Yk :T[lj,rBM9t s\mEеF>7Rc)+·;ZI!˳=FFKhEA`܇kE: wD?)4.ﰨC 5hs-7QX#*R!KJٲGǝRN'Уn QW޼L3T Eu,Gm9.Gyث匆e{ @ B&mKÞc$O>8"3 '⿅ElB)xͷ_?}[OQnⅅAjQ6r|rjL{[qj'c nFڃk`>?_>bهY>CfcUU]#A{%y5}fҀwAg7N))A5rLWR0ѻO+neڙ<m4GX5W40KkDk;)}rq8Ef?'l,E罟+/h֗3ûUTVf<=Rشbt4"m6UXsNW<>"b q])7|E+T;J"0OOtL|nlmijnv ![:3`Ts|9A3%16X ArN`ek[zu(N~rq Efv{^Eˇ_DؕO&a8̩]>/[Ƕߌ,'aRml <ef-%uB4m^#63jjDPmRzj;|RI@6^e|pV[avL#(H8f!yKW# [ ݣ 5LsQF~'ܴJK+-^ (~rӊ:)=rZTz:J]iUOAƄ9.$ Z랗/FF  }R"0}PD9yD$C5"(3KE3L6WqOgZ {w\92҆ ((ns9f>p`V>Io]W'$/ɇ9 c\S-777z%OѠ9` C6~3^A! &Ƒn:)}rqBN`oGwoo4u`,ڴ6Xt5f9 #mqزmQ@wiUMBo f^5b!D(<·G Scr^ўkδtm.$*᥄VytsE&r; iӢ~^6?8h/T$~cOG!e~Cg蛇'#|bKZZB{ߺ,.F0I.;)/E_5?M@ma܇Ɨ3TiQJ *i_Vr'W1"T0庫v8^ݏ/DUIШ=yB .t`tª]u1P:-ڞ>mc<ܬyF3'Dra^-7uBzX xJFǬ7]-I9wL,o?Ap`/8sqIU& 㵟k?Q9UJGit~vԈ~_rW pJ>?18\uX\_#y>;<3j@bo6;}1bO aYiUj85ӲEQ'm 0{$(ZIuMHFZU$Ri)0 qo"$}k&mԀ'|kFio5i ߤFBm%VXs5_5v5H%>(Ixi7z\T`Z64jӮqtu1KT;$X.c؂,rae˖ *E g%1{VrM\${[_aNtnvtO UQF \ht'S큑)/;b\p[ټ)~ɓYO{_j] \Ū)JS8vEAM(f~Ń-;]Ͷ{`XIҮon^WbqHD>,f)gٗEAO1Or@Zhz"~z"7A&tRNvb"@g%(Wa9!z@䪝΄+rhxH`LZ3l&V\Ą"wZXRt柕 d߼F4Y[`cţ,ۭ45ʲy%T7v_SV]yS͟hHz!xT]+]5鞐RR M}4gnjkج#  `X]j}!#vv_P@hNtt:lBk)f Xr<5 ou4NJu'ҹ_Q(vp V'#Cs';yIpE_h^|2  #A󴠿ϱ4_I!_rS@H6`:{_[B2'+Y@ cII!1# `9|&Z*Os>rG.뤼\mTkNr`k%RjU_Xs/}Ю5uiMǘeM\)[ jRBy", $$xāuQF~-Eh5eOwRnTׅZį܇)Ddi;ђq'_.~s$8E&Uky0RFNj$Aq~I,ݑLvEx}dR(֗Ͻ:[2(R 2񆎌q=GsZb<>ss6@{,1| U_L` H j C]LWiIew)!F*_v=_'%&k_5 aQ ^S@L&'H|>P,T:iPj nU|Q#a,Еhvpxv۞^3]G{z'Յ`9XqP(Xsj,@Pwה*>8F(dP9stP.Z?B]UhgЀY|ܝ6:R]`%Lב:)}d+j )v|).-خ)ߠoWL3woX0>+s wAE Hi. ⧖^|H5&mz{ʈM(H G@aZa-=1m%iUfbBxofd`Mr lW@ӊ`{'S)7B0MTZ 3tRz=os6PŽ z fim z&;)=^ij|0;~_Fw73)&`Z \%>>~qյ}إySRTLB[tSp +\:vAѵttt3'* T퉞2ұ>h<KuL$j^5뉓r!HE<2q!:F0_?Hܖ!ZNGE;z"MpUy NqFA(MoM H|xsX_/?Ox_] ۬Uy^Dӌ˚P= XLOA7Dža3`8.".h긘u0k |t\ ^{"xNVja\݇!=d}zDɕ ü 奈i;)aXOI~HavVţ(:u\\`\0ar88$Ս1KK~W+K1|W?Z`*ṡ=)(LBXNŖu+踹sRZ>"(3~]Y𼰼Pnb r&-V[ÛA^܍0*zr80V Y۠uwinZW>"r;+r% \ ȄNőʂrN )2Џ16~խ-o2XhN7:·Gi+䶲1{YC3GQ䣢ޚCF<+~YՐV0A"g1Wڮ騨[B{a<: )VGU5B5vH[OϭRu1K)eRʀkZVTs|(]i~FRIo ^4 p:o[ L6ZOx ZLx_o_I3cGsS5ך rӓjb'騘T#֘fjJJ^DЎK]j1/!n2:).8VzrkTf(R0_ ~S dʢ\+*$p6a^ ~' `Zւ +L%mbd7mK!\~VuRJ.b{Ǟ=ZPm= dKFP#ah؂2L=/k4Rm!_M q)7Ǹ]#B tMD|ҒƊ"0 +NG5k_$Ki, Ht3( M  ͱsR U\Me, /ITg7 wR$`Np)Ňw58uXpL\~L+z\t3. ?]62;nFxOu(TS 7rUlcq=Wn:f#jDWY /1J5ηYv6/L7P?snRjج(Ȗ="40m\nmJdcWʟ `|ZJ]gjm)ҶIJm=-vA7f#fph 麉C<}rzUr[I9+Џ_913$âk߻΢I"T;))3:r/Za p5%$"W#Livp㜖\10UJ) H2sg 0lnOX,L5pOflBdIa`/>RU96s wR&f ڮa;Zk;0Rvp;eL-ѠCn>LbHL5;nV#|i6^ul 0I5b2N''F8u\~`F#?%_NI6@aUNj>;Bt] q\HlD@zWr]I7ʹfN=# nxcFȢ2. 0|Kn0H˿85|nFx﫷*5&V"I ؝iZ_4.H2@G1TAN{~n4ڗϓ,Z(h5-@i9f6X–r Bm93Wgi4۱1eugÌoQX9Iy-8rQK.÷u尘>ح6RLD\zˁz}fͭ}wR>ڜmk+Ā"bB [L]M0)Gݭ}bc7B&[6kdr ?_q 17e\˲ن''&]YmS%^߷[4`bڪquh;ݵ1dz,.o,|R-W s&NFyy׸asłV$WO\^ѴゑLߌ|$N~Ý_j q=#|^1)zI,WJE`Q(4.E+L{p1IʋLW+NE)-FֈjkİR- 3{hv͵uʺj8[*&bp,}\ nLM2eBgQ|w#}Z#B gB+5 C qu[D[Ϭ sIJia(M%g#J5$fYR:zdۮ:|%O˕2Ms (mģ@:.Ev% o0V$1l$ 54}EqE!Q9?(ï/8+զsRJuöm_MrEa8ĆSQu "XEDhL87UU(ڎ]rA ;^ًglZGȣtLI1F\“?i i pTeOOg%52@N&Yս,6"ɴo15.<;wXϐ7]II)ۈOrJr\O60AK{gts,^6 8O6b+x2Z<"T[0[ 6dR\ Hlxg07Y\5,LA|Ҝ}x)|xĔUDMയ?p,{\P{*e|5hFFy<š黫 kv%QP`UiZT-T/@"fSPW8&9g %_)"q Dx5| SLD+6;@em^|.0k;K3$\ˣŹia,(4 XrH)hj9TݰF6buv,B/Yd^ݳ*uٗ!f {`XV6-\Yy4A^r:.wWp-֚8J7,W7qN1ac(VDȽ-xbTZRKeQHEilkg~m>72ܖ4;6 Q"͐N&6H.b½?_|ps! 7ui uRm"noDPR?=F.SJ: ̄mvTV^`U%ύΛyYpՎ朔|Ŷ/7,NʲlPa cm w3ϊWe=گ`&sav6Vʴ3:)1!ª2!"EҴ5\\$=չ7Fb`Ԃ`f}gc}ՃF o?Vyѫ)xm?dڸtMhZs~%UG 9+[( &@a)rٿvCZq/Ki9b"W_'?s_oٿ4v6LmI`זpEHot 4]a%A&E!AGLCm:<˥ڇ9ʹmǥ*"Afb#HE]5Yc)7c[3+IDAT^ֈ儰ՈxU\9*-Q.>b>_IyC6"_{jӑei&n Ĥ)?m?ZqԷyԔ6~Z Uw.$D]MkZG;rXj-9!MO7>1k-3_ՋU#G*xA փ+Aԣ1ʂqqZ2ۚ^ oϕe[.%lWq< {ILo/MI9Mqu|@j8춺@bٿᇇg~ r8pF7/'Eq땆{~yAI93+,mNHv> uAăf, Վrz$:-55y95UcTZ0vmh_EYq@nvDD[Wsc@bO.L`s`ڽY@GuNKzb>9\,o2ٔ xR94 vh*"|WB˙ 9,e#$oVآpppBѡs9b.eatMLחqjkZ<)rk(< JgO7 XüoPb u@XZJ\Yz^67{!ăwoڪy#3w-rGGq\0'v#&S `.αศ v R7xzҎI¡"L8lanqIq6ѹ:qSj-U=<71J[Ĭ[S~5qo ӱPR{p˨u]Z]R.iPiyRuKzkLB][|yy#9/yJFYiEʁzG*|1_܌qP[Y8 qg>'VI9oX#|߻TKpMwݺn8W-) zR7 uơ0:"J.7j ;!]mB(Kǘ5)]aB #6iZH&~>UU*-d{@r2[}v&,wgE0֗x%xVҿ"JmE<'*ykXC|ǧGo?蹼anp뿰ױ jզ.`AT$@G.C&H?l7Ʊh%%$0mՏ[SRVVXˏ0 eaQYg8Jnڎ랖zJ*Q@fP:&F~md}e/'n8`5˘{w r<2`f`2YV!B&F},FrL%`[7o/o2`XIA}z2a 5U@hWZqw-, xԌ:Gy\J*&բATn}Oうe/SEeߎjkFj("Q gm[l:x<%۝r#UY"m.rUE4{S+ 'Lmm9[4W&tR2Ym7@.^t[8^VnՈ/SQW[@Z 뵧`k*[l+{J2l)@(s"{ aYTbWff|PE'z8/ajir\J(`O1, B24= RA\B#0d-Q5 ~;̩Ś.f9`jXvwU 8Eb-?A|6U' uVƊt'h|N$`_ 12w?ia|2MMIMe'gƗޫaR-KleY5&uhkB+-?qV*f-ad;sf6/y]}A#Gwz6s'E+EF*2mw[jK ~r6( %v Z]զh,Qa :!ytTuftk_=ZgSoQbWLY:i{}oVLջf̓V'$xÄ́ox>:loeϽli'%_~?1^ އ~k҈Y$YR0ga9|S VR \Ge5HB[GwbkiipםB@B#i@t`La*5!!:cJЉ (&&?`zV5ɴf _mUd6r$@ weD؟~!n(4 A.oiZWSai>5a{+K0vJomIw7C;kH+1HڊT9V380yKc80ڃ+{r*Q_*`}|Jt_۬#_E mcE R2ӿzrk?۩.fM[8,e:̱N&V;+۫B@p\r^Vu5b(m=PkpH^}ԅhC3}|`(e]#TAWv4C5vx> ^6b%WB6`~k-\r_3}'%_zt~-b?+xXXQP Rr{/O_۶"ANd0gA5Bn5FujRh۫h5mY6se@B^}Tx%3m|\󣣮fY6 wC2*I|sKH'YзGد_w!g(םJYx=_O+Ƃ,~ >clQDv̼FY%?w 8^ۏVL7T#{r4{M(uXM׶;C4[+0Ϫ1IgWΣ}_VYUz9)Ś!Ćto+${O R2$k&LWwo-໭OHyr 3aJw2f]9-ȱ7?btO4<۫R1R]x|`hѽ4ۀմ=_O+.W"TalQ0'[ 3J窥T"knwᴤNHo ftwU%c;ONgԳW&ëi)-vyr]r\ܚhid!ˀ9\fӂ_E^LÇiuAPj\ydfoIf/y xw9?w `q}~;`lQxW'ey}qj?:l==-"AVr=sx5L n.O=`5wj/v9ᘉSquA3J+5朗Uh(5N"o?L xlzQ0>ja/퐁ya]PJU %լ;)g nO,ҿ_I{=~Rޑ͏֨>=Ѿquy%iRatOdlџpwQ ѯ5G&#yU5hr:\ ^&uÒ_#ڪSm:*Vf;8j;>7+Nʛӊ.̏?R趨 J;Om؊7 !Yݳض +Ѝ<]{^=wQkZ#`5-$IuO IJ'u`4Z""#5B쮅޺?9*sMWư?ኒq7T[NՍ޽7Γj&ͥrl~?sgE-c›|s6jD4UT2q& &>/GZ#2װbv aDžnb(Yx0G~Zw4,r7r2<zS{j=C&fobaD!gW/j o|%.r#T~yCReBLc!,4Mᬨ㸮̝$ )Q$|}?id.+8vnfOKV@a1f KnU 4 \=tر ^V? x8ص ێ[m|GPRRn@> $!( +i-Y11UA%IYhjOCq/yP +霰>7ӈ`Qu3ln-a:.ɨúc6{ TsI+ ' \8`.͠*y0\]s ]S]/&mn޽hg^x͋]y3Uۚm %Gj#n&E~?ڙ+mDom0ĺ f%c,d{4Kۧ^tXKN^iڝ) FU6=w;ɓ/;7[^kdSy{Rۅ% "'8ewns~߯~/NMF?MB~(4))Bq酘 ,j.*i"\& z H n_CQl߄)r(+UuQ(% \6Ӎ A{itt.e36A>zbm4貓EAC'l[Ozq3QsLzCw:?٩&ey_י"aQBnݨ(U8h&B6/$$pe*.=D (F3fŶ+М]r;ڊ*\l48|&W-÷ ~.^H$nmj.o|vd[ 55b,%C#'J5+b9pFF[^¶6vO* 5t9PVxZ]*X)\HWZk*s{7&2Š%/8:xpϯ~$IFvv[\P"h'< g]PTe+jթJ~_ Z}uqEQ^4hզWVũvݝRKxʆ*@mdK٬QFdlْ۪.Xmm|? ksy䱿^[֭N }vkyß@Я 8(>7֓\TD) fM6EX˚:2rx"0t辠%W;;/B7QC#t+uc(MPj++=8llx)ǯMݷ ;F\:pAc4+" rRbD8^frJQeY1'`3/furOFoIjPPj+vGtq0?~4sP_ чVh+VҺˇ v63s5m>]]m]P/ym~ttLP$:ܳDcT 14gxA." tO/ׯ#,+=*C ,Gypp2v&ȶ/-VĬ@:Hli&)#RJA%!{sn X#6 Pg#W Տ+JFꈡnkRa?e5b9!,D&}A߹<VI33sjnc~mV3;=35>^]#9ЈB`s5Q}koӓדF$2&I[A{xVEAꬄFB իNL$0L6_I(yRm5LQjDuQleOE(9=0WN& }*yAyߝ??ew~qMkEčCウ0D7adr}`rFΞ_6StC]ukU#JfeZ\c uo콯:}jߩSgg|9&,+*L=(I0L9d,$= |,-/'(O,( ( ǩܰez S>jt5BwВ j{[?忨E$'RHd~Dz;-{wz ]-'ia~Eka0F3KLiJ7ݯ.x(|TUu߸Dz݇ԩJ8yK/h_z`,!ٲ.j&/Dw6zNOn@ǿ嘢pk37QE lF_d:w;n0$BQL xUVh4i291⠋[Iל"՝ ,a"4Y)4M\ QCsZyJɼw%2;5]M٤*6 ~O*JeV) &74BW8AJQhe&bGA̙*K>Q0m) &'iDLYؘk) &% yOov҄\ q`rRe!Hܼ"Lզcɶ\#p(.>ПmŦcz_ IDATxweY~kOCW03,$a0"gc@`Mkcl 6,LB$ , I3<+W:9sXqNWWUWYggqQJ>%M&ƿ7rwp`7e}Ww:)dة3| ݑ&>{G?~}7"tBa;|~Ͽڱ1AnYq>#ݑ5whG~ϯys_U !]?Ke _觹;cxiOkv0³HlcNRIn!h^qw8HpGx-³_ ć9јt/ cs;B칯IEK7̇c ~zA2{O-"p&^3G-]^Z38NEt+;`/wx/ڴG";]>޿qlJ-Ƴ;q'ܡ,9&)nRs)ֺlDu,ܖ YTU)޳]r~L36|>p&^˴nU'&Ť{gZ}e&wgNWďHP&K;BZQ` f&؁eŞ(ֻ mdZQ9MBt;]'3Ϟd<B| M*dx-sl[jf]fGԃ>H768Ew|~s z5`/ܡWՖ׻xó !p+>C؈ryree"+WKڲ[ƴR3.v?uwp+kEg{Vp;HG%ԾF0GÜY2oLhyu,nҡci/g9ÍI>50q$f;;CfXywHvKeBZ]:b `cGQ9csn!18wŲn-vM">A#C5 'o4PrA=/whv~7&T\8sw~W=g)=fBAczxÈ *Pl/)e c鉱L!9ZjFuuקO)2mJfc/)zjRַ=ӴsSg9~'wy82_;PhuG{'.fR+d6߈%RWx9)`V69wˈxܴ1 `"^]LgoŁ.p/^@dn!=argC_e|,%|;k_f7q4B(pLieuC㌔^ƋMB̾ ;(%P=S -VĥxH$ozZ>{+4ƒ|7}]:90 )m۟dzIx8~ŴwcF&ٺÛqVsbEqT6@>a(*w{'\" Btu]Z!OsϾ>Tvg(ݏ|מ\,KQD1/0a/uܡCaiqga̱ FtR5 F OLMھini0GOKD HIc6!>!9qVW/_^f&G@6]L{p˝vOǎMa/ ܱM?{G_ #!HXkk ENg׃ H#^ep1| sSyĘJdW稿Y1RF$'%%K3`+QDn~QDAqNې_wnWy?Sx⎬ŏ;_]{0e0!4bh5J|5/z^l^R(X*>._eɟ.Nj1Ɍ"0fe5[7B0U!=ca.Pt, NXk|M쇟_.B. C8@(UP\L)WH(†@736P@ b%&d)a;(ّ^>^wzt4y>YݰV7˗WxS'e5y)wpxܡ]psS㣃"pin|n'G?x!b'#i <߽4E-l嫶Kb]3)r 0%D@UxAq^qЭ:9zfbC.atȎMSaRsSwy6MW_tM؉o_xU4*Q\ /^\ܺsٵlon甸OdՅ'}wmlmS/A@1}S$8 B&!"VCnm/&a K/eSdf?+yWucx!B;щzHr~Jsj7Zڋ۫mw };67.^F5kVC;`ǟܣOҷB? 㑂 Თa0t 3oZğXJX/,:$,CEU;FlnRnu8@|W*8%p1ٽw{i $T($I5Jl?dVlޱ1)BQd@BʜWB͞BI!T+o5?BTǟ883µעh[@I! >|f7g>7VLnThzScC/&u}&SY|;".ZX_Deوq=if\#tjb܋p>;9آI-L$w&ސ0lTMPXՊ Td߬ ѨiN \n3LB-f˴R4$uSKo5a *wh>O>xʳO_99$HOtV ^%k;^/_VzꊺUuڎq(BIB,ƥZ0,+5tv[#@0 Ll\'K-͉4fy.*򓆫1/L0a`x=xՎRKo}"ҺKH?)yuLl\=vdKԐy^il{auòLhgw95IrWCtkMTTH7J0×ۺN8zy !\d/)#^yXw]v Dg&./+|-1~}smcB0t2 &t,L(XBqCM@aDY?:1@&=7Sg1Yd^OY31+9T#dX`K ;^g~1q?~aIH̎GKM.o;}-MZz&uTVsWOl<>Wӕz\1'˞ѴtYoMy)Q(R,Sbmr&(gZ;މHh;]G띨ށsJ&Zpm3n#vR.=<;ebU 9; ԍMv6q4Ln/U_Tdbdv$TjgOװĆW4i{tS.znF=;Vqj @G 0"Ȍ@j`=tTj6A#D>̈́'a$ Kg{T.zahUxo{M_q4q}ehZ~9 ;~Fvv@8zgY&˻K!!1(Ei D^\OAh9AAQJu' 2l뚄c".!cqN?m:IOL'5u} Q?vZ.\ZmS#,DS{`\Yş|XT`^>̰HKVu?cW{LR:v5X F1L:9 "/}J边kW\T:_cm2 # "0`V\5hRFj˜>uu9 cm]qP' K16E՗  "R>9[!ܹz-u<BB$)j K}>ֻ/VRUqD-jP%2ikѓoVgԃ[+÷Y `y$HJ<&ʽvw|?560F:w#]n+UmagGQ;4gpKO\"JaRTcPmE(9C]mF{zփȕnljzWqU>E@Q\y\D~'<g[*_kuY Y&v>VKM(N={߅K*/GK~tt4_z:k|ED~ϯfWr CW ﻶz:Lt4~*b`%Q0:yS@Z^p [ϠD+$Ø&TOv BY 5e]5{aQD(Ś,S7Z؉ZFrA\E1^>y$r {矽w1x;d|m[Bù}vS%245c.?q璗er3wz?_rA?@%!8g{99c^\`(Rn'm|KvS&Wj5ǀ2:x5)7)ei/%>Hbj7FdR;횑R}3c`LF3& c(Vj}%b$Odʕ~a)\ 'qd^$Wuѝ/K//FNunzXF{@x9Ӈς 7Rj\u 7~3įGhZ#Y[u_r> {ҍFr!C& Badk^B{F }+z3{țd07pLUF )D͙؍>RUmt0N Lq"#`,bFĈo4YG^1DLLe^ {E*b+rCjN ]Nbˉ>To8'\Pm88GSyO`Z/-r91fM|{%Gpۖ*Y `R'X;]ynMp\nzLx˸<pogZ(}z:>>=J՜}RFW8)C!; == wi^-su %Ez,#k2{њgxu^]k&/$|!њ]7g]Uԥ cX䆰0`? }p=L-ɘ&+$&7Ja$˭#n"Oof5dxbsI@DBЊ9>ں&FNy|!6٦Q|\ BKXc41lx5ŵa[j=sn`h"v/*k5 v 5ԵƗ'Moʤ`]$izyZZ-1 1L DHF71072JlZưyʜk5 @`7' eAiECXk~Tj 3027M#O?xG&+Kj&7H{7lXF#Bӷ );.5(Z%iu\_Qu5WSZS繛NL>Iro \A"H5zÏV )(MaPk9:kL瞹tLZ>҄&ӻ&ь †Iaa@n-³ƗMt3^m=˸Ɯ=r7dlݼ'K'Ę &XY֨jZ#{t-Usmwqrv׷Buj'TJMv4×>X.Y.xKp, &!]Imyl`菧-K+ZAf̧} v A[+cNNJ* ]Ѕɾ#I`'c˒tj2:3={l.6JƳN..~yAZs;@_65hbn?zEu4$cB !mnZ< bsz>{yM_T6Ҧ#ڥwhFKeV9n&owsT׍(ʉm|jkֽȉRZK^\,-NoB"n:HR ILj+tmSމl Px6֐7"ߊ u;Ғ ,v=JKr*Sn3'W2+n¬lydd}%~m@5/?1_3M^bI1Cw B53J#dt;6`cJ$&D1ѷ:Gl.ɥ\f=$D^^V{O ?Pt,{olz׿?//N5LhFxCL)mŇ>' B:FkIݍ'.N2$A\oı՚SF 2omg2jys]\]D `+!)F42P\"*7zo3JП)IQ-NQ1~@;trH{R7^7a( r 3^6/sx7S3wͼ~|o~5ID\{?yK|9+c_p{4޳r߉aah9xqjOǂ\‰)nh՛C!$䟌ŧΔp}f(=;W3#j^JzxqkW!ޠD%>q+z&2\R *IZQmIFTpdzr .bEpHU{p$ǔa$_lbɈc ">9w$圞q)HK i☈DSmEzHL8M(7G&X.ͼ # @B\G`moEǠG ESZ^^#9图kcѴ˒yh|7~o>T_+x@1 3'@~}w}OfG0RC _x0=gѱT7]8|w\{]n.`o/؏!s6Y-_`6-lKXs|vM|-Ldc] qQ<@yI WM&PJ IgVKnRsMVIxM<{@dʩWEΓ(>).S}ݪDw|[}05&sNͩ_&4q|lrƒЙ3'\zuZkZPX 27m;V"_wZ,pc:)A+b|HFޚ{cO sy2O:Cvtum<CYKπiUcTOdΧd &D69TXA1fZCDT,˲<@W_b4g?_}RWqŗi'tԹL%Y)n @f c4y|r\^)1JDKإ?pS!p ĚYjRˑ*m3:>R˒S(0-O]VnCRbPMiV"cO;sʽǜ++)v̠9?P64]4E\4I;}Xܠ{&L'ebrTI]bh c~CJ Yޕŵt<<NRʰZssBhtDMQG^.wM&S,:_B4i|ޞ 5uۦZoل9=ȚV_OSS_ g"p}F&ŕczWO8h73-[-49_m4im 4PZH<T@VF}¨" ''s3 BQϤ^;}3mG0A-T#r]SRVcNO i[1JY6{-:ca~<6,{^ Sy+?˗M>}3˿i&511M(G~=u nsxk'ŽFZ6n^B+vE!2m\LkFyMb!Tt,{ֻc<{f7!!0_tE)RB)? T&Ft0B8>@QD]Ci_1[k]$n1 ,%ka/fJ6{9DyQh4QYZZ[if}@)E ۛBgJM0{zujamFkU(յT Od͸12בv "D )~XP” c] K&>ۈmclQ#Vuc9z>Dv\YkIM"eneMljYH scl6Nӱ. $"Zݮ}J׹m~)zi"u݋00@RGG20* {fo^oc/2V$Ȩ~ 2 l^<K\4eyo7-v(s jᅅ} w ÔmC9j&{sb̜L/ kŮy;FGE([F!TgC/. ~i2n.M'ڝeklLe`KW_abt{cO'%57@ EA0)]xJ)+j#_fE"V$Z Rkϩ3'l./V䕪6jkxDNڅ\)/g*u/eY)@.A$0SЭ aPhTn=ye}|9[131Xmqx)xd ߚGK"n]^؁ D $*n< a;6Tj٭RLnM)J֏8.\($K.yQlX5%]o!6]UBY.QִXaL+I*|]eE3u=_Ozp}1Ġlāmd`v+iN'WX&RJs<6dqޕ7ŊB"2h{dU3qwV\Vkѥ԰ ]a kaa wϺ V Hn2*sјRp 6Qe#5P"^`n\`SfK?tDaݵ`/#gk:FZ{lmqk {cUejlw3r*LRg%q&Em41`qh;nxbBHӕu Cpc@d{-Ñm_2]22%_ØK'FMW7XJ_JǑ",] b2rNl%16e؇ pCǹi9FkaMs|y<;A !6=ZifaPa5{u?Kh`, FQ@`r'Èj2F1G@8>Ηk^\ ~@QR1jmtUM5]mD[EfF4Dvz:ih & TezkyF8= 2@*ӷVيƤc" $1XpL1etQZNxm5  | ՅOK)+Kz3ɣ"ʖ#Dmq%bI0aD*!̠(MmDa*V<9[_ih=2u˻bSBCR'3(0`bԠ+Ͱ;xmc:2) W6.&}rP%r|eT:FX˦U@InRsyMjGCtjh_ \4[s'e>-~ԖV[MB;mc#DXa_^[OyTLDI^(`]fYrrJ3p\Znj{£f&iZ@S̛2'x{J raEZ0 x9v7ŮtX6d1`1a1Ax B4&KD."$MVb\HU^w2y~˂m+pi'& H@H ⪭ڂJ:$@) R\7:<[wQ Tƣg ] TiMQ RNjUMoO!"pUf-b~TCڰ>J>i,QE?Y?zP#.s>x$,n̔*q0b#vVg'φ1f˾&FF՗@ӳf7|eA~${$kK釮G $WQJ!\āUH($, %&+O, FcdA$,OVCU0X](O'sƩwXgB,j*7ZDLQnx>kfFMLdz>{Uj b9NpFm=GOamvg:0̝յɄp#p''AnLu1pcM#/?A6j4Ṗ ?/ׯŅK˫%a~u4~G?TfhVuFC&Wԕ*ʳj:=˯׿i$}nm)WLTRÓ tH P>b)Lrf6%oR933ҳYi=zwٯ>?>;34iy0sw /*s50mz*-]' )! dnֹkUm=PP*!r,^.9ETIjp4{%=i[YczLRhH|#^.m:4 a$6 tپM{.ŊhX}2뺻H"} 300`*.%>`,#c,ݥR(ndS B'`ZY^ (0>w ?9NA$OS=wlEQBMO3ozWuadlBč|MYf89urIhntݾ7!hq;Ӷ1r%jkq ґIXRb:o>ucϒ5ↆrӮe*7lBܣȂiF }T$Pp<+ӧSbeMNRR 'bMk V/j'0hP=BSM (uOV cS~S.Wh숵?M +yRZk,?UnJkKx#aM: 7 5,œZ f!Q#p"'ʍ |3f0Mk$_&o tHs)1,D6R]%>wLn{56*IrI9?J0]fh7CaJy 1v~WU<خ@1E*lD$,p ǹV+YŔP=¶` ,-kX7}KKPN /}m/ipBd\"qfWJ)BB%=i;&lܬ k+y a6\Z0"..l!Umbz@($yGaWg X6]npt1'ƌR+mD<&е2q‡Fk 3^Md// m#ٸwb'o.oDd-o0i˳v249h4m`I&7߭@ŏقJ,,ӹH{lv}:\of/t\hdy4a4ET$^SDYv(!3ɬ5^??.9i|:*Ml n a X~?)8YXԘ2ݣ%EΔKFLqlKdtjcO '>Ŀ]oܱ4q%󃐖x6-]2tsݑؤɖ/.>[zM坙ɍ⋫J nknOK;MG\JoG∭m]N0ʺM`ÆLE[B׊=~oTP: ǾO7bLhX,/̟]wz|ӊ}]'EU4FȲlAElRF!ayAgA)D|.dۨnxcJ")3l JUln߭3@=p̍Ω˞_`yzVeG;V>' $ryvOã=ibkWI#ioJmleI^$q '͖^PW8_ (u49Ct/?]^~ITΞD)]o.^q邮<|2'CTxhO19WV15}C.9vj➩eWɎA5"#ZG ɞQ;0 })c`MV m7!;\˧jHqkF[19Pefe`Ff2GF`"O6ňDS%^0ˠ~5]'6~HX}~gǷ;4BRǹU7.mlwmb6i"I'!/0nzyJEt15902)>:01d4݆hIRfR8KI!ck=a}eih;e%EM}g릧J3t%.UY)a,fڮoamSLB㍷\YxUt;1q5!.Qb@/Wv|LBW`6{m`\knteE @j%TWwfTZo[7r+Ȉ,!{FkǞXSa ߨ}?^uF mCZOΎX h_Ķևct3fԅ ,07 `{P:T)CHB%^֜(u~zU%YGVLvDlJ-׻Wnb;ڕ*h  ۋy>^,rezY R!uIf! /̟=M4_YNx*uة/|>n J) چ?׾[}_œ˟sL+A @dVH 6zi`\Ơ꒍0XgBE t$8mn 4&M%Ƅ,Va,7a=fS{-rZ[REZEA;N`^`X'j]~),bDk%vaY{E6='x\c<ݴM/ i[ZVIrht0Rԑ%"t ө6{ʨ4R^SgJw?ĦZFa1a"M  3,ЯN&Š"Hdb] hPp tx e]@5z9ލ9)C1LK}̔3($@$K]KYkOuXl~0v;Ovp=GX 7);3~rCOLMd(8}v0<`oC(G.|םy>?tJ\J&qbTj,qDu9y+YdN_^掦 f~ jaanF$ w [M!̛./( 6MSdž:e"B;V?=ϾtQ) -o=:#"("{; :i /&S M1&,L_#ޏCYkb7@v 1qQ$r KD~[ ěgյulFiʝB<6IB8ݑ߱`5z8Q^ze @~HI! /;g \ڡhxGP5zxD3 zPͨR"sk=ب5'z}DAd슍V {fnB?T?+sWZޮkuݳs,&53JeV7l!+EpjPkmq%8s̥Cs%^3,/饴L ZHa4..\Gn4bŊxI@] !D\|Eb fo8k1ɑ&9%|0AFvcY z^_t:oTiȀ1mO6ޜxTܯV,&T٨z۾Ͼz5wvށkka9jpbBHoglɈZ5o~+>riE'20sA (e^^7:ëx>YVof4Ynڎ{r&c">wSWNiB:IJg_ )(I5T6iՃwnJxԵb>ɬ5.d!uÃ-uGM(&lKf׺Ӫʖp|i+j 39~yMC Twm|W^ƔbJ a;>Y덧z_.e&n={4bmav1x ˚w[Y{`B((w\r4'D7ƻ&nt27榔ƈb0d3T\r/U#wn$T/&W൤SQDO~0cyNPZoz䟊:Z#^7♑ހk#.,8mcs{i9O A*UN9w&. Gs3 #QpAXY*GKec\gqQS} jVZ + SN> RRi֌||Զt⻢LNdsW\^Lx>GwmjY^; _ΛfJD=l ZejUJkY)E7o.-&& 2%cg>Rz;9Ҵ,W*N7ir^le?+eq4ڋHЋ#TklҘ(!%i yPQt~͐[4RfАaVv<ѣh"V2 7r+V/[ۿkF{iGWHQ$+zrcr}䐩 cȦnxzCh ov<]i-H`pxn9}C/VWx6l[ IԪxGZnT':lJ!g+ci4;q> bB T-]5)ǝ^3}/u~;IOM5W!}g#,FoߑazBh/[@뎮2qmU?ZretB7zglw*=n $ug𩘜EcS}D,]> mO^* Ƀz4nj\Sš0e{(hVihnT?SWwZGvvәsK;O~$g|AR%n9<5RC91fXPRIꐈ%Ja. MFO E)Ruݍ"4$%zqI%ٸfUTә M긞bԺ\`a;sV-&\TA;vڑ[@f4 ׿Ek6VBPw xjq@=".U|EȋC#o1;2;5-nS86ΦWGΎELp=2,XX쩮ˇa-n̹W-ĕVBO/Tleꅭ\[S$A/hNj\uOéqi|// sGڝz;3jPD+Fb%MSq>^h͹ h_jO_C}W0;FI4\Xn-f V b4D!^n+Jp4w15BCHQ|a#0!F2 vE]a )MIՋ"z LFh:rm㕞;1žջ> K⍷?]\lො_g!YSJx72oU:6 8siYYT)ҩv=|v82ĄVQ4ݝhPSdxo^FݳR=Pvs/lLaw@r >ݳ7{,F7n6\8ɠ"]Ky*;/gٺJGJv3軏=?ͩ/,޴WxfO<䱛qIrnRL"Z9c:s'~QND)CVkaB,٭aEXIM^gJ1I-MW_\ו 'R:^,VL!}T" iKe%uDQ{zD=s*xOVӲ ƅ|ÈWJtP-%aLY]aI`RD^waFTj2{4ݸ\#vDk%}*:(G{'z*ׅ nlztB)rZZ(!>!& ݝw,c-WϞg+G@)%d l~z-Fr.IJ\M GQ\w:~yѽHHPߘu}~Oj^m.Witٴ÷<򝲜^\x\x931}Xjώ,WkIRGJhP̎ί~KKO_}A+#kL01Fe$kXzϥY'4яx2ZsaQy"Z}mJ+Gd4]R%-G`A&b)(K7xO'<&٤0`Ho( "o0L6F3PL*-R,Wd譒s0Qts9J`bL&fb0B֐C1ONKW7,ǖM&8AL!phQASo|>Fƒt-:6ΦK|s eQ'0eM):{cʔr v|"S9Ap'7M Du6Zb((zaFS$6=Hw>.N5?}~9(x͎ S<Y|㙡L5sR:'m瑥O|O26PJMX|=?KNeZ}y=F`rƈz]A<ߔEHf<):vv1;J-W;,)07bXYDm:YGG\[Se6HF6a>р~eIS&X,Cs^.s|c6|O1{O1y:*A y~K$I@̆G̍)ZD嵱[ {R !)b؜1,'WF'vH}x9׽&MB<-hn菛\pq[`wSxI'NjIkPWw%v.N?<>&bփFlx`c8 #7eoI?G܊#=-}5l HA#Fp !=3ɕUyu^y[ zA瓧64]fF0 "hײVp ѥgQD0BV."f~|i }Haab`:EH鸐b%a3^_vtm=zC^8$D&HbFfPhm4ⲔN`"SSW#oL(5yey4ʵnL.BeW۫܃KABTYXi9>{ѱQIdgG*r/'l<x pk1'Eu! >Ǹ_~.C]AaD+L0ZO̖[pzuO8ku6 gQ"o<{}rus,2 fc@ݘ)8M,/WɈ3aws&4dc#N7Zba&0l&"Ti1_X&FGGK'Oy1EYj^0l<i??t9ҤF%ael!0Vng/ "'TK+!v!ђ:GFz=jA*@w8 Ga}'W[mAE ṕjJL+9&h"ӜȀ /6So NH 8B RB sw 1.V%I.Ҕp!I"{jl}`\mddKO7I6FԐWjg x`qLK)@Qkn"q}u_;9c?s*ߗxYjYZj1]bPG2=\m`097.R/GHh2aȃf/8>?{eS.@sLlyX#4³oΕe  +tyxLLk]r5igH4jz9iX7J@wz<4#YLϢ3=^ol@ZaQ^̿XQdDBu{&c9#1cVq׏[a;\R瓺7sL*zrP70i2s|rA TM븵]d*hFQQASe^ 1dbd0G1*.w)t-fF3ضq@=9=FUFd>8w|iY 8M.W&5YZL{L"6=t"SU]E(=&tEE{|È hx.2qڇQ70Y{ZDի'NLLش1p߂Atj?Ӂ/^´>ңTպMRPP1Z\H މw? AS% Mי*CP?;9Vlgc]t47o Z-(7l„,bJpr|Qc/R;fX/2588Nl^/kŌ0Wٷ$"1EX-\0Sq|kḴ^ hQ%ĩ Rޏ\@̯W[*rVZd v<*t9+6zxØŰJ[(9չ[˥R6)||pG)уǝfN菮7dEnE>TC %LDvFep2Ƥu{"=TJ_Z,5c;ȦtnfD!2D6[=m2E~p "O(w 0mb΅)3 )nJ ­Yya"^^/ 1B׌SDԸ֒Zsъ-Kxea! ,npjr,D4[iZn1M:1!]/%^ַa< s$nZ\2}뚼p]o6vf>p^(kYhwZ.ňJJW(=kIVkŶ\RÛy8ShZ`\2jnuQ ]iqDy4ջ1ڵԮ{^*&V)Bun¶r2Jh>Mpz\uV d>'wNf/LN4i'zKXOx0A'/Z}ᐤp+|l٨Fn 7DL˼Ժ1-^"c#5G~術/, Z.; {z,MwnAX̋ôG!a$aa #oQ:Wɞŏe蘂]ZI-JhJ"ю+Bi$sܕ#k:z+ݵaJ Ϻ,C.2(Oh-Zmg)~80C>%rA lJYJv6^pvFɟyotq׼zQvr#uwYZ1dQȥR>҅HO|`luC}',o ſyR.*G+E &T$T}|m_oSé RH,C620j5QLhdb|^{rd9%pF lr/Q%FۋS| ==sL}jtE"W֭l7nW?>sz V?l\֜^-&=)ؔs)^WXɥJF1Rk 93-!I&OL2}j%h./"O79l/8D t8CDetzk~bٍkl䒩nt:h.ѵ=1u=/0;dr aJ gnu,liÛEV4eI";#!;ֽT}$q3$ Rs䭃Bfg7t GNIiOzGM4S*c ev.=Gۓj2 :agan}M ƫ5~mHm0@mwY=\)DqWt=qn%x~HÙ83^XT.=va20k=5&uR]BMòT<2X9Xq 5"&g/@qPmI=LN"1#iI:f, +E[<.l[}OTE Ab" t-}~#Azf H[kIdq]r8fxv#PYOEg2"07/5O5d%YLvHv_:&¨SFHɪK5&bTn&;aj_ ͗>}G^H\Zo:vpPU 7g*IW*ƁБ4=67.lƷV ![&G5v˴M\Z<%q}ҷ}Hai4:h`VKTOתaRq7D=ǔ76/,/YIu˂ُ\$+&X r*jlRg)|/ߴDL*=w93 /!,l/B%ID yh%q葻BOg_YmI9櫷:?٣s6Z'p۴Pn ӥ{E`V"JqM9v-}":ItɎ)+v'{sIr'R=!й?kJߧ4ܴb bכf6z/%XRjGWj,/> 69330%>ZQzltKWu}A'"mOw+o{'ݽ͜<[b5=0VT\غ"I17nM(k4:Te)JxѺ^8Fot,ʍȈ_q`+WqD[f`mM`|g*$}׌X)Ġ޽rL3Ej[7;l 'H7 XA.6 cwT[U`w!o]FNJr J(G> ,Ց, cVS;oTŇ`g=]\Y?0Vcnny/ϱ}xdX'%{D[bnRZԺEB.9ѲB37 *wV3[6(&*N-i{21LY{mm x>:yyOQ {iM۱b2+nHppyЄK"F!u;w0b+\)Fc? C81Я}huY-U eXU yf]o0EӈR:K -aJy!uX.Zvʉؙ\ڠERlFǟ&6cW76hbVDFŭ>T2` v`+T=Zc$Ii}I??~ZmH3v} XM8jnFwF+]O[wMZeU.z.M7.cvQ"&GSMf2m'~elђ>q{'fϱ=L|uho'#2wP/r/oAbrZD8;J|\=PM_pjBjBmv4ܬg&s$F&-mZiѶA7Y!0R9Dv@>dq[LJGcc:G)tv4)QL%S Ֆ;Q\9; $R?DAn:}0,hr#hI68"c2I`9?Fa%'ZD;^cz#던>&@9o" /- UOHi*ח9o>ꝛz²M>vML~M`M\z; ƤⅎhB܌c:N\jm<{ίh]!L孾Q`( Y>WKh#R}M*P%vf~wi@Z%V'ìָ3hkzG;X au]Y|e4"GpaU)7e īw haEHjB|s%MMLlgf7iPVOOg[- uW >F>) "iT.0 s/-c23 նc #`NL Wd(5KaH"sn]?DV[}qi->5yD]S}Mf vTZG֞x(bm6=BV#ʫ̅<ӧ]]|.8 T)+|Wt'b 4s|1GwAy}G4Vq*eyMnu0^+L8~L5ְ# VL}MY :ȩcnY lCX^ؠprmͥt3V% ]Tz7\àTN@R XFM0j9%w(j g {w?R"Vx} CitLt,qa,{5B`# asg/&aPXCԉ W-ORj(7 e@dYzxpՋx:K-*KWh=r \Xr׌ -I3X5p  f03=ӢztUVUfOڵw/Ț+3P0&|2~.bN`z{Fem&}G\*T^n*KI"{jTQa1(#\m=:w)TUU`g~w,7ZZgug'ty~wnWsp!Š5+oWt-l~ښzWiYrOUwj/\^4熧kipe7H!m dIS1ËbTL[a[nRƦRkgfɝ3~htࣂ)OMK{r%IΔ,a*+ ?87ҢFd=M&C `iƇfJb,/& ,GIEx@jWG|M= :Mw`hDl.2+5:z @=Z.meJ_oΧBr' v tjUZꅮ` 'R}PzA$g!Fcą|H̀뉵r&V$+w-fG\lepK űx|«-THgH9]R{BZy&RZ*m#J;}{t`=wam1utvB7&˝ҍ ݣ.`VR+$VimG,TP|*CW}j1]dEܓnukg>}B(nIDAT{&c&(NCó|v-i *D"ޒ ܛe um_Dj)3 ݪc[̯^ra2\ҴzE(VُoEx WlYX ƒD؃˭si# Um~e&ǩImhZ/sZJdz{[}YJ0sQ.bZ` iL*JhxʀlO]b$3ej6FS 5bJx4=6]Mѿ¬Ř@6&g 1F=\5/^F-c;" kG,6?,xKՊ -4ys9z_{j-W$Oxr!3qsPmC+sKcz,oV !UƆ@$Jy7{{Q%C 3\gj|qq4!2ٸK)IZRkidAuHj74=Q$!Eܜ?T9tN6mƂ;8 zvUu}Q+qA@ Cw`{r5>H9JzN={#&#1 ^nKϞG"`mO{68g,nx F{@ōDŽޕs>b9 i7NG>B_\O5[/caB Ƕ"rHahDՠOw& AӇ+Z hW{C#BEA(݀sXkpIW_6*BS'0bb-ju6tIEF٣]Q}02TwwH't>Naʴ3fT7cFLs@H9 %q1cUc.B!H. )K;+ }sm'!4 /6x-7Rq!j &'Rw˫KͯOPt[d2^?ػ0RrKk?q,{;ң5NUO#.Q+ Np?VȐV#1* b!F9ǃu_G*h$M\V_j[xab#6Xw「cQ"xkm`Zc=/)u`A( "2Nn֍82$2Eî=fҾÑZ|glQc6kzbfgxpqO%G0IvoYmtk[.m&璛(q=뛓5 i77Zj[/?Uȍe59&A/qˁ8^?-'IUՕz@*&.LԢp)A`#W<$E1Z( NT{1D-ҏQ~(>?^rgP:DL0Mo>W> ΍Gk} 5y!g[n0lLBkvrIOPۑJ'6+wE0*Df'u\;|ǢЎX0<`'{V]dY 1v)d7R¼@R JDfX#%T@HtvWsFH>Ea<9irk]z{N7_T?j)bY*z\+77xW~oZiv-G2,(ν#2Ɯϭl.{R+lEgWO\OMVt/LTc.`.O޺r"@'^nK1?Z398=꧍=?nXSd 0ܘ~vow#He?a,xD6-㻯)rI1)XSޫ]5F2܆;G铕ȧ͘ 0T0hNIJ0HU#QJ6{P)ʚ,}P!10~]TA.2;;'+MOGFv]Mic:D\ksgW3Q`uu6;Sya. p^zkUr=h!Z }v<I,pg+][?n&c$8wҵWWclB3Ny.046GBDw痟87%TM"?J|5-)30 XĖjJĄ.sT']3;]Èl&p=[YѯFa 1=qfYo2Ɵ={|bPF8.a,WB@&Akm7,ǟ_'6v}Dh3/gg ǫ{=UqeT@D1Qi?{ҎHm UIY.S+z=\˧\*D!"H|2յȋ!BJ± x>T{Se ?,e}pd/6*ӣ|"Ȕ pBMJ# jB39e(=6'&0"NlA#ų] SqMfL5E[+E'˻XXNuDWx:=D"Jf"E_\{8R"ۛ\8>|k_;3ZoU0rj]̮%͊5[KjGuhĹ#M8eƷO)ntĎEEV9wo>0YhRr()C!դ>U2)ΨpؠnmD1{fMRjm\AZ.D"),'gOmHcb4&GѢ B29??~`Ce@ܮ+mI0/ 2\,$ 4'ϟ##Ph0Z0&T'^-wp9$d19J/s=JMŌ%SEvv/NvVwC fDRѠZ|\?`6X3SQ :;!Lʐ(_Qjr}8+DIOe?,oM?mŗnRDu\`?Z+v=H(Cp~L#-ƪ%|vMĊ[b/@K5K|{_ͯ4.~1=5Ƶ^'~Ixx$S0B}GbKTd 9@Xr6^{]1hU8|M["fuٞpnõ~7~7/}ćwlq}f`i\1a<6ѰtTʊd"m[(aY\+dXA$K0:^5O,Jő"AĆֹ"?$\(DA*|j(7F+^b3Qğl UO(:?ڵe4'wbjS{t;{gU^GŔv`a6(민ijqmw|O6]@.R_LzБKˍn@cO X~0G0(hcPLtj"FO-WlY#krWMp$/R&G2׿ ve?uKc> Xr"CEyJ&WvK{Kݕ"GVCMk"NFS +9Bkxi`'õm' BvhFyUJwc\H4׺aYgkA1CCniD #fTC)3zj Y2ѬQw1RYoeYe.'zDeB"Uh[J=qo5sg%bkz;1;Yk;,> D_k}|L'ƛVl4홺~rIHrvcSgA_}Q(s ဈ:ɥĕS-ixoBa/eJj3/,޶ϞhCֲVnTF'|qltŵ&-tzU"aEO*3?i}ʍѝu|bJr]a~(qeU`+ .S[®d }WIȧ v4aEݸ|&=wl<ŝL!+;+s^uX!}^ܧtXNT<)1bz0[HVzӖ+ʩ!WTCysVMO#L,3jL+aC6LS mZfX8vR}K?{PMcPψ^__o_oHӞB qX[h.ûNć|8U$]JW O;;-U8.0UE|3@᭞転ͮا50e)MY4KV{%UEI3rUCAdt".l6 r޴ﷺ[40 ȇƿq?D.䇰@=oSESj)wq)||; ,֓&%lC܀]J8zC3O6 ] +sAuGkœv׋-֊Mo^-MGh|6۷a/>o%#,̸kǟ")J*Qh>73*>WNy^ĉXqYR#Rq.TZh/RKd#55:7KC3EL=G'j[^*,T .;2G`Ʒ]P×>KZNbYN%qQH$SgamD\mW)ym~r}lOi{,6bdRcZ}E s;k&B:~G+ cicC! \SeCq3Oǿ99"Q 9"@v""zd,jFIv5|z~5{TE`wX|} 5qPq)hZV\ )cnè0  "Lc|Ԧ,/ W2]7bAbD Ja- ˏ}T~z쳼&Fz;p78K%v.[#4ٵ6# GBEQ841FJ-c[d&_ۭ֣XRyZ*竓I?[R'f . _3 ݣ+763f.rkᘨm)_8!?S,󣻛|mIB ~\vW.;QQ-B=raxtab C.]/i=hPHTts;v68s'SE"4۷{h'!s666ؾxTLΖ؁iCH>e'D~Oe/M_|tTBW) 4p i~b %/e>ی-Way0BC3ᆼq!#b\ %3X1]KCJ1R$,Dis&O0Y@TJxƶ'z_*6U!w&UOK1#`60eT?Y'k1?) NMii~+R>|;7d-7F3%X^[F8]H;~{r$f{ljG< Ryv<($D!=K绺fPˣ~v ICq975(! {_:A-+8M"~<8Vp x*/"~?ܳOer77_,2D CkzL;^Piy~Q?3C³\j"6UvLc "qT]ƺgw9 <5&nx:)>[b%yzs c)#t|mq-7x܀b>X.[)ՖufbtFHV0]%I3ɕ>0[Hϟ4jXzy1.յV#W;PdJZhЊbr>j$>yHicj"B \nb>ëgS_}o|~罵 %8zCo g =GVL0LX]`NBA!L \} "uhchO:z@zPɧW6XڟNgVpIlv*sS/hHrPX1CSwZܬ9&.S#f&SUl0$" ˌ0dݭp' GcP|=Ycƛצ7҈4}vg46pR,t%:b(W$ Bx' ٽ%'|qC4{"=zEsgz [<]$/ֻkAXds)E1{S#j6oDh|rļV״Sz?;0+[Ϟ|>{ U TA/J85KB#<*ʥ*%.De;hA_:AL#KxwAkPL,ݰd=pH`br߽[~Rqp΄QR|uϬFᡍ˹ a7SP)bA./BYg\:k??h˗D&bT"\Ο{kύf!,A :Օf/"\ /0C7a2m48$M|al8D0Zdj[=֕brsV4}"U'4WJG+\#VH| s< Ҫ.LJзy&ΧE8~Im7M7$WN nTUi>/VwRiz=-Ջ0̦> lso`}0OA]3MʬEܛtTL!,̏/7{7.7uG8^ @:ZG@IA˨iⲬ哫bL&z(CMMNuouoZ|0ߓse"df4 ?,$*G q@@ګ DYҥ\V"` `,*;?CY.A "14юnsg#BN}Z>|]ia 8\ezKx҇A Җ4pe $śZ#% !&*sŕj ɋ͹FJ9ڭ"!|oןnL\pMhj[abHI#11~@XkHt|4;Lyu) ZRY;+ 7P{L<4U͑O'Sfc";,~>Wcmks"z89(lu[@7kAopW`ckeQվxr{"h vs踜q;+$bd]mMLe/d6dY}\!{jݵWNR64#3z{r@@0zt9x0ݧWOlj QĔVxL,v7*1mṔ@񇫉kǑL^Yt`iaw2@80fJXZk6:LSw!5uUW"Cj["R\u}lW"TV$**M20h]'Dz˙\JA1Mk=]jW'Jkxv³Jy]SZ۾N@Fb"*\ȧ,H:urV}qjaT[8x>ί["Iu,iT}+}JwN> GA"F.rg2"z^eg wݍtl͍jDCvHӏ˵?߸j0a+VCڎP)r!vU cQnZW&/?/VnWWϤ0'ױH)3'8N= B{2 5;ƾ#Ń_D:^T'[Б4J!`&*'Q.ueq^Q!" `j *A&5j;n.BVD0LkT[k=:)܄pl<ٍRn|+]+q({v&3_o[G7#?aDS%۞ϑ}b˕l&a @&Jp*pq (EHv h˓rU^sb1m`K iC\J'D:Dh@ x1NR% l~t"Z(fNj{ojMlCO@mz꙱=ڻS$ҡj"1k_YVm}vzevs qB"tw)~`n-rjzB)ADO.^V?t9'e7ؓ5gmxD!2G}K T#bHw!20=WV$>"q4v"J=uJ-]B' -k̸\ms/\@k V>bq03zw~7_?XN4 ݩ^//#%ctDRɈqp<0wsT!U= ^5`4dMU-{@#LpG(d岭:@MPL}'k철*X7>^ߺ.fM }I~B0SXA"8=f{/^.XsA*6Ky~ K"FySwұѐF-j!Ys47˵V/](21[lo :n]"E1"N84’Wnjv-UM;B:ŬP}"\[sھ!Ľ[_MDjςVOt|Q*4"FnQ(<1f2\)2}Fn ' ^27ٮK)6+jUۼk ˅2^z>7V{vfT3H;;{RGK&Ʌ ;qc@#ph \_DA"Qmj[3$'ŽǒF=Yof"FSpWn}5lkcwn>nGʵ 𼦦-c[`ð:Uϩ ;:ʽ.KSH\)l2x^/\~Tgm,?y̅|+cAp<.\408Oؐͦ Ed;"#|a楍R1ʅj%D҂[C{ qN0fŤTOt~BD`;O.|ICi>y0Q ?Zt$9?{Vx>Z\gՏ$_ A3<S`$b20Fx'2lrrNr=TPc#D=Ȕ+۹~{_wQ'*ݥ" JKڊ4T׋+GSG ,bF^ |ݭ)AJ!AO(,E>.P9^H䁚8M σ+'vq=B9ZVL8s[,߈s,fq EHFf&(>bpg+̱Ӥz`^)>z _O˭AP.4io-L_LϞQ眒8Fh;}o:fV<A{n,`{ SݯM|N_"a-ɷ^ 96yĻȒM*=֜F0% AC+W8'$e-}<;,`DL{WJ=*acsk#KPi:LqwwY\Yw?UmIA.J X$! "?aDgW%׉ln!SB`*Q.rI7爛s/?(Tj.=qJH:uuMSaȺS#l1A@Lr}\ENE/dè[ھy:kh̹,8a3cmt"@q花F p.hʅfk~~5d/?E\`GM('9+zB%LDA}14H(@ 4y{9ܹ|1Ňu䓻N]bԁ#cA$nmYMia]\B N!2F"Ir#_$}C*-_{ w fXvCxC/.F=矯V˧Jtf,] ۝2) kC6bk$mTGd. ۉbP&gI. $f m4Ux.8!(TU> +f*n~"V!"ay+`*IJJ1X2lF)HɆ< K21HowݮQJlA?qa/Zi^&KX阍PjKX]9mДSko|tX ᑬZڗz/8RwϾҞ}7%Z=RB8Iqð?u.Sq]Si+;}K5v:5]O_ZX*xB`W,3.k"w<y4{6CܶbE0 @gӦ?Y0T@#Vrթ1$S =WH{ F'oί}{IW=&4!c;Y3fW;c1] 4 a& ='j0XQ䇑e͍JЏ~8e0O̒%TQŏH wE;&YIŽǢ#|)D:BP-Α燍V RvG<!k/UM]51E ZViU_LT.8dDU9J:c#)q!Scmx@Y?lSJDz^6|3ԯ C$"D>莗Oq څfgBa˥!CK#(I' qǷ0 $P[z*-:$  B &cZĠc(f&0~:) H) B&v޺efO{rv,3%!7:SWNNc'}6ht^c!*c^,LkZ$m"uMï M#Io7-c;"KDPi$DtګIuTF,kLպ+htLtT)Fskt~vj'dQ& Y.ruma9hP~EHdq9v4EDgi)Vǝ>sp"h[@AM*|=eZ U="8)C88@'TCJ BAğ?7_Xo,pA̸nE.ǖ&ҦD BuͤfD@G Yk$כ 0uتB; c'¨򴍀sH܋jS%(d_|-{Pd;T C7( g\z~Vw8X҆J Vj;4v\XH @/j 3ܙXנFS\-Wf⩟|Qk9Κad?}h{bv]5}MxB {ڂX %< ,X(Sn`$LzvMaQHmWm3lw8,)Q^ ٲ,E 6$XX? Lm(`;O!I&''-Q<Ҍyg],vƇY})dr0=>bն%-z#$BњinVt*SgkEHbm སGJ6qlήPQ(;Nr|A).Uȶ3wnݻw >È̗y{ M%t7A&0flvmr|"f?kccy'w6&+Ooܟ*J@w%hN*-V]}C xoAIXFSrͯՊcb0m4߱|\h3LO拙]ͬ0h)uc dd'lW'n=~F Η3HWFbrjT~FM_Ys\5;[. 'v!i (YUKr a[MOfbA1~ل"(xD>1tPG $ @]Gn|ChEu s WNyҘj[G? ^<7,Ez\i ݩ|ܛ%L1;?jc0D€<~8:Zk26GMM-+% b/5qĩLXWWiY"AgvͭWV vj,0gGV-о+yx Eί~(C+Co4SHm!Aq?;XE MFdB2)iPJpMRJn_4_.@ JFސLȆoK.G \ #Aؐ+W`dw %N⨼gE%Wt#&NvwϵJm\%ogϛ^],\)~VV:`&ArhNjb@HӵI%@C.1yh/)=zri e䁯MP5WS19]TJߚͮ"V ys$>{ff]]?<KX2 T06>a\4:;I?D7{9Kq??/EǼ~.-֔uFV;tVn F!/%܉6ZHWGvۖ5WM-xB'/L?ZnD1kx5e?~o_A}P AIvEL!mĩj+|@H3G esLUXa5i|JEC ^;S<;ӌ <]hmV>druB br&*{BtV;ɞόQ 5#vhiY-2UDߖ/޿+f]mTPy*%MNG$BE1֯b3p.FOD'X PS`?^DBfJУ(b [][C c^Hz]Vah8ꝥ40ZHy؁/Ic^EźlЭ9 9}qba#Hc#\5өl*y.\1~|^2d,Ã͝ᓨFOBѭlLJePs3+͓Ѯ_kLʌEVkZ b Nwo޿;3|繺Lto[0UJ?ij~[],Oe,8,'=gpwnμPobu=]g,z 0IzIUm$Hr z5J|pUhUUp̷hBTZD`2?l Jt\9$p_kׯeh) f,7ZjזNҥ!OP[VoJ)ϴ{b@ SgX1{Z7gД|}UyJ5쑽Tz6{[ƹգc:6izKt)5dL@ t Ό)Oσ0QQinv,P?nr+}I;1bsʥ6 O?"',<<*}"#7 FPkZ(pꝛ`W7@š=Km*TZL #ta|SAAbI ,REDL) ؿBCqI(H41QŇk&Ƴko`'uCPдBCE@(ʞF_; F UZzC]]T3B&Pl4ӯK\'#ً\gps0[ʳk^LZLp-`/&$]q(~wUJq)w&d}((ݘwn6+>[4;vy"M4)@xi$3zSWZבNlUfM+A!$LK ݧ)UP)#7'7//O$P俼ٯgf7zrl;\w+0b\Y.ih Ź 0TV/v7M :: r|m uBkإF/N<"%u)vMQ~덑'j'IDVKArt(G*fwG\;{1*A({75/L* e7({X/;,])hℹ[OH:ebm(Oyb~@eDC^oИJxxtsʧ|zJ̋)cxF*CB&f/|wz{9>ul?k(\RJ `B,A҄I>1hEI&-=ÿ/{ߍJY38q cEWo\OYpKJN~z#m$ō(a Ea\M..MG٘Ri7[J(:%̌xWy䅳;bi Lņ\GL+7B4(bT߾s^ Te,Q+T6vkEkHGe-Pdhw(uM+ z6v@b0mj;iz[%RqhcaD -?Gk--)ۍ4>\E'n/sɧ@a:f{l$7AdHTx`Jdb6Ň@fE߾Ѫݷ?Y|h_쩊a;LLm!X-9ףN1ixE/8^8=Gs0f+0Ⱅq̧ALÍ3cď>߻4.M#.OKEkڻwn`{w=Z7 Ϟ_\IK%5o>;sq:Ui;}Wt fKGNΆnPkz]?ݿ:CPkO#N*[/e WW}e0$ϧB&cbR”#yV:w*e~L׮dd -of Mqʶjɧ߾#>[^_N+ n֓uqn4!8h~6opn1i5_cKk 7^dR&|7,8zkajIEo7^TvNX\^_޳#|Rꄿ2P1MG,'-q3scG%5H6c7C0n6qx'M\neZ& }].]',~BSt]Q`&$LX7kBǴPl!OgvR&[G  dJ-Im}m|:|vB$ i7:֏?X|߳}|WSa ,f*m1}URzʩJίYgRϜ 0Wƣj{8qzm#dnt\f-gҸyI4az+B<K2B8G0%87GL#J_DD v5E}'ևwBv{0?3.O<\E%=O8>!X(7Se)0HZ\ҧLĈ\A"˿V݇l\=4PyvDB(f,Պ I0 #Hjb5jhvTcc 8v3uHJˆx|65^Nz^qU$>aOrc6J=:&ȷ_̼a\{v"p$v4w ^Nq*6Z_=_FiϜF[q/!wzkW3Itu<"+GO+;uBDZbt6l̶)ˉ=ht:3w湩?zng7wƋ$dUm{OgĐbE2;dyٓ$/Jd@ Kw_4RJ8>ǡMګiɇK{mRU6ΖFhwr XHzF^?=FĀ/mv]| o'riYϧ4 *oSੵ:'UD{g@x:zGO)sa/V}?H&o'kAFCă%7^ Wjb!Z5hY\%ɤ)sJ&~@\Bta55{X6=?jKƵćw#/awZD@s0-aW>i0 /o8SZJ3ǖ=^KMi.AW[ZiSgOaڙQWnj-7rHh9a'nWflBϻ`@R&qA]2>d^zj|wRv^k;I'=YύzTtfOcӥnc-Tf͞Xy1irD. ӈ-BEBO6AO.̮r=+S%'5Yt=?Lv"ƒMt{OԽQۢ>=1Z}6Ϯ x%(AZ}zq&Wp׮zvVw6.pؗR3(!2@M7z{==R;z7T5zQw-E-2ysv+2Ox{.~:pfN-n2"+9jz[tk0T$D"yoR I%Wgv@R|lu[;XᄩǓiO? :WF>}ؼ3z4茼t1>ăBa )nrlnO72q6M#14v|o=dpEfogyN(cy)4[V#L?2jJYݩ|ܘ[mO&Ir[wz/]yXQK7ϵ;?b?@=mj{N۷쾽JOL,,^x~1?8ĠNw^b9ݹTl_%DQlQ @pf6 י_&-$| |UCq Ol%t 5@5%rv[nsr (ź71ho(qtWk8׻$dJ=s5WO?(vvF-UU1 :Lˣ aB&$A(}R!w>[_V~lٯ^ ;5z Sd1:ك"Y덞ܝ:+<3 xy}aam05tnR%i!588licqi2([Ue`VH tvGH֋ٳnM|dq$gz }Z>.7 ﻖc5;'C 'n:捦;`y ]/R:*F e;\fl,gdN&@}c_2{s>;OlmLvIY.cA!t9Yk Ia!ufAϏ屷zOLFJcNbw0H̳c PcJmq `/CL)pglDPwu]Q?㝎×*\ApPHt&2h4=U۶0aX/'g'Lb՞/\< &L˥~tpΏr''kv1Up\~+/Gƴ郟>z_x!.I{j6ڴP VNDA9U֯MٻFg98.x\nT. ZXĘj PMm2赓#)oyeLLWlS.On5ɧ4G"0kSXhSR#F7qU=hU^dya[UWT@jL8A`F˚˯QԮ )X*[sчrkR3x{RV??^'uDw'bU^J*SST Dl?e1a͞^k,Q]Ki>a{gf&̧m.M*M/b<E23q&/_/N|j= b.OQd!0BaJԢrKhIη+E(:kuO򣔠1*k՚$gcBroGrl*o<u?]VF{V6z=$q0g Q?瘚f2}?ZeWXA\wώfA7/IU5W,%t @Lg/ GO&0S( z$5"]fj]+ꕑ̦#;^@hcH]s @t%{b:M5 `C$bs&„QXny;n?]έFχEQ\eznkƛELj9!?$m©Rg7:}'_np!̙Idr${)pO&P*5H!!-T:ҴlHyУ #'M%4Dp|cD|qKp9mt̕ (w Ze~&B| ?OK'ZO3ԎҭAD]frIqabɵ]ǻDUG= n]\\W?QA(*kDH3͟$%뙾d+BEwRxzб;\su%~FO&NBJ8%^F{Tdh^(v 'Qʒi.?X.̌sn &!.8TvZIO6ԏiK ]jp=O! G+caWs@ vǚ~/E:B5"1f' 헟7+' 7Ǎmv&ZM +mrv׃iz'㹍D$8lU>ît5Q )@ݖnTl5k0jaR$k ,}hI/1 c:%uOW-2eM?yl-+BO 7i> )cYm* պ۵:w|K,ԙ_zgb֩-cUF$%K 6Dm!] '{RK ʬ8ZJY1T=?%(FL(= (7VL#JR(5.$9<ڸi͞~!{[Ct!'?=ِӥd7CJ UZht~xPLcr2ƁM+K}ɏ˛Z_*>YmgF'_n\;8¬`<[8Gr_R,$ 1+M.x]!'rCjqLA y@!91,O}:2ggbv4S@* $B'}(n@LJA)zt/HO/N^-&t_ݻfoʥlKx1`u򔗯Dl ;yCj,:Pq!@01s>P+mRY䤬8HZz=(wV''7+v!&F[OZIbR4NS^:M]Q))<TJR_ jJK?hmZmSW;^v7c8^*z}kAiG H*v="fRz9`iF`9^g$ 'P0UJ# 3z*n?yxj$f >ntׯekr!!e .OoT1FB(bBPe+T~q84~-i{ E 3ij'R*-Jo[ku/ ekRR@1^+wV u&|+_|lփ#vC4Qn{csgtVX϶ "F*ݜϛ; >X}o{TJ.]:a`C0Ѕh2}@*ȵ i>d'.$r);vR*ah =ž^:a`X S9"4L5 $:Q(Qצ>}P^۷S%6/g;/gaİ$^8mЅz{I-K``?\TiAV+a !.)e11-/7,_N6+e٭֜R5= [NB&QI†Vw|~,gV"9q"ZU8@dJFLƣF^JtQD5dž$fHp%a I緾"#sb3Z5 qD(EX]kD(t\{*FQ:\73ل'NϪ+BdDTl B ab C_sVc &tQ\xa~r$7jD+ԤҘ$d_~~$?۟7WOG'B 9Cl)kjC-Y# 6Z apHQt2} Ԕ IsqD^iF$= A)Gh p!KGTN^;6+fk7. Xخ58ۿѩcF!) V^ܺ4ICC @N&X'krDe$|f2t4 rcKr/.wqft:"TA #S1yXϫ)v߬ܺzD1}0P~fSrAF/ bמ6=zH?$Ɍͱ*ʥoNEk~wIb^6sIt4I9ɻBmn;khu= 8A6]/XWJmA Q>܊@.>g2R&G3xv/#?hF^1ɚ#@Fx#*8wK3>](Aܱ10 %d՚.e|wə-ُV=bud̙k?u\Y.ĆH/TFδVP߿1~괄6a>I77@8q@a]Ao^*Βe.X~t̖~+M\0]oK530h"bzNMTh*U<(cl5jOo|eן*eQT*`,@Eӝ31v{>Y'1^twܩN.M!*)Y*%4I i\w*gƃ\2|h[.CdLȻEׯg)jkkצ<c.Env?`yQcf#v)2tn}_~+eB()gX^(:L.)֣5aDK rĬDG^{&[CEpN4&R}8C*u]R\!Hn6Z7HJ#bXڊtPQo [n׸teJ+%x):\ہiUSBsNZ iBU^8EGw[=aLD_(c*kJXi?gݾ(MffI׳E\u_g_~^m/J[v!DKtn&<=x^%ekTĽ>DM abvD02xXJ> bJ٪ri$CL?M`8x+&@,SB7]-sXM HB9vY -~HvV7ucnTpx^%'hNssN#0Je{9;vBȭL>)'|R-_*oX8ܹ w~E^x.oV^D:l:ۨe0nNhM Y횦mUk;Mq*mƔW#KxT-:t]ZGhX\;zPl%\FTNɌqUe;_]_bpT((1C-hտhw%_\x/pYZۛe}_t +Rkej4($/_c5IId4kx(EKF~3Tw- ʹ:g1DR > # BglyyHg)roC8x6F0j .Z-Tp}{վ1sW/@p8*`yHD)5tЎWMv~HM%_W>zP~nfƳh_da<KYR:ҍ1J\FQapk2l!e0Q.X!6OA->ߚ3;w(VS1'mN:WgwB+%dnN>QB:ۃ4H BU'xp]/ޜK2nR"U8|fd/qhWq*b(A%lgWS'}y('IyDTsyEVr.o`A9LecVB9xU+KR>ϿȘow]#2EeK-u){qNB]O/Ww%:Fra G#a~x>;Å|g6ߖi17@Smh\o9ܼpn̨oWvZu| >}fŹ.! z ^9 ۬nʍ[5c_TW&eyl!:SB& 0/K Ͷ5ߴ39 Ы"+Ɉ~ke CY,@鈀)N8[џGhadKRvq!Xsqnc.dCi^ۈD$_~f Frr>CM{iakF5i­'hٱT1᧕OW{_GDϓ=]fbC솁z.:v&KR>ɡIiEnXxik:5閖9S[S|W_KeO>_uӋ\b}x|NLP=E8>0nDVNmnݞSgnLY%IDATۗE "+ฆ0azhqzgѯ}޺$xS]RQa&+7A 'j?x]yw!륢؆ +# AF$`C7ޗ]a49pXSL& Xr8/R|trB* m"Ld vLVY*t:,AUs6CG#%L]26^Owڧu搄ke+1: t[6`ɣ?p|Y!=I]Qa1QH*9VPBB5YH3xѽFEcD]m+PrF*r. "Gφ/LH%/HmmޭTW]^-كRZ}b5ql5uMO JUcGd+7>nW?ksf~#2T,t dρoݢw­ZGte+֐QbxVYR1<3D+zA s7ͮ.uñٺ!*ϟ߽qʗm>%4h!ADA1ܔoU;1˃>!`N?$ 4,zșK3 ϵvQw>ij۾pi?]21#TiAg|2BkcA29rOV[/6?kWn$O!zy 8*@x=#=2;ⶻQ_ElLLgE4mVdtp>$@k"ܨ 4-Pby+5ua6׋ʿLy C|͙3Bg(T:}M˛,mT| k#qnX(~ }pM?z0{^w;  8ȶՍ E|bp e:RۚDH7 8+p{k)G:]\<QLJax4l2;w_T޻-wR*FങζoQayYSk CwXD`v;C@w/w65<v"9<7?ϡګܥjGw~QfcϣDd&Lf1-`{g3qgՖG|#=jB ΆC8|b;r."WŪ&j9<"'Q*8aUNSxHr 7 LHib)Y"pIu},T)[Q_iw"mj]~(7Ԫ4[v χGm,n \.nvf }ǥm(; Mo{o.w;+ϟ}6RSHrg0i$LEώL2W[Wb/~iE1۪8q<@u6`6+ .۹xW#q) дg\&Oo$HA :6'K6 9Cj# W߼Kǝt~kN2S~kdgn|JN]UԢ M&r3q2Z[&Zʮ *fqݗ!Aqv;~k\U"\?y Y'ȴFsͥVnK]Jg6gyڞM#&@,a9Ӂ6b P4h8lnXy>1-%)kN1i|0i4% J;Z޺Phyi<ͨ5#ӿ[=[Vb}þP*amC7gOkp\ԗߙ+OV[h1#gF-WJWo閳]^l kӝf7q)(ϭ#EyGۚiW#w4zȡDöݞO//Kn[z=fVPh}9EPDwZ{ӽ0/v'4܈hIIɫ`0 /R!6=OC־tToC=1|Hd#?7?d\A$تt `3n>.<Ԟmƒf>~̫WKr1`W&8]H1&YnF-@!&fm"5 7{q\`2!oCdzSG| [UTrC7Q}Vʹj;UA]Bb>FMRڃ/x>z!MQ=kb)wE^_w=\6qu9 -*/cNN ݌VZ{"cL(]U5Y|VH(o舾$"J|Qg?H)NKۨp!{XpZ:*ښؾsv[lT6HGXt\dTQ3OCY-cļ&}Vi5o')aɚ&3ȌhQ-ht6 \#"uy'1t8^oSNLǗ iwޜKvCdF?On+)xr-&xi5YhAУ kiv,ɧa o2ewsَ_ oXA@;a>"4rӢyb?M;n -@B_fRqZ5ɫ%jt,yT5YBbJYkTZ?)QW+P0r?0q`lϾ:xL$OWD$~8 &vj\۴|VUK^D2^dӍ\EmAIsls<)#"pp!R蛊QE[7A52ǿ~K 1eTniDe$ 1OLN^~+_N^O!C~ A a@@س ˍp$Qpcdt^a1E 1J)Bς0zB{c>I TKuѣqG] $Zd"` 1jp\`<1`fݍi04*˻qƀ Wt륒fJolj2mvTL򑵥zj*(b`:B, ` <(>Bp"OF +ޥ!cKlBxܻR%کK$nH7qUB7N PLTnLjØcH aLW9bs~C5?MOQӗV[8Ȏy(Sktl Fue)vl2KH7{$ 6@ 0qlEw zѵ׺&HM^f-]Dw SPw7ѶE>jYh'm8ͱy)C.L1cՏ墵 K~gvJY>MjV\H ݢ]]#7n޺xj튀 B8rէZܬP@8[W1o-<*87t\& B<ƇBY%OB5-"c_\[~\ }tM06(斶0GvGhۓ@)@D:K0?SIʒx+&\2BLG;?oes盯Rd;bw>c]SI??p] ED^"d'wF[i+Y9\HӍpǘ`$#G ("E02f] 딊4?L @3Qk, >5Ww/w7+95X9G޾@81гqOQ9UqyLخQUG<Dž w 7ǃ;DRZfLA>*x&lƅB,#f( [uȍepVY4mvz~yDpc.5ݘt(0ri_6kd"[?Du'n@T:e ( S\s.E Fsc o͆S-[UJ0Dd7n}9n%8 @b*OQO﹛esl޼|Co!=I r ͕rH&2e{1UkwV _z'pցR9K^2nX}f4\_"XDQU/yJp<cձri}YzI(0M #2$佭D Oj\vԧ 7xdጕhlPd^.:^y?AB5n϶D=| FhkߺF@L܄J @(*8.MPLF, E8E^x<3Dw}s X>,2_|}^4ιKqnԻ9UTir j/**glRxk7L/Yȼ.M3xD0lo9]H҉,iژn͎-$=Emısi5Wn'.Y&8 ]qd؎5ST2TQD-,r0  -DO 1!cZJ o]rӿX]Z,ٷ+ B4d~mgN,*<Ydצ:UڍӥܥaT.-P4^_C5G8%2mzt.xqjR@ٯ_is t;D`6zRkLbe=xP$KrV]Ez.N$, z[ ҳɬUL( ~!i!g D(B:^ZMؗ X29~W W4Oju9mYVDdRh&'i4~ZIǽkKS3YUNDDo>ܴJu״^4M IE-f<ґ^L28vQ'ߞr%+kv*^Y4\~zn'rړҎp޳Zal"#JB 19W%Zr^l/6.7;Hq> }Y+?M?ܼ8\n@L;=E&3nLiV" s=߹56Bp`GwuUcݗpi2EVώ{\bk 7,!8B/A]K^Teְ cݔr@5QsY"|F=3ܩ1vi욱[B^L.lM .FL CHwV2:p^QÐP7~g_z-¥D&' k^U@ \;u=جJmՀALU&[ .G$p"O`6xEAkmL =88J=gg½w;պw-N"B~"m$Wfr&ɨ_·՗+\bӔFMѻ,4m0Ӏ#6l֥"9c!ܞ2D[fLk-,h1@[nVo^au_S]X|L,Y%]ݽ4щJAIR   SYI Z8M>˖㉈RrEPa=B0x hk4C4ZFOcbϑb\.mtA|ڢo?&\$#Oy<Ę^HO?yumW7v_9[I]؈D)4g<ΝڮεH1=OBt ˻G{ŘRNvu>^碊O Q$q0et4kƃUaqotɕIGΘfHҬxѸnC\#ݭl1G/td2mw mS6r'(bޘ Uѧ5u1I(f׺~ren,ܡ3g:sy&wY_D+͊} %N}N~F6:ũlH/{.2p<.ﰎqrI~&.پ6Vռ~A{cAv~5veET)蛻Fxqˎ/jbq哱t=lLzFPLA"|52"ڟV/p}6a,{+J>)|jt-O棯},|TpȣZ*d_Sh>apk[X#Uu)%Mec@ӇK2eō?=XO։@_@RVYE6'grB}]/}if&U' 3޽q0891L ;o @_9sL\v0bt{jCMN{ԚJtOb?jvQLzg%Jϻw~ L.@qq|Z38K3IޥbwiW\nl<ǕƾY/Wƞ7>r\GOb18(jPBzz "L29ð0r xY!  pm{U:ӡފشL}( ](2%̍]NH:>YF"?h'3d_}QR%jONk m{D(anY!w_ZJ.1V7FFso3騍p'=:.M -go= [v tejIU/j1hgM35,suYK8;]MtD1uh"O+Zl[${&_^{oɞJ<Kak+Z;?0bFs:kCSa\($B" l+gM.;wSKf8JXq,LB)UrqX>!Md!;֋(bO=xLtg;jr2V0k53ݍo>^qYzOjh:Neу%"͞_.L\qb ? u>j?]U!鄄Bҝɓ[f=sպO&sXSҚ~wQ~e9GMz׃=`(P»bmVOI7T^?Ծ>UỲ#6!|w 2sWK:ax}Υ)zc [5zcLLn<6% Z0L߰YM_{Yܝ4<ׯ7[fh3vvXe< A#E32! zȰJ6jȂVz6r76ka jo?y͍V7׊٘eRy굩!4xOpv0e<ǥ,O_!-Q]'DOhg/kb_,8Y+ Oٗ.zru@Dm:E#mC%X)aC.ZRhg#`_TҪ6[G=)!zk\l>\y9yy:/ c#Oq7&n*@RU==bhc̎cy>3mUi>Y?E {:Ax8{ٶ}APL/@n}Gdi[`6Moa`{mM2 "LȔ|>xcIm0A;qGc&&GG_o/Fl{+͑>b?9C-᯾fgo_h9ͥ4]3qǪahaRȒ2B;K>n`ك T}z厰Q]reIFC L O¸6b._(#ω >kǡ[h%`_W/fqQY|>™Ozzjq蟇6Ry}Zsϟ5.|={uvYHSucz脥zQhu09{{{ӍL~y1K KgrQ*10uSyBhaMGkeqp.<+I:.*jA:{hJ VJ rX[1<-ˉa;uOv7寽8Ƴf.@ G*\O߿d ; cjLTb3tm gZw^VwΝ0<,hcBdǾ)ѓPBG WcdN}b11"(U#9%kǫN#RavzoXSf_諆Tfc '*-1b `Zio^ޜ<]w_a9MtUF 'Zs5QEx^8nBT]WXOVI^X=}亓v}%qbB9*zn/n8Qo%^yyQŰމt3ʈ,kIi\xeZ$L dS9YxNp^I6Ds, V.p \q2=7P |_7>a{!@6> Ck_m =Aff EP*ijc&2{mj鈭r9bZ_}.WSW.=_p`e͞o mfB/MUðȢh*B^TVbLdA4,Lۗv/rti|%nᶎZ:n>P P Kk|d\j;׳}ྤbτ0NFLMl߿p9-9Y/2[ 3q霪aX:"rFfz?l+ӎލ[y,~ku8`p$@'#b=^u&,-a.>џL{z%z{&/_u3"n,nqL:ͭ# 'Jugb"L==amw|peVbvLUPt}ʰA7j Wpny7ia2 63}rTР,-;-,9͊|:ze,ۅ3:B&u%7f~\tGO2ށRhx?WY75=|)^n̊J4t\,𯰻N cZ6!sg8?t$p}0MOƷIq,"bIӥc8i~ 82*߯ٷrH?0/}P+ 0]KT[2PŠdOGp_biA-ǃp5~,onvz -=NTb`L"Tve~޺x~:s=1WmI8׉ձ} v.>DH~xt'̈́<=Xf^P5{԰*Ip}e{,N1%rkN#271)}3Ty$7X-׺Tw:w c~N9ּm5O_Hs7&VM8\@Ti:nȰN19S14Jyِ4Mf뗼Lږ06N(H-3٣}XO˱ &сaD~˹G˭Ov-'gOʿߐLض(lSD4@q0®ɽ،SGN\l'<,NLQN5_nA*v\fڦ&etD CX3qEM™jvqGm@1~Gk n$a('1qF2VZ5|IK >ϳUs~Aエ`*0(AȭUb1;BWZw%Tw3|CIzG( =/p\ņ{NRi-V8?3Q+$Sy.J~Tw~vwgn"5!j+ mwdʩ(L儿%qvהPb¤gJWo/YY vv[zsҥq? [m\ψQB۱KiS7-nY:F\5L;@]t 81c,_ {b7|2FU,P_96kr'L?Woֲuދ/ow| eqҀC|Hra{W~ArtÖ7}[ Yĕ> "<'HB|nOCMfSdt4k~\}5QvЭuFtb)rnTBWv2p'|F&kK A]n"Gx="p[oM}w`{^48)Bʮ&ݗnWGXIg[ɌYn !ȶ/K:PA{A{1#~;K=r6m+^''c%sİ&ElͿoM٣@ Cj9(`@0aP:w_?OW`zg{_|>Eчg@&g@<>PnKjt# 7l2۟8N\M>WS"SBl/_Uw^_=p+_͎_|bl\S'%E,+9q!}V?{{|g&=I4~?T_~͠ vk@[Ui4 떽QEV=LSL}a2v^e:Ɣz%W;ʳXT`:TagQu 8\gupID06 Ct>uVru4{bm^O"=E ^l_Mi b?nr&Hb*":C MW%(b'tԙ>٬4 hl0ˎ6{#ɶ1hQp7=Qo㊩$'!c޽.-ˍ:%VDIjGNk#o̕n/Xaho7 8b8ʒ]h8-( &9xS$ 6%#sX!YQx_bg7.ȯ}yJ`n\ةG[8v=B8yݎ&ԃpR˻<~,!̿?ܯ[Ȓ2#itb@`Zn 9eb:C&Vl2mD$wc cz>z*ꞕU57ŤWh&LK"DM0Tm>5'؍ZE* BMǔo5}Y'l27'Ts>=)UGJփr֑BM3,Ș`75BOa;&ͩݏlYVL;.}_w1,N}dZox۪z%/ҙb|~ 8H*6KMU+QjtL0MBQ~\5+60KB,2e&2qwpdYܮʭ~$6sc<?Yio/t8n^QQn{z'\/뻁nL"74c(jYW;883)vbd<;O6۽&@buOtł>=؏o 7=59_B*MB : ȘM%*f\] zxTjQrmqqxksDV=ILFg?y~arrJxOlqЧq}#J _"糸"b6 :3d/_喷{sӷv_^}㛇?ӝF=Oe%jycNw6L%Cv_L4iv'GdHh\n ڟ}tBv9`c e|p~~FY]GgՁqrgGQ}L%/Nh=]](ӳ p|%Cjb}7(5`07g0 1\OEzV~5iLS0G$_x Rbqm#O{tiu& -j4[A`U tc۵Ẁi!(QwL~a%85IsA߹niݓ`ZM8Na-rB#Q~pe(١DyQ|b}szK1SnX#i`t ֜:˱ 8rDeK^Ůuu #+p+WwY|YY/)A=5q[BQE5ɏ'Q>9Y`|bM&s~STw߹IEHGS)_cZvlnUBp8ݚ=Rݨwr$42Hʿw]7 ”qwT7/^x`аA @Wل򗟭{#'ɴEIx"^p?fVطUeI㄄a{m0\@x> =/BD /B+A<,h'N#YK~FsJ4D5R*ݹI954a;0<:`?@~`ޘ^^^<1j0K]Km>EXt]CrҎK)#A\"њ5g=tdpr v`$)&QTv﯐+tÄQ5R .}KҪ Ypx!Pv@$x!E3IP_{+l'5{$*}rxj1?}R}֍if"F?z]5kUP¤8SVS`L= d~gB8ȏ1\, A٭ >-UڇK'+VKdMEbm`$0!ucI5EFC8qq w;':4m2& 7b\Rk~K:[lOJ%O}5SQ,Ag#=jեaѫEWu zQBP8B8kx "9bߨ᱃DD^*"#NrDK)!5![f޸ gmڢڎ3YL=:U%pe{Jw欧C,vr2@5X.1+n#~=)4+eAf1%)^ W4w-#h# dd%Nd>(w_۽ c"ck.8ȷ.\ȯ\O8^p` Z\iF6m'w|$ y7}+Ňehyiow؟-;+-t0:0h$ᅔþCa@8Hn5hڪjfTO3poY[ٱ)>auQĝJNcY6vCD"_8zTS8,\"` &xZzY9=+}v_F?QT~Ϟuo8Qk (e@0=/F>"939}ua~J=+o9oM/aH9>g:poE,Ng;lV{(aȍ XZ1|O9n^n/(C_wcS mՆcC:,$JPG0əIƷ^- w_&wћ-#dN0(j9g¥)/&z,IWȒųCec'.wsA (^>biۄfF3SHoA07=THx7z9sŘ O9';\yg<0aKN;@`9m8=]xoՂMR+>:vt\qGiǃY5m7&>Jgn3'N5at56[4Z~ti00)r$fyJ*ct [~"LTor#<:7S'үPz "JQ#?d %r{gY^pg %hR IFoty W$bG4*E^̐s\ rP=MPN}*/厠l=,?{d-X 6 $]SM(mCY) XU:#v.@|Ƽw$ p!ɶ7*BMb Օa; =}vcIڵ[y{ dc/wwjλcẻ.i9O6F>VE qJMԳr+qT:*_V=q17[k}dc[EuV|}aۈn[zs.OsI^+%H1 :ƙDR^E{K1g6b{b\޽\߬A1:碙e9nCze+[{⪳=P -s5tǗ:C.*rW&?BTj"!3vChN 5lMe̿4a|AUY;+ϞY]) ̟=Exn]"npAL&˪A9|:Qp*8k+@zFqebM3ޭ\B=DM* ,l;ݵrjH̍o,te!x66?5'?p<&MÚ4F᪵6jIUpaH|qW37ڐجCGBSxcGOϟ|?|Ynw6VLدdˁAU<%mpe܋-#֍^ݰ.Ol;sOsLi-8mݵӌ9b9XN:Bo <︇t&- r6^-B"X܀zvH%g+TTf?~]w7n'Cq&B<bجB NZ}ʷB39Uaꚁ o\'r5U,\ZUZN{k$ݫJ*JnhEO_ %]Bp`v.oU-U[ QRc覩osg*KKp9e8陬uZWbxVG#AnK;ZENLt m^(*i6f!T/JڅuۗsBVLZ zZ D] lϗE4Yڪw"?ligd"OsH~@&϶UMX(ms\9qËuʩ?$AM%c<'p뷢yÇ|ڸ>{(]*r ̉6l mj>ۉJӵ!*b*c%p93i}ggnrximdb RB J*p5PGקGkft&n̙۔"/uh޻&:d :+\L?((6RD6W$mHM-|#gCCMUCaJe"xi\c razzλct)OqTS:=gBQg1P% ){ENH[}T8G 29ӕb\2Qdmy)FekmַߞFyaHxliٚ&#&H㇒$"EY7mwA)5WW=?ܽk_]nNѹ@Y_Sb%wĽ~rg"ԳQnT X;f#q>(/q"PFD&Y:nH;fdise]'Bbx3Iuu4N;("g~dkP1Ter}4W$IN+̱|lg3d>^mU)ĽZ矶n-LJc2JCe@KC5i,Lʗٳt)a~qd Bn}J%Uzywܞ&<\5P[ɭ;ib݈ >ʅQR 'T|ؘa@cjnBJPs{ƻ(QdQũiYRnzb^Ҋ*,.Uf>,7b_93W/n6a02B[zNm4n'k$A?8 уM`ٱ'\' à ^[FIǰ"J2 daJ0`&c)7<f2XR'eJL~v<˯m?Xk& yxPѴGNJbǻ2A%+wu_2c;wR"?Ή##Ŷ凌? [f:g < 0C~@^PI_̍QMZ]r~rh.a==|b<^qJXD Lqs &^W(5{2pTE] cAD6kƉ! s LJxLrQte+zTA+s*O{d&:?Yv6*a[?XscDCJЩgQiR#-,[.ୟSS єћh&1.׌ٲnؗn"m6ȩS[Bp_5S9@!MppcC0y^̙B &Fr}I ~_RjeE6׻O?y$IE=bRk!E85?tmd*7cImS7喞Nظ:? M|쎩pcǣ/ۃi`!c?Dqň+0A[XizUmw?ɿW;kK 8Ƃ ?3 >xL+t0^q3`Q@%b# !A0C%Vm$yfE0jX'Ƌ!U^|F.ZXv]OǫݚƃmP]wƭ!ÎOa~BLj:P8:Q{m}]Wʄop.MqjU1^/6LRZ\b'#{NF( @5K:ۯj y`ͨ*vtfؒʰL@ wh]g)qva*3;d0s;c5itdZgA/Mbr 5fnUfLf`TsӗS裦94F}"ӏಏH+yo49D0>Lu(0ؑa9#\bq7W#:~*"077zV?_%Ddpv@jcs}Xù[s,%831ڏ0`G b*L kVCӹJi˕_yr]_T ѝJ/{Sd65ՖQo*'޸(Cc@6N8W^//®A,SY!a@~@O ͯN~3Msi7b@p慽Zkjn:O崸"R@0n{n7˻ZE% E焽G ?V?}j}mޝ¸72]{3YF@!5a<`4šc4ܘ.pZ+J 48ݢ1mTq6 &ewcs=@[ + _r;5'g>n!1˥ aڞ PS}5U9zŮ)FD,n>|_T^UM4:lWX1)݌fvt塷7py:s2X' #x w/+_8=\ܭ4:c$'(6 7kՖ=M)wq\Ĩ*pL۾ WRh">Wj[=r}(S@zLSwX!j2P<ǚgMV]nKSzxOE qq*^s'L40r".Rm1ӡ$fӘzd9:?{ɶ*숼G]shDUi^29rC/)YaHcj|cք,ʸ 6&sGQܧO| ^B,YiC UE'L^='rwD5KDtl2:<?9OKf}uY<Ӭl"I@DTNv.2n7yq\D5a"7(dQ3t<&P2Q!vێɝqx`6v0wS9g'"NO({Pxv;rA~QX hZvw)6߸erչ?Uبt`,7^3'.N7 txNG0͑%}f\n#m0w V1^/0vbRe#um9,tvƒV߮kr0!StD 2tYH֖ٱjY{H55܈cyO \߭.ϧȴŘ>g|7.(kb [ޥ6w}ʊA$`7@;]}UCJTN$LgL6ɼYL9r;009CP8rZW&|.?[7kgϬm%AO T?' CݤFJ1߼'nUzq&n3,흠{QA ًz^(imlīS>~`@ c0޽*}rjNmj$w`!,b9v>u&)#; wVU j$3OaH<ݮO%׶]nNfPv]Jy!3@HZ-UC+%y*t2Jo~uTCw.9%,J$>9$mXi,Nc*]k8jF#JBD{ d$8c(@ŸR vb3*RzjШӴc^ܺ_}8M~8͓ţ86XْdaqW:Vew=@ F F.\1vkK.\htի_=Z^-CG73o>V/2n(w?~wOҏ?kSJl`5 ) )M@ m 5ŋMruX0 Zz(0&7UE#4Hũ`:a.5r=tFrMERe8>a QU/L>Zcj2ii5ɋo~7 bQAQG$g i}n|809;teR2\ wM ybg7e^Pȴ B/0PEj.tРRN]2G VEsΥbAH"ΈR )_EafXufZ{rF0 B:$ :bG)h#!Ye@eL'C`:*56jxqBi( Պi0r19 7]X %_I #(>w7 a@DvdRJ0HWjW۞|jtZι칢FI_Nו¨7U1+&ctٕC@Po6^ Ti / NQ㋺Lf.(ZD¨dl0&ܿa=^3bjtk",8 1_I@*&7!@N%狝Υo|k UVϜr$ȎcBUZX9Jp}E- /x&?ZǴGN>i;Cm&խO\}twc+Wf9Kcصi)q]CeYOL\$dr(4Eowk.ppqZ2TG@ hqlH! |ԎȢtCQkR>c4,OXAX>YiZ6i}J L xd$ $!8S8v/@^#Îp60oZ'RI 3/׹cؚ$.sHRh4OS$$tElT "|MH.HB6r=_%I r9hK; JjDHWYO!aHN^,S-".bsl k2$(M$rI<3cV>1Ta z…Z>YB'1@ވ;H92Hz4kc("(G z}2b{Ȇ@|Y~t0 1$xm*nˤT۶%QI'Rzfo4bFB_ȩ`ٝڱ&bIрws#Q~k"OQ;Lb0ZN$/gg,/,[ZxرIijJ2m7ΦI;XNM!15<,aHtcm8Ukd7C?~ '7ڕ&RY|t0Q283&^( D.D1ØJ˭x"JɌVIh姖g'r KS8GyH%8R5.F(LB4Oꜚ&<ΥybL UǽE.;T?XH*F~uϽ\t-x2ʸPn ls kƔ j p| 82I"9ZinN 6i#7? ]e km۶`JBtq|VtRĭOJ[4BH:m30D[st{nd%XDZw$QZNqNn>qxE3 6]G2mϧIHo<B&pIm>YuQ冲DWՅ\_|fx69;@Z ,"hkl= '$,]|q"8I˹̭~t0\11]I!UxVXLvhX~S2VγrL2@1# (ʕFPNX{^n!qs$/l&`4PQK'7%y /1a ~OJͺ7anH0=3' (S$ͺ0qE[˟NM|pf{!W"vs.@e(Ol?f,&dk9! eSkV7|׻[+-b+wyzΚLItNCw@G<IDATCr cTvkW.$[}R5MGjBW({sf?Z>z އpe(MjBd5 ?3 7'OtUq,aGZT#E2.A/ Bs:3~3~\(4Y8HUĸ >'KXGi /<\<}Y괄zsŤWʮ",X4owˎIu,Q>c2 hH(%Ty{Na3 4ltD&|71*aBA~?^Q0m74TǫE hm|Rs9'&6CWȷcvCY&8!ܟhEoEARdUUtYVYml br)ORPH!OQq`YĖԻ1 bKma}a5ǟoVr_ZJ'4pz"'Pq{9 BdXWlgFϝ#%ʙD{z'K3×'@e-os)rkvq]Tna4eq2ݮ7 n8.6=0mnM,GnD<4:8*D 4Oi g;7Koo!xR_-/_!hQ 6 mt$/ Cy>OH&A4;"]Qh0խ6ݛa+-t#cP^{7rs ɉ@:\3GGc,/̐6]sfdJjv!qѥIz_f7 nvOi';[+ރ`\؟tBJMqaU?3H{Tw {9϶2ԷL=0T!KITM;5`zԘu,/)BX+SƝytdҐ]J?z!\kV{n@6x 8xWhU .WRq`OW(pýf xw xQ?+ x1Rɾtmjq-cq]sޱR, L̔w n)T/kPB">XۍcڻJB PmѓNHS DƟ7J7a|>bj"߈Uipv;-JcZtN[](к3?`^h eKW\+Q"T~zOP-rs 9߿D0teO R=w B" 2N7Ldj2t\Ry_Q -2e+\Y2.GүUGj]Ae}E.VǫaLx Nv].˒G2K@{VN&MLdQ偎ǍCwF} l$K"<~amqr=փ;+IYjx)dpіIea(K>5*}Aɡ\IzOMnPv!a:e}yve޻h0ed6chc-26nN7mO#jg0Ye?dRDJZp=[DpMzx(!7q^rd\uӦ3u~3V;pds훶cJ`p1Imv,t őKC@wןiI!{i\2Hj7SSӑH>F݊,ϟdtV=p6a d'kݡ}"G>UQ/?i-k6yH(Yi55>&GAm[<@p|I6!JC=@"qzc U Y&v0I%M9!SF.#d.!_mm9kY_^X=Pm3ZXP89Yb==6)W] ?MWfbC_x]گQzeL\֤ Po;5u!Q7p۷X&YEbA\)D>;^\X/M%,Itlq>^ i24y}E-a)m C+#5~>{g'Gc,vB ֫Rɲ5PHr1`ߪn]B4!C&fVjRKCRL!U g 7rӘ_$BB*ꀰR"&mukg&Hwul gr!C畖PEt%!(4ս@T>qS^1s۔` 8¥'񹡪*f>z:ⅉ=.WÄa8 HmM5(I+ag"~_1%\2kNy|͏uӧtJX&ePi_gW$)'Mvb0z G%o~;tv=F4E(L<>Kj8`Mf{. G"07Dl{"0x8ߛˡ;n,ܸ*o̯yvnm+/~%ߌU&]0f[)g6Le$lADBzXKUD[U3)5 DiRvC}|p8k zo1I0Kh{8"SރFLez@!uG@x-ZH)@(!|jgj(F>v(9umbˠؚGL oHoOXWBŘ(ϗ:Ǟ}4/wbkj261Th4ul ̣Ņ 21ǫg#fWn??)c1MNg.ս{JMA=I"Af\t p澃,l[ E ڲl^)dsC/;f'a64]FA: @s9XIԻAd.>Sf +#Y [ƻ @#;y uuKS“'"m(&K/õSೢncVzh:Nn!d;ضp顮.]'jG8'o\&n?/mZUtAQuU `9 w CDb%c> K-3x=4D}ũ>?2m~ji)u>LECaט5,U1ƽK/W?x{ *( t-` yHzgQPvWтQ E97 9xxO%;3,f:9 sJ;Q$_(\^1Bأz|op35)C c lo|_L|`˂4ۜ%ke5 taY `\f!x 'FhtJ;&>K\H< nVX\/5 X9_GĨ1Ec\J臷)6(g:M]{_K/_ʞ0XLp/(]ecBB:Oڶf+o"㵅J&S&L\wXbz1Tf̨uVk]ܔ~su>Z |,*eDֱB!AM!f8e+J%-éX$e&KJFӺj8vR;G8gڍ4}u]RiUuq/LB:{% qt Wd :6;ՎjD)Q$#/qq.}C c]ula $5'hRֶ|xPɧPLl+h"~5T`d1tZ&Rd2.Gk0)F[j gŹ  %AL-t1,G dgOt/~!:bGN'Kk3cONœ募_%|30ߖ st3鎶m p܍ee@PޢW Z4EF6`!E?oMj3`1I&/Du0AiS:}qZJ.y!׻G*0D!E'ِSW8`7c[ڥt\w1 ضߨ&/NF2Sv=S1T$2hs]fkxۖoG"aۦTBpiؖZP`~O7eفd(c^itRC)#̥$\n'Pt23fo/z7d(-Nea62*"H{y~]vS>:%#O*f/ϼ}#?}̙dL;169c"~eX*ه2G&re6q{7RַԞXf\G' ?D%G)Mo&誼Z#Wob/>k%"'҄?'H:"CE w, Ḛ4F|X, 8xO @89s<}S ũvsM344~sfvd땗޹~qNP13< =r@6ehrQfmJH?2ؑ/\SFJQ6,a|tc=!jr)7qx~ނTתBG2旛I?ض;{q<:3D[D)J< J%)Kk- W;8 Øu  !`o.lw7&z7:_7S &}GS1#ώ}Yg B<~l}oB} |&z@ `HѯmK\&Ѽ\bɣkdFZ4 B/ ހe6yΗt%JI\I+8N($S}aƞ/I Ϗ:q mUfu,}@hAlîlm}>D>N$ %QKccwoYyJ}ڙt!aĬ4 aZy6f9uRKw|a(m" gVw}%M׃}Tahc$ Дx5ICU:4԰lRF7O@Z6ZH-vǹ*pݿUWkiWw.VL3- b V?[ /=qJV^sSCr!;}p(Y8(kE[瞖NRwـL +É4zMpa 7 OFQq:R "JH&!Fz"vOW%|X& *1  )JeG6 6_LMΖ~f,5K}c}ԥ4\Z[܃O? `$$pk۲㋣NdN4-M} }bt(/W8cT0)kLv$e{ZHfl'HX:^ٕM.ivųs+Ficx\EZO-b-F)ĥ7 Ozq',x0Ϸ5-{֩@x@IC%*X=gM4];/gSr7N%MV `,3*鳩a]M:2?Rb,FZ2dRTBjدkB5b{( t ]93x)u  X@NTnqCڇ^WBI~!դ N:l@Xc^):,8VlK v/ `(>ri۫Po~hvc㚎G fOk՘ʋ@@]ď6%"yo/!!fՖ704XnXFK{zrVPiJ@/\UNW0> lwiYaR>9`.ZW`HTE) Sd^jo;euo$<#,\H39fvDUZOlWvۆZGUۤ5 K]HZ)b@XGD2)BZ_ rjy* &>\OWj[lNF~ߦ>9;`>Z 7(P4ڭscצ:dTH\Ćo~꺞g>Zx1ΌV\5%Z'`@˷@aUCGeZ١uEE|ҶR wrjcMbxbJicӧrڟh2I=Ym|j7q$I"\YDYKxm!c;nHeIGSg&r7a$g6e  B "fm#yVm+]C+SaȒp~u-O*WD~mY҅4)Vȥqq]Xn %Tf?ZvSXkXgr 8لk_R:ZŴFgxfiyedZ 3mhU;8 pcJh fJS"7߿'[3\yL@fky.ʕJJX1HCB4ucDB, P&mY!Ύ$kr fu$Psd;*D꽣CtfD_O?wWO"ٺh~%';Nzs륹vۜ vU'ZGB&!&D!,ץ?xyo=1z9!ǘʅs2Ǜ!c9(Pq'h0çnmkUm]x^ÁI1rf遌 "襋BF'oXz0?hgOKm XB MrBLTE0vFJ 2肄0.h7)c/[g]ү?r`~Q80"#!du=ˣڗ/iY/6`פ=G g\)@! ܆L1 k-陔ƞ4ǺKA6oB[rlVVSDZL_./M o%dY3}W+ck9S?IT ]}` 8qt\Y,Q]$`%|iԖDcpa ǔ( I:~OK_ZKNz)1;[/'n< kM[VTCxXoݥrt]٨C_u2C!E09cy$@-HN(Ӿ0N4Ug~zd(jխΌ?;՝n&Cp4:Ԅ jvPb*!b,#0Xj!mkJk d- 7 dQzV(MZ~, zY! # qȓA ),tv:0[^z1+|^O(Ƞ8CQ2B6[Oe2Zۻv׍ Hu"䥲bs}tHNqX|4=gyv9-XKc݉ӻxWk83r2+7 PNΧ>57ϙ`yr@$Q@Hj%f:3#u \3xB :vKc!=fm¯~1]kՏ\3. '0|Czr1:8b{l7el?TNbWI2;ͭB SZz]kAX!>}`fjJP[LY |rgؕ>.tGkvW_IhaZ[XыL~ Dv=#iW/@ ej%?O;7m<|05{OW ~*-2G+Ft 8;eQ!YQJ*j]2ͧ08LùxqA@fKJjaB_I|ܨ6;/a۔djeWkl`k?Q0Grwj3=и*V!⇄鄺חox"=p$"Jާ&!e S;AKlƨi;1͏kWO{X00=Afu\ba0tK% zk7.h2N~H pnsL+NL2NGHD1yՙp^{Rom,ΌZ--'umǦ_nd&b,a!/1UveG]-wPbٳv̊C|fr ԙm MV[Y(ITWo<W}o%zuO#AUQ<5P\?D7b ,{&bW/ID}39lmઇm7:|q]f#'5Ƶ [y,6\o<NԍktӇ#IDF:<xu),ccwbb` CVd\.Wn6̗Fs]If5EKǟ~KH!b騊~Vo[*Q:.t%ŦP"x/I(iQ#dJc~#~~Ԟ٦~)bلW枮T'j]2m !%DBOa9ԺqGihq5LWrE蔡z'QX6 p" &$ݩh{PL~>\ieh>TBʂj AS#Puar[X§un(x1re:UH?Z'GG09>1i8UȎRR3d}*ƨ5}{J_e%'JIIJAݞB&G|=hV_Hg D0nd @:.7:]B2\lD7klĢ,N:B'0)Qg&,~92XeD*\|(, }נ8x`9Մ(OZ2꽅yZLUuPSrjDAa\lӹXC$ʎ#XX _>}H#Bm YlEa/V$%wH9$J2BJ퐥) fZ;m/Vi}DHr`7Kf/;eJ4n`E8\ gmֳyhH3_oimkeB:4>RmJ^?m||vqr˘2((=xu]6 ^ܘJ?ݐy 4ٳO66U+um(&"镉i0[^9 Qqc&+9L-K^.k#]\KAr#FM۬w ?h/<4.C/,uK Bנ$AFh]xs0iϗ;'_BT54+ |٧_K(wuiRdڿX( ?kA6?cPp `itjTF+é9P8n͛G_3+@<%V_qÔжCP1A\?dicRu~Y=a0S?bh_^dP$gP > e~@)L~s}2ĵp,I}ঝ[+{ >Vh3ADʍ$}^/#9Qwb0M&~rQky GwR.GWZ@V+q]F 9)#L휱ۀ"(IQ<"Kr9 8sC'д cX0>{yJȿuyag UE%ɪ9D?qX}h@0ȸ&E#{j%t/5ɃeKM ?;9ldVD:⠲`?bcf鑣Z;.JhI`9]R=`!- W- }|]ZӚ|1.|#v|"1dM_T(onLJd2N\۟qpVV E1>J@G8_4v51'rr0xIq 1 y͍fӚNc}Rq>ULg݈ qwcx6Zy* KT\IA>j qM*w__٧7ZϜ;7;(/ _ܝo=8jƂ8v |"83B:=^SC~{aǬ\OT?Sr#|5n-g6WO^zL02(Mk52LTQv)H:^pOh (JCF6ξxwC-4d /b,V?c6$nL/Ē1ߴဳݭ9H>cP~{xmJX>U-ERiu? U%#!r|D  F1룃:v0ٯ:/TpyJoݨw,t@M06zݾ:2٭xA&ZwE;U%g8YǖM)e" lyP}d2XW·oU^9gh:Ip XB"gI>/K?YP[D_4G .DqHYl+VgqxOèiV,r0f ]ȖR'cJNcy !yvR$v:n -shSO}2꩗WCRrmXj|-|1)3cE C%! έ,}[n+tըLRyBl'Vo%e{Fۯ#/^]?54 =ww޺Qٴ]'~l[k.SJCPnB>Yw}Ɠ-S6 ~dbݴ7vkiP. (jv1,/uI2V[m+>z;$I#>l7=f7]zMJMX7$ۮ"I*<^<ȢcmX/eKOnXޝGov+[ 4`[Y< V @x`ejmsDNbBhlhL%%~Jh`4E. {Zў02Cjqci*CNlfhc rX툪 ңU&vpvA08;r(Cz,j@M ^M-_j*$~o2S EY#޻SkuZC5O\\a\N 2UrsF)w@R0\"g,)$q돬G+Ⓝ'MҖ9Sk\6O7VK=fʼn@6[J;۱qCs:V<ODž5 4ޫWYBQ>1C$TX_zavTrj\Fe: !t$.N#zCFhGf B.l(&BipjJ_̯W:XчKa^{_hJH S/OeӉ\|vP4M5:桱 ]Kz~r^b{H+ MamS!;Bju7ڇB+^4u73Qmϗ:,xO521 f޺ܬ1Ƙ{mʕD>HsI0)r0tK/7셩WYoh.n8]Np\R‘ TLosd|\Oruz0$2Fj?gD+MZE~  $3#J! 15Z"\.-7n?i :~(H/\Svyl} e')`!K ;҅$цQHjsk!)v&͘",0>_$ߍ O>XµL?{9wvL>̬hk3pi qֺGGra4W,; [5]6M 6A;At(BX%ahtvt&1]%7)SMxJl0c,وRe$?YD|)}w޹?]%Ɯ<912x-sHH<>SC⦻^+v9yYKjCtbt ҥSCO>5;~pK 湙ֳԠ+e\mB)`8'CYHt&Cݦ"1 w>/L1DrR?|AA_ݖpxaok)3ʴ|L~OB%Hvd:@hH5DzU>[f^i_mxGv?xcr͏;_z&Oufq͝U˝'.)F}:BSM 0䜋QjBcmP8r}JE)p.>Z i>jA!=+Uϯu,Jd<>54BGH$|>~k ,vTpϥ&6_.SA+̭u^s 2 i, 'qe^Ȯo߲ߺ|lv9b DP~Ie~tz ֊j nK?XV_VP/{D;d֕5mgb YO='ҽ(äKe\b"X"Dԍs w>ZF ӇGW2m\>"qq`Nҥ;ܬmTp>iB-sSekdvD 7<4У_w}K\j+?;Y"3tgKVnncvUJs8ύ+-R=tuzF79PP @(%6u%x>w-/_SSL\?Q"_N;\R4~>3yY! RSKڗJ#`"vk_/$QTqmQƇv ܝp6nO\>):BH$cٰR=O|jrR3i(Wdcpj"TELk,k3JLz(iRmf}W;Hݔ狦U_QYN.(v9sfO:v׫afE P<ٱpN7+pMř8&qC~vEeh'cMHK7UJ6!ΎwSZ&D!$g9(훭Z;`b\,mt( "x<)݁94W8d81ĩV\Ξ9da/N(ue+&ˏWߺ&5-(5.{1 ̣r.lcvɇA0"#:)hFgk%(1\SpOhJ(Gժ4Őb!1MbLv$Y "D.$ \H!tS{$2UYZ(%l+֓|0&J;P\q1Eցs$ 躊:EG8g* `cCW7-O|m =dFݒj4t}5E.1c:"3o8z5ܨ}xr |2{=(ն'8!Jiȹ11E^P߻Sv9MYCG eGhq\bY%Ǯ6h QJ]'NW3&Hֱ!Ҙwom.mZ+сL +qE9 pfT B|w,ggݿS{m$$.OB|# ]mb؛PeϽߺm.{t4:p/<^?Y<Rvcء~r027YS 9V6[` ֲV\2vDݖ*q.֌kRI0I ,PMȁf;G"!&MPÒIj xH:QL8_9FP=p uL=05,d(E7:S*WfwVNJ3s7 |fI&:~yW{\eL(Bʱ900j aJ"(E4 3Vq,wJ3ç0+2 m" C7׻+杮5>TOvzv^lEo=\`d<:88:J"ns kUN}gǫލ'O.Vbe(?Phcl/oW#šD:)j:;S ^d3ڑ b"PVaeɡKj^~jufw Ŗ\=ID06` fs߻Vx@yBBk!5qϜɎsݹ奵RrΝ 9mk[.ш*Lv!썫R6) r HΌșm-x~@+(sͷn3q*o@Wgt|Y {)"D BXp84hEPw ~Lq=w~S(cΎ=tT9OtL@G:vm5yᎦm[殚 Ӣ)J^S"`~'ޏ?EڭkrB?v~@CSѻsTJdP"R]ӏWc4EV]q} =u jֻAzyi,ovfFYǔI/?[}Ԛ7?pq't9! e7^JǫO;-VgXr0mo*$ER.:sr1UZ qQ4t2`aلFpV:"TNߖ1t~20ا7g|]!ϜIArTqdp\ֶ"t4M d!'HBXV/!|ú5}1HvL eb͚D 80*5f/VؿŶl cgRj/EcrPGA5q˺rZFVpo,m9_5듓3j"SPV~nbdyP׃zݬ4*y/ymJ7gfGo~;³FGs͊lB~fvرfrŴ`9j-?5RSc&]ve*Y.*ݨjIAe8/Śc+ӱut싓ßPgRE||?YpV:,WO j4beȦG,W'X`,x$fL0}nfC9{aerRm'4go?m?k~1dHr +2jЫ)8`pacQR\??:_OɿL$kf޻]?߮4v\<N;8Z2 ׳潏)uDQ ?J.\\|yvIu"rKăo~wnY'S\Fd4;29;Ri5WϷ[杇w̵cT6.VC sٲE%Ό*y!&inApPk-״ zg(RP>S\(1~RHyݣorN͕r >Sv H\*uAs~Gjv;^L5DUJmhCuKS"Io$(LȔPws8SX?M0t&҆EV >tz(JYAJ@BC&A0bڌD*/"/ҡ;YɢҘ_w͎tܡ XRX"DY'|Xq1XlW/0}R?Xl#C,(_~+Vc]Ó~:i?WoB}N2H$Q7&o~T|ޓ39s'] 0OL ?|OX'!PM\f/"z|lrHJ<]zY];wvh6+I( gr8e\Ip!]n'Č7ah1QXx!o$Spr멿IC0~G0'Ъ?d1(&cޥ1{iShuCשj>Mr/TAVMMLY8tBv!8&ݑ |$ryMQ R\a>؈Fי:QS3Rk(8fnMVkNU9;PexʫWRH"s0Q"r:|$x;3Ⱥn31Nw%& th/;<2#V: `{ xofZ(Ҥ˳ܙ<*>c'ƅEШiד=#q\˿Nt"ti(~Ik|nZSWQݺ"14u\;U1߽UM<.^jOnn]Y/o&a.G b1۪ PLf[wŊu̠stN8ʴ>~ub->5SWf&Ƌ[@tѨ;T܍6Ol ar(U=]4E 8` 7{ ;;iu}\!m/y]Z}L~<ꀜ0l.?Z_-~s3wnٟj!"aGO H8kBY^+c$ypgκ57|Kkˊ$\Z!R`:}whj$;#@t?(yAO*Wgĉfa$XB凔D"S;ޫޝ[+_g{#jmQh-rt}TsdXpf$gF"K]F$xBk:- rVYR⽛(mLn$yGM>5*Y:EpwWebәЕ~)ʘh9ଔ 7 cGM\^Qwg~ݥ͚Y^١Kf]MYZO?+=]umMUը4Bv|_2qM0F@0Hp"~J-w }nGȕi}rP}vmoL>hP#*nu 7l̗zK|yQ؝͚5Lo|K gnikv97;i]-Vmnu pH~GS _\zzbn'"N|F6ۨэڮh,`t :32iMaLN~h0b\x#M0!RThz[N!/Dvȷy5yV} ECpYb' 9An` )R}،ao"E_GM}5{yB[0$Q>U阡," ʂ!o\gU@?t0Ӿ9xt]2Q8c'ji%1 ' _-5WwY\yӱmOg=*I~>h_Q߿e_=?=/3q +Q!%ːO~[ڻpD!6Y6jkE>Rʹ^-lz2Zd4pfzB)ESp<ȦͶBr|-e(ewuݭ{t8?X Ehf);dbqR9!(87g5v䤾3gxOW{^ǜ|L7TzN:8si]ܢ>8ϧUQ/N]1Ym:dR$eMcgfIѽX>OCPj/zO)?tkv?{m<O읦SzE4#MA󅱢O*)M įͦzӥ6}%Q vZH")MB{Lt?`v sqzGsCv:sƺa*$Iҭ\Hb!*w쪬$hD^9zbmkS{rB9+_u{FaO !U}jv8#~9EjjPO1Mwmcu.NPETAxB5QoOW;O:Q3czĜ_I&]tj#cK~dE3B6[̠GNYIJ $qy- elB#v #Ŝ6:|8q4gkdn Y?X-ֵD\?^j `r(K3yhk3dӏ(-$;&CDLbb۹t%mq,协=gh|n!ED1ݖlʨȅqwhR1'7ׯL~P} V^}ƅh2H,Фn#!Ss@u7(C=AnrOrFlS#$3L%u"7-܈۹~|P5$hur V*ta $Sŀkfj'"ʟZ;'ID_ɧ|T,R]cvXu@:Vzbyh70{. \$KK"IjFG[e7ۅ\(KKgZc?]LeSqCYl~4;?W{a&N\;jDZ@scۺ!93hi|X#IDdL(H6!&Y66t3K#\F>?DI:ݗ3瑟l"K?T*5+Ăn4nG??`skn&'Zet)c>hT"E:n>ukⳳct DMMk ~y̙/ՎrIҸSiҥZ9Dl a6P; %/M*I}}aSz 0Sm wAH]쨚K*ѶI䲱v䀘رwaÀRjnò^ j> Is#IȢx|^IFǮv"KÙMY.= 3i,0kqɁdMLVh/R~i ?^K&t:O @x Չ0ds{QE>U HA9?Cj69GMSԖmן`9~ͮ =o~>AGӃ?f'KQH @$V4XD~nė6zCݺ.сRL Yf& "$011y1 kăBODXՎroͺCM|dAE&NW~Ii2ݚ`> QzLB!]3Mһ^>m)ʘzeЪE)QA S)4Uh! pX&=^:vuR3l;=F) h_PT59ӇP}Fh|NTEYRÐ$E[P3'Hᑁ9Zt넸lAzM e?xK{/D:X+?r\'j pc :yv6Tx7;|tY1~g>YG?p6 I~X!ةSa&}sxYh7^]#P&s`>Tox,9I"kvn>)zO?}ҳń4tt\_b44mkwfB4Cd+d&$a,ZM1!۬nҶGrTduv]!Q 󛵮j;53*7!Jך78M.B%8 PHj DTE >D$35+b7FH B37"bhJHgS˘.KYɃY5%Bg%~['#)fbvp?m:-wWj)=۠hU?^,wB qۥ/,pA M% 6f1MEU"t\dLDh|v[,jG{OL,D=<D^K{&nf{gIk-;vĀel,˸!`M Cl¯LL]j=-x~%zbѴF'8o=Õv~D #D&I-!*lF#?"M e#ko=FvAtV ?y^ kU(nD`z$ĨV7Z _z1XB A[mA6e_?,a5)]"0E/Y!5igO]eё66+xJ?|OV9n Hb8fwxaGiEpaD0(Ř;$-(`,2X_WZC{ Xn&% ̨|s.P.7kf< Kr6x"B)m錩{ {>g$D 5`:(wHФo26֎kݡtBr.4ٔQa%D'<Rbdnb9iH $lBky>zK.:"帑zfxA2$ Cw46]Y,D+: DtU<IXOm(FJUhmK8?b U 0#&^ҖrLScyN1XC+LNN%uHLѷ}h8G~u#vwogp1}d5!?L^8C~yJ^|1R͏(PW"ز(CJX#^:g(#9xfZY*ӼԽ8][ߙǃ" `V!qmjZc>F[DDup8gB]>. W_JSL SXT&5!ijš>}ٝR H! 4@SQ ]u糧jB<gy"|~^WA{ҥA*&t1ĽTe^j5v 8wN1e(q]ӌv1-Pr䋙SyYBRH7o.f^@DphtZ /lbKpjs$ L cNBNi)"9ՃՋѥoa#9~e B5*'~_ovggs#}OBdqkpu2T_B<")uOYΎKwL?N/]Icu;첊h(tCiZ57W𡰨*^Z?T?oE|R@kzP)/^ꝂsÎx2mDap?nR.CKũ=5Wz꽹jj7p| rJTg $)yn.u@$,ȸLuS9eܸ$!t|isreYt#lc(!^%QbO NΗ^|఻_NRJP m^-;q!]dKV"&O 8[BK4Ъ1y˄ 6bB' BAt[GJS ~&_r`&5k0,̳K07?r3p7ƫM/VVlxF+'T<&.O'54v[3Ag)N6Mw!- C} vA S0<!b%8r|DNmǰ>ӘX Wt*x[T>|sk]Wyimye)F]sm#nuhb"u. OM2Y}ٰ'3L;C]wXõ3;}q.OлS`@ķ|[<`Vo,8`[BiRygDŽtk !\anfF`mmZmŖÊް鶴٨V(1ͫ埜dβ8zx8Kd.;x`(rx},g+,ap YfG$ޘׯΪa 'f!?Y/54Fp[e `e¸pl_p*@`p8HO]\>nLBhfJLxd{ZaX5[Z6Fhq$B#}.Miȳ1͗44 e61bH55@YC- V!^dbہyNHh[D_HݦE]O4=lJm[ZȖ)0 *4+c|Ɇ0+)Î=G,SW B)l~znBA,W ;[Y[r9mRNh$Aw*0iq;nAQ8&.br^«8]a3Xiq ˜vtt7]\`ntGȝ/.x8b̊7(mZu %p:!"Vfoĕ/|Ėee >ٺ2%5&M̐510BtGD>󆽻`E.e+#Xn9<B~3 0ܭaaR#,v&9/YR;\ \*,\Itqp+K8>qN2ްătUӟH#H7v|sZް*C[ QK <<ٍ6Q)pQ{6a]L.ϒD|1Zpc`KV_*`1VZ1@oԝ*f8?y0#t-No~__׿b]u|Om>L[#$K9rŴLðYw,bjh8桑@K+#UH0b!T(\_rpg-ٔaMaFU,ڿg&IƂ3Ff>XJKY*dIBX:ȃ0^qmj>WT;_J$ӠZD["[ҟt[zn$nΥg~35U2>GU$Pd<"&V4ӚYB{3x{_ "y )">{lcs%'\֧7Oڂ񋹫BJ_.2xdʳnt@c)\lFRtUXV!R#~%tC.+d6rt+zBJ0ubjZJ47/ 3KhXKs2 ۶0ǑxLO mE-]֩%8pv:)WlUb9L3q2݉}~ ʡEx9;jW3omZ};g΢O|ow0J-o&C{+ qKz=C[ʢf)Gz*=TZUjVP]Vu0'm~ˬib,)ܵsz /^xdkpEU ^_`yHdmU4] 0jf+GTk;þ/f*)m`pO?n$*&HWJ[RIoN=!7HHKbK*Bʪʯ (Jh1,\K.h]1El[ggW\өI0R*m6Օ* MR약cIȲlY,ajyuݖY82qu?ߩ͢!M0yP~4qm: )b9%oQ\5&}H[=Ůk yO[N=L8L 580$.dO_)%ry:o[d řjU bRB.(R]=yKggcJ=wE]HE-ДysBW(D)ᅌ4yvR +8b͓I+S9{>e%m]ް/f`׀(W",iE?Ș=L97u7ϭ f;e5gSvǨSy&.[sq٢Q(!љl$^lȄyMͲEM.YUIصVunOk\l&rm¹Iy.Jk`כBrt'n],E=cޖjُ:~8ݰY:p3/IDAT](##;撰(!o+Ag{_?_$VrHom{KrL82W3ݒWĄbFD4ڶIa`v+Gۃ`+ޫdԴo3KmVlD 乍!fWrLXf0)Px1M]J_of"ހLgHw oR CD sR~~zaҙC5]zlP@ 0uG?&]L;)g:h\c"2p,W.8IBtcnZ<ՙsБQy]T0mY3h:$iVLS(`Y`ـnXa+ \v:q k9Y7oQ!X݁\*Vx3M}ye]Ӊ2wU[Ai 8&_f -j;Q!Kq֎S9J a>rlopy>(J O|&KhfFRo ¡avǢۃrқ{@\ݑy+'JWbZԲj;ni\PLE=h`5&'bPOը*F-5͛'ؕ+ I?f*N1=5 v162[{96`凟GoV$Ė Mq|6?!wv6;ZG oyGGMMȾ)4$Th(Nu )3w\miv S๏ KqUO=v(ofD`C3I58'ƜD3Ox.|bg ej/K k֣Ďl^.`oԲO[];Q-2EZo_x'g2)UM_joKeP5* .A\LSmX4 urmmÄ 6 X"L `PLݯ.Fia$=_0QOcD^K{K^6ty ^i9V,ѫJaZA/[PڒxiMlw m܇©kS7dNCPq%̖$dV,?x#cLެʳ=dlƾ0J_^: `x"JC+^.E"g7\) xbGYTYjSrsjL TtRŏ ^^=iY۾p`H՜AY28> '͒YֲcpmBWdV tbYYs%"g>x]bA\)@ס EMd5I6'r@4^{ KJEdW9V8bgw.GRv9ֲ[$%ðe/f)9lv](u1ó;{n3Jm;E.ب{u]4ܵ8{pbخ rn+#=$w2E fw\vt!6:4ڃ 6 L`Q5"ޢ;AF:l`^+ Q RMPZT\%(:劮tY[6Sr*$j'빪+t5 ^>7u<6>dNo3*W"X̅@ɗȳ|R .U9;Iޫ[Zdo6)ٮTMm9'yp8ã|I] Q]"`u tnn s%l)ᇺ[J RfH`['31 % Taǻ{!n V#% t\<9LJ*^f:lgm`$մ~~ӥXtma^Bж.218SeuK5(<0ȫO-R8yyznwpH&ڶuC1MG2XJxT.@XƦHLPQ;1wixt76͡ҵt2Aa7Hƅ )ٮYg]Gs\]R9Xea# 6UD[iR5y\m>AU[zb%1VkS|V#]pNY"ztuXDA~>Hzpk.kN1 @0eN^O$c ^tTzӡרOiۻ7c'9ǶU-[rscI$ I!xJ]j |FȈ RgN0k {6jP{Fx;WݚϦ\nTtj_W% NsT9vn}Z 3%Q(6MrPCxlc&x=~tgLlڂ+#%wȊgIh?z%]p?*ژ#dQo[mu??sTTnr1TbW9z] 撛-0B^|9V@Ef/S|3dS&>N~|sBOgBr#zژ>ݾ?:8,5Xeg!mgN+ٰZtxu-! VaD;TSR,sӰjT${lG9i5lIx֑$eY+We^8ӿG_ۦ pKDGc3fIE.KnZ&>o\xG7 Is]{Gx.Y~p#9Ӱ 5n9H((\Δ6v0c@p3A1ʲm;`'#YIM-9c|`*;v ?sBN̤RRzLށ!f̚vF(kTnYٲZz|hx'1xt!YݬX~1EKUO,q\,W̓/||4Ǧ8RyvudlS1 kؖBQYmЗ}Tw4b#:Vԛ͂^}vO=1>G9^zG<FP(:D=_})GT!Fj=wrC7xcJ+$ۅ8ϖabZ{mJ q_ec" (WO\ N WULWJn.O_%ϼ\1=RӬ#_HɫSB6g)XJRg/7X.5bҶn1a,g\$3-xd?8iM֯6陫20ݭs§a$PEU(]]7{M#{FGX5~ik_啷 >  ~fh Fzf]QrIѓ`y`p6yi9ͻ͗*]Qa5^yϐV?e;d([+(KxY9v)"[*m2۱D`O٩<;wL2ؖ4&{|U ~eVL!`}K {ŽLG#=g_ gBK#kmd2gv2gϺ$N8tyiX U9>NwtՓ\L9RXZQ WX:_Ztj;;_ՇjKM F3&˽ F"G!I7եTVՅɭxe &\gKWe;DvD,$DTt!`#FN_ð GL;&3!ůY{3_~K\?aJ)!"a2T|g~}-Xm&Dac/};iHؓ~ka?|0/,vILг&p@dInDbvU*mYb"2BcaD ޞpKyfj %uM/Ԗ źa"Xpi&hGyxۑm8tq@BŶPj.aR{'Ǧ/eё[m K"&gw& S6,z m|<t__aἄ΅`9d% <+ ihuɶgx.ó>lLl b[yl\XN8}kS Fmƈv>:qylUC-Gݠph5w4<̱];T@W IO^fٝ :F3+FLAq2M:zT$pBS5O@4K6Gi:T1;!R6HU"'Pfg'72OSN!G.T ̍;fF}j2D87 0MEiq`di 붛}fchMj8KlJY%̦]6k0&rN2_"{'> 1`dRr9 e;Ă/cB>w g56`;LIE=Y͌."ܹi0ϻԭ4LCac#3ib5b Ejµr<`rj>\G4GnTM|zU(ml} f} 6m{uy46bmgUC[ ʢw.~]Igq*W~RDFT ,IN8clO-Ymˇuyr< >92GnVƌQ; }G|ԟLiGН)ʥz3,"W&/tw ƹW_ξwӳX~ _`42bo7›3sS@ iI߿O=s `ȡri\zگby:ՊǖP4[4v?3 E1.se^]^ BďoRXC"l[^g_+:~Ea5QIQ|%<=;Ui%6ڣ@_f /嬑FlNF;^:Wx,p}Wх3/m_S۶-4wUCe~XeoqTD]sg?/~dG/;Yá/΁v.yr\_ŀo:ߟ\vzx}F|Tj!mJIVS}J07|];Yj4XMfhk*oKYA;dsοx^O``Q8A^Q$7ZGlɧ=ѐ0Iwkv1}735xGcB0 lDZm9ulwKVFye}1\q,Izн8NvYp&t>~l /sw?w3/5cT݂E^a$5H5ؘ5᝟geWkAq'ǵ ytIm,ZjZ:_p?ǧlwEv!y!p@Cw{cqbfF0C[hMVaL uLa+#,rUy:/Yu"n >sjBl85GY7]JI|zL=B-L3)U*bzۂ4v%2"]0ݘy,<ߡ#hh6w,sc#w8AlC]pK=F.׏|nL8.4r2iܠ񋹒[˙Up(Qw M"C {ٴtID>Jb\" bYVэt.Ah&(r2jfhLŒF} )J]XAP-^ܶM]jV(U,/ŧݤTu|%GGwޘKcE՜Y;{lJ릎-aBw| ?|o<#y5/ypokEv-R"J z|B>6f@l"lP>0WGW_}NU4F37{Zy=?±ͫKk`d4ƌa}5<(`mu[mւ4:puZf&It\WЇoh~ڱxw5gvs.JBITlD-m]74sYRLb|4R[!cze.,H)uT;s~ꢩi*PD#'1uӊ%Z.:~o&1_WSI'QY:8m]l/[FZt5u弩LX522菎y0쎾v! +@ȩV8M1fZ]^(WN +lJ'q6:1[YzȓG^LL\%`mAn[4z8 '?fPK_ݢnO_IV௨^*\j"ؿ"X"[/ *nب_q#zFL0a@vw[n}?+۫;inF5JF1/+\P6 c \6zw'b')І[y;hb nϤ3C[DW?΢eښQM$җֿegMlȞё=+?b =-pR~r}0 gYkJ?,8- 1?[:G@J鸾B;hb sD:6µ8 j,sXe巶8c+{ sӳSx(ey7[F[;-{MYJ,9lOXYS-Ml}R8k} ?k Yː>mIDATxw-Uߍ+窓}s<B 01}63 D0&00HBeif4عONuN};;! guSkڈ'ۢ~w?7bI}8Nt/~Azk_C{G_7L+l*ӵ\,D'넧_27G6$]赿|˿7ecXcHR':gO'c$"ό*,+l)㿚BH|}W>~/Oz/*ZgX&pF "C" 4W1v*ә&SvX;{Q%ިosUB8.̳p]*kh^GK>щDM!s8|v?N:!y!csɊZ<! ij_ {'o'_)iv&_.]8u}>|?BAљ,d4RhRJ b.I3iTsff=/?ortQ\YF8> mj-duo+z٧ =="f}lO?4i`iAo_l ^O~>ino~@TCq`8NPe_18bn8]/6TA*d%#Y(o ]3} q9q>xnfvX1%PNٹڊKO* ]7Mx!A{g|9щ O?5h;r]~ѽ(߁Ա= a I"G*tܷ@B)*؂.S>=?pBv+3tGKUsX[,dO~ܕ*rI|P%' *p7.f/>-q~}މNtb~]~3QL=Whs\͵FO14e1M[8E(;h%ULCF} +>wz|KeIVASl> C7_3Z4O;4yd'1g'fE S iXanbN@m9f ]4Yijhdy5Hf)qEi≂,)EE/^]Gcl:lo~H{woog*?<7]K%^u>rs_Yc|'1[!gU;l"U˵(ASYF,ՂbVPOX:ein;㑱]~L$Q+ןZ^nP7N3~V8Ѫ∣HFFl%_/}GUe!ݒ!Psȃ2OFx,RIJ4{_5U~u{Ż質~m'=e)룲 zmSJ3*\ `OS,^Ʌ&%=5]u!VcbfZRV:9D3).?}CNm|Уjgj<8{yyx2+tV<ָU|+5m\E,ñ,tݬ}tؾL;,q+ۈro|Ugև>y-#)ݵKOz^sՕ必4o+c ş_ӏq0BncTFtMcB9%˩6ࡥ~f7pL))u*l%O.sU,y^ϺtQl:]./qK?{|#Z]lLO)RDΧo|㫮?t}:F(8zaχݮ3&M4ʊ [ ,jߎ$m)Eh !5vIV|̯D_YRUSi>dwcR--5i ވ/5 g}FPJhFZllTNjܬ"`mxW=og[D uρWW}t[8)kS=@f?5BqQD`;OZ."E;`k=f3IJZѴs/翣SBW8'nz补_XO=~u76ꄧǯoKbj[]nbsa}K[uFO/Sv0Sɹ&Id{ffJߖZC6Gj ,f]k޷ep_GHڄ1}7^`l@{#v%z2*Ypgys,7t) X_k1{-ֽ2{ vnΨYLX8edz-iάqՁ@Q! ~77W@'x Ot|\^Z=kaqhb7ح$BQ8M OR9UL }OuPCJù }mͻ{Az>Ga\6kpr {~ℎR4 Tn+YwPUz؋Lc$> #NLtgr lIO5;9#lzǓQ1h{w%i?EYf_C˥?NxY[[CUM`7[1J:=vyflON]@,DAHCE͝2ֻ#fCYyG?33hM"10F# c1飜{5SJz+6{FݞVRة܀K Qe[8QEBAd/uOlA^+NGںv/:Gy0zK/|/}OI3Uu{/{Ǟ\'<]:ǡ:,7Ź9yc9PQg4nmUqT+VZVOzt1/~9 Vq'" #EzC ͨE7OIRQ4bI1ӂJDchS c,CI}VïҪdLs\]'1fӌo1,.$uHoKG9zV҉\2U7{Rh3_ \Wdqnav>tϢG>(pqSCd)̡}:HUC 77yAaPo}:_s*[QUQ\?mS?T`⊌]["d.6U˓;dTe:}dSj{(M#OWg&DC[HRGlk"ØFSMFH隝s+."~,\k%SYc ٵ]` 4͛wkkg-TfO&r|x|`aE EBJS셴0AL){b~A脧z­'qG9-2d9Ҝ K㼖~<`EK;ш ԴZα&qqIm6B|.tANU6*#źط?K.KUO>i80_9*̐-k\)A]sOc_8_p1'IN@g~m?Os6:S-ĉ$x Z؇W S|Zx8b~鄧z;$%9j89zQ-T U XE 1W>zE{rSxC뛤?B~nj2e9i9Gws3<~7R`z[=wmS9J.xC!B uLDr;hOF7U_x8);aOtwZPeVE':_\QEt$Jj4+6WF\}Ʀ%##SR8 )q-[.c:N6;لSHur!N*l{6'Ce*3oFW~?#.sӅ,8s_;4 VFF_MS%>q;(4MlD>ӳX|s[tr?!&nBI^W͟_+l5++$IE _SP٢H*9E&MS7H:C7tE+->^pfgt!EF:ӫ]95Ʌ9NU~_~;gM7}KzǏu{Ss3!:7ꅕDHUsNcr eTRj.x[o㾅܀,VrOW%VYEb,'xzu 5ch|i9&@Sh=e0wTUoɱҿȂ\:_}ׯ^><,넧V7wxbuUqd<c<5Ic*0^qkT%OwFZIs={ѿSX=깵\w23A*o6GP{Q![>NP* ¥>-|6I\eF'F4CQ|{Q-Y)]\mllJYv# T!24|:{vf 4MU9!@.%st e#昈c"UUq~8/)Q8JF³EmەSOiVOdU4PMbMϡ!85h8IɥqOi+48_寬SR6E S;20\ MR,  ͶJ$Gcz;1SXzc%3`tƋH( 2*ݙ¸mܨJ;Ow~n"bh|S.KhƌW:_!AӅ'qb<+h^'z=wT@8!d~Jm,#v0ɢ8!@Q@&­eD3AJ@ FΑog~>g~cS88yzY+ws nl߽d~g~! թGJ_ zsj_:ݟ8]"o|Agy8'&c7d%=3A-9뭸okY79SH:Uޟ^ r^~h{wL\j/F.cJ*9 wɅytq3o>`=6d$ 8~fa5T;yGt㳴2.ܡb$ggWk]#±DFg3/H:=S]N\P)|YhѠGy i=R'WT;1ug6ZwF4&\MH|Zi }sDf6f\5m*<,燦пl)+[`aCv3u)y>7慫/8ޮ-Ks/d*Ikkd$QcBHX͗GX21Bk@6#&md~ FzekޣEJz0_Ot) S;q>,uLyt!ZُG 0tRP<iտK*`ϕN7 H`9cgi:]Q,wk]#ݓ(B^E9 Us@Ko ?7OtM#gc0(s?߼̱WW-Oxw˿)80Ϥ6c3dl= 5ʻ_S:Sq#G|a R jP\o< {˂TZnȱBchTu;'.r8vByݽ,Auڃ:P0&UxRv!/Q  t 8Sjc>*gE㼙,S yUݣ0~|JNMe{u5d'΄;"R}PO0uכ8ٛfFXӅt|6o}.y Up(J(˅vTw:`)5TόzQ}w~_pCjywZR7;\{_w̳ߑ uOE0do~/ǏMb dCbD37CBWf+,ù% rr\BI} ]7dk'AXuMlT#/D~O\(WLcRMSr>@qEHMǙ+jrueL'iv䠪Ը说xaߝ/j+={}r[O/KX5 IGNT20Wx3Е<n(hް MS+ #$9:tV (` #W Yy)΁-/r>3ۺghK$X H:4ŜPWjF5?ڶ8M竤 xx߿A }i˜*%.)'JZk(-RUJZJ/][l"MB ,'}qlVR!,ϮJ*ԩ):J77N<{0FDV"djwG18nAW/"tm5 Z`Hc 'f6Q}+ͫ'nX Wz|@_^oW ܫ+^w6I>Bѩ Kb-%>:P*[]o`gA:QݶUBw/]O7eIJY:A )4g;W gF^7{RэHR/Da_1Y@ #t(Ru>W(Oݨ|e%=lHSxn}k1TBr,u>@* X)?L^'YϼY_|h&Kq47d]:y$J7}Oa<=.Ε˹sN{'|6t;}_ԡlEXs33Zc y:gW ;:d3qEB$.:,لBT]34 #Fil}tCIP6:,YZ6U1r E^h8Pp"mSl$.iLnlvcbZ,wYjǵuYziiov}gXPt~+%wG*K6W3 ٵ=H[tZ9%.8[t}0*I׻S? &i\(w=&c h`Ukx7=[RW;H&x3͕F|^^lf(P1甠з͞ vWď]ϯF:&J,m 2X'WWHzi^Ϯ[籇FO;E-8S]7V/akTW/qܔ4;z޼n%SR&H d"}}n(lz҈q^l"0nO5(+i^N j7ٔH/9hh/lh'W-Z;f ˣ`ִ,^pN |ǮvFdh>ŲyQm8r3}iB=`؃_DdhxG4eA P X˭##fҴ^Ш$1ۃt`$[YbNn z#@lșO?cJ-pZ^)xHߗMo(.Z9@G7҇ϰ~ChCwXtv~"3tFoq2Ǹc8&,?\XGB1ǜ+ |pr2/~F*j (/NMKSԎq_y E$>y%vJ[. VyqA#n(-%$˻kX.] a i\֩)4#RňC%!1!ٙrkDaI[IϬtLj&kL)DuTo}7Zg'K3YǥXLUmi}Iѥ-/Q<{/1L8]MGj$~vޏR OnG~zFĴ8IjM͖zc&g~xHb+HD Vtvw!Ζ㧗Uydoוba0Dl?tx1rY*9n\ӷozMn;JIb=%0'a,Tj'oDΔՖ@4plR"(.Ǥ0"?h&ao8T9ܪޭj^唰$=;pz㻌U:gn;;^KT!,aIX=Dq&^)ǧ>b2?hYzx4WwI1<#n1 AP 8trI"|ɠȁ$ͲYQnu_{ Ytzj*~A^^p*&8M7w^kq},.L~D|Bt Slџ֯85 _a#ȳ|%,i;9=َӷ \9?K3;OWܹZ>}cr Fo ^t5 zu9?<@X`Ppi%iQP㔀ˍ|w9i pK˟|M2$O4 O)dYoÐ/|䕶=24  I^$Z>$ndI#pW5gO]ղYe!YW'Pj*'i(2 cw֛ED M2 MX+ o<|NDT-lN7ι23Q>Dqɀ19?GPUD, #ЛꉺBI> X.[ߥ\ e3E6krS]2hEP2S&OJb0,F@C;lw26O  j$Ks\E#Ȯlͷ¡ɳ,-g=;\4r*һ$^I K7.GMi`ݍթR[ }[7}RryԌ1෦8w3'(kbEn}QzP7 Ca:(䇳U;}F;][UFs2 5dd~Ah9~x:!(NO°h ͗99 H%7깱K%ݭ¡HEbN./3TZ#i̧ AN2x'PzTNcpWzt@-@bY=t']7/:e@"40J|Aq6W!($XxDJѶYlg*lZVIOͱ/nx 94xOh˱H& j r0"7fXY 폸QI^H曎~+$CqiNKh~$ ۾c Yד^\Ր9S$yMpYwBx×, 0?g|_<ф%gj jc]atxhxAf{i ]<'<-VCtlj)NűB6:54Pťd:[$Q00SMvanm+(N%^(ח;6^{k ֔bI"OJ7D. gej9FH.M3SEW7}KZ14.!'5mv ~'dzGlۄ)%zu<Bq-*b}Y%75e0ov{͔c F]DDi B)˶oET1{Tݲ{[VInjbw_w8e!~T>Q+_kA8Yd+.%"{t}[$+Xn1Cr*P{nd܌;]􊪻کβ[wvihf2Tvf*9p1܅8L1h:-4$.rFqmwϾ[~'~'ˎ/FlV˜Yzcs$W}bN<8n T1Vgg*B.9SҌ^ng޴x0UZ43dڇPdv{ϟY8ӽrVP}L I1ѦovX+saO!wo=RCH-LDd[%WIQn!:Ԏ%2 9Ѥt4Q}8ggc4 L-ا[ rsJ4 .l(e6ZzE`G2Rvg:^[5LX+]1U##*t}_HlV3r FØ̖ҢWrb#f9{aSͫJ2(R92TJd]3 IK M\s9/8`yҭVcAJQhB?u[]7^[?<\ Fge0āreX- Nb Eڍʂ'6=R0}w?~SaҪЛ+(l)EjZ9ёD^UpZۏ%Mc/tG1pR4[S|J`(N:zj4q{8emLdƈ!Fx:[).=.5zz'ײarܫPWCaP62P3[vZ![d9WQٰm'YE,PZ1.6 ɄpL(v1T m2P4Vr D} TΡJ!ъ뽻,M4 y$RJn۪K+qUgoR8nHoIgJEqv bchAdVN tGls@kUOJWrA "),r,%-8;K77y**Qj;Ǡw<i X _<ݍh*^(9֖#m$q 0]zj.*-8)l"C nT0TrK-8%:>/li*)4i J`txt^M<>uod,C DT8>ӖI:ZUNGL1qQP6$EOtNGh6L}=r:|1}u*\g祧ܨs3Bɚ.+ݜ$Q c PwDGRuGHemՍ|,  *B1fk)n)^ik?S誒bБ`(@[1,.Eshyx$^zP=twCU0H7ޔx_i߿[s .DCIkF0"P6>_;24uqrF *fM2SJZ6WI[ _ZPYQγ=[ꕼ ӳ"f.I ñl'@N۞B٩֛Q.ُYeYyjyw-,CL ~0;O?卻O(͗y%fR\,ۋ{kKo_Zl޽{ C))+jPT!+DHGoAd[vbh&cLS gG~^V%\9aя11euT%|gGϔZ.ʫ9a,j9ȅS=Ҟ,N鲑䔨jMq^ Ԅc$O%>Q460.j-˃k m9o:]iKq&@(-*klPUBesc]_ޤdQ4nz E+ Dӳ,pr2@4E!昊Sp}0rv-8rJ\׏Y;8]+f%=t1J.-ŏt"*9n@絴FqF,nWPq*NYF` <DpeqBvlS/LV tՙ/fp/ex8́r(L'8cC^rv~Ǝ3yS^%*BH:傰q]U#Dː qwvOTE'8>2IQ2[: 'ć8Y:0QQnaVl(J.REd[.܈*D?k֭ݧ jWӹE_>U[kʽ<$)(a y/` gy_LL657TZfqn`$ѭ43s̙hR\P[eM}4Άc^id , Ϋ璽MN#*Cˊ#s|OR-<䩵\o350^5UkSC y|nLL{-p^EeYN1I${g!Y'',#6Li*8+v}1iݒ3W%=1dRGM0&{9ڞϯe#JӨ }?ɍڏ *8&UTӭ.9?m p,Y $Wi֏4^JF yE 8B87Ye@cOhM~Ryuga?yƷCe 1ʲe`E+RTw1|1gaT2*%g = N),W0?vQRR'?nW#WL4U+\h1%gPSQ@4½OTN u͚>(B* @1^,S`^int[b BI[f:z̓vn6r )$:F)aeRUwx *D|ClvsP#0JK9Ib1elR6P9 LƆ Y7ҭj(Am:j.| dޗyFU!Yҡ0Y~~H=FESQ@afe !>!U'딜K6NǼm!$٩VGrp7R: j0t0K gh>3-] c50 "4[E1" )!$Jҭ!Cy7TKnyJw$nOc= ݫ*]+-b dsű; (>rO-pDíꗌd|2;[@0Q)!tAhumfX8g)|`SEN) hJ[6^=#!s1."k{ukmkCuK*[5'# LՈd)("FL+® |}PȀo 0cXo%²]۠?Snȩ>d`9WNkƍKgνcNspǓJd:8Zfoc۩LPZXPӂ: $b6 {pFGLG崤u3u7 F/\#23>HTө&OuGا\=3OW=g#Mpy^2;O |>4f60XGwiNfgIg{H8has/ލgm:*es>KQkzͦ aA k9+#f?p{K~8Nu0NbCSU9T٤o4f&zȧW,/ffhH 7#cCQfd6,( WDty0\kԲ_r <]t`r]*}z0\"WO??dS%,qiN9 wP]n}M4S2Tg ռ\^h M$9 QLh4&;gB*Z Cf+![l_,/բųGuKTQQK&"C3 ۷>lo3Av/K!$Me/2ܷVG;pZ=s28){P_ M22ELʺ_˻ .8C ׯkk-Y,NrҘc٭Hx4C3m{k.wB) PGQڙE^8;pi{k +۫x:cI^k[]c :I -LaJŎwȢQ]N7Z+)듛u3CQG*;6*P oˈ3ޔ˭vkY D$-H/t"uҩ(kAoY GSxv=\ ǘ%@T8(ft'<// S;Z<;o%Owl)t)108hr/I[i]vo1P|AX8j&/9Ҍ믄ڇJVMw+qz:VVCX ؉0oygϩqAaO^+㻜?Ǣj-DW֕0KlID,l`cd9*ˢ, #cTt-VLJ&J`x\0 avԂEɌ I^^Lf*MQQ;TϢn1ǂ)S BcP+LG ;R'HbMJUb{Д_3'^&~"pY%l*ʉn,NIE-hFR6;EKP#BhۇTg [8A~e" a1jg3eT-YK*js^܀B~w9wv\zifkq8O Rsu ?TIO5rڷv<W\~s4kL1-snBf~X[TwJ/=eOoO'gpy?W-e~tL539a^vwgĂ50 Iy;z0!r߉ /ɕ 5Y9Dޞt\l-L^1#ЛG뻱!A/!$չU2U$C14 (H݅ZrU԰,RϦ)Inji'o-22ԐbztUX 9z|^GNN:aRG1uܤr^[0Ɔ|ɥml?uoVs]YMG܊=iŧ! _ <5_)cZҡVfJt9QDH8N+MpXm~߂T#O{TZDuRGh ev ǀLӪ59{Sk[ZK{=ϳvξG#̤`s|"0 y wTV?}V+pz kd ]:&`9lcS} WXk}r*|OduSqinaDFؙf!%B*?pDҩ"?[nL7%a FQgmHϞ9Cc³8A_<׽B@Q8(Ep)(,"7.41fX8|{k.#KKZ3KT`邼<[ջCk[=4sf9P e,C(윛V{v"8ĐcSȲ'oK WfM2v`zC<`95nkxPE[`8Ƶ܈,R~˜vo1qloWx Tm xZQWrJ4cХEk쒵r#| EQؼ$nrhn5g'~CIQGJIೇN9a 0=$EO.XneiF0I2 {"@J.-ێն}jcA7dZT^(6T}aScK8mZ֛!Ε8$frir +۴?ZU"~^%˽ չzIV:jkG@,Ce)Y*i~fFy*#0F_(Zn"HuS^z9|rr0w6c_y~I)BnW-OS6JJ# to9awSQհ ޾jLCsL j 4fL/=4)Sp|-'Jnx\^_Fc*;^ "vUMÓhUbӛÊ|r~R%\W9l'b{n04eʖ{jrJ]xv9"hP=3LD19;"ITmw{ci]e#p` IS89Qd8%+;BS/ i̘fNNJIN$+0;^?zpeJD*T0?x0d 7֤$=)ˤܑ ˳@Q_o9NB9~mMJY7͸nsvNAN]TCn]]Ci?Xg3e5;,= ˫ҽQ)s lhfECsc(7͂$]ԩS,ƙE!EQIbl\r5M# QEX(|U 8ڽ秛 g[gn(̱4Mi^E' 4K#ET(sqfک8tU&(jA7|g. +%>*c R5TJQ6E)+c< gi@\2W0a}u8O^Pj" 5J*M?T4pTԃVeu|J0̊2(ĪxvB0{Y.D0'~>t6k< O<"_ٌ8ύ\~}ϕH4%4ųd$S:A,Dʵ @Z+ Ј,i B)Ź!4s+s.o5!~Ս\wQ{$+ɪ$b7Tnl71_yV+|r_=EHIsrF2ߙ$I}F.Ɇ,@2` 94E.E$iTQфpvGiǠ(cqIj.\ʏ`{Ʊ-pIaw64eK ik Lд&s96+B%I_rAL9^$c87ʣj{3s Ҟ%wA+ z0=# ZБnnEU "< }e+et)KQ{2f`Fhe}[ :ow,lM< 8x(q3 \;6MχzԻ8Kl9腵$I!#Nx0PJ3r}9[ $1%1I$Qҿg ˰C;V0vd2-U!s}0 ,9:?8n"qA2/<09{O՞ FOw7G²1IPoՙs=[+[n#f] 9ahBQ Fݒ}L1ōcSdXPJ![]VCbȗ\Z{z=>5]L݋/Mj(b<nBaox゚[u*B%L6< C3 "ORp6W^CKStAq䵣* x @pASGQY\KO?eCӶ:cB9V !cώ6r04/pBXI3$ \Tnn+DFX`(&A66iIę.k~Yt$Nc⡝4QoQTAWxUjlV/7>%+S7Gt"3,͸~pؿ$QzمAV,uڶ&Ch&I%I.^Uʉ~ |aO;>'@c0+N9܆1jStx2퇤5["ղ<:fj};|1NhQ`%a.Tq G (c6J豇\rRB RlqFG*ET8=CZӅvs 6Tx2P`bvN24*hPTjVCZ#kSh/pbN*diJ*` luGW C˭r޹>AWT>BQk`%ą/gpMLΌ0i&)}yK%7̕aF6g]:&`~otsq|OdauYJ&B5!NPwlؑ=h[q0|>c2tGSīuU)^&eGm*F~ *|#ѝr+CПۈG~@m'59rјE'+9*<,Kd6U$ܬe%e) Ms%ĵ}.#Lew\uV5߆z(7?ܧ~FcF(#=0\X]#Ӡo,6x}.!ݷDݵ&RBD>Ym%,1 6dASb5Kڀw/}n^yrS[nj P1\ͳr]݇Խcwx e\ܵ,ퟃ jKޔ{]B+y|a)zؼs~ \+z@"NI71}~#piりk.CQ#5as7| ,'I}?>]%rXcLEO3lLW7Yj;:C3Co΋0ɫShx>S8ej'I0+CaS3Uoen\UXLab'r6 QʝX6g֋O}*Vה"sst= 挧z:=Uu?7 8YJ╦)O;]ْeUÌq%<@W(*c*C#xeHR}rx}0\EJo9ǹKӅ'<6tuO]4<$;|c4BQR--]젦,5;|RԢ [Tkb!:a\u1=D]ML{ͱPK=-6QArv4ɩYYZqςEZt2sEzZe=.>Ύ(vgT?]Bg{A*¹9Cyk1P:֫/|sy@OMU4ˀ"d9%) :(7pm 0FK.n[r?8ߑ&ey50!K4)bvcy഼P8CGF=-03V;^2?7Nr.%A$P3*:ę3SBF(#@a =Tq^܀eQE6W9%˫ox!f9V׮NL ,V:y}Y;Ȳ,þsy>|U񻳋v "DDH$FPA,$ AI"HpfgLO>{sJWU=X}QQ{=wߧ:ɡs'˟rR1+JmfTuRzSW?mr>S.V"lY_,l"/V\ZtJa{>@B"G#Ұ$ {BrgR-bd{dm(Ƹ;I徨7w; }EUSpݝh0Z\Z4%.Kaߖ%ASI T|н~s+%o|o~6.JIVav.~ MUyPӞtLd__ 5HBi@Q>cy(\3B#  O, rbhp"K.7&9x!3wy zK侳j|N`%=Gfʎ+;n4R:L)c?ɇ ~$BGa\Fԛ0CMz}-) GA?<O08G9='jrVPV[ѻ Un2Isq/4K"$BѱO&ȃl*ǫk{$E!&("6ɵEԄf9-jE#YȆ{/)*V?(p4c cw4Re x+XB"`6RHRD/I"sRo"ӚdQEQsvl4Q>(e8Mg%$GWo<8&gi#*\iNP-MfQ<E2pcdܳ.O.8$i~0!_.e#(9u4󒁻C OKaդc^d|N/cRz(:|."i)+4??NގB_i]?~|+o>Zр%1r)Llj'EC=翺^yka?L?&Nh'RWw?h@ifPsjGk4XeSb37^x>*hYQd!>ciN(ؾr!tE+e&“썍fqZqC y0ƼpNQ :>F^~| Ȇ=؇ b{Ls{g5L@<-NF޵^H^hf9MJ %In(IhR33Lo,NQeU7 ~:ؔDW̯)?e<jR7@^4  n](IE(0"`Hh&t߾:ynGFSGnQT5soS,0HX8utPj^-$,Va9LL Sc9Un8r~wLh9hNB QϥIdg҉M1sdb vyd;+ls{49xYw6PRB j~muy̏k :ü;BG/$z\wzSR_n :":JwQrWƵGFۿ޾R?NRj_v1F(&vSYZLGN1I?9?)Ҥh/r nȏ]p*} Qۼ&9?Up(Jdc ߩM3Tx$0]v%lAx3uee٭Ϣ+f$Ua|f/qFRJ̕TŨ$7 ۴J9IDAT 'pdE-i=? /:δfntjIۜ|ѱ@Ixtf%x@шlw'!KyMK\ K%k/VYL}s`H$R._0 (=fGS?aYa~TsP dF7v:zחDRPF7ZQTMن<_1 F:ĢEI=WO __:15ywhw ;Ag⏭Q/Kc/d7_}}'?zY|NLV瑼7gZsJy(YҦE)nUō,\]UJ*FTPGؕ]yo`ŷ W[}(Lv݋*;"}?/9EY'c P6m UqN&skpV?t/(=" 'a+AΗ'1($YjQ~mV[$RDuca!0_֪+K cFAƋͩ@dUE G(FGQӜ1F1 Q?W*&b]۴7ʜ|l]:xoߜ}P',!*iSjklʔsu!7Uv/#ͥc3+ tirrw<߇x_h8;jow ٷ|ώ/#+yef(&v\78X+K |\ߍxO>zwb`+7^=ϒ%&vjT XKFus2 X{jsQ$ҨՂxlŃD9N#I= d4ved>"rzA\4ʶ{#%6X$sfɺ^T)6ӭjw:e[(M9vفEj |tfoJGe/FD9tHI*$IOd&,҅jH)zx  }3N$N/f 8l&uK ~ fƃ=X :#ut%TI8=i;qHQ%yFWYܔ焝Ѫ\j>cn_s$ yaS'EJCs()[3%={ped1JD]Pfa>/#0C 0ftg̓륍3)_TQZvS}bA${Q.B(YoLf'CKOzy _IҤ2N<}RPz;7Wu~K7~OZX^DciӔI,7^̳]:!9x }$P@VEKwZ:Ěe,%#yVa{ Izq{xՊZ J m/>U/%Uoc  R1Y]sC`$ėsru*` /acu([|To'翾ZVEҜpxMI ЫG#Q%$伬b?sCR(Ee87ϯ-& /5~I>'BN@[ޮd'qoω*_x~r3v(O[ȼ/ħ"Bg(aNӖg!8r'5ҥ1e8{}JzPwEAWbKD{27ɮ&TZ\YC9J2`ѮY᥉"HL]^0fZ緱Jk$YZ^iĝarAs)jJP+={T:8G) 㓝W[w]$|}54$!9 2?'o׮ пu<}p/|= Dy߷>̶?^_Z/X7Z= Ͼڧ/^g?uMv/8 DHz?,OќphRp0Tľ Oe *;hƔ׮ t8k]O%mb(bVX's0-ZiN N3FsͷdpR #5C̙*QBVU,5X"UiywdO,g"Y{74!Xb5.AA4)b;3=xp\zs$ $Gx\3ӫ-A,<촯?Ψ&rFxxv#goOy糿W =eȐq㜝DFU;zB<ς^mغyid"UbJHEbؓ:6V-Cm/eǧ)%ݖykk8N]ePyjA Օܘ͹Y<=-"O, {r"HdQFb'b|;-!="\{qN {jޮ6JgD*1v bF^Ŀ8t[a lgM (NANyaKqL5eݩ%?<( +|' & 7?4@HDE=kO.E|wDL4u1.*ةGJ3`,?*sB< Ƙ7Qk/pWr$?M?]?DԿrw">wX :XK|ԶZu-8] `ea q#lLngy8_}ÏDA:Au⩇2~JyTC~i>e9!#o@PaH>88a,f w`*{GaZO1)î|_+{xC?@E=OiyΆ34qsTYWO1Fi9kVN0dYIO1+F\`"/)Px}c4T/$$TNssqS(dP&V<`W\i}6AwrC]}fy/0Po,̔%dϾsqj&\$/M8̞ϫ&WL{({K]D'RHA4 bLݻ̑G#W˹,0(ߏ`l*ʕO`H'Dc?I)G+ z+ܹBUPUVUU!PTXYal6CF&(HYN;VDֳzfo4tM*#2E/3)E""2w-BXhTK"0'3')w+ҁ%Olz0GW[}O^|U24786PU5%u(*fe (ϏPNUU" IU9p!"]|^Z>!k_ſBȀg??{z8涶 pT)^,z>tbZ5#YȚQ4,78>?ջkW;`jG+~gZZڛWWW7HX/&E('*X,V5(kdP㡕p%%C .YZQZTqN2d((0"?5U/yHrf7!Y^l̙d'kR8lvwϩ`9E_-rG+"+Z =G PvqEВKu^k$ő[<=Y) Ɗr&UH:?BAɹ@']r8ϳwhWrC.6= *k,-a#vr)6\mo 6<"4f!* Hr[,$ZA/TrR6!c c%S"q8Y^*f)/h&ؾۡZ(L=K[7RIaK|2 _R/Н &i{^Ut7`Jc~)dw<\:y8"D 9R62fo%C 4@*G LTgS;e;E:c>`rwUN_jkq> k%bkhH0fywCLE>YSE ?Qi8# KUL?*D[axq僑lb%T^ 8c@~ѻ;tɞ]o_O֛󕑅`h(ԋh50 ",YJ'BĚ^={!)koH*@{`TB$-ִtIcixo(_xXiPQIBUĒLLiv(xrMmۨ۽kjc3I+ aq3sZ|9Ǝ N)F~xGڲY>hj[ZQ<8  řGw8?`f_KZEg8=I"\29ϙVո<7zV9=x0,דw ZaKuɢLR|!(G0 S h@8} ŭci_Z[|i9Թ"zE7|9I%zx`tƨ di2 A]/Ù6d@(@u |\Ս/RƖ@S*f^5zbRb͞J'=HJJk beTTo+Цy02܀x!3+]n-wcɋħcL_]D%pMgn^2s.׾wdj2RSJ//-H"ϡQ KޡVP1㛫E Ysn!.!X_[f+_w~ ?~|eg%!w%硦5ᚡre=9@J}sؾSex_hRL<1|%cqbF3pV:n{չP Z|{i !Hk)GXՔ'ヌ1!, ~UQ$H [Õ>~VBa pI‹TvU޶%d Y;6X-\Ac p0\/W<^:K k(g)0//:pVWsxAilj"=gjpUCp!b~"xXHy@^J7j ?ܿxzTR-+a Tƀa xp) }'>uxpKo֮$\Ą.T3C5f) "^18U/4NŷNxꬨ25M܉U7SK2pnAUm9 `P[VvQb%5Kӂp0h6+&;u웲#?bOӬ;c,OyKT{}DTxcI3hي?TKz\5>+E? W 5[-hwbt#eK]#Wj.bN^~)Ue7k8 z ܸ3t+#/n='nFTz \kE|vzygĖjz`{ah;kAL<; Ov{-"kN<@4Y(n[',2^_Ң(?{AtA,(JPEjK25epҗ͎䗺7by$q%1CHx!,L5Ⱥhqlfw']Qѫwڒ+svFf'b^/# g^ a+N߬E {S6 l[}ܟ>ȿxl^FOrmê,7°`/At,e yVvjw,Z?S4MƯ]q L?}?Q2cM7 >='Bgg 2}dA$WEXE>}uY=^ADf.c6b' \ԔTE>]kQ [+d`M2ë$;,#!eMk׋,ǽұZzHB^+D_2Fܟݩ)t'GP`JNϐVtaɔ=_lOEY~Oo_^ x'<,MCUN^껟Z(nu2BHӗW,a^x ɥ˪ !QCEN>Z*}܎S #2q*t$ VH[e_s'MmoXAA(siI3?̽~o›aʮܲ,JKR,.Z^h*B<ϡF,( }ߟ9FB6w찰ݿkƺm@2U͏<+%%Q)/ࠬ<Տ87S¨d籮J_7h+e$0M@폓(X \\.[V?<-}w O;O?vybɝ;n0Qz1"fbX14S8ioy*ee+Z3((ۇr ^<|k2Zk RTnH~i=)\ ጋp< c;Bfz!BJ1O塙{^n{}U<_3WZ,mO'Yx:p0">}iw9 Jz\.PTo#T퉿=W CoqVuL) A,+' 6US(1e Qgc+kULg#LE?NxRT^;kxњwBNfY9@ҜLԪgRVasјi fUCTLXCW`O߼.҉5," a]L \1#ɓ7K5鳇cI@ *_3t;jAљL7O_0 +YWkkG_z|If_si-ԯQ+V̓%iW{e0z;R͖ l}Ue?tu$ B~ 6"I@vn}vϿ?Aя/e xAҵZwNpc!yao 9IIWJ3"[ן쟷Ma))R{ۡGQ;9RW?(ߝ#iz*&,7ޘƬ;fcW6f%Iܟ9S0.<RCP;yI})\:ܳ<ގĺu(%S Kf ?FxA?h YSꦹ3QCAIʼHL26ؖMĽlƂ [O:%^4e(_㔅na m#8ȴOh]ie ` Γ{E$Ή2jB'F0v(mƘV+玖sN%K2V$[w?U@JQ\O o\zŬwp ieYj UcOUӛ-8V5 |^%-헯LLs#{d 9`4 ޿nD.QxTYxTY xY=(A3$W+%si Ri]NqDFM^6R hl ;jqU,s8>OQep4bY^,6:fIF-l2& A +Ĩ(D뭠fzCj߮+"}ryk iX>P3.ؖ&\#GsLS]ίPzÚ?y-Ǩ]ƈyc@wֲǝ$ӄnD黋sm Bdl/ :(e$-cGҍJ#l̏ί⅊3.H.B79#@I'%#} RK@yj՘Zo *wuD>$▟6ZO5iɐ| EsyA L)/I.ʩ2į܁}8~}X)vqE;¾4،i,""v_m5[,| ;ymgy'ʅXʠ\~ /uTU 8%N0MVҙ8/O.I &f4{9we9 0vў̦|Ki26¨&͟+l+76fO+io\K[qNl>Ê$Mbj+ bS }Zݽ>Y>>h+RҶfwLvD));fPM_;Nhgt*pLSPSJyIu`5NsL(fQ>DzwYI=˞y,ѯ\0RţX˙.'pd'ͪp @*msc!'GqLEm`0 r*p&E%?J8@HTDwg z0!, @&߮*E{K!S"W& l+wD/2ADl"X/pbD5 13U VjS'} *C'Ǭ40j#[]%צ9vQzu}o^oZ|qH(0?)W &^\'xlme U{_+i3]h<Řkl^\a/wRg5"_X?[~TڳϛXSx#IJQЈ!golU(9 (of[WWt8\mNYOWMOIcD>/-^I]N59qCA>)8خ/Iom}~ɞtwAdfqWZWsV: rsP %+^Ғ+a6s(YEY8I7Wun~94s;|喪3/i}x?1<a1J!LBP 3|?ɕ/ OW}疗O<A9r%%_y; z&AA+-n&c<͟MNY\43]yNchOsvicikR9ûht͒iH Sf/`r3/FI*hÉd=zH3:%_ȯ'ʽLA@]OGzLu+b$)_ K|b'qBw0JIf~8(K`xxw[{]zFk#ڲ4Zί4e`IdK7dka=xzc@pa4;ciw@JI2-TE9{L7C!J +jgrm< pM+}K_Lx,Öo_Tv{5P/ >-7jF)C30$!+jvӭp9|gT1B4'j21A WV2Ko}F67֊g%SJR:7ű@H^plB% r' Z1yp1Ñ0 4UOsQn%Oō U#9($(n1to gfg>Z_k85JqI3 R!L¶CQ ^P@Wp?+`C MM},IªWv J;#4?1ͮڱ!$k>7 ԵAw̹˞Y8M[ `nT '< $47\??>;l+Py1Wo} 0BO+=WEY=fa@AOpWӿ~+&9-Un9f)y~eS쐗J9?ުM>"IEC Nj(e X踻 }_ipזZ!V%oFȺTYt*FWR緗?1b -QwD/|QADD 1[IR7V'/!k%y"Rc̥i (\[q-JD<>EE/R'1[m7Y+Ҧu^*s |$c+@JR1`̍#zy' !wt z_\4M&ׯWaZ x16(;~b' ׏5qn7VyVPݾ<kJ6=^ngWeYC4׶F+;1Fe3ofugm?kA 5nI;=SdڍÉlXiȢt:|x9u͞~h lŜ}B%nE.ya΍boL4Co\S5I6vT)BբI?G#ÄM 1u%|=|wPLKTbeߋCiJƶ"ESIb 8yi-Ԅ ݒ(4L;]yK'~ h?NrMeQƇG~O&X c<I`%SHbuIҌ>3vC{'VLt=mI"2U\%ԋLWYH U3y CQ#q)@Pb@҈UL1*'wV$O#\F 8O1RyQ[QZr٪zPgJJu!T+/1}s)\FieV^LcvO K#\v<=J<NVhhX c\P/u['](쥕  H*b߃"JKbacRy3^t<%EQ t`1.)'*E=E7xKw"LS#ЙjǪeXJ lv`$CtsCJ:k= ع0¢@eR]WjgI#Lxs\(%inXQhi=GW 2(u wVsJO{I&#Bo\R$;v|sY<9ZLR*Vm*fEKyV? Q˵:4ڛSDt^EyEJnaLl|\[~TV[\x^:fVwo 5ad^ BFzm+ʝI')OF+BhH`A$1_d+? > 5{mcx8Q <+uc1Eu8kׯxw̝ŴIhZ)F.]Z!n\Nj+;q*qRM{P* (t,WV~)軏_nq~ yZNj,q";}H27!^ Fk!\|_͞&x,c4$n(ULJZXPI|J0]9/4,[8NXLzt{i;7'#V~&y?P Mwn Y0ZO~j*ruLA@o5no+2S$ĕGܟZ;g-78ܝѝۇr4Jps)p6{$>+3C3yJYoBFę<ZUI𼒚r@d.Txd "z0`0gmA7yD*t xlj8, L,N(¤]o58J3 0Vwabv\&ى`Xk#IqSD:txI~}pҮ>5O-/G n^S;Z:+TIl(Ex\x/ҿZԊP-(嶺QoLOs>GF%…/A HiZÑyzo^ V^H|@N3J d9 Dmer撘6 ,7(x\6y<MN䱮y߸*ߢ%srtCqB8m6آc]Ln.;40&9YQg3G ]Vf3ՊhEaTt :ZmgcWV}+"* &P} B6 b-l; ^vmaVӻO.F +ɻb4zk,ٛ]q|>%&'k-My1Ȩd|a BY,fIv8R3 qJH'%CF^g!`tseI:SA?xY?uf?V-/GH <y,xJ3bjޚQP\3: &‘NzOZcY.(Aq?g֯3O_惫˵k/-j-wO.w:%#m {R|&6 f;>"|"ca43 Y>k!Jl4L|7t/iy9% ƾeN]3S$@ԝg,N8#]_m'g4k 3C<,\FJՇ[Uu\ֱYɂrsBg^FZD^YHjYYt;jHZ!U%~2FUs( 3WXuWZ;q U:ϥ$ +W 9PA5ב_Z=.pjU3Po޻\(<~*&(=]dYq| fO +xڝm -!q y7 eʑ,Or9p!-j+*aru!k~ف<ř+& cR(柈<]z7')up‡1C{Ze!ωd >XOp=,~ferf{8/Ӄ_u]_JEZ6|Y`k{'h'0sykgբ*9eeg][2zcIGۋyW0 q5Ь˩") f'O?e\؝ҧ{GzTL*m,㣅f .i#bV^iF_k? p4C0Wn.ףI `</H˦90`H׮4RGa\"(s#1H[%´rsa F[^v Uπr4@?v ^ i*cx{cQx/ӿ{,gB.G}d,rUWs+?VrW/]߉,̑ ]F e%ێ p:dvC-̇8bUwDF?t8 aJހr(d\, bf!0um*h2Z7FE)l=*rIp|leaNJ(&eE-ُ#7_wDL J ,gNx&1DXs:&Hѐ&[mEoݠIvM-k.us(;w ѿ Y152ԦA853:DݾdU]meN@>g;9ˇC ;1XhW7aBtgŹa*m.7Jҋ!+Âk\^ɜ^6G 8Z;Fo?PO(C )>Ujzn$YžW?|ܮgC3!I϶8(Ug76{7eqg*r%QVͽu)+49ē(g&=n^o25{j_9; BQŋ,pБߞ!;[Z*w% ~ϣKɝxwh|mqoXUA~'ֳ̹T& Q McQ[PJDe#*Hѩe/jgR@yRNsvjET-vEDtGss nh6?tk, "~ȒUbXӒcGk̎ Mn}Pq&R%R)@0G;JFi.l[L GqzX$+&A%I#(\Nf.d?E)hB J:٥)1ɳZn,'u6Lw4 5l +8G^Jz$Kd*?2,S/^8WM1D)'ϐyߛzBNqnDdȸmoԋ {k \ 8q7Rm׭]]S/?um+̀֊XKD; O\Ƙ*ԓxї޵7 f|:*[LrՑ20 Evg6KCoKvc'5so.ZpazR!$1HF~)UL+ekr﷮ϳ5f\fO(LcuG#aF8*9mfpRdߪzOlpA\*+l8Q{05`cFoLt|u ,sE#]ld۞ڛW꽊8jrLn.zf(TyYSlTXoӜ9}YK-{7)ɑGk8FLLMЛ{R^Y0iM\,OvzD`дN/7$" 2~c^iprw%cjs' (=d91]:H ?mvVNk]׏F E-r&11X9e]" 2Qг,d/,y%/!(8:gv!Be8ϙZە,iE讜51f If$Rd`Q,g|CX\?8uK!|4"lAt#/yJPN#7ؽykir!.X97ܖi)i|g 8eL(hW*!dؖۯPohrwʬߜ*0>uxEH4C\x~Q`J0WU_qcQ%T8uG^mo ^fB;h$q(|T>)B"^5ޙ+ 5SIQ*@ճ"Qju{E\0ET^؞x0>TJk<%67qPZyRBL]% #'tyE B$ HK}jk& S1JEJnT ۥWusӾ^Mscu601'N@8 "0倉B& ^<^IžԈ4GO{AZzwqxv S M2 ($!H8xF(#dF)N4m$Z\9+i.la">^ 㥖6qY#C%t/`4h7eUQGS~.FabS}LLh !4P\%u Yʰ;g9|/, IA0}Z8jfB*_T? 4~"4GI4#t@҄4ʏ izDř{с7+_}b%ٛG,qQG6prHr)/UiJJ/*eHޟ,ݱu'0 zi`kpT;)SLR XA5)yji&Hs0.NƔYg!ʀT~ܵ{Cb:j+3$*H>*"jeAv{A?e*lsm_~0}3u4$W!2*H!I$ +Jܽӿjc,UWJcuYR OV6vȆ"7:K[G]nTn~|~^dVYQg̽8xS*t4^(܆$%/i?ǘ"AYbdrkKS}s cHR&rDꫮ)J#M,յ.66f (έA390R*+< ߻?ݛSQ[QbmEJ~pReO6n 3WޑE K#G?yqTЁv<352p̫fymuyΈx\r>u [1?BB͹vx_t[Wͽ//%{F[`%X)0vy^*4 YcC}r"c,l=',B8y,}q0j7F ݁\*t +TWHG0k_s?ߟ bm&R2M N0y'EJWE 1{4<ĭ?eئ9RԼaMu;,/4Prh-uGRTDqX8Sq{ki2tSsFvְz  r/6gGVV D?XhyDZ{cU:쌁[]I??|%P3FDnrk.͒W{0_]QFTqOB%3НxgiLZ6P/ݞ2IkPAA^(|f10&kT=yhU e!gH[g"Wl`GWC/V]oz.PrrF/Cxap=6+,9(MΘ@W8?"&m[ϟ`:n/բwx_wb nuީ1DH2}5cSK yA jp&mLQH5EANy~Xke"yBq48/}Úq̖O~+J"dyL%e?횷BS9ΈR08N·ttza㤴ɰ%ӃQPSK=c?a E2¼8 ̩')tkhia #^S0Q$.%QE4Az γ73xC=LpQOBc`7)/ F+~%eIq>ƴdꮜB)ˋ4=v%> oL$Fg=u, !0lBqb^.QX&'VcwsKPYՒ p4I/H<<23X>_E~EQE fGIbgм:U'Td7}E.t: VgS"eYr`AbA:K|4ut8iimrELE^$J.Z#Ɲxƕ{M5jBcF9[LJ)Y2| y*ѥ xJUhBa` Hq"3?<\i75Cp޹ jN,I:stJv ɒ$ݣޟjaa`*]WXn~0`h|'K-7:> Q*@жݞ 5q$dۃka]Ra0dBB1eo'[G]dxl\1Da ݅)bwYSi8 }il‮RM NʯEI:Z_ rrp‰m$b|RR\hV{]״}ʲ$MLO'ƿ+j_~,sQДIvP Nh=p)^piضq"NO-"``|s fZY(H?yp,G?}YEz3*(ދmTTU6247^(eA2x\0TǻLqOHJHҕ44&we~lɻ2ު@˻Gv'BnƝEFϔ3XB*fliq<-+E ([#u71jO}|LCZ8$zh8]+w1Gx<[|Y쌦$4鸦*/K tcoYkMgrzo*,'TDEQdԊjj7ϸu l=y;_:\L{e+(;:I o/mw`t#> z̕XY΋$AˋtBB֚GSʡD z M͎Z1cɫ;zӪY5iI}ajޱَIp?)Y 8/5Euh/hmwxY~!Q/0JnFt?vv3s;w7qK:?;:|DKt#b\B 8(BC8KVa9t ($ьDɩr pa?'+.cs/H@+6c,֯~O_Ϳ_-'d[͗WdQ"FEoPVH\!?bC1-s*p%Kl,Kx^LWܢy5 rG!i)5 Gdh8/d2giƦ}2uK,'3M\J^AJpyxaQg5mvIi ՋHD;{Ov *%1d`$2WT/guBKNՓJ[YT}ީVLGS$Oc)W+I5_<e9UtGHE⍊Tza3`ZNdJ!lA34ʬbCOכNo K23!vF3jW+ҁ*$''7ՈS8X/&xYK6x y Bo7x8r aU a3ihr=jiHkbPRI/76jWSqsv>+O>ٿ5rSPJxN 9.G$`6%qPv騤rqGT? _Ԃ;.6 B(f7ڏ0b]Ls6r.s;ypBk; %űKh燻=وJ^\7;`X[ZUWxAHdXCѐPIdser Hz~)-ґ3I2DAT#$4 bYL-G[f7v;εZ'NrS7\߳"LA,$cáσ) K= i;2-L'[o%D,I6E(ڧfi|z4Z'9,9gycϬ&v9A5f4hЃ!E*W-P=̙daCcONJW 88nTE$"IJN[űeaZ{he5'Q^M31D#rwYpo4uYD;z|^(cU[>*#LEq;}'ljF9~71n j_<^FU,4M@(3YH 9J؊Ry] W>!OTVrB;#OvtU(y`^v`xa !z;5_#9D[%݉_t}NOzx48\)c6ƒօaiug ³_[nd8Gʵynl6v'# :D–;^_$D$#?uk~ vmbnWFK`rt||L$/pua^oalͅXfpO<11c0s=f- 1 v8x?CӲ_NԒ %xpŝ)(65.=,*0uv'V dDpC[ɿxgpdFs)eDtCjN (s؏E+ˆ"ĝXg_c*VzwVq&UxO#P4&4egp^4Ў&B%.ׁ:/$ f{[)ۣ[Gcf+38'eܣap'N]Ejk/XeQk%Tz6ߛ~F(Iߌ﯄!U]}&H WβLl&4kh9 hޟ-̕vknOM/WgJJn˲CDW6%ZH4xшjcذ+u'b ZJL&@og`z0Y30"DYsO.V ~w,GW|J81}), ϰ؋jH'\G*/~h<qzd>ݏSR`1OHlz /sҞmtXCI9 $tN%#.++#%C,<:_N|%'[G@s~2#Xƛ] yKz M^7dzx=A0L{9BQS'릞3t *ioyLIvkOH1eӍU/8glgUM:oe)o#rםr2|qB $^ᄑ3EdѥP>W=1.\e*mnɲ$If`gy o %C *A-TG i.Bgmq !R&)aQ${IrBDAp8?MEcw "7ZR^_>L-?x/3*JNH~p# ڣ#g/ k{Wd9=ʚC]iv5s`zy)E۫Fi Porkio0 *]ލ5_6tB߬@ϧemRX:pҒ%笇F@*Ĥ=(X3fl܂ڙ3$ΔtR=SQo.#>%eB95;<y'+PYB53 )lJsT\4xBn~yY^ ړtBϟÓ}vux:uS#ǞaVPll?dOv8߮xvue9OfN50*0/?-T;ąZ.)DB1b䕫3 |!)d/tiHmO5:4{3ID؝@qK CAYwD>$7%8N!xt&/۾+i}4ߪdE=:sh qM< Cd␉;j<K}S~p~,;M> dy ZF0?+]o{3\hQ<뚈N%GNÑ՛wo9*F;/N|$^Z4(YF*0 vuX-B~tOdm~#ə2qbλ?{FNT~oi+,t4Q_=&zUV)iْ gWHڭ p$zӺ0TԍBf?'x`*5+{q+0iLvZrY)tG1ؾ*8QmKo$Z6oW:Hixg2ʛӳ8␮_O#r]ݳOLqJ@/K_} ??|oZ2AVa?ʂ@J(`/ûr"|xسtڙZ^$G2W',Ǽ\V ^kK=`6z}e:7l|*,ml(`"Uҹ2rdha& 0:9fdh-N(~ow{¦5!PbZ54E"b0AA#' io8yVO;%uԭo *hBOw,C3=K0 ?1.D?nС  +$j_?R N (QܧBQF)R֮k2U$J[-ʷW YK2~B)wKYC?$h%EJ('X,݋ 1}[e)zNm4'+s7p)קv%&6n4?p7lв28 𛽅ke@pN>njt﯉C;8HtM"2I(F|)ھuf4,u9oFMuRA.DqinP_|6fNȕHWˢj+`f^h陫!Zk&8+Sw7 _n%qƥ9>(slq 'eEt93$W~w8{BT\?TdA8 g4%ߐ=;nGݪnpV*_]r^tsBiv0@ɏno=? O~]7un/Ͳ|:de횒á͉;% ԹIeu魵aqG64PhMR,NVĉn\Oe% DC$덽2e:zhp J dKق c]r[fQZJmF+e MAO-IXT6a`.U 'hxNdPC>/=А|^VH9}o}6lMuy0dݾh6UJ&]R2?b=茐 Ɛ5z]';1_e^(~n%k3n9|mtpgNFNt"L~&-Ӡ|dZI~L~A,f1LZT6l%c_?t^ l޸;}fs֒y-5Ӣ@U1¤T(Fg01KSE LϫjY=YlDz s {PRѼbrTKR* Z+޽_Mɍ?x^fOK2<yEU8Q/rcTT7H..hUՔy5eIjYK=rNrcx{M} XJW&<*Xnr2nU03S =gsnr}(h*]iʹn~lxoE(zE+,qruV^Q{9r ю3ف3J;#x[7T^B mzuz\Dա ՍpB|ë T-:'MV.ymNػ+ M:^ҟʾU<؛βǪ t4qbdiZx~%"@9XJRT@AX9IpX>yt]J_=*"b?0Լ^KOw*L›;[GAu;۠ʲ Q,=5h|o̹<_ Xgo|+$󑍼~`` +K8*汮she 0T;)%W_kVp*Z{c ݘ~A TzSua񘮷S?Xs 1R0->_unH"fy,5ȝ/7X_⹠|U.˅ ymx%7@'<P\]{J)G{a3L.(^{!l*V4/V:mXIӌNZ6a叿OK&5T;Boҗ+BEO=|QN\g0o,HDpm.+:v0fN\Nb\.g>ٻzҋd_x.;FΙ0{M%1_/\_Ʈ1^8JbgYU!8v::?r~C͢{_x.o-n}QLs֓4uּ_ ts3W&4JdFOԛr R8gp⦍O Jȳ05ivQ$~εi.WQZ|cD.{- {"oD/LFXsx|pU_V9_qH7=]>}=/B&t2Fq4]VHG?s^aiN$Snaν`3\rKqPLp{e]/OO)A"rgJ4@9W{ 9az4R-K2DUV(}M!RJ UN3[B_{SI"PC~Cz pjq? r6I=05KQ}'Q<#X<ȭ}FeuEY?"4WdCWP_]#?Xm/ Eo/qYދeC߿<jAŘE3`* Z*$a8#^@N6$4_3{l=7UjRZJH `~{HirBC mvz4FI`׈vY8铦H>-Aݚ~7ގ7wƮQˍXWkF֛/$U`H{EWޜ/ yJhiJ^5VZZpR˜X@(Q,Sw @Trl<>8?Zm20 <.d@S; menݢ-q v'g (vi#Ld7nGR5WV%9luhjIoY^$hZ ϿRen׸9fұÎyBo5|aA,l )nQJTbNDMr=lOxL"Y X{毪D&?#Yoo?r"̀!#! x׀ 1 r&A/Vy޿]ʆ o{닧?KRr)=+:{t )DK&brdeUp"i?x.N!l9>y/~Mkx?=_}a]So%784:< ,I4$W](ۋ*Mlx0TY ue⌓۵߽($\҉/;-ԣuOvwW{B0Ǒ3Sqn:# cu~d^HmnJɯb#IW )BD/o&o] P1/hwBWؐo6'Uqd(E;#ꝋo Dٜl/ ՍmU"FVN^_쩰(ܙh{$0K.|pU-nqd(L@/_=@YVYdK5;'DYv#l 4VXjg,lNE4ucT-c7ȗ~~D̓0>ωߚ{[t\ G]Q/My^QE.ؾSi p0ˋb'C'`g>1,F~gfxEN19D)(#i-׋bMܼ=9| ȝr$Y^0,PvfAv A%TE p(aqe(V4Q153z42MA,m=~'FO mu;ע( zec"W<c (c"Q؁ p\LԨnE-T͔Rt8RW4qw֬M ^`m&$^xce*Ҝ'tײ\ݜYl+,7Krn̻[b/*w`6…{qvuۧ \ɔTT4%!pGQ<Rzw$ :Mb=)h10>v_Y,7>x \ yrªf6Œ Qʩ3p vOYؠXP,vMI|K J;sB%JRʔ^)9/R}/Z_ӪJ_~YЅs`.O i.. vv́GBv{i>]hVmw_P70 - ZX(;jkӈ[ ֥qOǫf`&09qw "qBW-J*&FA5=00TMM&,*aE*xU% 啄\:üe^f޽8x[{b(kr7K33mkmbBDks< t(C۝%Mu92\)e(#}uEucQO&(+L} b/iC5kW> a~lЮqxo*[tvW.}=ɚB"3v274+*ng Mc8Ziz(c'Ms zbD)3/x`fgf rS}9aYΦ>1pZΉ( 1;JWĬZL߾vX4$.<(9 udtANKy|cR톏xD")Kgϡպ[1Vvq*(6Wh +f)4M2nIn$ԩ/ 9[*qO:MM.XX9G#٣Pk`TCp?};yB/%e8'OnnkP~>W3h.vxZRNFvR.4V|TWU~a]tI wWHk+5?pVѾ3\Ģ MuHS?p $& 98%:ZY~qzyN=.I9x_<֗7N۪ p`qBwȾr)Omyh4D.Y[IZ$s #>HN4JnAl3(+Q8M-n2h"n6X RÍT;P/5ꘁ)Kݹ >;fO"W+)5 23Yp%:~m_]?⪖ѝf0ᝀOM,(x^n)^Qf2#N<*^xį7[,*h2msN~}udJ?w>S6ٯ1Έ 8xw`.H?wgOfy9-tFWTن)UCY21mwoږͩyX|pzjg5CKG#)ͮx~bqfjRUs$5$jlY\F 瘓g| %/Nכ-(^-[CMڧ^eç>0{w$i!Piðm{i/G̔܊0{r<"ʪ]EuB0TLns L^j.֜E>YPX)=bMڬQyQys]lw߬^‡/>䋲$Z,r*T-QB=kBJyAǮbŹjks.JcOnh [oFGE2 ii6vչ]IqUpOӎ(ȖYnNzv%T2K+^l.cwXPUBb^YAA]GQq&Ĝ+ϑr"Zzfvy*iu'(4xvcV2Aᣁ[8*- JG;R.n sFq,rQ&w D漢|B=E+-y#Wax:Zr%p ~xlSqǿ.~oK/ptJ7EaknFX)};B8xr2q*玪0")F+Ճᵹi(AU+3f'1?ɨɗc/H~\$z~`V-awmot~^)yx*n@4]h0 @rԏ&ޠFM \II{|_k]Ѥ 6ӟk p8>[Oj8( 'o9Y:2Dep޽O裻͵c^ rZ-+s飽".B~хY<p+v%{" 7NJC4,\E)0W6 f],?rcoZ4, RTYgaNtiM Mqӡ|d!'< \0\50KQ .?vyx`lC!'3xAw'#Ĝ$D77~=kԻ"]P"K*s(M24*Yͪydn'h7B" a~W{W jv5'y1rd<0kdhfݛ-J7S5p9h Z| H 5<N܀%)>$}?idr0Wܝ #,x4/7Ro\">CXo[~g|urI[I€1FxNɹch_r#|_^l)F}!Uw]S @Ѕ!/p\̲魅r rsc!DIHi -5 *9 )ZµCrX&xcsqǪ_oUCNӎS+zuNuWʣr̡ J$~Si`YiNɒt~t}qqW׮ӜN魅} ŋUnJN/v}U)b:"P,1dB%aeWY@e s*8&PT%;^ i3Lx;85M]HAɅFղ\2 *^ȒgnHYT̑N}%ypv׭lЙhh$z_>&?[XnA& rSxsy(x;] |cTT)r(pa|lMM?)WM3z4T!Z-#eB˃VQ?T>c}U-(Fy9rIn,3HX/!! |^{㸵 3 ןM蝧@,<2htpX/T $ nH7r{KECBEg ^><_}TA̿>nLIeo(?]Z*8 xR7 {l8}e3&Kn61;#q ]/TܠjaQ7(}nU;(Zq^karcuOt}FR /^vؕ{ݓ4JHH" 1QXztTF4#Dk]K0UlFOHF9>'X4#z DK \ye\UE~T9O@TX%PM 'ܑ=Gӣ٣OT9MUON[482jOrJ?;f(6Eno_B9@^Gr<ēUn.ec$?5XOWQۧ}es{WL9(@%7 0oj y@*m‰7g{uE|ԭQiZcF~X+0^wC*iV%qV7 @{SE\~a!xY?TиM;xC8("+чw clYz:c bS&$ lG~L).Pl  ^y$Ga<_ݛIaV5:C fLt9+GHDS#O+y泯vVeD)x!9!Iv]o>QgR ԛ#(AC4%M`d>_)-W' Hdrs<ڦY.sX}f,^OuY8LYWW~QtCaxWSDo{SDorV6x2W7FQ2ǡ'oٔ0ᝐL_sㅕ9?Iwzl/_TCH$>Q^0y^Ȼ5HlBۧD r`iwB -\[~dHsY Lδ=@ٜWJ(at2NjyLSJI*%)L<=JM,o4|}hA,`HCrgPfMZԪs=0Ig8,ʱsvp yw?~+#>W)hûu5F)Ǜ'0y4ˆdy6[TIYNsz185(R}&7['7˕B^t#EHdʈuQTq{1o{x^I2JnDi&1lvEXXZAjZ0'+cWM?z?~R B"J!nE-ԕtI'?'N\ɏ[֚+T'p8HΛ $G|3"Ǚ\͉7"v_b,6dfSgWHH=#̟nΗ"7~q=Zj( @rZ4' !$r7m-,/=z_O+zhJp()ѯ9Qs+hۺQS7]rN[̕(`$ѩ]&vo,sUGr $zH9'9ExbO*9a Hx yT8nt&[ e9gS +b߻3Oεf}h돧$Q7XS9Bwz gOVqI,Cumv:5Ufû:c1P{oE vPS}<.N2Y:c{P2ЬXOw'/j!'p~>t4ޛʘ/c8:ƛ玧C&.BdsUYx =98nz~ahK^~Hmt 7ۼsRmͪT w&q[2!Hr` 8ACq`ߪ[%?mϒsM'Pj*M +j aL_.wC!&Z^/ɍZ?sB0,M+/_ Y kqوsfo S ă,B "/><"U4E(P6fq,R:KO2?sY>%ily1رPP>Lt_)YNb 㜺EC@HBerJN)BesV˧uW9P(YƄ$ $I ~;RA=ι~w2ݎ $v\a||J}*vFc¹,vl$[x\ zي;{?ڎ -V'R 9< 9NS^TIә~|_n^?c/[=8dXeCģ ^[U(di SX$S$dIH\y % BerBk`hܢ`kfg(ifGW)piN:͎k~=z^z/Ue)^Ԛ53 ։SxU$XZ)jL!c@#HRH)]p8@IJ_xfEir1apm'Ww9nHe/:)k:RJUP[8qƃ<մь' Ǯx8 i^x NRyjp㒌&tHOO Z-j čJ't3^5y?]/EI 0ÿzL΋0%6fIhg\b:@,2cf^nҲX.7?E#O"@!ĢI83+n-_3'e$>7AhkպHĘÐL~ƽ%s/<-\؏I&u`G"]Ow( cLObmK|u᣻jK'}u}A$w9Wrz1&]A3u/)3Qe>N^sGm]:pWwo./솉tsJ qiMQxu!zЛY&%~rkXٯ^qrߵ]3peq(@NP5@"Zԑ$/ ɷZ-^+'j$YN;t|Ao f)iB`ywXn^x񉗋<d_>rJWݸᅂ"JJ0Wņ&xۂ12D7EyQG̗78ۙZյ9/ KgiE*z4&HT7r< °ARX礵z0vߜXM3Д,gbիɷ7Ǥׄm w%;ˠ\mw'MuF cR\Q(M 'I*K}ބ8@$ \oO2+`aԟ5[ɯVcLN3V+i FleJA`_5h\ؐϾ0#GFtJSc6",3r Js4> YH߾hYD okA\ ӿt, 1xA?= y<au '\FAEgym_}mHer:I.hM e#e4Yr+ {ْEJP_<59Fȸ6:wo.~7 <|Yg?x;P.iPT ?^6ϲf&EJ# P!#v7׆R'`<'\4JBvj_ pq꫍…,9ARrgT_,}b89>Th$r*I#/E2G ܮY;]s­gx0!UFg*ėE> G!opBbU8|\z%97s~&2 ԱJ=>0<J(@QNs3B]s2hV_??t)fT+"L#TT@ sd'"s5z<|qZ!5͖(I$㸳d Et?F^Dtny@H9$)0d.UFCUr"?3!lIOKG'qJutO`0 b pO44`|>l$͸K f0=ӲKWμyZܝqE\Yf*##|, H;yD ɭ( i4}D ]r2Bs12Bӣ6 Rr\sa 0aqy"΀YKt'_NLh L%,=AHTiƉ|䋌)]>2x09JĄ0+0eݴʙmEFDrybF<μ1f!1kL$Ǡb0[/jR81T3az3ÄUdI bʀsF?JJ߸?rmC*4~\/֎ޖb:l7섫Y 2 #I1 #]z\=lm;,M('s45-Nxgh (cht8}[)kysbz~S1AQHnX.3n^ˮt@'ʸ BPq{_qz)<$*gL*)Ʊ@")b܋SDrLav[dr/8p0[C_@OvթLPhoR(~ɁsEn9˂1 {{WNNӍ>b5~ns:Í&5\P"=gApuʑZ˽+ ѻ(Unnlr߂B0 1@ږX5)cDPΑl\Q9fItc, #?C+/~'SĀ9@I&"vyآ3 2wq%Q|;5)7߸p Ӏ l](,GK8,9s8A?[tXNuu _zs*y &pv{_s)í!pTڍVk3$>CE; vC 6~Rq]WWJX^;tI6,Ou (JHz#1P"[@ ,ƒX́)ep̶3qgW5@]}p%YN+[x+B Iߔ@ЛwW+hV)2:|]"hѺQƢ~(mPcdqU*YBJ?ߘ i 6\D?eO;{e+^ɰ;o rJ}|AQQ:3f*uƑqXd)'| E{m/%D\ ݴL"$q CVJ4W`TB)%=E4yT`KτowZL!6fz{qY-GҚ2dP*ʢ(}&rpg91eS'D [B,KI?22uX"c8|&-M@UBG'fqCv3]N'O6{fHd@(HSΓp_Ula$_}߭K #,a=ufoTF?(skSGc" I iA;e dЩYg@Xjmkp4k,Echf0 =" C+ȹQ:%1Ŝ n͓[m!D.w^#$Q):&X|Rm_}jNw:x>)=qͽJmrJ^Vvn\Ss98yۥ~n;&;'Bǚ 1s9ypQ@e:k6E*yae!@KEէcߔAşa ErBE%bJ$^b0.WdptaPY9t|'K@; Cr~=#$w3<'^\Zm 0D@F,92PX֑*eS$9M &LηBҘ/h#ϣ(FnՌ۽KSla,>=ל*RZɧ&%UM/dD.S'2(#~VtkRVX  b9`yYS?b̆%X_U,P9%Ґ 0kQ@&j 8LG.]D{i"XR %)n6&ZQ`丅Lz6ղHq~ȘbBFݷ}ozwoW $QՔ`(5Lu-U/_=o|i*" ̋~{-eb6n߾CHR$$\u.&!2]a?~X53浃_<~=o 0t> B$ ֝|K' zWe4b HX J$fRR%-FSy/{'ƍa_Y,,s Fv F ^o/ꄀ2ǥ};9h5umFI-QU ,7%-7Vegk{Ig+_MlQR67 B91|J$];3jK #Y cPV.VZ#l{+/jS~|,oZ zV66)'n!f:ՋΘOWc>;ADSB;%h +nc S;Pɚu=I(ȓD[®疌G|:<( '`zP@Bem{vzqU$<"W!ߚ=aiO@wΤ3,L'/;7rBgUgb~{#Z͙l0UE=G=mfRڙǛfșھ( Xr Ԭ@*o@b?<הּs-"y:{j3f"CVgN/0EPq7 }G:,Ne\rIF{ܜ'`9R훢 x !wW럷u'PS^>y +T%=p?q#${wxO/٘#3д}!"Ƽ) 7fKJWC*gjrZQ2'_Jު3O6wjY֦Ν?Ir:)ѷ?}٧֝Ӊ"ѱa3 ًH HyJA$IP :OD1kelɚƕ|泧ݖ=thNH5/'T Lǒ=t.gA?we39D D9zθf.V;E,l?f8B&^ %ϗPb>ۺ9r*ӅF#;t%bpfmݕtyUQ?w:'eMCYG툱UNL /L[n3t.vi>7W\ʏ&^>[l']qʩ3*2 f_x7(=Kؒ eRj;:Oz9C#k$P4B.|{wfSnI/iKC{ s(N{ e'*if,zJÓ3DQHH`NF4oO,`~fE)}xjNU˜vH({b?xkՕEع6#VoD2!A|Zg?,}0d,Nvi{~ܹ$ 8Ղqyu "U`}"G$QxKY,q2U`Jn_^'RF}Y#qLSHiVL)S7k[ ?|=ѓIUtR޹_~NkfZG;-&Ƽ Hf{6HJ2`lDe(j/}3u^RJY^RzɶwINxWۑsz8qsX&=O2"[߃J>#F)"{eRQgfED  QWI*_8:˅%7߽|n7[l:aeM;fEG xRP%'Wr[M_3)yq$dv`ʄfL-E2e(mH^֓}:_Lo$&g 3fS'ef!g ~lIƦŒ3Ts}644w#qwH3/Y"QL9UPvFu2c2L\*IDB8k S"BMb=/NWt>Of?o!kC3*zonG(c9, >y Rҕ~pZ&g؊0z9:hv% \h,Bgrr"x(u8H#l*R0pZ"ި ]qw΀ɘHLj'gwLeקY8saR>>^PD'>o,q9B|q;0p{KGOL׋2ē^~Qb5[' 2^Q{S:d;L:6cp U$.XͪA/kRB6c5텢l{$Tch;f\14a06djKo\ZhC;:N.S(5DNE:Qo[#v0JoOY$Lݦ/ݙwC˙p!fUb[7ҖíC_uCGNJSЃ$8ZL4(bɗ$ #fxKq[_ޏ_n׷Eu $TRRTAZv9{];YwwZIGwp a79ۖDKbrdU>|v.qxBR/5]LJ|[3]\B/A$VۂGOz^IM.kڐt9X6Eih i0/ It)ET'D65ыvP 5>y-j(76~= @UϽr%!D|xڣ `=,z+lJ٠<%OL.ImÞP2ɾ]yAA|Gʾi]{潛=h,Tm8oIDATb>`z!'DZGOviB||iY !t웷"9ڨ'$5D0]h(9sgɯ(Q)?o? -xgAcjftjPz>n` 1k(SG߿ӎ?%aL,_J-]3nΟQfWg_=}aw_R9Pyr 0I::r(3W_L^O$QxDCjTzGVc(2[ʒkƥE59&QBA".N6Ѹ3]f(nt=Y]3fV 3I> +hf! c~gPl`!'*W=f!?rҥxuVqr>fg"]2IADMi΂µ}VdF.Ŋ(f`JHIxUhf-=A0hBJֳ8\lMHZ7ZLu'q{xt|ʹ|"<$5Rq$q1.+bPFG`j/iˍtU~n*ԋ%g Q`j;}Fojff+K̻;( 5~6cjN՘%;SmMPK) 8%½nq@U}O/M) yF1^řsWB$zyTXXUe& S-G*DGΐGL&߽yL\.cĝtֿ8c$Y*l4(*q˦C``qxǑ=y)m9rg{yA'bnyF1Ra@;]O$\&ysvU :YC\U`Oۥ? LS[N ?ݍ]cxͥrN.,$ 3[WIbo,h2xAQlQb͞{ʿu[9m֭k~`}cU8~Ə@=4oN0ڟg\~RO,gۀZ7kԷxP4rccrj^JT.wV 3ݹkV@dhc`-(~6QU:JJ:Kmv;a֒~K̦ԋ{hA 9 x.|htgN/|M[b7L\RH@n6aeFb۟>vYFp$vl-ݶ ]קi3C2#ՏM>xɤwp@ e@$PZ?e'irK͍㍁ygYUőhZ#y1uyhKq3Ȓ2W%!zF-B{G=,IB,O`aj>X0]{}YN'q|Fa\.%@6ʙbߊlZF̙%gYK[!tT*9쓵/UU8i(WS&Kƭ257bxmϙXuE-I XSXBѯ6" `|+Dɧ1ATPI]m(vdeګtr.&%ju;[3OF31l JQ ~xy'0 lVZ^BՄϞh&_HA‰qa^ޭ+OWАLrֿs)2Y"V@sqm $BgTjꪋFgCK[O?# n}%qoF)n%M+ B a !AH8~M}Pg מ8Z-y!(%59DzLo/Rƚi)3Kы o^E˥al~+Z젹Ȅ`q/~m2$K/^nXY7noZS<}p$T?V{e/Q;AgjQUXnJS˶2gk\%>D$tH;EɥaM|2ϥbS i^~xwC];b-L0+YkJ`htǏ IKg|`ޤF?I+˦Kzm'88D4#d|{O?[ԋ޶` t@+9Â&_]sjD;= \SRa S-m 2UvP|*9~; kyUbZHJC XǞʧN ;Nw~ެWЖjZλ"=dK4V_/ %Km+= 2Y0P@ĉl0snGń􆏹x Dtac=3͐Y|Y5dg'Z?e,LjW>ݥ^wwW٣8 K)sikFEBvГ( ٠;Q ޕr^e"+c:/^PCa̔Ӝf,7XIۮ=5T%]ϹcTcrGLeR?>SYF~VΕ?'NL(VRG*e>jV`F*SJ9ʿuߜϜ;xbȒ}дoe!ܸgSY "ӆoy~yRY~ xk;ܙisf+A@J k dSFSk0 9v?@ {(NaIk@.[׏ 956LnO{9V\:-¸x(iݞX.rr&4%SJPYwtm%"3M0Rf#Mo߁.9DQXʸl%bN ϥ\ CL{Vx t 'aQ$ŘBL_TNƄ"l<3w8e2K^B긺¥"D"Ǔl]vY+#*GK&\R):UnT G^+ܘ|4jԽJ w6\蟼O{rb\_}5˫/Cչ|o4oK$(^]*N(m]fJpR:?tTʜk)we, #UKds9gI슢P;9H/)+۩Tn7S Sjv'k褝ڹXQ@+S SWlWCBp8cC'I(HY•60b5rI [C%0u0i~ő=jPK7 \_p؉pRT?Z~Ǐzomf2צۈ^|=+Yc&phgWakJ AnU%IIW1n4J-3}xD 6u4_$n(צHXXB͝0eщO34RYNEcgj.ꇗ^ ȩ,rbtF mꆚPSU@0t{pϧݷoq   1LmhZKߟ ?9߯dK Rsh͖=/=1⒀P[oe0R$^\"+cG^yًfSQ>Ou>mѩ|NEC EgbtM|8u_v`rw0[0-YRCVBJo;Q 8GSƁu^*|9Z;p^1)iH $ pGGZVrыrDc,Y5,}^*7͝CcaΤ (("Q Q-7**'˜K/{+C>%O^PI9%h!ё^2nv3uE! Df4Koi~Ճ5x}TP}Ysf=\׶rV?'aL6&sݯzj>4]Z;\צϯ&JܳX巽+LdE66jdsM%g*_!wJ֟~?&,+q"QǨ-DLc,+r*0NDr0$) Fa߶^,T$2}cEB|k+ɖ*cmHl/f@By~X~ck٩"TDLۚQ&<ݫb0SnMdw@rzQ:#Jn&yQꠧi\?2j ePkHU'Os/oϵ 5y*AR8-(\V$e*b8XqĀwk %lZFjsp nyJ^jyaum_p(ɵvS/*I#軒`vÎ]\hj^T\@տW{ 9x@MBSX[ۻK90t9G`@JOzQt'[sUqZpCi}JiҤcAuYNkZ9V$h D4i#Zr)t C>ӝ&{/"HOP^l-TdvzvwK#$F#455Ƹ((?jgH QtioZL^R.q=YRqDq"\p񶲱_β颓:Qnۥ҄Ơj;y9D%; y@CXᖽ\*XȦȓtvvsԙG kbVLiv3 #vsJjS,F=(dHL]1Wh *7 \zLH1e G(T N`yV0rOMvv̂,$ 0_wi^iZX8ItŴk8/}FqNTKI45%N_4BYp4Ԕ_Awⴂ!_u41 l?>$IHH*F|Rģo҆բϬ)~Ix[];/ǘW8 &c|~bG @?"] eIm&'H xT!Ly_-eܼTLQ0Qr:-Za~n#iujOw(~?;|A PU`"j$*2 cRc`O2ܜcNX('_R$\ZѦ?֔,^nUTH 7wzO0©ApXXt)_Wgןܹ~fr3IܢxApRg:9 8 toz`d#M>O$/K{ml'k[7se()**Zu{16EVתyFn^~mo<>΢f>oZ!ݷ\WX#6lyY.otoy7:qkD$1%06$)޽ʗO,ū&Hr6ǁݽOg35Mf \^l||OQ!g!~?)ṀZ+B[߷\wo߾ 1Hۍj|Mym9Ǻ^Кj1?Se25h銪Ւ(8;Ѧ]2CIIJKbgAo)R.pH.%3@ۃsx )m!7Wݑ?؋)q%9.ao]K^P/&#y0z":7ų_`b{wzX ,V8~p rA$0˵S#THp `}I.QH9XL]o 69K㺢I݄{FLcQ2w5qO+SGk 4ʩ{\#{f\QYpQZ (DHBQ9Mw$}+B{QN 'Dh)p$j7h'sɉO=kpl* I#DOX[yE !#au;'t\MLRrp RVu0iv[5չ̴8> $& AD )eS=u 14m?fg?oц#ڗrlRkˊVfKri2 9EwsYpdm׹9/Ƒ5 !T+H_[pE/:O5 A۬&5GQC%weeSB%/7KaOh)M?ČC;#I}o㡝D|-gZvH-"_aw]/fU(h!!| GFypX-U'欽\G@ kJ>l'@X9NEi7u7YSͤv V]fSݑ* qHЊ8ulOc4ٮ*v՛J}Q-RZ 9RvIz `PQo SDS^?١6 MFASEžtΪ~b瑬. 큿ەʢ(_?q⤭\%dY6ʌ":$LxNIE3sqpʁ$/gC5.z#=7u ׿]S:8-ɢSTχNȔLu8%rNU뜺&3ӆ z}@, "74, +76Z#lSYrApNhK3[Q=5."KDS3 Zh w,' ӿ9_|;{_C˜cgk+}+Xs9`>;^jJp7S-{Q.ps^WMY>pJ0")  R#ɳ(q/Nev+\ kz~w}/%]qhAOtV3:^"Õ&zQ_R_w Z)Q^g8*9L";?*eVb\N%H8]ǿSz:FkbՑ%;F͹X$5&=Rx*n [?^Q߿~$[oNqx;}[qU_V-݁b/͉"TzdYOnXu߽\Y{*3U P&2>n:r""Rڑ3*_(C;Z*<]%F!zVٷePɜw%ʨ+ H S&˂ [n(E’(/rʊceg(G"|QtH zם~JnXWZn;۵o+'XIdмl naZ]KZh[𿈼:3{/=?UF=? S@mLƁu8KxL?| hl5IcŔOE« 5 +Vt(@gwnG{Λi0 ߾i=7 ~.o߬;amwӡM!GE^4S;È}ݱ(O"ZF=+@sd wIwdre^txslZd].}LHS/ eE))rtFo.TE=ڱ+weQ!__GX!e~ vRtV^e\JFZ6'I^/,'4Л}%I{ߘFv˭8I O<\ `|$:ߐ),N;HYLZzZs6%hR!CeL:V.rw8@H)o3:QՉR A]* }zvWRCw &|#%t,\v`{(`ót8E~jv (yETcyo&+5ޒPXoďv/J?:}-/J<K{@>ɒ׼n^eXy}Uѫ)÷{װ( w+Y*95LvNYy$\ '43 $|E絖=yr ,H hON߬]ZY׳_MkwmR/e2}+Y rzwK?%S9Q~) S{4SWa2 c0E tD(DRpD։qL%jG˩l5.'v%6~/W4Ղx|m?_OTe|8%>\?=D;Iԉ2DkTҍV:%qz{vÏ='^bicpyϹ?K_>o'm&vUcY85;b^ο`<Ѭ98A)RDw㰤HnȊdm]ǔO_̤zIq>_)""oXw$먇#gZmigp|Jr 9 \v'IߘzNVq 3#rbpCZ ~?Fg.AdZWKPoea.a`*Ϩ B1-IJ{'֊қRK?|;[-ʽQ/F7%!ɚ_\0SwBڔƿB8١w,}}F3˧w}s #4twibB8w,YbOl6$gl%\tOSvg\S+ gno@A]8x~þRɜ*}t0/9M Nd2Sab,bپ-ԋrE{8oPRGi5 agZFNQ%a(kQ+S-a!N,76Y2E|RE9ce\ X/DG O1LYopDiI󟓙bSIA͒'_>o}]+uT~v˛dd?|Oit/P-Mh3ETN[]Btüpg1##0 )}\)'w/{"F;aJطy{+(j9:X6Tb‹Fg ZQJ˽Dmy0*ȏGƸD(H*Ov!r,bA,wbI=[)#Kc$ ar浌ٳ~RS,򟯅W[?b'f)$g*NA߼Vzm*T%aW*M{x>xcRxii3SC ~YLiQrLPX{OFb"ԉy)}]߯/W7TqDa0?R8 Kqo4Ҧ*U=OwBVr^}IRXTGhQ|sNqCɎwϩL ?qKQz^7;ѧk/hoR<[Mip^EIîu؋mu+ 3.7![Fc8kO f=8,b"v]U5jӒ\0~dع& xc͆1",GG?~FV/OkU͙w~ۇƺ&]#^"8} wz!JsT"Д q è\:/ԑ[U3g |ʷ1姊S_AW u"S6{g%"38h~'kOǜEg$\;01Ow3ƒGGxEb y),^F$ 7 5J/;:CaDm/QV7`yg`4S"?4PY[~gt Zۏ[}M#üquȹ0UL3fy!KdĘBtY`]ۿt3#=|sGt8'䗗k9_il8!"gƍqu^wrt cv؋mXNJU#V9]οk;mYRT6Tˡ=|]BBwPs]RlIRٷY ݕϣL%Ag4VD׊$ƵlO?JJEA۪$c04NJs֪WYċ^l FHGfO_\.̗`;sW_!e-&`Sֆi 8od ]bLO%/3eɗƭMQ%NG|Wc,TeͦTF>(0v/yV+`-~SXQ<*=Y% k"b s՜( y!siIIiڋ~.%K5{&+3Ţ?>ٲ˩ڙV| Q"h@$!G1IXRѯF:SZkT EnvɧOo^o$eNHPd,"pb0CO?]ʄKSׅz)?%1&ΘUY4iv{q`0T.K0}D$̔KED8}I''w&]?ؠߞk'yO>YvRז\YMh9M;@9HENG L(ʊ5{P/ drʘa9 ^-0_4 YN %NLbjxӚbqݧFhIF$J%Of [3mhEB:CnhFQ_S&)@*ZF~ gj9#e*d0Re&e*cʳ) # ^Dz)::@p+b`W_/M-AOs'01P{,`Jր# x]L(v٦_H>y1?)N(:зp:ijVPFG^(w;uy=9#f4WQ UX#1PUr`U@|1SJ$@0>9CªxJxK48.R3rlBe}TA-0F* 3IdT _5'JyQn-Z1L f<O> /$+Pɳ}aӹjN Q[J*Q$ezVH*9QhX?q0"q R<%yǜVHcC2juU>=-b{3pf!c)q!mX3Bs ?@?|\?P RQ+sNY ˛ß||5UÝC{2Tigp I?aҔH_~ Ƕw'7fF'f3ətJ"5)lď"vzAf +ˈб/D!G i iah'V:IoH0kf5t˔֬i\՗{n|17o9l7[;<=Yٕ$QX6k3I:S!GYN1EWUVɓޟahF);|vh^7VUIS\1̧3RT -xn@[C$^gE 7Q9/Vc5@Ѹ<"] FNX`)M5𞞾54uyzE\rяP"i0c8DFnms$$'kWu`bZ&r iK ~dug0#+T51;kt暽# gX(:]QCޱ$e I&р,Vv#cѥY;~yAPz޼K0> /3^G# 3[[.{RDQ!D$D"D+3ʋCM6SƇ \}x; 9EJr(o?%?||cXo׆Y-VO]1`p?)$ߏzqSN|4Oôa{ރQH$eBdc\GN,k6þq!EIf'ID{YH㸊E{GoEt~f*yeRiw"Q@fh Mi)"+w/'NLx[)?|ֺrM DX׊iPφ%yt]l;L ͤr^tH0&LVv';۽F5ڽwre',޼`W]Ȧsߺvc]VP:yJM r.e*ՋoDt!xƻN>Ǽ>:ߺm?釪?x`CiHߴlO=K^/G^o\<`-/UV3~xtߊJG(v: .AgЌ#'RYrhnHh僠_({ĤttNKO/LT]֪gGiHYBhƩ 3A JFrexmEA>ܦ?~T/0ax @}}cxMiA?ӭ8v%(VpDQBF0=}+S(|-sotz:`,p]*/u}]z˲hckRq=UEb~x׌fgn5Ok=׆Ty ݺ^?["KkgPPʠRFX߹G1v^+8vcl e[ƥȒە6oe 6S7oxGaWrfeuMu-7:@6].eCL-:n<~߯W4VB>8W7LWL۲FNn04:W .;x0zI4!e(5mg6JyI]muז|A;GHӦ5pÁǔů?zsN)> 6b+{پ~PkAV0O2T :5@eG DJb] MX$3wkPzRbgpPZhF#5ѓߞmA* CW "X*)Ȋӭ(~V8؎&+9Gxe=iȼq O>n(K^&uQgagHB톷"qU{DO4ZZKL-1$%TgVg* ߺcj,ǿڒqʫrF> Er]>QG־VqŚxWZw޻V$ ;g,?xǖńrŏ+Π2F%yʠ񽻉1RZ$RF+D18vn+JH+_}](e4Y˵ֻIPdwk?87fEuqw…;MN_# ė^@ B IAD:=3w={VS2#߾uqHΈ"Vvl_P?EmOG^=̽$ =sgA"r@dry U8,w9-JP&ij= 9#6Tlk(,fK󍦘2(w_èkO~N/?>'g׊cHoU.*K^R% xXJDHfA8.zt/(hFEx-qޔ!*b°e9ӮޭBi]A7O Mc2ٲɒ$/Ga V0X1eqז#dy@@Y1ѩ$In+> wڰZ(r=]B؋kƶ9.^'j+$kr䅒&_B莞ZD嬐7ŅbϹEIxҥх wUÝԤ,Li磧J~ɳ[S|9,q9Zk^Se* :4oFAsunz*ʙh#I~΂űpEV92ع<3ss4joGK| 9.кb}UI1Ǐ%s1B3~caDfѓPͩzޞ/'x pc.[LYcn*4FvueA%!"=ܩ奾 W &+83FW|] HU̇/%I+d̓ sv/ @Ɓsce֏f3݌JOwza%`3z!j G(2aI\3􋶗jtʞeD•݃cuj@H #ۧ,L GS>hU-dD/Jb9Ęy2bK"sGq$vm&MVʎTI 93kjnud;ńsL9IX!-zIh/+9ː~"#C9p4l5_?P1`jpmZdJh93AZ%L,#UNr&-ezѯ囅CMv%ZN]Opqh a'@t ßϿqKՙtO1 5іitT[J6):_qWjJh!wQ[]CpK(CQGdɚ.2uUVU~C331ܒ+p\s5f Hvh_OΪJ7uݹ+ƽ7[UfdđEQUلrEX Wvs! BJhr )x7Ucm.l;+%xǎM3ӃIԅׁ {>Ͽ|yȸy+dl497N gK~B@ s~;Eݜ݁s0B(6ht.Ke*lB 4ިdJxB"&0rĔTS _St%M:Q I '4C (۾59R9R(B1X]~v{ 3@0 %2o%Qn٧}L{ y[H-!.P)o#.ZY;??`悇h5jObf,$Vѡd_$!7SW~il(â㋵rO]8<4\nE@ p嬭g(aL[l}vKbnxv3:l{!iڮ|hxSm4D1F,Cg,6Nn>3ܯ1#N4żr΢`=߼G|iZҬV IW [?A}pK-fH\RZkB[ FTSzҟ\;ˡGo^쏞_:~{&lc!$5h7do]%揯o|p+fmP:f-R%taUGz)؃W6R?y)w[=8gQ5{*0§ )#D> 4y8KS-;7v+G~4 +(?O̓awBȚGqLRdrVKƎtkPJOӈ~kfksA<"F ^oxHxQI*u"H1Ba5 ڧ1#Q'\̦6 敶>AƗl5jl> X(s!Pr^Q2,DеFoG-Ț[SW\(siu&gn _<&9u4xA ض䍩\<%ڧr#B/krvj|6̇n8b_R/ϝi?pk!Ѷ_L搪ǝ*.6ۡDѴe-ٸi;>[V>mxfͽfyzak^)2 ~(duIQ^=tVؐD&~OF^px%3(PM #o|tj!ailkO~s$ϹE4DyC|HtlRX4b(+߽ѹ΁n.~8f R?h6/{C;!nJ?u.X! c;d߻i 뽱bgl [64VQIڹWZ,aD~FRbyxl6~ K'Q1amOV㌍$ ba2 #_h6wbno7JG*x|@̑{| NmT^a8>E'e tGVu97E,S`1uR.=A8X4D4i/ӃeMY?̧#% [,oͣ`h|?a/cRmC:HS0KĘ:zF^ٔJ^2` Dƾƣ^5O!uzetw|-U٤`/jnO JU]Ylž%ص—5R&oO&?TWOxD$ߍ͡ƇM 2Q+e(Q^ءINfgwWkqEmo IbnLX8uA՗'S4r̊&|lpp+ !WcQ}K!|Bӥ5#O ;}G9BlzH#ÍoMfEtǿĽq ¨M͌S={ך׏Nyax~G+ѩ?s[j¥B[}C?{n=7cd}]ѵM9EY)f7AzV9$IǘsqQ%z$P}`I\XK8,1>ZH`tJ`[ow{sNԻ>;#Eeai,Gw]LRNkpc1D1Q% BHWSŹN!bsq8qS$n=S;lE1mgo-LiMwzfG K%G~:Tq !WTTT8v|c~qO>(j!cB၃FدGGxhuBYx:;. %:}ҔjwV%b=aUuzսyU?%h!3cv6duq2ۨכ~{:U:VlJ+ҕw|fXE6!𜝮$bR]e&g;Ճ;WDwVఔ g/?stn vON['0zKǘpTEMqΎt'PXl\?NKs$0Go,+ p!ٙ"p&7M}Jgw.^ uJwđyh>IsyM(g[xcP^︎:^XcnF܄[sRV6GI<8`*`5l 1Ca o(^k&ɀmMQ:zOr0{]HAO7V̓㍣b6SJ35wV "L4z%XG>]m\\⻍åWKTQpq , ƂhMK&n:ғe ֕h|gW6-?p$9B0D(YRtdRع x5zϲu>\cFj]박Hk=tM}fBo?}!=w-}lAn?˼q,2[H$J;#"Q1k]M5+Lm+9 e'riv7]nLkw0l6mW0|#=*7:1(nZ{9EUx녡1=dRoWTYR c|3Xxt#/JXO{#)% {˕d/V!R&lڬ'~m?trr.3:4B2yJ%]*̧{Q6kjnO0~^A&,TJ7ZK3_V|`N̎ Xʂdo,oW T|1QP*(SI)Li`q.a$TYqR&.o66*M7*em4ٹ"i{p.Ӌ`JtzRV3d6ocXblbz+J2ゐlw'VȘGB/5r %^3'%*f)VZ!\bQ (cKI]zYwtUF3LfK{uWB\"8yLB`v(m+#n]ӯO B3cF Ù4ȋ' |@{T(m ,?JB>2D>ƾ̇ϟ ?yK(g( iX,WIJqw\`Z"? ϻ |I5у^yN_˦`qZ+1ֻ:N խIKkLqP$~fqx^n lʂ>OOZ!9l>{wk@^d9ԧ#IӨuaOR#L\qΏ.~x94w/S ͷO^$9%H\ܓ蝕sF\RwQs4; Z^`udjg R]qgŪuzZgӥVʯӺh ՝J g_SWɛ_=v-]wp}v\kwBHb.YcRP31"34RH!礞-!r.m+{,M+Z{y.lEH&B8$+.KgN펝YbN!5\`tnڪBw3nͥNML|C3n؋i;gbf3~?~+x6yAƾyZ:ޙ;?oWbC0g3^W4<{-q(axUFCw*Iȥb[W_/J)?cM&S) ^:ljZ!Z}Ɗ GS|]'?("uQDg0N[gw0$zQ϶ :;3-Hۗ_RY摘+B#05* U_a{R+eLߑ& VJn=G4vMqN |.&LL8fc8u)0m\/'OM賹ģN E&3yIV{řd&sK.|:%W;S7ق0? CÆTN1uG'_Q>g_%Ioo_3VfSA=ح7D 3r>4OVnL_7<Ζ%8߫ o-;~/Ka+\㪵'ڪ (^+TUMG[|OxzzNo4:×QvlH gy !aFӺ> j1(:XtHoLVcmw4i"D)K08gP ^()+NOT'r:4ULLMih4IN41M-O? 733oQL, t=R Q>Bd1̍n,c}!01RY&f"d)<<ssLc(}YRtE\.!~X4 riT~WLVDzgk^jnr!CS(.Db1UI5r]imo)S!ՏF}3"MŲDEb?SBjS?=.8m+i[ys#/{nj@ˆoϏ pV_mn?*+CǷ{7Sݡ870= o/]rQ7fDٳuG>o++s^9!^dfm?#]GowۖaҘKt MpV]WKR|^dԢrlj&|dg̈́b!mswد(HZͰQPro6qFԖi^1 = Hh= \*գGۇ{Bζg@LY"rگ;_=Z^atׄ|bh~ "Q#AƖFƒf㶠1%^E&nBC'-5rmasH-Idvb,tM֔᯾sCZH;;UzF4LyQsMf0oiHلz1 >Xg cbǙ".~4r~%oD-sX% 4Js B6N$_q}㽯q@-5,]:!ވg6qA?Qo'LhZF>h.^35{H%_O}JGzȤ8 qֱ#&-믻dKm5Hjq2:1굝LU=RrfN) ==3!o(`]tJJ0n\9|E6r}J? wԷu\犸ݽv^NuJɞe$֣kp;mi(29vfoY9C.i"lR}8y$M@ΖJơΚq)xȽ1k Mџ6)V$Yd6đD0 n2_VoAQǜ'0W`nw[~(zxF" Se~bU,$:' Co26 j4 ^jƌ_D1 {ĕVO9G4CuLhaM clD|x\F/}xTR3+{@7 ^1 #bKAWxƢ9UϹErzmݫZʲzT"aıDٝg+b[ wɣeO|R,8v(|v\!#K) `RrFqV#0B.Ox02ugqwLL{!>}kq?hj[We0AHHYÑ.L L$KJ:y%3WC7LVxyFf{嗵05B?0~on/^j(Fki]90]NStЌV}/wAgERBBݝ:)~<_JF58)ŌKbKseH2M[%1#&fIDAT{oL2AQoٝ:c=ԟoSoCxs}LcR2CZ=fȍEk_?K4?y?3=^DP^7{Ѝ"S+H4 887@jJ<.QH*R4*Y,Z/7)<JLn6m2 0HF?TB frMwK3})>xƏ;ݷxAB˲}!s1ޮɚFf 3kf֟u/\v?giw_Yj~n=D;4zinχ]'Y.aF( HUd~GCEJ3209MW,Hvawlel 4 TdiJ+ k{#%z,5\59]C"frS">t|xXӭ?r&W/DR͎qc~/}0BGG͉Bg&%xgGrNkq0Sq ]`XK%n?gR-Kbocmn>0z.SI)pML u>HoSpaOQ--@L&Auch+X*ҍV{s_ծwg"]2PQQVnwjf9hjs1"e*VS.IL^fL:ޠty.@4v(Y3/$s3my S:JB , cu]]AB;K }4Pw"w+5}5.w"acqh7R;z#J cʲD&,Ol߁P[7Q>3Ffyk=o_;~V? Bq{t|>pX;>rt2W$|P학G[W੭s8)眥Z{GIe- X|$ޚyJ{7-ڲ0c?T38ۂy< @qS֧ZGoz 1b.!m|66[*i0T}0TRR_:N95[sRF A0COu<F䄧`LׅA0˟k%OԻv5B `iĽzW"́j˱evBI&F#JtW|1ysqMLT\SϿqVdE0g'FÎ3*m|\P?xF>=,+dmNۯs o!,l:Y'AD?tMT_5?;~(xD705.(!O޲vET>J9Mhsn ,.j\4?5;{҆?e斑|:_*/{[GyjEgPw8F. E_@s$@j4^T{I-@*SpmKЌv߭GXJ:h2@It4hNj^LđrEiZ;莴Vdx<{kKAG2O6$E33P".H7ʽ08J\ɡZf2^J?:z|c5w_nl뱦F8Pd}y&&֑>kZ`}=C1伬Z7}NQ {g؋#a<ΚaaEs.NW撵2~{ۉLlpάlM(mYIrt}HN/g|Y8hǞ[+[伴 녦0y 1x]_Y`Q ~(fs8ImT7vJJy[)3m R5&F#ԃ&p.=5/dLY5 Dg͠|^k(E0m*K_hăl3xO6;gs}g&J#/9SjI~uЬKb 5y<DD03:,eע[]MUCW u2EWCGL62KSZ򀊄V/?Z'.bf񵘲ǕocIHⷔw-LR F)x}x_&?իk ^m|J˫Q($L%{炌=5}yWw0Uo_\O2XOG{LN7f~f1c ;l­mKj$Ls8#!tecxUJ0o)՟=\c/m%竒Y/>sxc8T4̠d?AZ,4N,emS=)B,IK 㧨 V,ſQ%?T!PͭqA['SD.h*GNh>Sd%탾["0)61]y ؾwZ6oҕT7V397͕ZtC\u+33YJVM:mPk3v50WiyJZXm~m꬙|_5VaPi% SѝQpsKrkwl0{:6o( I£ jtz/{_<ٯjYW~AxXo/jodUOMcB&J dO$Ɓ?Z$޽ty_)XWq7FRr/ e?'¯7݆W:k6؟nh^iy`D_)9J×| ?h\%11IRuvQ6R"/͠hm;_^uY<7f /~9Br`'F9%ڞaN(f a 1?yДK`4xdž^||:W==ԴDDz;NԓyM0(I^խ6qaV{ ]h*0 E܍fVR9,?y+o~دwM=X<eݭ֍8j$+;C!,7{WݪmYr<v*'F^(V/h?ki"m:͞xyK 3ĘStwTl3^&BDJpy){fCw<&?ۑKs i|gi >zFšDxB"3B0N ;ng6fA)DoٯiwkpmcS?ݎE6HΆ6펄}!H\؃R5f7SH7<)f ]ӉtTuy$#x{|?7rc1g{kdJ߈[hxݏ-`\tIWvZ7gOŒsvnS셽RfKTܻtR9a˨-QLqHNr._~%-qB_VW4mY?ʧիB@ /0V V6>K%|R;ۘD|!gҷ xP&SFI/;} ⳦H%sN,gIV[Fi?$D;8^sڂKbF4̱mgfH256F145^X>FxoD">hf4SvI(-rz']X$1 O\HެZ:Z ŵ0t5@gԗ=VB j ",V8es j0~4ν\?*S)LOp2$5#xC|@8ݭ <ˢv~M$$Q?M~gF/e:rK~1uB7w޵L2-D*(I~h~uXw {5SA!^X^p*å+ȑs?ygnzf+L \(\E"DžR&L5~$U-QDP,eߵ'Oޒ ˸rjom/t݈[CqhΪM݃{냵Uzaj荵7Sݢs|ȅ8S٤T#_)[wr{omPI_mZ޹s}^S$lP}trN*EEtf^B$4{ޫ] h 4}cc*@K|:[k$@j̑e`zP?^n*=gs.Ka;WH#-G\f9jnή, 4b%::޺x cuz"zDƦ++0su] :9c:uIs炕;b=bξ&/^Ґ{ǗkOsx!%N*QY{'1s%=댲a\>}͕!gUR{w17jsoN $mVS;aĒ\F5EBp׻M4jq!"XZ71NN4s&3Qax6.0q& j/;^D}mxRI*D٧[ }v4U+q!atH"חaЮuST2".^uwY\)Xv cX\?*2.&x;9~gZ`<#DTE)c{7p=(|5mOG{>8^Ʒ[Mac#[@'GT#.o|۫o\[\J$f!9t䶩cE[1UB^ZJ+2㋉qD[Bf3]o JI&Sqtcq9c)3`LBqʒVg՟?7+Ƙs1y]=EԀ학ap|v# W \mqꬍP4.wt G>{a6岪I:l͕."GC>pA"pHP{UlҪwp}v@7v<7ekQ*MOg7fک75cvVs0%}@/s姻`*;TIwA/Hۖ?ѱwLuC5*J 4٣d~蓮7]; QOV^q<Xk&|\GtPJݵLUѯG rbAJE!Iqs=R ٥$>D* ܫ((<: ,eNӅ }l0ݟ~".(-yC/1A6i8cYU˧a.E6A55ƂYz{8D*LrԻ7FLdۯ/6}!>$5axPG?\'R'mFuq[7St,tǗl$ǎDXx$0F!ȧ?_H趲612zCڪo>~DJx}k|:j;~;ko,~x &wHD9-<JZO8sC@Тd7_}Z}{ SʗϧC]x]M Ɣ dҏZwԤ_?1 aɰxp}ŲUAk'Z>8^4^aic0rvcΉٹ}|괧98}4OdBQRҒ~ VPDƥ#hv~?"Wu cb5$a^#qOSlMDծ-N۫GelFp?bO?q|w7f(\ZL(g1FA!ҀƙE0ٻsyihvC1 \Gwv붭΀lU~Ⱝ+x#a)6ȧ ?Wi!ԗo/sIlDs?b6-Ն_}{Gi Jm69RSD='[D(u{o<|:rc61:Ȟi[K[|S0)!BsB҆]A/)ᔠ\J~Zn4W«RF~y\vatt}^y_^2VL:xo<3i5c}_ "CEALwz?dsO[\ Wj6TMS6/ɜd%iLZISzՖp)OmD^B.)vKBdXz  %e>?Z8j½&oM!]Ԝ?9T:w[L 29]mU`p}7N8g_<*'Dyc}X7K|Q33LZ=a:K }~il#zE99BR4~`+%(Br'n-'(֡ՆG><رz xXqB2h\)D}bM%V1>1PE3%å8<5 C[.S#q&-x39;3nrPwϮ΄ Gt 嬘ᯞ4$1ǑA8_hx#i#ZJ Z"K TTa[l=8~1yI;7 }|Um)̋bY,3g(eKm7QI )ދ6ګK  z308JZ\[DB(>bwR|1h< Y'?K*q[{0ƈEUD*/~\04PiWԁ?Y0÷]\ܪ[Nf X)x!i3ݡH"ӑ;t!G/L`N0 0JNgRu贇ҳMQR#k&ZQ4g;.LiL^Y7GF6Z/G0puyk) iY4dy!,ɲՓkK'*m4&JsTs (f,MF}*eqM0)[CӷL2t<"KoJ}g(*'2zB^.8@0b?|ƭAc{EYA:\Z?{<حuE1A>W,lEZTz&%E{'xs}^hfM9MfY'Q Q,+05ԡ3D6ԻŒTio&-]1V~K&y44jŨ7@Qz#V%j G빿(^m%[1[lQɒsӯ{Gm>]ACE!L]3XU@3u69I_O/FʞQLwX 5;\ K27xG,[/31|$A@lMꎤdm.J֗No5O!!q!wz#fAOoÅ|\apsQykMT۬eވs^ G0,SYڝn!>ac'oe?y;IS;'wݵYvse±e;~l1;pxx̢#iZPQΫ$\. 6aF+Jb` @Qږ{6BCf :>u-#qܟ^ل~v8a\ #!S,~p+~!1;l v%q)Xq"PH'%>i[t ЁGEtag w) #Fȏs1JƼ*4Pȉ$S!Y:($3! c?~oF^{-%8{>L ITuhs,vuS Sp Dsp }R)4[>>3qNYgpl0F(Xu]E]ksf[#nCE02F .=F|B@QP|rW2K ឮH%k6܄)X~]OSÛn$f1$B DLغwOo|N⌶-{&fjԱ* 1@BPg񉵄Z;ܨQW4R26%hT>Q k9"'(2&#'t 1Fw9DIwli ~ngODd/c*ΑD!!A3HY| }KRe0SJIsO #SFR&,%^W+30-{nD9YvinG#3@t%SIQS O>yedQg*S⨝9j\( ~$ IR`4%[G5{Ƣ2GoMV԰TxIi*-8/b+xJi@@ߡ #~FVwݵjcEWde<…}d%%րVH۷J[xm8b0N%vZ"^178-WnK79:\[O0|8>)P"!OMp' FJDsg:-D.#4;eE=?:)A1'%, - .yB(! gѸYha課s ~[Lv)+-a, EG$/ZN\飡-u=l7f&I!!Z;l;d>%sHlWJu}" 9&RVʥUƹtӚ*{s^JJGnT儉|‡7o7 / live }1%"4CECm05HY jrivCjkIBRMYjn4GíɆu SV_<78SV@$UJ`qDq4K-"64+!<朚4_Xp`<$]>LA!B esދB1y7?{:=8$pʙbk&c*pY+@sVڟiG&זޯ|yO^n}$(՝8![bX-wz~3Л^' ZU}Z.5@9@9;ɈJG ή[23徉듄q|'o>'*nj{.^E!|\cuW+R(~-FrǷ0D#O4PǴi L 6*Y?/x2Qӿ;q.:\œvPxq}en( F /yeQL%z9A=yؔ+ fss/Cf˞SHRrKdg4{((i+X=K$>8dg,+@ !](B>l;G{|vI(OY(hA6]|&TZafBkӟ BTE"ل\cxf)whRdU!i cNWջ JQp Sـ#Z2 5 0aw}rc bc OY\ J[|p5+u|jk5枪(& jʄMPEQN  qcF|CCDDwqt+.qx]66D92M&^|sF/HtG(aRNNfnlskK=Kv=mJr2B$i4 $%:a~' JU8hyܿ1yt.zl~O^n62#R T~$Ō<=z{Ҏõ|9כB,H;kozҒl pR)C!@2HHȍIU| |݂ȓc[;c0]"O6Bh2YěU9< c!O<ᖿ6K)|4~xw1eFs9ᡇF4;i iPWf5`6@[g>=R&Q%_41% #^B>sC$HkX(fA ͓h]+}((gxB} Ca`(!i6XcdXs!ٿ|:Pd-9$ 8xgRzicj6^ni'lv|ptGc]&3W5ׇ›=P)ud2G~uIUb6])!L cq~+CuX;zof1,p)3䨬ѺJ[kJ]6hb7Po<60fNخe(1F9ڎ6#Z l!zgha>l+Ǚ36 ƨmA!VnXY~a´m:h+yͼGOH6:q@/i[ia$tA 2L+RXCWhbir}[L%t&qH8kQJ|qƇ(17Fpñz4C}36XDWԥfy!bc.aeGLQe@4mr~(4b(]Y1e}ӜFvi!P2#0}BΗO]؛ R.ةr*K O2"nACBfMR_>p൐THŋI]`LO`t M"Wӈ{#CER=ۇ^*ir|U:yՉXOwj'MH, +MЋ9gݫDg2Y,O)d H }ysX{Gs,˚`NP&D*BrH1B0f3B%Ki cs:H\ ,ssdq2~u\L@ e{I(|)T1GaqI#4i*I pT9qC0Bԅ\  aw[ntłõ7;YwyLuԲcPd5Fq05F?ltG)"*m8s.I@\P#DrFxv~. # Au疙u1XsA9ЈiX 3Lg;q6WA,3UJ;|tQQĄA9}sm'Tq,]G8f̞'1o+°&lo[X*Jn1,ˋ0We~pdIGޭKֺ##C|xBwޝA"Wyw.P‚H\;jO™侭utY;GX4*ylqe0Mc,-6p!RjZ*-$| }?;=bpmO( '`a V 4~#Mn][)+  P<((vLA]f\(~al;nAC9l)~;Cr2FM$J_SjsKLQ4dnLvPѩQ񟃐ݵ9qrox6D+"E=QVNfzNohN=3R5ezFzA泗}F9)8 i1@ e4ve`[e7sgJuo6OSVCBHږ#ғdqT? sid+mkO;+Itz[q4M˞D#|-f$]2~y{./ i(HancIC@H! <<:Ƅzw|6# C}=߻/BJ4&$c/PqntT^GXF'h:b>yG2 e-SŬ0Pםl£1N z2(8E1r|'bqn)kҨ9[}=2!tEbh^B?dPe>+2NaE1AJbfmZ34en)uDh;y?g2Po=nb(m IJ}̿ A(a Ʃ4ZГ%(2#@aǛ4BRFj~\;_~39v}{c|iv8?Djtfi˥~9uDdzVJb!Yo~JϏlYb@3n;Φ1֑M:Bđ% B=?>Pe9}U5xzf).sO7lBXIT"@Q۲odp}~3I! ]5O\~|b>{2 T' ܼJOIGU$R壝uc]qb5mbm佛3`-󽺦Msfw ~}zpֆRwJ_w?~_@D,lJ9h7=lw\SAH?vM./ c2U=p{'wZ<@'-ې߾IKuMƪ&jEɵh2{PJya{F(C*-bo Xqb,LCB#PC=> oI}^cxuNsw% 8zc&:d!zJA{qeBah K@`N^/%7[ Y:,J'flD@BG?dF)OVĹ7UuyDq9KƶI9cnNJ1@EL aļhPOs3>ogSo~wAcnqO_&m׀-Ҧso`$Bd!jdŔj ]oshW);֟ *Wzc7MTHG߭V3Ic%LOI@Wb]3H|%-m컵6# bmj7rk`ziQL'D w|"5:lb/9[U/i* ƸӭVBAb>0u%,3NP1ɫ]tT.ͲY/J LOXusjV>u(p 5%MBJNs^)V= ҦMdbM vJ 31n}GR*9./R'@m.R`hT , R&٩:RNp&dߕvQorvݣ; rvעl+dQo#0錜D9OX_=q8{$.ҿf_H>u@Fi'12VR5uSX?DBBxzaJ) $#`%#nȸQlT8 8:݀v_~_qgc$>ՓIc$x9MjrN@Ugmx)l^JgFFd`ajE@el ]0tGwD9QF^۴A1"4-k4v;iFɏ§$Y/~`> $W0>k_'mH>R2t~'MN<iN*™z2Qrڧgx@@ k42X} IȤ1 Y DbJzyöPtP9 aohE)Rm᫽ w \g`dc;)eJ>q0 )֔`6/䨦AqxJCEC}i ^ p✹Qj>uDi #RAT:(){x2\0':߾'o R BN15PŬK C8>&4IfuJ mw=S!~BN+ Hݫ97(| RVkjm'LL,4x-~9h_̤ΐMNh}7vg}t;J]*4/U m8$ cUS5zJ#9|0,1?ܘw! %d.ϖgri[#}1: LDžLy$Jť2 3PGH[-.+e qkɌӘI [cQ! Rr cF*a->/ȫ3l2Ҿ8&T9]p9S) λkj]c&/% bQtS$j^`< R ys?$˲;A{~ϵvRWe@h І$F#~ь4lhC˙к*Rgh^~Ȑ="#~0\䓾$uxz")Nw'~Ba䕙fJi34Jg*Vl^ zPR#C ]#%w|_ܚͿw\09jU9[ɘ PHG[,\w$OH{M64Bst\۰4Qs^Ќ=0"ES^%Ҵ+bDfgW2II/A9 !=Db5pwNQl*Bx>͖d<6،(sh.g%~\1-UZ;閣3( g{y[Ӭ"x4/q;.\1]nA0[kl# =U'DLͼXHrmPA(b8BU~HF[q Ϙ"t"S*_O@6*i!<@ɬ.VS%j8Ar o MZ™&W1osN$RIag`YYRN*WxaFNx\)Us {m9YIyDw9$zWKFQOw 4Ey!$"fZsxIkϩ>%)p4=n!q\+ "*"ďeL4TkZ2eR#<"ۅnj6\ه-*vX֍#ITDedb<*B01g0V$[Rx8?<{ G2M]rFZׯ__)$ΖbKFOOTkD#%JDx{ܘ|.hOSx-~Ŷ*'_*Qd)aQ\.T("CգJeJΨ$_4&ҍLB,NHLmuySEE1٦<~&R?/`gn'RH˫{l2 ==S&{e;,\p9l[{|7ktu{.N&ꢲݩ)2Gl*K|JzLck[lE@D(G(`f 9[ 0fnRZgwySưJa""DVht} x7`=KkL FPGDOs;;_! ܩbĉrw$(H8BB wFյGg"մ|H1R%:[թ£clA҉%QJ.KHJ/(Cb8T(E>IbL<+Pnk#d)fMI4,7 N5aDrCKʺA?XRxSZ7rg\qs|r|Ked9LT^9*sV[v]! tm+W@_ݵ[aw& c QkD\yC ]ߢ4(uۡ&+لfq.{ex P25wMktZ8^&N;0mUDtT&Z}?J8C;~_L M9YoA5Co,>ܮ_+{LF/`q $93m6pqv~lRN]wgJPAgqFjv^}w{=';4Gp:lU%?qsiKS?+)Rve3]m_ި/S7N?B>r(! #Ogt+8bT^*{ATzFtAh_4!dQ=`*5U<Ò,r |R1 ,nqٌɡ:]3< DrTZL|i,Tr棗~.I3!iM<@D1J/kK=O@u51 @`s=Dkս,:SERt}6A+ 8. 4EkR4^vڮRcqwÈ Gĝ9#!a:ô(IJš(Bˆk3zLU0aHѫ=)i`8>|.9ڙ ˕r|-%#0$Q.G.)U$W' "/ap% d9=0C*G­l5˽Bo{ MNΎ! r(I=m1r)ن;[B!/5߂7iwHP꾿qpK C_\,Q$E'F);V)J/Z\%匼6 #ˉ~ bwo& A;b` &apö.g3=2v׮:AWQ^gt`1fD~ a;4[>^&te*ƳF=U֋vpay&3Ly\$\R:~MxjGO]#C[,K8D1!p,0$SFZ}Fat7Q7j.sE~dx u۬Ej]o͆cBoq{~w!Ig3 3C߻%J^1 @(BRʟĦlVQrR|Ts#f}a"ڔ /^̈́tЮ˧ˉriKӱ39(xI`DSMio4^7O?J'E"bL<=A}ijmypR5(q61jULÀ"d%c~\9v'a #6Ze-LBlTN  zGQ~ IH(rcQ3vAy*,%4)=@h3&2./N{tb"4ǿhe"B9&n_Zx>d 8} ?0x9RZ5_+TՅIuDQC  ЎnWa:S)@X*"N㯶ޯLr~i^ aXh+cTTS@iQA޽Qrhrfl i9Rud,9C,)g;K0un4*Q13q$܃/[BJlch'%h"6];Ӿ.ܘTJd/Cj6!gQy޿InN "^XMo01F|tCKZi4&ˋg :~-ZXouC?D15ť4K- |r~x`q-U_|m!@߻w(IIAs\ `;0S|~@~Zr $ZX'iR'rW6b݂jLgOJ0"|ܙ!єFc<ܝ( 7Q! DPȄׄ <%tO Ja -^SxȒtNt ]a0gAۓ(c)[`4UL7jt&jd԰&! fN|57Ց%/tX/$L0]Hx*J8pԍ>}⿷4+Jd:5LZNz</ywp-L70!`bOŸreŲax,'2&HE($a5^|h؎(\2 rp_(`/϶"a߻w/MF3>:̔j~FMEF2vBwRpp{?V~͕ /Sy唢ȏ^{o'oXFzt;B u I"fW,fFW٫۝vGFGBپn% `B4lӟ Nu϶o6x<PN47sƴ @a"i)MN #U }ƁSaZ3(ܮk[E1VHo ~S@ĩHB2laӪl-ˆ0&)B4O6Jə;_;e(W&bey? ÿJk&O)RP:)$)=覵0{Qw!,b~R9oL?v(ޥu|@.)cPYM @$w}t cn_=,)$JjD}(4F"OӚKu=}J8CiF?wxR\!E',Q"c k{FO_}'"ޘD~Ћ Dl?7߿t] ێ6DDhDɉ;ht9Ǘ cOҵ(r(v4R1U7`Z9YW;|8zp Fz2GuԿgVmKLb`3=B&ee N seGF,?i&[ +]3ɪϾYFHK\uKSC k_~37$YH;+P-^^*Ջnuj-&o"07r UJQcc4 w~xcr{asx$JVZkj!"fy"Qf$3SU4Z/M}b痏v~4=ϝҍ &Ky4m#WQx3 :eaON!y}vUMwB9qM]( Knj iLvR6`"&r!$ J<'4 #Tܝ#>mW.-gqRqL-`98jpȢC&O= 9xO ɓoU%MzTxVHB W(``'bJ%1n÷f!Ext> }b싂g%ՙB/ m]1ڈ~u`F?8A<`@:vtS< )1s "4.U]}@ӂ7jaQӶ1F2(9 FŹ,ׯ4̉aL)GK+~KԵ0}ݘ.YZ>a$e:[+ bV{$Pim\>7k^_iȔ@-g:G'$s;s1 oެF/^nV#s~ul!dgXRn7[+x_O <4kmOSOn@o3Y {tOZTQHk/Սԫmgi.VTA,rkF}63Ūhͫuaz?`w@法Yb!Wѫ]0]Dռ8Sg-ACv-WlZ3&??2Xee `ja[u&&frqHMbCP`gy %{oؿpҸW{ܟ uD#5Q$oNΆ+7]:RO;?{>|`< X J%_6uOda r'˙AR9M5 1 ֳKOo{u"hݥsIM YSVmqЗاϩ:tIBqm# o !%Z`"|ְntR'&u [0QHLX:C'A13ixWbU ׭cDxO%RٵT]SOqCo@@YcOL͕pgȶ}Ip88#Yg[5Lw2l"Y{T>Iqeޟ-' T^f>{KbR@ӖF繾Ig+c*pL)5p^r}?[\#Q AeB<+r)HT \QS[>}cErHŏs]/Ȧ#=fQo-MϦrV.ge?og-ۋ&K2F$~s*;/| 䓉o޻YWO3mNG.6o߼ӊ^Ωi+IԈ pTQ|<,wϒy^N%'R wz;vMچ xRpk7(d/L'U%s?r>ښ;hYS2} K췌"R=yvk<):sn٭A3TζҪI1l1ڡJ:E4a;VHor߸L#a3Y!5+P瓥 [ ğ`x-3Ey}vwf<0 I^0[U&OΝgwg*Ұ|{P JPJRtS*|p5e:kseNSa6dEr\AH=4esl$<; qRFGM8%7 =;~.?=yZb#ڙ⚎W Δ7aĆ=~Be❽F C51ыr1\v)0_NUgdV5Γ07׸ :?ڶ'r(E޼gS˶jv"˓đ躭>;W !_6LBsS婸ab+kG4"2Qۊ*1UR1UJYe7kt=ݖoT Et<TbhBք(f0?= C!X&uQ؄ €gTJ \:;Va`@(Y^m}SYXlEi$W:L޿vvjl& eKD4.\iuA|c}$p]|p!@b ~F\/YrR /> Frfe;̕mjnM8i+Nд:6T߲ȌZKg}׳ X@_ْxcpNf/|F K?|mbTN-}/[`9`T^y`C-Ct+ț~$'Sߔգ90|SSlFjbumQ*BgM平}^g*@ =[j)iO𴘯 {]?]4e>+O\ޝ̝۫.,OWV~Xy.$G0em*xᛓ*ch9FsӪz֝E3x[u%pL޿{vnZ΍)7q\6G#s;jJT%H E4~/>;5co͍cECcddMv9vb=^aaDO0$ZI(oS(9CB%RZT6[G]|Tȁ#DΈɐL8?͑d|b;W&1M߻![p>U︛eKD?Swh_&|<6q%,&mzQi`yBcdp>G阐G78Fn[oS`{#쌞=t+ eȱ{v7h3H`m)艂SG /Q"TJ]&N.k R7- qc+11 ijB@ϧxa>Bplaݛ;CM 0nޏn:/dQ |dI$Ց#2Z$Ob }5D+B l|:ݯ7n^)3eu(nJyWKpB{rN huA ׻|׈@R'k-/*#؁|Ƈ-ғ-2\.-(x?Ӣ&lj~/ƊpؿЃלּ=^k.gwb^$~ % {"Cnz7\?͍bm2#OՎݼ5ѧ6r*-Uj!B$9ظIDATnbO?`?r) Jd- CR7 ]JC 0 Qg׵KM=V툅`䲛FϾ xiykrE/KujBDyQLh() ;X]vl U-} .CW#pG@Qgo+14mS_uf"9q|YSc阥 {1;Z:T%E dQ[0S: ګ, NǜFS,pbʞM Gx#܏ޛ?_?wՄ|y:)Sq?'oOl|Jd,3C`6-kd\Yx!%¤o/Vv"K-q2ֺW® D`a Ȣyz"81)p`(vBk)?THX#(1'= n!B0&IFqM'B*Yܘonqp8#x~v+px;]׃|wf֠ѣg[)26v,?:2uZ<90.KRL3!Yݳ[GbŰr2]RG|.iuԜR":/ PUHØ~#RB>IOUL)~QJ?`QYȟHܧt'o-:!Bn527(Jl6'|L% /~kreǫb6q?0I6@G r|ȏ]zfcNwYNF4~;!s޳ qx2lQgݴO)egSN_/˯֞@[?5ൣưk%Ԙ&\bW)T/~p|}ZiZ۝slˍ&"?@Ͻ޻K[t*&™&k~``Z=0AQ6,$Ct{ϲ'[ioLsC,n/^  F L@53Ν9N8 JbwNXS0/ƃH )?7 NW0\ s^ -^UܩW &eZkÖD.);а<'4kslwjзpb aĶ{[Gykb87.QN^n<>cPӽ zfɖZdQެi/SEѶ ʽ6ŇFMчn%F^*薟X:*YcnR;|2JueBZ(?HJK7H~&&OoUsZ\_4{7/W~pGpDQ^~ ٤M"lgtAХ[LR&Jd|3/vҧ. {7Mjd:-iTIbj̲{ ĝu?%M96?~ "1߼! ES'!)IC3x6̧S0sӯVB ƇOw7wn`aݘYߠ=c, ͨ3w+Y(%ADE #V|-We7_@OH}?pr9jF:&p lR&WܣuhsoonA: PUFV0:S`*zLO6AT;{**3FNʋ;JQ,& (#(e܋]M©©:el"71W\unx8Ŀx& 7X%ABl Gáѵr1[3q_t@oϧg1Z F[g3`yJ0beʒAt=ՆtsV.]4aYKGMMRJd"6tJ\Je+\rK?aݟ;ջ9OkbY@Wo*ns%}ġBܘ>#>"/@|ܱ>}!⍁rYIkJvaw?y'HƘ"zS؛tZ"'өch<蓚<߻.|hl_{;$. BƘq۳vLQK1KnŘe|&H!Qw ٲ}h qae$'4n}g"i oڧUb,,8OMdDȨ(^DyR -Q+K94%/bڋWp#{td1p\RtB8lG8F,}{ᨚ~\*YkUr /m7[sEhuTN;1Rٲ7.(n F)TINZ,hMGϷܩ9o7mkş4.e8"F4Zēvru)+}#HWxs&yR7}+Lӗ/g-7#uPg<\}kj/} cD>^͔ߙwL{o[StJ|Y bǼ8;T=4ޚFyp M Ŕ&\a+?|(^{(ܩ _?'"xA(VxmX#KxZ\5]կV {qCƘVSVv:>y LjsxѨ7zI0GmghzƈR(dI9NbI[5l!D>ҡUq!z5HƑYق) W)Tk̓d17R1.z-cHڰIWwb2t)Fb[RODLH6cޅy%z*H' tM(g{ڍɀ/f9Q2ܨL_AZ.+󛄵\I3 e>(5߹ l10344ȋ)/Xrca'g:``>p|碘#cF t!~T7>vN+XDitLxLj!Ȓz.OF:p} Ox/|Y&p;~r43n|b}-*H|G:F轹Dr^4HcfݙMhrR3;z_W)w" !;zVF7Z `,!S,W ']Q+RxJ4*5訿^@|*'g5ow1&l75_}Ӧ{AӅt㳕^B&KA'dC*Ч3bnqu;CoMm]Ê`u4r&qM\ :CRd&=yitc`{<\+F&GE`#ب&*D]BtXH}F~\<]1x.OYE,"F]v_tsIKd fR ns草D M䴄S;4tQ ϡ dg/f7kF͙~N2Tn Ov{OzsI][A/&:_ݞ5XGڏ6[+SpHhϒZpc^WJu$xS x\r)ܙ%^:{t!\,i[ZKy:#F߽a\׺I2'C7̈hhV$^lS>0hJL5wd&&qiڒi<=5BwZ7x8~!N31mm[KQ1Y3 -=$]h< =VrYMѝ$p!$¿{O.wÖS~U2 Cw0E\Y|r;Kr)WܯsI1#; pN$.\dYV&YQ#I _ 7fNGkySS`h cinc{c֑_}WHks !s%/ɂB3vl,$i5~Ӧ %T4˧ɢzg>tI-eeU4Y_|5r3I"Oř|cZP**ˎB? Y B!Źx3P >]ZqY- .q ]ZT9k$ݝ} ŬzSRe)u~"LWJ:UCL뚱T\%ܦa[)0^Q\o^~&-ǖK^R7;K˛{Z'cdhk^wZv1]\KA%nrܞ$#Ŀ NGH d C&'tՓ_}X5lN)a6z`ƘQ1Z B8.gӞ|s.lazJVq8|~P-h;V,bl ovCbH}O-?_G`-fxbWoz!fߵї^ɖ{q I!>^H6,OIWяOdzbK9^Aȝ0F(gnEAVJ;;+ծXWS,G>ӭ0۳X.*Y +INkn|y2^*ѵw߿4w]&'ozFAH nhkzbF5;ToxS7zvG<0f3~%HF\f48ՔTv_Ep%,J,B@0V2*[ndx$J6Ts\Jjz\jǥ"A(P!jR3.R^.ic,GnY sҌR!҂:fVn P>nT 9lJڬ FB<\vДiD3!1Nj$t5>osv,VH1`,U @hL>>fn+]θgӳ(?@s EDXR\(7zbևU[ D?+ٓM=T7FaШ^+gL mm~y{`79QW~K>{ xfܬ.`9 1ӡO9wVQ j˗98u5s/#6]H>lPr7nWE^'2=-hmtLBğR9G+'D{??Qm׿.~=铞[^0fp3N8ۿ{.|[_ΉB~ݙnaˆIgt!r*+ :ւu;0P מd|Al?MF0Vgm j47|2yeED,&8ݛncJ^чgD_HeL΁; Kn^=?\p$#c*$ƥ,۾҄Sg3t:bNX\UQ `Y~i+{";0S4)N(QtچA~Deл1_J\8d*Yā&2ЄiHtxڴJV;W+ ʐȐX|1D@w,0E︣j6Η-5񢮑٭+˓F5s(6DBfҿU~vBWe7}rs:r_M"GR3teuߊo_Agj%5X֓cu4GfKˡ|G?},ׄZK;Vxsp#r՞irкg''sm4[HT˗3jW=u/O:/ ql\Ý9]oaRlnZj|EQQtPZ!QZo_ȹU5M7FK\]( A;P3c2 u:\Y]?0FWxM*ɼ$죎@5bX,cLNjǜW<31zxj&=qYl%K7{ ܩ`:|L9%ܿVc<!?6Q_AVkJTnfjYYd+uSW%-dz>>ӑW#%מ.|m?Ȝ~zZd)#KIӗަxܢ( cdtVs6F> 0rh͓B%+SO~ܧ!2TӦb8zFɘ<͖%{.2o۾q&:pW󹛓Տ˓۳w>[~0Zٳ0ٳI/#Q==w7R1xw)@/v\/=]F'ra:Y+3J+&sGFЛG7kevmlWëj=e|M~|V dOGR1JbϨ2WV<#,t 9 n_XTq/=*!ar=ۍl~7[34$"#(E|D9?pnZ)Lwri6qܱϚF$JwfuA^7?'ʲM5ev ׸G8Bc봞QX#zFE=SMS@^L9E>"OkW*!tI5i'?*@e p%EA NM\lAM2uj=<.f5ًֈEq%UeKDj]ġ(Ibgks|C\>U/5Ĭ&,MdNXEdYHȧI!bu(H"/Wyɾ-YA,feFL@I fio-7_6[ҍt2όg,d9HT(pA2n7QS~؊?Q;8Ԏ5/M<Lf -Nj񩢞N& [/^O?W"'|2j -aKUv^BF3Joito7(,Fwňz~lr|)ya7%AENOS|DW?x \$׀Ro6c {mi"_ (#pK?rm 0 LzR ~V;3SL`u.K&`JC }/HZᑢ@V`|~wjVP`L)&ϻ.)g~_<x\/|00A"!Bփb46JQ@5jF1н.E?5bhMX~NØb1c,Qz+J{7 {w-5{8a+pDɠkLQ!Xnً|Jڪ{+Ws]4@-z߻wnDEg0ǡ(H:f89DtcNVJHUɁ:33yCGw?~Euӈ]g)kjZNR稾<ɛ?|>lY(dAZvȽ>_~B a&v]̭c$ZR+b&.[zCg|2B_o&k}2îwUcZmh`bQ'K/fW_ٗRp=]]vE]U ㏇v?ثߺ;$! ^7ucN.6Vw.7`I߻5m[/^vlGpR c,<Ɋ86[nWQfjxslW!(@i8֝zh!d⺮geDxw>!;n݋DJN-'1c2U)/\n = P& ܼ&E/P=Sl":Rl,`))N <$VKOs.|5a7|hF E͡ p]\ce2SuN& wbHKwHtAX.=T 3 "w !VKmT, 9SNbEnVZ%"צ< ߭?o܇? ?}S ^nrJLwvyqd!KM0Ⱄ&2R~'_|Can Gj_o-૕^ L1}{*|.=ٖ [ 8ɝ-#+tpuڙlBaKowZd}`^K/Vz~i"w}-Ia!5@[Q./nEc<'>$ 9u6W{Ɓ[9ĹT\?}nݩI N1z6pY; Lxo9S݃`=Xjt ^Ꮐ)tP7Z'Wxot篸|2(cd~{1׶8>9[' 1nTD)yFڳsc[K FE31IkXjT<Ƙ%EEYHH)bQ.ZL[t `,oLQgjfdRy!4cYc6c|kHMGPlk0m `*JN\M$nwq4{{s;j6jg|FO>$4 S.H{޺dWHJAB25u]Џ1˗љarWo& WHBcSKxOlUXfn{P #G# @&J"֫&Dj?pds}.Vd|d{0fG׼$O$hpx\u 郛+{^;oWS 4Э\@CT JSZ,tﰵ~X]FR&g;5v^"&CQxMI\/4-C=n\3swR͛Tu݀*kE+upb@<]F4;Dej!6_~ꖩEFl  k@`?i?dfX5/'Ůma?PJG:a$:wt$`9{vρ$0iH̀', ^F;51vqwjI9MU&-G =ndv\Bm~P߽yBsY#{<|e2ҟ|@̕otIDb Lx ] ô<ˉZ}7aBE /߿;oSӡ0Vw+X! bi}o_ӤvW.`hZvP<:|B=U IOPL4)r" &w k QeiR>5]~TaDQu_? < :SvaB]/wS9{I@XcU `n-,U=Qv87Yʙ1^3^4& N9C&_t}2@]/(ͷ>] K d]ooA@-B ܜ&ѣb@طk$u;9EQt:Lw664ʸ ZQKB2M:(Dvr_YcD([.;sTD8 O$ :>3kB!US¤jϖHe4&rv2kDJպT>o J0=Co%{Q2 1g=O(xE!y_ WɈۍ~C${[}r/_ Li_$^qAq^ZDE*@r@mǭ!E_%}4hXye5R=a2 jF-?d "s ExMk^k(]ܗGw### B$_05LE?n).!G'*5P.) e}#eO; 0?99'Sy_N/JP$3 XBGbED1]:80!GkK+b=hAkt0Ud8YhQ7=I! [*w?<'ER׍Lؓ灉$$e/<ޤoRNZA(B\1-?sNaiIUeq?F gѫ*"=s/ǧ@)M=d,81yqEb!N=}v4Dyܙ]wbL*˽\RFf1edQ4L>J\} s zBWg͝;AV#TMٱ* )Ӿsܨ(OfKp<%7{_?|ݞ(h[l eT^Fugq~sґb <&qcsц˜ Db: ]8A$4X҃[{ Y PcD~m jqud{:-Y;Q*'dN5E_=1Ř!2]mQ;w6e bZ+c,8H9G(D1̒:I \'Tq .BC!$A:Wgaē0z]Ul8:kN"'أϧ\r~!^|S&~q4QX?zۜ8k:7g`nh+ׄJ+vɰSh|k*2SRctST G]V7]Y ,3BRe1A-oQU{\!NׂiG-?\S437|J薆GF( /G, D ?l0R_(>ɨs1>+z+;}#SF*Ae6̗y(E{f5MR.1.7褌QgFiQ'ѢyttG߃ƿ|g\LeC9v"s!S01lej\ȴN0`ZJ>( ?bqSt`rÑwnl~W L'cp:vq-<ň9nص>?)'jWlE~Ƭ MջfrI1 +lg(IX3b* mJf(8~ 50l)WB;~`b&߽'}V&igkJ|x%5,5J@g9RYB!rTaĦ~?W#<(BmTcB0UD| %'#4 T2UK/p΂^<۞pKQs8ƽ޵>@t{ᆸ?xCдj6[pﰧ+I, n|:/|k=8JXn'i9<-/?wLb5DCsY'Rd(pd5/jO7Lu1?7R"~J.Ύ_JhUT yU|AL1Lպst 0Qyy^S\ku00t|ydƭ=Édh;:ao:T 9k\+~5sH:6xAJY9CpyNM(pa/Kao3S :0g 9Ӧ''Q/Ul[UZۙCWV_ S| >o2e IfxRJ銜 h C>^$] eo_`SE-(ͯvW]G)Υ:f|2_H Ti08h? /{?(Fq@/Ę}Zqsϟy g=Y3nϨģBݘsRY*v۰k5rn-,L,kf:第2aWU'""Y?4`9\J<.GW~ӳ: se'ϿjGK7dI4\Hriv=ixH5'R.8BX9+&S GoݣGvޚ‹*U26&鄢JD- f "q '$.$E}c-p:߆qCN"o/ jvH0jxwq}0l8TL4;l~7!R*[V-+GE`8"2 2ʑA-OQ"t,f~#$qUmRZG]uq2ϊiWgٖ{ F/$)|{ߓ' :4)Y덳xzVLՉʹi?40)=0'W-G~fMWzSTTͥQ8$Q}6tB0 %!8^=Z^a3&g|\jE*S[,غ7M/8 D9x]~xw.j/%>d޶47>dB2 rմ"۟fѺܙ#͏p֓'Qd)z}}4縴ͩejg9R#7!NSor0||f1o/TVv{VE9P毱)e*͝ʗ+O^_*]Z'X|)X}"߿IbfoQ"$ސRznBDaY&*sW a=``}SIiWj=aD'a.QI{NT0PRJ=و(vtP]CiPiրW%Pzs&ݯV.k*N|Z/1Z-`I*|U9C}\FsHhh!Hj$M=Ke?JY ʨ*cbhF+iSƴdt!J)x:6h +ٗ O/wڎΣ'RP6o,x@I:k8όoAՙ JD\q{{Kłyj:K?.|3az, hʞBjPXk )G`o56myiڴ441. 6.e[;W2ga/ 4;״7P^f)+{.)KT"__9`CWĩ@Rc1!Do1 &Sݑߟ.E0S~%L{ۆT]y;j/65Z´Ȓfq#P"Bp-h%/W tY)/$e;C+;77;y(l.*]1ycu4дC%M%Ovӟq7H5EQC ~Tnn]>SeM%~H N!D9l`ͱ r|O*4tDJ-TZdZ:]J ]%9ef2 T*M0a DDI]0JӦ ?h78;TYm˔TU10,$)OxF! ι4b=<Cabxij0؍UI 2A#Fx:n7LNuOA<ٱrg)g{'3公@~jk1)% ƥ(1jT i<4w/ƽ4,eh*ܘN_6vew;ٟ^^dj ~Mw~M_jXzS/V/q$u _>ٺPR.sQ= N՜(/ʗσbFYV2od6o^v=ǵbau\voWd]4`ՙ֣TGl&+Όix+?)bLePPX1#/Z,LT l4$Jkdo7 լ钤ӭm$1R1y ͞ZvJ,y@ @t؉LhǼ9w=ܭH8oZw呗~Np}?xs4MER)1r]ߺ׎0)gC']3_Q u3DLq(ZK/$"$usDQIM !) $q '`Pg'` Dhp@[ܨWWRp:c"0Si긖Gbq/GԐ0-dvsӵSXR/U[KMY)?ɫPR,ݘR`jɹz^ogyI|&uO7fÂԍk?{]x|1_6 <\E}[ | ;A:u}鳝Cr75njBEQFqxk|{Ig/9ù ).DU*ŬB=o,M{UB2ƄУş=T ]^H9&x:ISe7[b5.0z%鯾a3UHL cw3/åՎ%`2mq[5M>){/eÓW^o!8SdnEq6H44sUsdK)N^Vf]b'{#Cf ,~tV;Cɶ1z]}8"ݘuh}h?i^ba߼t#g,Hq;z1{F=86L4qY0M[nȉ:p!c gL*x}wJe !M=uK-SOk`ƿy"kLEp{D|C\A@pTX/~pzƏ6'{_n?꼳. ݇HQ/}B\S]NK6Lg4'b#*ףTʦ,2&}[E&tBY:} ?;{nmB z3WJفvsb(DR$LrUNd9(at *@%ȭXPfgp93/R_0SDmwowUh|@ 3~$$%,.{vJBa+ӂONs&Kُu@L @BGo/[+$ƒ pu6(g8Tl^֑$MA=KN.ᜋ͚CTWa%B~q1kB-݈m&Rdtm8euUH.Dmg fR;MƙE^o/KlLpN U.ڗOFڟW_mw&ehGKp^w?{/KT.6oZziB:M#\kMWo3E&k{ʫj+3@~*5N=ߚ([R:+&ɜ+:C6$@/i<nhNG'o{La`>q0%(Xb)I'[,\NߠOɸlE9 KI>ZҕsM:ߊb痳St|w:Bpof2=8}r ^ ߿j?ZhrƏVEK7&\XՈ{WT_͔ 1_ONs/~cM^ca_yVy㱦Jf s^2ſf:ܾ:Fi=ފrywa~3"6;!}xG[NJg*v²1n-fZ%u{,> JE=Cr)+/cz}[ .TE bu,Dj$)"/g]rӶ'i7H tcFQ ˥$eOw_YBB8"\[E(f QղjjJ6St>\xeo0Nt%UK =f?edU뻕[{ h]' H3IrsI%4Ó}?SQ͏o/>\F!~6 JO>]h)?}}q~~*@Y1:ZNM8|(b`y@Nݪb&i[RFxs۝y+-M::CӇq& ՋNȧ2Eq|I|k3,D!.m zno7߬<%auM!Fk`ч׃ v҄7 %?ߞJvϴ^Ya۽k챿x|:dt|fvN٪5њm}~rI) MBV$Лȋ*l맖Nz6CVˆOX; #wZ/cKWgtS-5E꜒V#򙿶!W$G%ok߬uՂJQjY-qJ=Rf|Y3{W\˪ |aW$2p” g%re&bLt0n oB^X#D/eID1&8GOuY\ P&`c:SVPa$dZ4"_,Ldzy~ Azu꙳REU3Qf0rABbᤰ/Jd]`[ٱ$}Bp觋*[o ѯԞ f]$& 88J1P*iCִ.um`NF i )#X,g}?+sw@3V =TJTsL:V>Ah!3Qc`ĻNgʺ)đA7{v S,i{!lWgNDΈZH O׃$R}z@Y:h^ *d*Ȟ?Lw[l9|$*唳6ԏ/ %|M~^{7?zwҟ +sO8?S嵏}ƔksϟZ!gְI?e I*KuQ9Tt/$14<7QM;z~tzbtA犭=N(q ͡[RH%8=8U X"jGoibEdq.u2"&E+˕g'Jqa+RRΞiBgw*8eJYtzs+*tzAL8Ƙ%E4+ugztpI5ӹV]AptfyiM0SKNoԋYp|s="Uqюt tǙ*ZPduTKU31B!W 3tԤ$j Kr2*9&xnPIR$!o'(6z~1#O9oS_(B@ƸZÃ(o۲]UN3 IWfԛ^+zs%<cіuUnݹeh함z>+ ԗSCa`O dhZw|o6^zJjA8nvS8I5`HdSSmȾDDQ#A!NoVWÍ^1yچ<Mʲh N)edLayvVJ P(^-JZEfd-)o+fZ\Ը^{ ]3͆%}Ll?_6]%F?哳 K/2ڍW #; NC,QFL&RkT~q8fN鉁TC9}xf5w6 8 F8I!NAWD+49qh]0( eR9ާd` iƄDQ[Y>}$XLv;V޾pc_QR^^" G%mKT2ow|ڒZ5w.I/G'@u\Tp+%qåY 8|< >!-V/zK&~>$jTي@GH r|f/9n%T['JA?|W KA`$@NC}" looev-!R2_eNd+2LVX[MF˵hnDD=|ߴŖ:ՈRլ؋_OJQS50y{T9JR}w޹o>W0Zg:£̘D9C᪬>4Á#; cti*3ShYfZ;-Sl2ki܀MF)E &K+^L(Z5CӅ}L,a8FE>SF"ً$,1tkA).ljDSm 4X"'`B` 6)[ LCbNl'r|9g,U4+ ^};p."MQz_7[s]ED/MwѰ^Ԕ=]0{m!/Դ޻{= uk,zRglq>JY`BuQb}ecp3+f=ݻs @Ɯ135b7(eLk߻=郝Op]! & 7`QIa_;4YCWw^Z7vl@?la/\MM "\TQ<"́nj|Kr%팥Rʞ?ps3[a,v[AF)lЈ]jV 2M%Tǐn,^7S chC!UY?yNU M jy,dq})Zad0􀕿~ګe⃃(9)_L=)hJ=սH洆" Tn,N)`x됕J /ƍ92L%i B0NG'\Ah]8R"!K Y7 !Rvt-_Z ypL|;Q{3:Bgiն*X^t-ި7JϨfNl>)Gi*kY֕%Sj &%$JЫv1)cw݈XkWeHZ@:;pEv0WQ&]F큦إtP4* ZҤżk1W r nOwՔ!U>G1B-qk*%7Aʜ 3ޡnMJx&W F$0J;l4tjBΝFf {ռk{vp FɅ/]9>]yc/X﵂ٮh Hϡc1cam*o svf*G)=3Hlmp|,Q4 uJ ".B9dm\<Q"TΖWɆ4$)`Ӊk1Lux H[=6S=ZlRTE8P`g+@8;/>n$)y=tsU*IDATݫUEίq[ Lw5$]=R.*Z'ixwW#iU2Nm ! #/Z2D1qJjE+;FMpVMR&B !Q0rMMQ0xÞfOH9i07n"?5E~{EӵWھtJ0Bs('S^^١jVw5U.0@`!cD F]-D^ZnZ Tf%3l+D('ZH~p%B J5&u茽p0g{ۉA 4z뇒eg22]#u؞eW~8Ee;8]i{чבLx𬑾"_y+iGf…2tG,k|9S nL` RVWdxE&Ix>ZL#_-[G 8|::v \0U g)A)?QǮB#W*ڽvʷ,$,$,7@zN=8h1K yö4%FR=`/fSc-fvDD)ɭ:OhR}y*2Q,K8oǖ!(Uv; (n4mJ-'#K0ʸE&ӈt.Ё0ƪNg[^<8a! "̣>B-"bU"iG_GoSWi)}tlHXX9"Dm ˕zpQ'k/n,YW/[A!hȓz/\<?ϕfZmӍLBǏ6C/~IB6on1 4[ !SD08W8vVrV IӕBXOe y x#'|)Zc_$ ,d;m)xeFg_Sd{B=; \ Z1߿[!d^v[d)r̸XVeup4f)#RR>hevI$F/]g ^3 fnw4ڇY=dT I**#rVPѣV1kKh zcg8έ|g0㕔{g.Eх@%2 VHN:~$ҕxW46G5Ei&B,qNo\ʺfTIxwDcfd1:֋T1u{3{SAHLe%F5wog8Ml)0* \Adkc upw(@ A,$Jc8*EQas5ڨdsDU@" R^75!s/X#&|vPBTRFL'ҵuz5h2t21;lFw0If a ƘR8/T` |ý$EysHQ)̔F$%0Q''Y"z0R0sjc#9$KSa/I9o*@z%)_}`Lu[')ntLc1lU{R%rKF|O;ҔN0J>JJ6TDž\k8V9:GQ8EI¸(ѴD BFNpJ ] ZCiC[rjubMfFH 1J8 !B0g$I L tB~k\f)R@B>hV)wO8v):+s 4:8 fkS쳜e"RJEL,TPQ)0Xs|: o66^@S^ QŸ U082gaY~'J24yx-T§M(zc8={fzaüy G[T!GI2EbV,I &>H"|(4$'ȗ%CD| ф`1#89K7ZQ1&D=`,`,(Qzy98]wܷ P'̄S^fJrN&"syzJD7dl#vBHpTl9r8UÈ!1Lh塪b)#S`,}[]I1bBB:*GnV%z| DD|Y4Ƀݽ*/OOm]Tv[/>S季8K%_m R8Aޖ|s M&S%)ꕘ")"a茏&}f{k{Yxv>Qg6'B!p9g@o.gSȧC^Vffb^z+Vj[ȆQJbWT(3ȓ &UrQƖ~Y,N^˯tKN?ʕs'e(L@0hћUacЭ*~YfksBX 3cj49e_ Pyn Эsc`ARQ8aQ \ 2\Lҡ2Ӭd-e褮Ј+Nk*HAtq2t"QɛAz<oǭBݜ)\ &;ʹh%BS rp hot ^ }9yxCǟ=JNL05Y n~o~wg\,Hm˕'&''Qҕ3_Nj`_N&i @X02vfg fV3pȫ(c z&ru;=H~d 6 ~y6~iw 4}wj?*6pCl>#k4 sPpܗz\(KK%u+B|Љ=wdIY ѡ_AG@ Y~p{*,Ӌnq0N~Owy~~bQtO;iR2؀ "G`xAǏХNOmB$Iq`@P"N8ŻFrl6f_^1}ðf*0RIEʼnX6v{ rsux%|MQ {1C&L%%'80N|F4-< !M1zTDu/p|^IuwHef-9ԭ|ճW}7?YO]>tl.䇵.s(g%h y q[cTɫ[g[RNqAY!K3LA<۹V@pTO^ !1[UY;tyE]J̙)/{5°@%O60d[=}L kv{/;}-1Q;pcva2pIPҜeK95JcJU䦄iq$U I%8v G~Ў|R\1\4U?Sao2WZDP9ռW!'l[ S9`Mѓ䴉c)NϵQGSlhȞ`RT{L4;C9mK?ﺥ1H:xESow跺r64:l7 LauJT7/wʳ  yнX_jC;J, ,=K1i%=cO߻ 2FϿ~}eP0~Ȕ0A~:C' 9+gZ'D~e"!G,RVkxD`$=q*=_+]6l c=o+/ L^T-0kj1'$`A0Џ0 ( c|-a\WXHm g *>_Aa_>zIis9 qAGARw}SIu_ef,^W_\]U:}9Tz8PS&2z4WF*Q0 V$(?MZCm[.2.'aכ^lc acr$|UiVb:wKBVwCRՆV~6]J 5%$iQi$ g_Gፋ/\U))B*i$IIsMX8XfH 43P $~&GfnѤXJŖMi6ѳfbj< ЇHLkT) J-T.$)פY>BM88 r4s?R|S#d[4b9 QȧDx?[_kfM,p~?";d_,K5gqQBBJ7N*Ygi>&,Uws/3)nC~:ͯgW*9(a;UO?BPY[|u LWKCC4v=E!0kIA YV4kZ`lqΞln4)b]ٔ_,rRe F?*'po4nK+jYh7D24a2bq49 RP{LQo/\"KmEs$QVO Ve9@6O x8xqJMk8⨗8MmS*deVNkhN”&͑ M0;Av4lM߬5/NO, VP mT <ٞU"^';W3n 3_d!ʰ~N r\y"D9,nZfkSDΈ6.ҫW8%A8oaq`zOrmsEP)іHNʹx H rФ@tѵԣL1AX`(*v;S S2veE5UWp7~PQk~`Zw @  L]N 3BS&%IL#njN?v~qfBonN<E;JV$I1;:=BFqpedoY(r&*%"jʲno\2KOWwlH2=DIb0?zig!(+-ݺNoCDStUDHh,AMJ򶼾 6YF2;vS" 4EK=JNmHr^Eʪ{@9KYPCGBz1EꊷqoǂP 3H=݀eܜم_~]CغGlkV%('9NDVFJ$a[Vb*i3%lt1Rqb ]Z)qTrQ|67]ٹ_pBDBJYV+\"XLT@(nq]\QŢ5R)fHڹ4S_Ęr^\[3 ]CaH "=x\p.|̥֕8~vwy˰'.m7]QR0$Jd#LEN˛(TUG[(!qJ@F@D2()~;2 yNaW[(2AQ)'Rƒe)aH8w;cC"]La)r%Bfkym 8( {mt4MT՘dL=cMexߜa,RNr7k: BWeJtR Zj%= w~pb`EFi"WT>Ks 8jiN劢/KJ,Ƨ>lQ])?tNZ̈r dFh W2*ֽ;'.Ѩ!14V#az㸔v:_7(L !H$ɟ7{]]y]B\Ӿ,eBٕ bް2^V"F̤PPӾ)Q(g# 1ǜ(aq*c@$Y#-g~8N;+de8uşOqG곤&Jڞot>V(ܜi4%c OvF(d\敥/>8ق iٙBJWψrZ"zؕB4HUJ (ELT}-x)*΢<8hTP')o'mDi;ʌceEeh&r:$N=Cc,"_\: \|M!lp0& 5&hUt/KEe' #q2β3dzpq3WJHVj[pO3ݪL˜qU)ՃpĹ%02T28KSa tj3ĩ!1'v( U՘Do@fFs;~zW-U2 O9Tޜ%SU &ޘǂ+ u\rSoU8wsK g+;^ l;~?;Qt -}WU$p:Z}wb6F0=4 UE) si_=2N֢YYx'(-o5tZU9[fVr ۳?,oWK/uן|osL#RcLkq|tHl8xH}Kip"05Ir_"Źx\"0r12*嗘Kܤb#;WI .c ң%lc_ݟBQ xz6F\LIJ(fENУmyƯ,1ԴD7{/߿ Ktb|hӏ^7vCE&[1BUn”]2T5g۳J+5_Y=wXgن7_g"=+PM59:]c,jLƩj,|v\_!"1\R(Z, |h i:Yldܒf, -(|z(q?w|oOQ^~~Bkn1!rwbw(HJSTZ,d UD9ޚmL̮߿[t_<?a ӣ'*eFmjWj y 'H@L YmL RX5Crqqڇ=}yl arY-BoﵻyVF^W7Yn3^pޞ;p4pSW 4ahi:!|*Sng'zYcew|xg2<`R>GnE}i%m陫ቋ:]2.E[upy1zۿ=LPϺ,'rmBnJ'Dw."KpL#8wt Jܣ%brR kJ\n52> t=o|xĦFZI&UB6[nh[4ІnZx~$[ +(AEXGMR$4NjUP@w87p2f'ȕ\D,7~;O~XF|q_l wWYz{t|R`$/+:k~|/i+(%Y# lg+J6"Wzj2Sp|1tFi/'ۨh@"Ip'O6y߻ n4q=5M+f (>NlXB5*yNw7t}yՅ:!\.OrL4D D7dr| >kh2z7I5I;~ɮp1bJ|tx%˷0 n~30ÚxS)A-3'CMQu`E3,]X3PΈTSUfMm[U. 2~'XaLq7Nۃnh>hG| c3^;l^Z"l%ĝWe)9Hpt-C77NҐRAq,Ox:xJVi}O3B)VK"9F=+N SrM$ړB)3[Zj~ae0C#JFQ\QUg\^,8(DS%~mQYDF{$^o$oʭ&:+zHL]O`+9tAsKM5mu^?vj:N )F_)}\4 93pڹXeMF݇Ơh)t9۲^&$J1hJXW4;mTmLs1>KO/г;-4-r@*=xM=e U'%b^Xz}L3JJ쏿W|?漢}uXro̷h(~W wT/=;3< *!{[6_wW[^xA;J? )աW63SCF2|ވo7y&i!)hyצb]un`AW2}IxA&Ŭ?7rzN]dzdQ8e~t]vrh /DX KQ呗1K&3n;*cݽ?TR=8?~k";.b& J҈I%s{xHNGDUƓjŞ{Ĺ>wӃe6*PU#]`|[* # #/) @u畠0 b2(`i#ML`DMO|&k}OpzڏMܐA)8Nl:ǵQtΫ)e!{?uޗ[I г_n˜3\;S (|9nq+\"KRMHoLo"So:oy?}w c%Y#-'#.nz-NP,vXzXHsp} xdڙWcga=d}xDҔwЭE(g_=W RO$YgEBlSj$Dyӯdsn3F'iBi a<) li emǣIࠫa3SL\C1n1[l9S׷Z"DD"* R6Rd4p〱6մ䭅:}'5FĬU ۈ֭ bUC%=< cH/e$| vM^핋ńN@0E1sT^LOӂ˹ӉUSMNݛS{e`{HBvgݜs#>s6Z㵃9f+ٽS HǔGu#wTdLJ "Bzby3BzCI'di:o6^ULJcT0LBN13T׏;6Rۼ@0WO@4KۻŪ_I=o,~m%!4ǝj{O]pP~x-ixcqRE ºQ;JʚTIE 8Ią2Ƥ7FKS;qQ/Z.dc=wu%EH%9b;IOZ6+$H ]iwsn*0=Q`bp:}9;+#h%! фSMe Dkյ7qi{ i.WIJOP=\kD=#~ِj(e kwIi uZAE{ BHO߽~ !ax1RhJཐpC7{(o]^ug>ɵ?OM tIw=\,M.yݰ Wf*cCUX( 8O{iI#wW0 u37T>+f/b V,WjEpӥss{0{mʣ )_|)( |,zOW{ǐF+}Fqne=H.ظ׋ٍFGKa}3E>W#/i_>=TjnRn:,>=;ļ^~(#ydyyDqq/eRr%)i̫> S\8#[~WR$Qʼ22_k?ڲg:C諭ƔZ!aoȬf!N9FAysw{,& VEm>hU KTSÍԳC}C5qz0{~[XvU+g|.(Is+a A[p"T4ot>ƌ GJF޾[ǚ@ pr/C,O*@wSN;3|^s>RMNO)%Ze79#UНŦ[M 6DI%'բ:pp_ ǔt` @+Ҥv_|zPԗ\v Vmo-4di ^ntv sT?lV6Uҳh`?UHoհ4WD"7rggɶ) F2zJ*E*^,OwjnX{{[2 p|OSv_ w6>;AY{1L,M`?L2jva}a'[EB%λwW1>ќuq?.";_|~T^x;~w.N!T-My嶎/uQn[ƻj7Y}K-' rh) %l0^ʤw_OX }yjϋ4LiJdYRIk҈[. o΍luW ~ՌU4ݕÍ<`V VtULhWkݘ*>[V Vi:Vc^p骾slzir82015eOtzCLUW_w+Zx8h!/CWZo$@H*gٚϻ6}Vfyvu}pgIiJZXI@H "9tc8w̵gUz>GȪEvT>`Q qqe1=VֶwwkEVꇩ5"7_a,Wz!QJy 4qdžXi82Z37=;H A4L[::< bAO$uF9Uo,>1h4YR:QEmt$zY_Xy){-zLYkgx>smv[$L-CKXd_~:*ehvfX'E3՟*1dl4f/.߬Cϵu* 4E$T*8 @bH{2QŴ՜Ԍo,0FJjvH -Q(ͥ0;di܅'Q1ph\hWQrr+qjbe3g{a)v1>+#۲Ֆ }]C@g:يhL:~]hjW0;WFc"f̡0KWWJ=W> _M :eux~v y< G?W$Ywl2Ztg'T= W߽$+dۃOJz3q E^ZmOKVJB%ݺ|dDE p9[q[GhnJI:iJ3L ,([L lO;'{ʙQt*N,ُ=l4}TidYc[KQOw?\<~&BS11`Ǽd k{,lYu8]A76/|UȔ}@&xI%t$n S̸P\2A @1BmJUJfn#~ Gus GtG?$~l9f'ۗve^tdcD8BEx:VQw^%oPQ+1l5ww}Xg $7$>ȏ$[OۦJ1!Ma8$?X2,EJ DPRFɻ ثBP@B ryQ!H2{wSIM>Sij`j0 N퓝N WGavs fX4MA$L,vjpA6:o)B:kGf::M;hY{~L PWe5(}0a<XِQLKxgJ9U{$݊}WV<:{ALL-=ȒRLV Ҝ9:Ssv^|VmZQ:0/VY2r.87N9Sdbbjn߽[Ϸ|?ӎWFOm; fL}c DRc^TY){="5קkB4"%EŢ4K>|U"IX,8t( } (]u0gW6חbX2W)uEtR՜ݡ.f^=Bf`N/?>~ܩ燕|vLuw^E6X&Y[x'e2A؏ʉF_ˇݱυMFrl4spWWemEW_<~g}Oz ґ [Oj=GݵuSd.@KR$tH y=[ -h-$J!ˣ!˘N&E?N\8aMO0+Bg* t­^¡r:fzJፋDUsG^w;HP,e1 !pgpH;)5p{>]8'A:e(ɑqMo IgJPӔX9Mm1SK'm Rv$ b6R5J$]9ӵ=liC˽wiDK~H@FȘj9I`QX;rA6,M%@D)@eՂ4[+n5:`%P)#vS[E]E|؅ OÞ_Ψg9d^,m޵V^,+B1J9t%q3%I~@ nBೈtOX߽6M݌ Z=IjqytL1q,RVSp42GXtqz͑/Na@z~KZ}O̗+ -E7*/Wfb;'4H2=/jU_O=buTsNO&4p J/a.dٳGULND0MzQ\ŵRiNcΗ_<\DpsA[]ʶb%''+TfM>ULMxdI*^'GNc~8g$IǏ[tz1s B`_7.mLHD骪j& S5yR]s3zdKXih";I`?>c[5O'8R~RT!9k+{α~ORf%{4^㈿bM#rT"Au5сKS &@ Ą@" #}$;|a1hG1d2tgFxX9WT0'}FAPggbnTYkhXӖ(O^NKRÁ0&eG0u=9;ӭT观uc޳[D0`^u^;invam4ASu2ˮfiƄV{Գ:$,h1&'m&}e(pHPlw2x0OS$OZ2{W6ǗR6SPzy`Y81 dZbuV?4H.N_' ں4$)'k=#_A5nhk˭C*g_{Zt{٦Vh 2T /S=y7TQrTDBAQJ?z0~lm$NgqiT(\9۩?^];NC5nVK;3W8_qjnS^7JԌlQ>o/:t,k'ˢ.)ن݊4SUU$} L~9As0p(or!؋]QIp(3A09lcg%Onk3Q$Sʖ'b\PG1&SfvҔ@lN,P0:"z.`w.E"Ɂ㊜.ֳ2Xϔ}  x\ȉ5هf?K$ F(\0ĪDq!σ)){TZ'sэ+|ycr,SX){w?=bHG {d4 7n` _~]gw )SQ>ywL1SHN\ΗAt3DG{2&{p<#af)cCك!3*݄BtQW1_|yci.ʙG_O,c,)o]ZI-3t>8Wʤ\ c>U)$^ L,Cm3T̲/X +gd`n-ڢI^~vo^}r}ܸ=CB4|&ٳA)hj1pyFWl7h̶ RB 7o;ٶf ( K[v~nlMGpmQo(c)#Mڻ|r+d̤V+pą$B#`pTq8:SAs ٶHyH"(ňqA0.iOz3M 3ykBie;s'JR99f{`>Y]# ҢtQrzHPC9zznSQn 15o:l#c",; |mvJF;n3abޘ݆ ,V6r?kw1zA@vI]?BDL 9Lp|7=;Y[O޾Z5oJ97_QY,&P2:b,v! 3ؾ9!ku4S=S޹ZooYzw+MǠM+UM6*;n35'@f5h%(MK[R+;WfڮTn ~|_)фkӾ{K4| dA *H0bwԪ* /N2uݦ[+Y!Q4ްxOƎRHQ-: )o#!P Sc?0xe ֛շ-w!7~.8L@HZ L9dLBHE"U ALJx$(vgbs!9+z[Ԛ^)CriR Po-4&[2ԛlU u}?\E?MӶ3cSpnf0ӬUlw.9z݂ Tu,N1B*8zߚ~.J$N>.A~2k񼌆/"x8Rdi\ yX5Sdc?yki_"\pRQD`,9V gٳi I2TPuGY@%?R|glOJ$r4*SQ|+;3;uMy%'̳˝Ġ,%BX{K3U0+(yG@_w秋8Fȹ1x\n|qAp\hiV2e+Ki23x3*ntҽ}Қ-ų8}CS(>OX!egtE:)ϭl{2f"K8J B$JcDn<f;Ĥʽ+I6X/W~!_'waX;Laay3=đR>xo9as[O?gۿ8d@X9d,NDC廂74tk,_p19V"lk{%q4~_A 4$8p:V_`be/}[7>wL q?xϔ3TٲT vlɲeӜ8bU} o'&nQ(C] {x!4$9nl>Q5kp^E^! I(`7W`=n"G Ŭ4ԊR9{@~^ϧ~T(WhA}sܚo|`FS8=\-hÊnR{2uY1ujrvsѿO[6Ń$iy'n;: l2X@; X/v9|܌!+Ղkn圓YTt83iDxNq隊D(0ASGl u&&3/TA]-s݉ kOJZ}9 ӵFz"s<j$KuBU&0t/wfOMEt!\82$q 'z3udq1޸jv9OTYõ&ƨ^.A=F\{u2?ƒuH0q-EfKT p ,` E|+/Ҿézyy=j{W>lFG$u!I^~pB6.䦊_о{t8)U$A _4{.Uvw;nX+\E/+8\;7/Aޚʠ\KC@R؀%@ ERi'p!8?MUҀLﴒ m~N)f_7KzBSGC1Í՛u}[lx 0z$/dzn(T I谣Xk;ڌ:\%%q;_6,:jxqC/-6[$E?X!e*Nؗ/CUo_ZLC!xZ~SS|"?#u򚸺#E0p@SlfAoM5S:휦~>#vX-!qp$Hs[_ݏ^\Ϟ[~ҮDx1w`X:g_+FQ`lív?ojYǸy@5=2&/):bO%sUR+ tyչq)w !hMb]_߳?~}yMӤ|uT"EJizzg5TNmjTZ>-G8ג41>$)G*#XG2ڰ5Yy벿6O ~'^l ]BXSOZq,>TRs3HZ(e0z$w2u/!kZQ(D1xm7۫`7|@  F}`+TΎaFEÈS1!ȲyvJO)G<\OS ROο >yV¸Gm[o_CPYZ 盭$ [7?'"^zMu,(IϮدearfJB4]J춇{('T?}՗]֜JĢ@{Os=)*i`*GpƩՊRQx<0H0e+/yAҍ S.bV]w@g\9(9#Msf{83o:nPfl{`7tc-_b,U+)o^&}eϿ~eMI.Z?`IzGΝ~X2_}mYG[Kuu X}K+1ZKnH-ȸؚ浡("JJ6Cdi/hx`|X~Mܻ ~aj}32yꟉM 2w<ΤL~t+9ڍW ~acJ,}YVVvwM4>Jp@L'2v TO#MR-NP헻 7ؑjj P~fNS. g}36<bkƚ:guϷ"+/)]ս.c$_O}RWU\YdanjyYTWnϕ_4dF +ۖiWsս+3 vNK|B?zBky\+*>i;_W>A^ln,( Kv4D'TOH5/rW:ήhe;27%^rU_wBnP椼uQ+#tgoWJ4Rq!=/BM 0`h:M|DsA6z6):8g ٖuG޺c?r6j18;Z׭Z @X5e@hS#,=tӶhл;_t,)U}N^Ë<`5;TU&xg~r%#6JM(ܓ$S7rp,’;jnu z / k2s0_ˍB98ʷo$)?e??_ICgtqJ%HdO߽֙\wɇ#.o,A:}8:\[O,v0ZӭV!H !zֹSlϟ>c)DpΊf scB80GXEǽ1:R-|- XY#@H r (8%LK!?Rjy9[U )ѷ V0Ф R ƍmo{o] 6c6/a`U[c{Hl=Pi=LN+U_J3u&]G%a߾9=I8 .%@B)!g9F;<tCC+뮺Rk uR B9Cwqy$'Ԙ2~I$<3rHYh+qu_,kql~j0L&(_Ƴ5^*狇#kս|_uPwZm?(g?|,AWv3ţtYE'|SE,\>^'=!7o3qc bzBnKzXRTwq(x=,|$?f-v0U'(d ;$v|y.STzd2?~vs+omRm=]C:w?=YGGR@$c\ۧt¤1$rv*v Jd#9Ճ7d1)p*ct4(Tr('\Hu>y{xZ+@٩AHW#LTlM?w'.9K/QqQL2c.pBD( u^RX<Bou}Hm.`_>څ\g$8M>r"0cD!a*'Se=H2*Iv sVO1jxM}篥S(ddͧ2u/3 eQ.O=9Saeߘ8川$ekDž5RYHOw^$kZX].f|n];U? SW_SG~_Jx<"Z)N8EWttΈӎu׋e%-oYëɭKwyś.DWf {ݴwtO10ˋOegcVoBpRۇ1l(g'Sp0\]h%?GJ#YyG7j 8b|gk@d)Ψb*V$G4FMWCU<^gs<+BȄ6E@̃jŀd0h ԫ_9-;:uOƦ:!dP>!1(c O;+UYo=WKYS{S3sg}?F)]3޾,=}=c=wl)a C]3(c3r$#N^ ]58'2qUszWEa98ԴfNϋ,)ԯauUUpOf ;! J/S!})Iaͦ,7`uOM򋝤3lC1oSY^ƯqW(-5&}4~PqN[jO7n^#?Yҵy#olW zLVcl{Uc픊 JR10?y+sc^'O'7%1Ϳ拻yq'\/$lR}붱O~ ѯcwدX1/0Ԙ_LYN'Sh\ʇQ#%/8 L@x-U"&EUJN.N3qӱo 4 BbqN(?VNdd5?u nh6<9Ras/W{VThr"+V4U<'7޽Z*+=j3rG7+9HXemR bͬ1qɉCie'$D\7ٕ=;+Q<8dBzďވ*G}EVu}L4=~e,PNƣ2B?:/)M%B,.0lTt| bkjsI%t'jzQ_c $qʓT|/UztUW&h^Qj($LV X~''R߽th5NJRqEXc[%"^ps5q*~YhJ;D͕E{XSjG~4R&Z$J_>e rY\Wy!cvm-LUe?/\/*f/Gn3N4rsjE9#xLߺrfabfh+[6<~j獹M5$T-b(Nb u";rXZmut_ZTAiyĸ7e]ʖYs3Tq'~zߛU>(ÑwMxS50Z7v1;֩J$ }Wp2E;)%K 3g>ڇVu9_+0G^}DZƅ N~pϹ'i2Ɇ4Q|vӭBJJn.nr9O,亡!9l sO/zщ68;11L6E苵5˩?νwF=*uF Yb29l6gtާhaϑwїkڵTA ^1U =!1Ba3eT?{E?ߦt3"߭.D^>:KZKn.lB"e:iM=|^Aq$h_ꘒcs5MקͰҽvwby)SQ*XWL* [Y3)hf ٫|PhQ 蓭(g??SF.2S%vD7E)C)EvtEa3Zr!–%g-}V}!!ŬajQVBpHcF^IB)nuT޽cCEVt\d/ Zw.Yrނ󐊀 SUۙ%t0 *SWcgΈ~vtf1߹b2UE}x,)eBp|kNBzb)u(HpOR:Mܹ4J/TiP*(;u9! W7߻s'OyuBS">{rzh驔1oY7u 5+6 voW笽>1͙ģ 3wՋ2_8|:f RtKiׅZA6a΀)/ɥI,*Hoӟ9$ \Řq4R9 4 G7dIN)$SL^x;xqfsa:,# !d^7F)>N)t߾n&}5Ț1/4& (sq{#G_n @\x4m~T]Щj}gT\v+#D  Y[zv89OqbiLpHB%>.,aa?Ly\(@qz^7%I`4ڐE~ι0r{_5f@E2fKy$SEi6ԱVJ +řʎ. |DHlEy$hR4`l{W c>ŵ<딲7hx:)3v6P$u& , yMr](ՎqYj~_"P6HSIhej8%R^4= }&TO ɸYǁ{HEl=R 9[,GK[*ei!|]S?j~<})Ro~*RJ*(2 YkTl{{^9zX[A(XY{=`h)0jtϚAQO5:F?o52J̸DbhJ1S^2-dp %Sq!}5Y'tRe=N|EIzi0I)Ϟє=N­ݕw"DrZBWrG1ޞ9I!d8[USnwu: B @ ЋtUJ:7"=}`MmRw Jl;-MWF/D(dÐqd7|eBpSQh~,DQGm-^h3G)Epgɳt}I"VQ!i>{o}nҹկ{ΠZٍ̖IDATSt,I\̏#t3.fLSBD{!Kӟ~z#^Wfrv0hkFA*`cuW^ݕKv.)eB|&Ӻj^埮Fv'ͫ3naRVaV\ VxUQJZWRv6.%M/Pl j)b쑪tN*UE938gL몒dg)Bq- i9']E&|B^T]ImE I_B׏dI6426gC[g]s)Tvj{oﹱa02_n6mHNEW_zf J5D: Eܬ)y}?6U*z)'BdIZrNO 8i8hEPWlfrAcI \@Jɹ+߻3u^ me.`fÖJ#Pdra@Zrƕ=AD쒈\޽8θGps>15}Ocyj"͗D,JR`AOT9I sQv 蹆~lr*ˈHa PzWQS.#`D!iqN30H͙gAݪ<63g܉` Fs"3MݮUthſ_rTs Hߕih@':cpm:197XUM6p=d GkqsQ1B"}^$L w/dc1!>QJcRG[ $I`e,r/n rVTi.y!RmS<[liBD_TKE|yL F  ąSpzA"=V`o.6<:.E 4{lqTN&'4m4׋9}VVdsmtRw>dѓTIT/D)QgTW.qL4"Qhv1Q{/Pci 0|L(.½g,q b&oTSWëi*B s;CQ"݊T9A_nho^no躶ejSo $jV*g4u'z=RPwN/_6Rt Nuߜ9ǿ޵'I}޽œT XJbgT BB(7ZB +3s ,炱 cX4PSZj;?XWr2WNQ0Y^T>! Y(Dḡ:UR,YC6tG_XwІA{kmf+#KNstDyu~$2#Xóꋜ:Fak5pؚم(O !ٚ5dܸ2?{\Q(Rw4UH1uedY`ޘy.Pxz]r]iq"I_) jFvs,83J<`BUd,(Yw7?X7~Uq:Tq(ѿ}?*|Ǐ/_E$cARj+2U\5Υ D=o%_]5 \ޔnk/ԥz\ϧ٦Pl\yrhW:$d (]e^݋3%]ݳvIgHmc50 M 1MÍcF2B]v"2û]hf[{(Sy?΂Ȅ/>_2T ,ќ%w#<)gj_r`fk^HPqlY]kDD>eOnΣ"@ UYiWUlP/^xjB憦ʹl=ޙjӦ UTEZU ˝{fĘ1^5zT-#EQ8t+2AL% Ι uS=E9tgMS $8;bYRV䭮Vwe Ok%ճ{|lPwʜjy̋G@*YJ}J׿߹xm痢`jJZ D,1W&bj0vޏTEfa-̧Il*bV-餞 I!w~ J?5=b?gYT^Y`a0W_v~&G.?EnߺRk8@`ٗ7}^U!_bD:g}M"5g&\4[[mٶt[Ys򐞬 U^D˒@"!P.N[Pko%v%eY2mFn5$URip޹.p9=vWQ )g_D؇YJ,]J|y *-OQϪxR);}Ԙ^۬`1̟|.)׃8aB| hβU-xq?{~ZV_\YbŌߏQ5zƕ<@f`k9EUǛW/r, a̼1k~8I0g%C9'4Z8gY7ȑWȕ31FTÉSe)eLBmN7,,a'Yߓ`.8($UȚ:(;mbo_Q5-D#Bglp[ $K\gА%ql4!R;u2ُܺiOggʣj)p{=v:GڜcvR")JTfb> 6tG:ԊYgeiI~hիՓjL>=XN<{">o$e$d"$}sx|ćNЗɽou\^z սh5h䖧0B_<Knq&R^_7=L],*|9/״͖Rt|9N]O7 |//X'݃BYrOx Yr1l5%jh,2 wjA_PB#I*Ehê3TsGq CS " N?^ʜnD.qbl膌/KaL IWF/N/~l;˅^o4\U+ABtx B4igTDPӊ* ޸Rl; ݯ7dyurHc`a,:dQNCnCx`e굟ni<sɒ|(j#ɲ]R:E^$=P߹+6YF $?VkASz?.=Um%%F^#LOIE %(ˣPTAL c=;k[zMﵭ\(e=H+9ٿ(Ckn`g,;S.ڦr"D#|:\aWY8#N;O6qR|zLS]{ (K1[bYtb T&$gM෾Y;i!j*e;CWە?ޗ+⒥}L38tcCǯ8V5gjǗ*B?KKx@brE3Fpϒ?)5n6b,9kΥWOGaJ ;˙*J4Mĸ1sm7+Kւ-I-AC?HuFNqݞ= uӌJ5P;ԥ(#'o&2PlLLi ~r!'LRïA~;_o 1d-YSđ^= o^GO~+I%;ZWd_ɛȌ& kbOVNz.Or.{!/dV_Bw8hdQx5ƈ =M82pg |5ex֒X\qMs.:s^9{ R%YH(`b(߼dY, GUTpI]5*~DqЭNQSvsn]2@}Æ%}]V}x$YtŌ^0Of}y ,F Y}Rp_}&YhajͿo1yɴo[6_dQ@S!dN#`aœ?{؛{$q@WeM`bhcir9[X OM#+b8LwHS16TQ"}(dq>OBL1Y'-mm_cλ,As0uAfY1~wLe0F xzFVw4u}s?q e]mM˘R9g̖tJYY&8\Ԓg4,C[^7}-eBPr/"$>$IGluGMTLtPbR]?CfLH\Q~$mz/uʙL1F>I]cYIL!gHXQ@+;|6L,M2T'q2*eŹ%_=ߑv(gQ aR8GG*V#G9[U$^sKB=ǔ}>k>)EPM*D(Rd1E N6EK1cISgt)=Y<.6fSmtQ!68͞=d _H`DcM]Moh%?JLU gZ֊<<\S$'HfkrXlyu0Ԩ=c\RkuV emz*eqym"+;Y%m윙i& ]Aza i?rcIPXN)n4FQd I#<[3(jՍr wMUH&(S7;?g qڵ՝L2'mi @i[QCER"m*iPRY3*oD%Ɋv 1ؿ,s]KY{Wr u'0չL[Q-~ !ι1C/PtIGӕJ0NRJF T.e^e3bKWFZVs4E*l)zGJO׶VY n[&BopZ61 uJT٭ xWo-UC9 tQu`#}A#>AF~r+Ѩ0϶4%p[C+P7 U˕ zR<@ֶۺ{>1G;zmԼyбm]U Ǎ7 ڼEGi=bOi'd# byӘl5jkR.N^>Y\`p14z>6{4P@ʴ&Iopѻ;-=TTRgݦ?tZ$x˳J DtmrZ7}OI==wy@~ zDD yP@c0+(JB\.m1d+y[Y5lC9~xmvwf6d;>AX=Yj3a, *rctZO!5_G^[a,ZIJ$^xCm]tGZgh}D >ܻVQ&QN&Z"]/vS*]&8/{WV;o_͝gE} 4&\sϟ/1m`U-JN,w^Z3ӑS1 ]@"4|2mY)3"'@P|Yl ,YoUY4`,#t1 ?8KѼ~WC2=4Z!)@ADkՒa?xznXa/>>:NJFOx歓^s!D rft[R7R8E.~\Ѓj^əݝ1Byguod9Z/U9ٲ6Tc7H<_\umUEŲiawnz{qxmE:dUq.remweiN3h}it^x,Ϸ7g*v^sY *v9ԕיep٤S־y>~Nz}NE4iT`w )fH§>ztG~ֲ4_Fx>xib7kl -ָjH'}gSh\~{&mLIŦl]ZїIҎbn .,1Ճ`")gB8FA k{ hGt唵jt϶ {+R%!h^&WF#TU #_lh UO *Sc鍮)x5V&2ywLt.Fe"%x&Zne'͹]B0 ,$AeɩA,;?{!Sx}w$3U:HQ$8!gUca r޸Ry2ŏqZx [B(x*hR& gݥsD:4?^l-+WҝhЖGvϔ&Iʖl¿_>Cpւ4R*ɧQ1.&69O?xy|%3uN*G{/;q l}/j{KT)%:^ǒ+4oѩ<~&[ao~=g"Cj(,i޾1(V_cm$y?Bſ ?{&Q#sN)fŪ2IT/uR$rgSO'rA:'5KieXH" 4U MM XV2)D&P._ߛ_͟9`u"ډfd=3oN~DHVR@0Bq^'H6(J/)&RCS;5=cL4UH`iW| x'G[7b, Qkۿy2jg1`x.e|>hGIF|IUљJ%=$fI-}U2 )s@&`)4S?z_=IxX?Ʀt}smp7ϓw~';kswR9KPXE'gԨMMJWϟOƗ4Vr|F󴷯\()#=+v1b.Qqvg6';wNDv@BqTM|{yc~\`Yp$F%g]抭|R2W%;ZPǔ6Pb\.Zs!}iDZ?ָb]T%7\-l.LjG{K06(+* )Je8$cmO8ŨD8FRCʥ9H[)KƬn蔝l( y\] Tlx2"v qO@ WZ2.M]w{ݛ{IT5K'  )k.eNK菾."$GDTB䃍:Ϸfo~RϞt=;)r:wO}V'@RIS咥+[cCl6(|y*oo-JC'ZLWnVk{.c%#z44L CЉR3`Z't, l%{:{)ͯ Gt1\kWMJ^徹+ujKY)/w ?X~moT2.l%@0;]K{4].2]/=ۿI$Q'؋ͽH. \R`naAqnabD^9g4vxEG_"z#us#0iJ>%v}UBۘ] YԿL8ۆ}Ǟn6J\_8}i5c6kH޻UovUU(.e7.gA5^> I`G=M\ |}QQ$({2@@"⻷Ѝ9GG/Չk+;aJ~D!Rϝ`׋;3Ñχ!WNR+3܃U@U#,~F~¯) 7o[9[5u %KW+~Z1.-_\Uy.ob$$ic0-[T[ʵA)x!S%poitR2mh>Y~hkO~ xCl6(87ǷZ  ^6f߽JՈ8)tU>`kM[:vBe k\[c9W~ _쳧@0Œ65wA MӊNp]z>ݓ$]FtGw\_ID&K9S*^͗{+ 1 ΆvkI{ Eg†rYmSק?)27CO/W.sQ0]UbFϟ,QgE$+xp>|l'h2])ϻCz=? #9͋N`*8X\&Km cU'](Y^޾Vhv_="5ehÄ!)6nlXgJ_V\>gIg;!k[Pe c`}*o߼j,^_(^EC|)sO\љ2~$9{mS0gbB8#%JN1b.w\*٪Xn߿~Me{K_~ /7D+Tl>ڨ}:y9~JY"Q 7|_r#kTb,!ڛc1:5w uB&,bF~3 ;ܱdZū?9'^}RϟB0bv%{L"!~i_C ojR/v@?޹V%θZ{15jIA.j /V߼?EbWJfP}[6N9N+.ue"bAtz9':; KE }d:\(F) ӳQo 38peQz\Tx X}޽*,BM5W$fLTY uC#=:`}&jWDhAl/\Ljbqun;^o?)wF֭p|s鸋 }woffpvSTeA>j|Ly%o]ɣf+?frB!d[9ql}}(7| gf"f<ADQ~fedX3Qk8 2C +e,${r@{@ZVKNۤ뒭}wy%`r!"SkrrPh:~yVY&FAbϻ>5(`BdY5 䜽z-wde;^ vP>rS{ c& q9>yZM_$Bi*%_WQ:$ aqpP"GEt)z ^^SgJƪT'eNMiepk۝VމOLrzމYEf'j96{NN3-4wݯ*mrN%'dGƌQ0Sև^e&%CZJ]J {&fĵGxzLb:LǸ0 *|`#7 Zq"S n<[?:d~!Y@j=T~T(f0~m]K:qo=`l,+2fM^T])ۣ ů̧ b6Uv3*qBa (s*v,1nӖ(I:j Ȼesnq|.?ÛL )[Ϫnpw-fW.O^ m y[wwZmllj2gzU}ÝR5pyQӛЍ9+EkyCۇ~>&%=lvfTWJE)4G#) !:1/.B>"?x zyz0^a4_0.{O8bͻJSJBxhMYR{,ye y_̞֣!bzzF??oK';hb * w|qNElYXGpgޘ>>Jno!L_2NG]x6#Rб[^ӯf}'!eԉRTw|Se:)!(R79r鎂FڙMb"ҌJ21V4c[Ww%6\ T\~⁕Tvuc{۟$:Ü\B~ӝ.rS!Jǫdcz\υG֎~yUF5ԢTCLiPyPF5YXfhpUS^EI%ػ/FZ譁G?VF卑NFg x n38 [o+>9,gx6aqm| 0҉^ُ7ז7o \anJe&2:۲K"J-P{V%3œA^nrYo- FKK] S"z*r{nAnzPqBH"/oR{OǎWkSϹ0>-O?^qo[*q,rwRF<LTYM7vjR ,CݫX߹78_l\ꑝ?*yCˆ(KfNgt<2L;rq! j`=!oQjgD{öqg)Bݎ9QLk(q=-0"7;?EhĚϕRFlZΛM~j؊^ e-]SKY=kj!?ch h3 f4')B3"> i8Ws605A!qYm( )oe41R"@.4:bEunJ(iF,j,cMܙKFN^:f/9|gWå0y? *Y !E6$x)-=$>J1`-2W *t+uP(PUs(ÁۨqܾH±E6[(X˂ジXK@7J+rA#IRTi ndl^I:e4aͩ Ai'YJ)PY\#'.Qtsڣr^q yqj`r̞Fd;,'q 'Rd p_3Lkx.1Th0lɨv4e&w̔wWy# hGN g'&d%lXw~㣝W(_|12>s}_seS-YMQ4Vcl,hdIz܀ޘ8%R<-ވ[_"DQ8|$bY׾ czc~a1 vib翚DkzC |י~dq@9GLciVͭfG?:ϝg5~Eۃ{~YâI| KumBnY FX|d0P/H-/MS zp+$ G:K. ,wIׯvAa:8a1ӌzCe)ؓ V˪I^KKQ|l2.; cx2]=4_%Y{Ⱦ8' Q5 dOd "tuRM s[-DbbC{g1,C^p^Wx Jzz^\PqjЊ.LGv#q=z"&pm'D6;,2^ύKZ;4?@wW{LYϧ)fs2L]Q9 u}RᓧVjrnkTQ4򸵝^K&Jф1 _MW SBua-3V|,:DAQlm*? M8"-:[y@ҔpêbI`ULWw~d kA.2b#=J" DzhQȍ{G&$PvYvT"P:F6EY JJp@<Η>~~"SJfgh(A'۝0 / "1c.E$lV)ӝ4C;h[-:8L&[0ɱђWv-B,Yp,۝h/7{.8| n-)vH\9Pk'~;c+AXYED_yZK:Gde+J+*M0mcc'DȅsŠ\0E8۵™hA*~;160h8+rcgXXbZ)DI!{-B e0JuA,+| *+7Z& vj(Բο Z~F6}:w>Mۇ4^ |~xdtL_ 3zkیͻS3_I⫲|c!f/MYu–?|UVs W X, [ip95F60%1 # 12ՋRIJm?q9i5&YD@]q8aNS  a0-\z}8A>3r]Cqdc{' \x* { %'4׿o!!1 ' gMzN/6= /<K\hG89Tc(po][?,TyR(I^BKYe,9^\ʼ}{wzrta_M4#?kvm~c;P31mu:9%ېp>UV + ,8X1QHS7?q6yW-Hc6ƼOE0QdVN(?>׫F_I-&>~yAph]V&# {Z(Ovzfd 78#9e0w$ qB GgAvŏ8ex^!%he՛ En4( g]? ”BY-RziPNĝZ^5T+goX3.gCœRw^]8N8Z \JS}0n VIV;IG96B4%xy1I0_u`7[RF?ײd giS@Hk3l:tx2^8&֥(aH(#)Yz!!B o*~k3*0Y┶3Zi^㍡/:|XT)LW@v(g)>O`~5x|Y\Oq=O ջ0,B,F <#NVjEh+ }x*tS?LU8S׶ +"w{gyd9\?8QS\ޣ QЉ\Hx3֞EHr:S={F^@n,$Akꫂz令16:e:Ni޸}%JsPw*@Dnnޫ؈jA=npX<1,_T#OE3ڕ YHZd^ɇ#\ЅR>G4! ,Fk8x:]nDUqրNg-h/%ũ|*/}O?{#SΞވ^;#k%@aFMdmMk;L$OMS U7;L8hp W$Qv2/fIm]Qvށ߷Nȟ>O~a\lt>`N+=|(`eOHZ(|10//gZwFEg!0v{=[#DG v ׸AHSo|xaTzsezz'x2奸9;φK<2pq  ?B+,:Q:~mLڬ(is8!yIXNGH?WI9w Uᓆ/*!U⧋+: l2(lnIz~1#!S}vIѹ~F9o"eGٝ~TKEF^deprD5HgҌr8 xj*nɈE֩p#s߸$phH(B)K]ʼn?{K,Cjd2_jwvprta| )bj{ZIdq%q´kkl?%0!?`j8we(IQ.B5+y1Sdf5a__zΛۈ|jW?_o,E]f2c#t>%)LD~o7p겒5X^(]_x4䁣AM# 4< J7}R葵(J^0HPIz=|hs73gdtDx̙sE3<1ϝivG;=IJM;!l&S4?l P˃$, q4 #.N0kA<!HR~߸ast]Țׯmة/f~j#/޴)dU x,vf[%7| Sq;C 2h"Gq9Lhoaߕo@Dz_}%tƅq32hBU}EMzxD;mwi%)rQGASHw2vl^ڐxg{fzAL(U>XcE }=AJ38Aaw|% WͰ@(^u;ð=uczu,gu.clBEso]>l20Fq4@c7Y)x h0TwO^N}@xqM{6/wG'$Y :$ꨒ;iT1^ޤ4ƌ:,hK;X;zЕզiFaRģƀ˪&%3xx2 Jn(tvc!D)=p-Om=vFU˥qԒEg8=KVݡA;7 ٘*`_aCPq/&K(")r|_lIc͎U+̰+⌲F/w191O"ޔ[C8j )eԌBU)ٛnґml`㤭:T")XVckbPnwFW,a0gЫ. Qð%gy'TX`xfcXʕ@S3Q0ϚaLC7Jl{ӷy^z47;2Q/x}F25y*i0BLdN|zj1teS+u-7~" _2pyzX~hj>mT˽x!Ȩ3S'QqaNLLM|5F\Q8 @ wքN|IGɃd<(bDGڕ JcŬ:o ܑq#3^&Nɭ }E`KUS:GhbiN1FNG"*q5ܭ1 r*Bb4#`#3AZ87o?M a #7nGTcjYG*R0nSYC,e۝c1<b3?4}4ق &1~Lk8,@YuK&6D]GGtFgs%?gfD%p\M(r:czo-b폊̖XF#%>ҤytesCU/_9{&B(à"~csYiTF|EjP7[$G,buKYtN<ʌ""G}yxf^[N;CU:vk2$I*Q*Ylvo|.\c?ݵ~5)$IR!Ol=c,{AR4YԼFHxdo/ X1ǂ=Sגb i;77hOO3˸J 8EϤr}POvbX=L Nb$qWӻ\buԳ%Udi%?MLR9,Uwd:w(+aǪM6N=X×jt%YWSǿd g-WzӅ.=vGnjfK"bUɥF1a wǻn$+%yΕ/0_y>~gxy no=/7۽|{dؾO+cwVIP8bZX܆a.aƍ؏?ƣv}g,?~U!HT}mwȋ禠Ib{ðbii:oV7Lmm?˳L昲j5s,i;:%w7rlw*EԄdtE~ ?~8w{a#z 3~je^swY>JA!,lj,gfWzkd4s72_S44AUU}B4SY H@=C…,'tb1;=_nWmu]Ysa'B:U$'; 2YZTZN3S E"c{z'=Ke/xޠ4t|ZɔQ" Bx0%*7QqB9|O^ §!:4MF-yS9jH8:t7H{զ/^.M?-Q;CG3˷ _~Or ճ/%07 [H䣫UAZN Wn{zo:#X#~K[f[xA&ø ubw'\$I9N'_Y팵 G^Ƶ>0'f^FsrCNaEJ^17ogW9RJ(o* QQÛ,;yyhRğB23;ѩ`NH‹weXvzt $ŒrXfH]"1~3ݣ=cXYD ;OO1!Ҭ4^)rS 黮ݵ׮midxM=Dhd( [Wf6IT` s[O`*YJBsӻE_;ǾLg?;5MpEA~u}K|~i$ JbhZ?E>;u,oh]42NOrN VCiVg~v&dwEϲ}V?2|{ywyf3\Yhӏpw_s|{6oo0̕œ)Sd+ˊ,3M(I4Bm?Fƹ^(vgG(ѽ9`b^Qf FS]aɰnLoo}Ŵ4U7Sf?ΠvшnIwkke#ep7BQLrz{4FlԻ]rqF c"C9vg~'+,/O:$M=̍ y7םz7 5ͦOeB5 Lfw0;8!2Ǣf{b8{$f&YJ1 ?Gx咞7ɀIJP źg&fu|@NpEew!x? + ~XH%S@HD|kݪ)O//0;;/Rv{%^jyK+<0[}EgigvOxa#aZ^'ih,ó3QT?INch{@f .P&^ewEU?j3/ Pm E(h"c8I?I)(^I¯?rN'&0N}T  XqDS*B~=I܌rR{sou]wSO%S?`@&Tny}f=%JΈ*H:7ėYEalQ%J$ O8%ýFDA:;g/ B@eY BՒV0P4/CuS~d9/s?sW8卷;ѩ4\/崉CC)ť 9Z'x3U_hVrӝֳ^N8%&Kse jG5ErE#|Uw,7#HK_45?sX#_W7ވ^Y!)#Pe?ӭngwlZܳd *'l[coho|, 9)Ǣ(*!$8_֛HǛ-^`=Yf\ջPXV͜ ]v;㹾?茚+W%w2f f/+ER)H&hs,:! 8g mo:a띮(YC:'tugC'Eۏ qzfS sN*[&4*rvZugT3YDygU)(L/)*¨J<[iBa蹝!GhOV}޺͖R;8Ų `aA pnJJľeT`zՄ33}赋#gGb(?|{@!Ŕgp| I5/ʋURw & R<pR> ,v3&wP:~@NVf23 +pQ=S> =z~B$ FY59umwxy|t|ot \{.  &x⠪^ 9HRi*c2L*fWMFL3Y{4X6I8;2T HeqQ"fM^ɡLLzXO:dzͨf8+uYxzQ6c1Cw Xhg8o/Eq,O﯅sT+ab ]DlãMx!`d(loջ$ ^5hjqZă^BR #>>ѣ| "7YZ:!'1F ?&SHHd;G4bZ^"9qs6.Y9+FAZV䆔" ѾkWX[X*LO^|akpeQ;cP{ >dyNeO*Î(/+)R %IѾ?7>W e[KTQvG7w;S_=2di +g,笊}T08梺.l]_E|qˏׯQ B<S$3Ra#hp8U(l[W'  - w/~_MgbtE2Vks:80g}Yv?MI)_}LYZ^k-cZFc:S!Zi Bn4 Q*il6+c+SJvMYׂD)B%G]m|C@ЫW9OWzGO!({V& -W ċ:)Ub(/-/ߘؼ;Os@3*1\Yˋop{7$ LN$ev~Ml6IF&4|uY8{ @w3Cge3Y-?͏"?f銾O {U$Ihj)ݨ)age}M Ė@}jݡ+Kg@?Z56qT݈FˆԲ;~Oc g0h}]4xnʥ~1q2Qt+$D8ۏO Êg|dfkmA`Qy2ǝAN„YtmoKWSZ WӶ$%ljlߚy>Ee M"8L7#9HhߦR247^ I'})zsͨ3Ƶ;+W^)qL, ZsZ˜ښyF̢pc E95.бs`<.tL.V( ; n-rF/R*cE )FQ3r}[˳5.{,gRJɨjjt\6RYFt y@R9NSTjSW攅 4}.alBۏ mbKulg$e;`Eb)0y9C;P8#$LOIa!Fɱ0E0(\ J #;Ro™҄j2i"Y-J A=WS!JdT[_lh4MnM(?}&IQA Sh2By(@ Z+TP}W Ϟ\B ALʶPe.$GS-R¡tb䍼z3Fto+&aT'rLc̒ԧH`#{5LSY58=s_~b? rb- }cFVBI爤i2߷Y;ٷ=`#]!|b.6=+@LqBS/'+u/y &DNTl4pnU9AwDrXZTQx}V F|-A#Im"]( Sc)amaք5;q/RJ&A-R,F]èm6" 5DX6k@b^,}rjtpnE@.U0tы7RaY$q*wrs[OmSng>[{o3?B+ޣM%ghR3$АSc`OOQP&XaLWvȃc7f´ q\ۃ܋+3Ťhl|OI* zkwoM3JGg+4Qzwş(E80Ijb8wґ՛02e]qL /_!xQ9E 9Dg`Ot@Fcܚ]祋|2Qg? D&/<'^PYM(Rn5<ǦqF\9ٳ=xLMLVc f,*c/F4g>O0avoO7}7[|K{_1:h4Qzxzqds5O)J5 @O"1j3[^D^PZC1C(cJTWn02,?I!>z:d>ޚ"{l;#OCkY-;qd x@J;/_-l֡hfS?R/sݼmwDL>?_?y$W`N﶑" Q!nמcv/2 l߾Ihũ5MmYT!OnYu3ڳQteZދ̣DK.M)7Fgxe5TC ͬ4$) 8>ҧ1xqFb յ;\"/ȒqkW#<ڒNp^oGpO\Ojfrw8: `Irہ_iU8_ݎiX7 خ`#QBO䃾AWEEu%?ƼXviIDAT"B1q)|΋_~aP)";U.6#+lF)O)!77pMRfWw|Gˆ-L;EF&)ioD}ٮݵyÇ #m`:]䧋RZ&֑ǽѨ7I9u@$ڞv/ 8`{>.0Y3'`b 0Wol7;tA%cq#yqJLYY 6L'}Ig67(* &G<8Q DQ"JCN0.-3Zw*1~$WQ`lSILƅƧYL'^lT gR*"={w_q ]61uBvѽj~sTQG 5zHP")4X̱ 2'0sʱSIlIŚiWʚ~*L?>S7o~o|zNVty;yndH_kZ723Ц!I`aPS<# 4ICGհ.[Ahmu]~y4^yOM˒ղ()z&ܼ7Ui5htZ}ڊ$HBY Cn-Np~:~1ͥܿޚB 9儊,NHMHS ٽlJ߽HeVgʆ"d/EA= 8!muq8G6[.=7C3 qء$5U*fuS~.rF=cxyNimXΰק**,ĖF)˜ ]-Hϳ1\?\ʕrU[FlT?Yyʢ!F|襎v:[d˜s?hTJ^!?e!`<%)6 ϭY+~`RzҔeM`nz pwh7 q\jZ0E$VoڡϾYĜ?Zn;>Ϟf{5~=ѵ FOX|ݘߋQ"u I^_<; uP˨TA: cDdh !G I f򙫎̵~1kϳdQ*wZ]?P&,LJ=^n/@QHI̴@̳$)δl)xez7S.TG &|9$Hq'@J؝動?Q zNIdLOA\pI =]oU7&Ùj !QkRSE@A1C ӳ)4aԏ}_/_[(s{2Vn@w ;קֳ=ԤBg%IL0~.2W'xQ:wuIi|mj\ܳ{\o"ۋ;Psdɷfj34kj" \U4U#IH.N7.w[ 11vHgNtQ8911(i!v$NsE`3LO|‚,E^ȝWDHc( /]dYy_?K38y,}*'^<1on &rm5nc]b85hB^8N] VvZ]$cth 8d(~q}taN(;[kn"YWoq&v>\O149Ea~{gTo>;|E=`D^jmp"H*pw7.֒fjNv IX1Z/94=Λj˂dA 6%Pikulq~<-v-Qhtgxw EB$D~MaF^Ϳڍ|Yd& |3@2bkb.lYf`+,fafsX'ʭ`TɋSZ>6J?|l_6jQ$I lvgw9Nf] X.J_R.7_o,M/NOUGi[~d9CJ7`&Qx,41?)[n7DAQϿI _*\][IREZ%dx]uAvۃbtը~!Ex0TBnGY=h|ZsV67V)e Vo1X: f`]iG1͛ѓ: ^`Tn-eD?$ւ;Nm/m>{#?릩_ʟ}?J$i\ʜ#^ Y|nK}&wq tf_sT\E^~Dpc{7hgueG' ,jECmِL6]Tn,7.KRguJR*]OUY,dis"s,ݦ+[^䴻խVo8^\W]xޜxa&gNdH`0R(edQ&!B){N!aop|acazv,,4it=ǵtY_V7 XiREѫ(-O44 L]㘴;,/-deY, 0ayJ f8àhi"+ՃE1KE@)ڭaZ#`Uěr~HmAswy;kOP4ωR'g}V+a^:logjl:[bDYަF!u`fs0]x,&x1()(:#=\i8I)r$M$ +>:b#pT%T-VIHSrV\f戸c>%I481Ӿ7 jqG,XC?,LP)1<W=?3\Ì-GO??E{Qϯ%J;ЕSFeb rX(q55)$X(C] /۔ca@L(D)ⴶ0MNS{9`,Cr.ڕj,6bJc|d)SSLMYVwbn^O0s ӔXD,jh3hP&qQJZ10 W0O- $L!/ryiں4[LzhmK"/Ed "8>NvZ=\=皌 &7ق ֠>HRl`h4 T\-)NolZI>6߸5O}}5Uk cWu ,^+=h *>sei \{t=>x v&Ε٪(n |#?kySW: ̦r|7Sp>|]BQ)57 uX iKӰ"DCYea?q e}0-]'VTu"9$!Ӻ.u&<Ôdc B2]FO+?4&ۧFgwZ=??G~H ֥(Zj9^J(yԳw\&Mh e(p_fp tL̠X.Zށr C~4{޵=$>qi|JuYȚZ8ai>X|UBwo^FϜ6Ճ;hw\-;x5z^VSpp O+˜.ycV55ywa3\ 4E3EZy}}qY1ۃR"*kb%< eҬv y`Ww6M:*i^JyMrJ>7]̕YKFf.sqZ뻝FI s~/\@s\x"ʠxiS-<YϧN3NdF8=ʧg|)*c%VxI.{/P'0O|GgwLne/0X޹vhK|Dx|Ñ ZÌ":'q"O Fzq^bYĻ]Lzy1YXݜLZAf YCECi]Sh$̔TCŭQcU9M:Un%)PӚ$nPM-IbcrҥaEO ϞT!\Mgc*۔2~\>Di2',R '1LMi §;JY;6WtM Ӂ)ϑ@E&orpqZ*em4s鼭Ki?Z};n@1?%An`T-S9mܣșڝ'aD9Bc%\>Sc!)ED}ll*ˠ[pu8j%xu7n'FR/<,wPh7rj *a" >+~fw!4}ݲ <ՎsC*ma䙒T骯pU(~l5FO(2u Tnvn )gCfK#xS׿wBp˯\nDG P$q=zSɌ 9BO< 1˳h!j(dLL9(ds౦ |[tE)fdYXV>̊B d-!2`7δzNgm9$Yf$p9B74X)KR@;pxW SAkuwd;Q*Th(4 q?k;҉.?I0lC;jQ38$cd&lI0-= 3E'*Oxkv{>82 .ϥ"dղM@4`!eDKsÕݹRG S0  U4ce?|gQ;hl"r쎳RQd({KD7r(6'I(~{_Dro":#+)Ip:~S|O 5ml?no9=fw,q:^gotZ)g[ڃ7v :(N;iq4]ۗKSlFA:>Qc2۝z^bǡ`ik&NH/ iQ2(.)&ˤo3^g3o Mj@ I)s06}W*f4)su,Ϥ`]!`0!4ͫ7a0E(zB^f1"I/iY?Yso5/Hj ꥄ?ůs.?08OO[˝N Sk!k4;I ^2S",y7(e@HY ng'*T^?xW/},t:rbͷ?'i`; '0Hr| EK9㘋4--MK臏+k /\caJ'XHo!K @D5#/_ dy1S0\ sXdRfha4Y4u(xQ\Էl)V2==3ƀNk^w^zuI0jyve)gbF,fD }z퍒NN;8R|!7{#Q%U9T'w/o)\Ր(mfMc\Υ Mzϒi _%YQwbfqjeXaE^0Old [ Patfѵ;N-+b&%ȥcB8C 8IU(6x\c:}`R:Bd tF{z[=, MA J- _Hx~鹙C bV_oKQðo",PbO޽>uU[(Z/\{IO3`xqޅ`yMf-?c|bp5tt]Q_Ѐ,CE;t*1˧B'5_Y9~~{?aQ4ByvcL9&ThH)<8HŌv{kgKDLH6 ]e}ɪ{ rv}o8G91[[w;OX kҡ#nҾEga"M_{s_*n5]2g)p,2Wd1U㉩dJ9J`l]2Q juGI1;h;$Ema2t@K\5yAѶX (J)itbqruuGj^W0h`g\Fˁ_H85~z Әp?{7쬟O}?A/o5/z=9^jT "w_`deA ^f βۮ_Ȩ<,\APΝea%WievhV^' ;/p㝁'TqOaЅp%i{W y6 !8IYR(ۜ[9~RkoB/d.Ċ(0UFnI 3Zl&O(dduސRrk0 z.*s`Aihqc2di";]9a&f?^H+9i:tIΩtSNgځ㧵aX420 Q$d -A ]?j:|{"&^ +>nē(3t?Ċeuv.TLɾ6V*zY3{i ( O Jʠt{vuN9޾I7JlK$Gw1faYaX<`#mطsOۡ-˪_]Ny'F4p<󬉱3V?[4%!]vQCO>G_?ѧ=my%]Vя|R?eTa[L[1uŏ~ gX_:/M!YB2"6"HGxe9 sS$WGSaV51lI/׵DXh3Qm hf[z_ ڜxɨt@$r0wִ,mb׫DpT%oUvsL۱$]6=.7ٶ͛6dz5SP<( j{d?ۋJb,p\$`Lݣ@̈Jk5UGdv'J5 sD ˬ\.ϒ*SWAnVJ 4-`̥n;h#O3jk|-;pUA`nۘ~b>"(1-\$Y 85얞ɀ0 F_r\$2590VஞfR76zwS?C~7=Ѷg6rhҧџ'>BG~!Wg xHZm2,ôk!0Wdͭ9> Usfr?"̌ 卲dž1f\$Pt\vݵ1Rn{ni:\|O\G :@ 2GY6.t 4adfLnT,Gn'%Cl)[侮Z&ߺ:#jANe\oZvP5֪zS0,[uun:Cs"'G^lkjp-1-?Ax~)Eoo[->z%k75Cؿlƾ6gS$z 7֗]ϺИY꠩se{8>7c+卵7f, i sn~"SQ߷o9 ZxM^K@ D>*tX 0Mz4> ICQ$IוfY<.QD@Ȗ?WS{ҧZ4mQuSJ~["Y^ =Q=|ur|@FH"Z >z7-pJuPurejKkZ1M11Bt1p{83N}b_$ |xr-"Vx"ĺ޾~Kv 4*jFl 1+.bs+srwcbXr @"ug H'l&@7܀VO~O{yt3zx_3s3ǿh/O騜,Gtƨ PMѶ%=E _7Rݽ0ecG~ׁ4A&1&U*,;ٲ {Gzl! }v"(M$yXP2 5*pH\KSK˘[('}q$Io{7u|6ߺ^ @֭*HͻR.+oeWUCt%G`h@2;Y"X++ #/8b ~WR ‹D->F2YX|PP,HƂw}4ˎcݘmsF:[ˠǏWo$>1&pۮ`> 5lb(Ysy͙źlYX7l˭i1G7Azl苍E6 U=$!l\HR^8 1Lk%1ǫ5đ_׿}WSO۸Oy% 4Wps\b5?a.UbD &:nKRΌR!Æ$ 5֒`:}zn"8Ȓ)e"qι}R1i6-U5D S4'_*u˰D7sj iO w;V0G&rؘG늕Qџ  N;s،а:LTl[3T5,;+|?V_xpcɐTHs@o.'GwmU7bպ2ͬd3cըl‡~G?u87dhĻzZW%k6N*Rq=> CQ?(gWm(~>kdUkKqY<4Ua#^vE5t%ZPJ?;N;rȩGW{fdl)BX*վ8ULdoeĥl'Yϕ} 3puIb;vh6_M4 n7Z/WIrv|90igZY:W[,]ʭ=qU6XҔB/S;‘붩dbȧS1dM1uHB[ tΐH%lY6ɔzUOl)Ȼ no8<\lwk&lS_&)}?s>Ofrxw= /x3מ~oEqPΕ?i ݯF߰_1[o07ER(l> Kx={O̬8|>(Ҧ#Js/L=ݢaqM0LI`!*,!et[VJ6go/'4ހ^4a I*x$-q cb`fjfdLG >nPS4>W.W?)Oo}FID-Td#v><5_])@PbfsÇJp@Q]o:^Ń"Kf2BlgH]d:dsCw=:3\μT#L #pmXcYz| ˓;? ~.ScvՁ~ CnM OBTv.& lGX |p=Ie??]:qL8s'=w]Bľ:%'ULirڮ…;VcHSY-[C Fz]]8+7 ~~`|/K/^մH%O>C?|! v(E8_k@*=~v!ȭh7|QGl7G!4$,dyaqX(zqfumx U3j@H*(~@{X0R隱loc⩇jai]/(1&"AI]oW&Io:b)+6::復"cje;Χui9'TN` gZb {7nMH bXl~ن#K؍wfx۷gii9Сˁ|_.Ώ|&Aj6i6#.y yTJb/ EKwŬS'^u E{b!n}(S+fMP[+=dͯ{Lrj>ĤU'?q87bFzxE,4I4JզTm ZHnko!9kw רl nz+6XݲgfM(T)\owb e~RW쪭đOAyͬG&z8yR\%  ?ӦpXռ1O/nsk.E%IA&g^?{g^uttQH?x{ ̯5  Iren`%O=tXm:H4vX7-?8ѳՒ0|#=ҵCXɨıE嬦|Z̐մ XdYZ m^TrY NGwk_(WnW:p]W2פH׈̪^Xp#sjP$HЦ3n9T '1de(thKKMrŻ)gBК^ MJvOƆ%1,Ķl9EnYmn>O## 9Z 5F3ݢ\mɄKCCF*29W@Td8`?u:&mW4vXEhZKSܚ%4)FTު }DB gVzjn H<4ͺ2u ~ju-g'֢ե ZnBJBŸp,C#CK7&/urʹ6T3n?*!{bbR BsyX.P`bֈem;uz"$ i.C;gԕ)ன0qI j_\]FN$?BDYM/%AZw~}Wέ-9Il]v+dNjeA@x9Gx/Xp>ӎp<308GxNɦe+b+58d<`F>K>Q (쳈4%@~p]onMeXQ:Mv%?u/[6F)9/t$@Ĉ6Mj5[Qd; ۣWg*,mp<+L`R#!m|tQa"2P&L.i\M|R3c4CYT{A$zc‘Jz})TgHf|nyhDa)-[6F8=Z=Qa'Iy=: Rbf%uxfm0&X>&",d-fUFPk-%}C8["`NԲmnZ.f_yi!UkKQ9Ř\^ ecGkdie<apb7/4FH乥,͐_|˻?[)p Noͭϭ3OUu~kq6Yi;Jj{g"2oWGQr{ s[d^Y%x7f t9lUZsfΝS d^I/_ 9Rm4uY!c˱X7<=╿XUY -ֈ`iC˖M0ƺa0AT7< *"OK/Դ;Oqu[㧷%;o `Ibڽ,4I1ĝR`r:,2R41LzF  EXx" y"@F*lԿ zhjYxaHLRݹG`{@mX,G`_aJn2<|ۓȁouq^' 5οBPS;dG: 7Z~&gs׽g{0 8.SL[bD$卌4]HD|'ţbf<1_)_6֋\(ȴ\Âܟ <`Sd:bͯ\\:muj^mStxv7]Yw_g:Z9W3-۶o#̱>b] *]W[OХ2,P=[)۷H:a̯2Ih+9ӶL۫7\}3ي2G%s ^+6-Ǯ 8nPy뚞`Lwe|. =xPMj)뮕JQ4"ڢ?PxjZ64}RFai.$aוfpa aM@glǷmӛk6i @["fǴºPW2=jwg%LR5.bSckERY>^k}ȫ rرk-=\c%RgΞ}=1}t/FG1D=lY&4>#GF=ex_dhԡT]kb.+257 PѰ•55loKr&J_4<#bޭ" 'm [K~"yns*뚮"D"5ZM rvoyp|볚iya?JE 3s߼{x7T'(*h;lMVA 8(wa *XfΖalc02 :qrW+sqE{g˻hj$xxuWC|ʪ"o;k3?6y Y^)v3 mǛ41P9g@*B"tO̜=xs7|=\-Pnu*z M\7L \\WT ,/eQ[yN<}+;_P94eb8"u`D\Z -F~gbϤIN?w;ek4M)Oy0?01;K{O>~Cd/T4E2$+lZ*R!qe} w$[Rb-&"y{荤cMݬ@JٶŲak}c6QO  24r] f(4gf}S,IDHCe{E'[6,i&'R:rҺ Zׂ50vm㚺}Td"l׵KW>kM^~R~$Y=;^4F3ѭ>cJ!9dӑ@,[R1X>_pUzհx chn]bAH1r(0xR:J3/PŒeJae"MnC#,'γZUe_0Սz_O`E";KE 5²g?R̕ ;Gd#!~b@x\7gV F# ^MRҬXF1Vn/4rRʗbZW$M{b.PRB.=z/զ5e 4VuyV ͮ'6&CE^/"|*Sm 'qU}e.hCйϹkb]?rFpoqX!߾ua84Qi]כ;ډa㽏6!İ蠘cgޘ$|D݋\(,'~PeiӼL%~9=Xd8(ә­^$bvxLbo]pSci$USz}Ggz1k⭁][>$Ǡ45kjz-8@ c 0" !X|g3 [R"h*2_e8Inqj<]Vt&=w;mX hSY#sLZx (\cp7`'$דU{<'^Ez}~iȫ߾{?!%h,Z+;dܜ*JڂؓWJuc?=2>)1 R՛XtpaJWEȰ${ewO5s s|H&wF\QV*I~7Ry`D77f/^ct zҰ-H5",J]¯Xdv)D|v>i_,X^~#7QUBb=ih/Z2*Iѝ%L4{B$Ѯ ZPR(4&0Vusf؟JFQmfW'A\"2E>) Q5[ӨyD] lr Jnx/T<$[R4]mTrVɗKIR+6uWnWB~#jHx8XlIJ亸cTvQx:$DNq=ȖT ȗܺh{X4sn%[xm7t㒮Gug)蹖nsI%zT`zjAS PSi o%%LrۈXq ]^]5~Lҟ-9Èd?>jv52p/]oB3= ;~O'G{nέzoܾZ[i@[EXP.D]9ჩ;+i \h9˽~_PfD3Ryr- txJM=0ͮ,v~ףkkʤ;HRgWna?I%aLHHD"_'_&x}уUP {ɑHO7 +S9X_zyUmv) &h 󴛌Д5l^ɱ,&HvF {ձ&O@\?i+ C{29\bAaK׵Eq, Axg1>bG ;?6>Fo[x$K͔5"01D\!,JRV:B^[SSbe+SUc}s(H&iDdFd+Yf[kbxf* lyQ#4,JJG;Ew'J]X__X ^^@ @f:y˓`Yy ZXkl4T'+?7&*RTE4e#c)3b~cڎm,oo0 -.'.gB=5N:CId$`pFG nX:.1-`ev5HSぱ>cE r5nfכ:fWOG/qʵN9οÉ@G h׵BVpqӏ}zrtLď|Vܞ\6<'y`jvuq"/#b%W푷Ն" k0X=`ɿ 9VdX:trǂgiUW:k Tߋ$ض&Ժz66M:\܋z6{X(􋮭*liu7Lg`%<2ox*ͬqoF!4Cj1zp=goiN{BYϠh¤OjwMтiw6Aw/@6h(+.F;ďԦ,L/=bk % KF &C8GFD?? NWL?}qp,1|]Th  0GzMSުI f6hak/1>zd0p`6kRE޻SiwftoaŅ0QӣPyZoJ˪ ۖY;%h!DIl8Pit}X4kjCoɳӵO/HNޗߟ{?s=2 09^3QzT,?ǂ_k{x8aZnr 2lķ 2FUw8v??UUzRw$ƾpss)Hôю\kkP\ vC,ƤE%K`|2/feF(Go@1l_~7+W@{.nr UM-, j~mٯ'E,i\$kMtlX4톪Ӕ]SSY"D`̺.(G )AtlJ;2H_1!@# (bsOU;kJCvN&w勳3ӫkZ%$ȂRWpCx)'~})fV>Csw 굆s:7Aq=RkWObޫWsrWWVU7ٟ)Ҧ-+qh*64@9``ؓ$u 4 >}He;FGi:ڛSnSAWnàc 9k;zʩ3#Όl=)hRlstlݏhky 0BIRcO]b>O[m6g_.x)7/_i]A8H_[:1vч&mwJA=hXoO|)ҝ'F554.=|NOaDbdzu488MڎKDzԇ?.]=M^Y/}SGic@[na1u:6!"{wwnR'N7yןi,ă=-}ʕohqo/A E|Pu Y:(4Ap4E'l?޷_٘0~ޞ.iW!7ՆgE§|-G,t\gM`q7 U^rso"`5pRO9_O~];v"y )zQB[ۂaSq e7ToηdȲLxwә."]=s̩gNm=+ZA^,òL:{kk31xin޵yGQ8ſʧ ?7KSwwoln>8[̪ MRc1W #_R)g׆LVc@:mEWO|q9s[wkGCO\Mm^$F͟ӧ<av:ڕyb4^Ԗײ߸94].eZ[u@߰P^*iN+!NƻK(:H@StqC7E~U]ޥWu?֯~S5d$PO~O(>DQ_~q޴-I  p]zoXs3XC L74gE}ǝ.JAqϭ:Cq}׫>nCz͖"ػ?0y{+_KˇCa?L]{~7dž>SՍڲizӴi B]:.?yo?,T5~+/Du۟QV` UYQ[U ]~Q6ki<>j.K>ҥ3;U7ty{~078<2omqǥ3m^Ttxw !j.P'#Nv%zڥ}QֶY_wm9\6]e(R+?z j'>%w5t/v)D LC{yz`,Ma9CCsv I.˿]1}-ҵOtpPρNY6~T4t5'y+]|y}YS]8'xTYN{O}.v]g?yUӰ\HZzStOuzڥ-yiu;g$Ԛv vpAg@-ХIDATxw|UƟN$B DATԀtZ^ewu}uWTX  HNБJ99vgέ9|vΝ;o<2@ /@ @ G@ @q@ !@  ] @  @ ^w@  t <)}>/M AUO,$:y%@T |zU@`!+ @ #]TMFH@ Bx@ 2BnFȺ9 @P.p-DH@ U!!dW.p.B݈x@ | ! |/#]`Bֽ!@ x#B!d/ ]`!뾊x@ <!_"}3.P*w@ < !- @!q(#]#] #]P  @F leG@ G@($B@ p%Bܫ4B ^  Ľ"]`9B@ p*BܫBNE@ NB{B(ZW ܅w@ B/#|]!}q&B0x@ L#neu޻ߊ ] q+b[{w@  !ijUP녾 @!MTv_tT.{1Uګ/] m{%UAمk/]  {m׍{/] E{B֭—$^@ { >fB֝Hpw@ x{>c݂WKw@ !(u%^@ x Y| #CReu}[x ev j":kK}cAexޢ@P)x e"x }AA.p @ qw3^dBn@qw'bBpw@ $q7XPv\Ek7|Q߅ naޅN5qWf,F>ܥ@Qq7'XPv CPtK/G@ B܍!3ٻMowEk#b@ T0&EXS!ezS7@?|@  +#y0e'=&/hz}@ \w; ì{3*ke{Oުt{.] w)ڝ\a=n A2xs%.D{%[:}lq+ \yw.yE|F߅ ^i3fJq=t̝A7ϜrR+˯#xB+n-EPw+vw#.] XvVS< 2έ]eFT 4Ĭ26[k㍾l֮>IO ^L5#voCHЪvU~IP)pTvyN_OrQ)xN+Y]B ]"tuî? ,XHDFVSi}g˱ORK p="q Sv7Gmm>e=~7vMY-]Pu G1so'>[r33kܨ33?|)}c5!$^bD.J2bTY&5yy0K0*T]+vmwϜeYvv;aUNFN.Iܵ"8 voM|ba:OVwwe]Dۉ$[Fntᘾ+:?!'QwQm79eߒpfnL2V3nG4/ B&*U`B֩8w/E.jX@hXkik?cߚ׊^N/P*&۫{ dXRzl^Q͂ Zg;l>]P=9ߴpшmOddn֮b9swKwK~e1s0Y;&qG6{6x>s+a8g"]'Ҫ{loa_v:m?􋜖G(}@V„V,)&k9|)UT&`{{ԍinAN`VyD3sR!nCcRMy/@F/xWsQ5;~gs12Xeqjm(Wv37;"6ܝGU-qwq־%9xDcvEkC4y`^g6_aZjlܵvq=OIڢq^#e-1_$78l͹C[Sά=O~I k2p#퐵o>d.GT)qnC_PvпN*/ۼ77ߙ!7gcC]oVjv!]Ol) YZάݑ̌'j XٵSK|kچwwECىic@nq9bKwN8XywDI {C{+Rź%X%F Z.:*5qոhǒ]e:~; );C1n'4 3<UBH D=phD%1l66TM{yJKB5\oXkʮQd@ ŒU*!Ļ~z!=9tI|@p wDΣ't$ kmΙ9#V)62UU_IdA{%t,ä&v]&r&|WqC;nar:H=M)=rk>3U]Έ]RnڝtίdϕY_ۦ>Me2WuVS糛}-9q_2p3'M q,d1}O"qeWfk히;!nQ]n$z`fw$e(S^Pג]v)a_FG[RT FѧY_tVeD.o'kh[ D;ˬ] KYnk+w, WTԥYc5/©3f'54y{-xPn}_N܅KiUWUwǤ:q[qUcQsw!9֦}N\\30!koHBDX#3g?7(bȨЁj*?&ڑviB];ng+ q=|6q.AX}j9*nkع8k#Bw=<N.{F]3_'Z!;YQLo~<61sx)7?c]V`f&coN)]=6o?oQP{윝/6^0SD vGg_o>B:Ǥ6 xkWtFik~;vҒ%0b֭IcU 1Ļ¢&&&qwk>,yIvkGz))gY{-sw9/.Q8UO+~EOs K2Pht[Quo>ˬॾejg{,9]v`TFlTvƌWݨ56G$d0wyf=-WhkZ{%<$#G"t>V1qCw:㱳 uR߃!lvnj_Vhu.^qcpM|ݥKU/")7::vk2UE|΋!lB|.~IvEZZ"݉8e34Iu_OFV]3ɌJ1l#+V|V.O:u{.:Vܝ?YrSQ}Eh>ݻ+ު< |3BBP;fuK~ߵq\ڼ!w|v!kjyfL7c3N$kD_wto'92ah+{]Fibkʈlj֮N^wrd\lK1ΰp$3bjaذGݚcuRn.x~zA2H `uBͶ?CwX"Ў!]]X7j5kgwfNJΕ=wQaص-qY1g\6FqV L {dذGZ?a</ok4РAu&u1w׶v֓`.t3_껚hFrdݺ/; ;!q:lvQaĔxOйBGTwa7h籰0#g{ڻ7lxJߜ3gv߯j8tfx\|p+҇5O|wZO[ѻg .vBWCfh8˴FnwLoFK2yzNrPmWC;pw_(lO{w{ڻo<^JoHnO7{;oGsQy*zw_!w7ܮS|jV >>|*LMߡC ߵ^) o s 軼n$n[{ {IΣQ/2A!wiUdfHHVn[㾾5%jZZO`aj w;{2Fѻ i[V[]&j) vniͮHwx짚džj E11n6xQo6[7,̰צkwIn 1'/\4"y [$qwec2'Onӡ{E:ԨYؓqGD5xOe.y݁=NCݛH=ʳWuw {)k'ZommGd'Ÿf'/X-C#PmК7rߋ!m~X=Ttk߭MvkҎحaBO@{nq?ϬCFcH_ 9drNzțvswEkݩTuY(;!?;ThMՔ]Bif`U.ihʻ%N?nCNޭM^ylwq!k׊|mFbFG+H_ M{xwzG6k݋xצ^{>OJ_=ݝݽa6ѤA;^R\Qn޿) wm'On0H.022t}N̘9cY(dxTvmkg^xDO[3c\Iw]OFݝThh0㠲/O3n&wmBgtjΰ?6d;-g֝8^ǯT[;Q?f]gNq/_?sv'Sv[xfܒݸݱwwNk/@GwEU]k_cW>@ђ]xН0h1#fKg#epw'"]0ĉ)Bt`YݸŒFCw o.>bjC1#wCٖ!.>ۙEC盞4~d+t'Rh'olP Yg$ڌJqwϭ7lGZ;ËݣK2Upw<?2͹{֩o.9e/wj]nE8 ;kh/噘;$ã+;& wJ .&1$^ $fww^)=v}+.1dg-q;Y;ѥ4 Qwߞ.v_ʥnSt7gLevFq-̴o3ijHIu\[ݑ蝷vy^c߬,ݕqOwX3 ~ݝpw7)#:]~wSv=us3ޯН0:hP[bTy.?gLEOڮ }vܢ[U.vO'Cn턶kO[ʭvbk>[.' w2 5w'kw1N*Wv:tL5Pj(z'#2ĕn]; =2D.g<ȗԮݝAB6gnΜ=A7MdT9&Bw‘tܝj;Qz]<=]-t]O}25x'g cn3<&r fD,pʠA wJ}md2 3rk =$WH,dQE Ƶ ul:zkQsw#S+;^A|g"L=w!.v7~^]aɇS_|rT`jd MmwOe]2UgΞpFatNhD2y#g~gS.nOFvt7s(~]UV<2]C3u?/>ʿK:\oݛ w)B־L_o>5wJ}KT$,nW+kXS| Gl^@Ijw~utM$:1 2k$aV3:t+;zSC~bq9k'iU Dn1֦ﮎT]o -!{<v@s"tR`.PAǿXŊ}:vU-Н }1mImʬ}C`hc^X1B7n˻5m:in:;AӷyԢw;XQ7.x{'K3XqYg[;Fwϵ.] f싰i]]_P}]wטXѿu*ʿyg\j AB ig*@U PR_R:dաL%>t;ҭ~KJxTucmiw<~ҫu nnwHOF]>nL#پjxl3FnGk!v(G/?Xkz(Ub+w3kfp0w燢ۿ~/Bw繻%{ھfl4h]߾ȡ}0 :1lAtMj5k:tf<.G[CwTPn!wl 8?%+++skB=nwq1qW$+j=GkZ>KNIԗ*v ("䭽)w{/rŲ{d8eΨe~n!qOn?Nr°b_m*FtgIsGIoiCOA3eg}Y3 AS|<᭝lѰ@)++}}+/_RWs5 YaQcClzQǝ; NujV~yC࠺߬롆3~(B3{{=Xf֠ASIaQ6N {ub؛cěuƘu0kвHVv8'svп]kpi w׌rMΣqdwݭym2.swC{.jG4]$6xkҀT(U q&"t(&b~,q:u"'ezu'tk}m{֩lTCA*L RvțTv6cCٮPv &јuٱvj>[QLwu̪2(;ጸʹw>s B/."qap8}'7YqPI]xDḖAzT`ڡ7t#F] Gn펣,z6 @nNd=$v]-9v{z?߶fvw'uRv ySgl?x 0-)x^VkHF6Ԫ~mS ’D@ҭ~w%&}=츾k}PxFrJ-:ġ~\gێD0k*wwd]MU qH7;wq{% 9;njΖTC;Cw2qPqWvp1Zj.Bw(ZFIFgNHr5Rk'MjtXvP't7KSv[K-)bG+(4~#9S#F\ >h}۷^n)}-*uf#F͡#Vw_1w]OxőKU)<]ܫ3VmsÈn{uw @$nVuq'kjEuw!v諶w{6,, \XvYwwȖtݍL%֮anW4u(:İ;'hIk9|?vEij竉;#1΂U;Ԃvĝah:5yԶvEӧ%%%VEAwWDe{  3GU!k&z7wHȭc}jĴOn:2 UR_JaI [ݮq6{L=MZRL~9UK؞.okgi֨Cӎvkیmj;wFOF1b|]ڛ|@֮NrnOƴTYÓڧSvGܽq<%xWavǪjImP$}pkg8ѻ4G ܼ64ݽŸڟ]iXۚqw, $%Ew7cc&<*}GNoACoѤڇմ~>"tpgi;kLZ H;Fu^s2*D|rYYОS0mj״(|XCȨR,NMKCk^u8nOppC$%ѻcrhw R.#rcz+4}w2> [;ÄRA}=O}Krwn3tgA{lLؘ]Lo1.Mq}z @u>UwǙم'~"akwpy|Pғ9p>м[H%Ƴ_JRd<e+CZk!}:td8k:>KCJ_ >ޅU%,9V*#l~&6d9U iPM_gNA"&&qt3:i3(z v|m2gAI߇O{<ໍ7L|=!3V^`՜$y)aQ^ DjoiQSv5Wv[M5LZ;<7q2w+vEkvwT|kZ|wCu@ wKw.Bw"@pڮ3q'kw_XKΏbD\a<]+6.t)(83nȐDE>Ғ <ma{6o8?}.ImNdf:\ l9֊!e==mwв&ykcyu!nNi@.O k^IUwZvc(Vۡ;"8`5-vf ULGX=#ztgCT+sl[e[{CT7mD8f,vrk|SSOg+ Z=~ \@Aڦӭq34#d-__|w~ <숰ے.|mnԎ}_:=.7a`\Iոze^ޭNv?#WS0Y;O6#ߡ3VQN#Dvg0*)ЍmnׯEAqˀ WsRXİ>=1<,vp%J#iott˖Mʕ}t;ʣus_ͩ&vƺ:y~WJ% z4mTMq] W@4}WvF쬖2"ȭ]Vm|Ǽk2%kw*UyBwy]<ֺ30kvL¨hNPά);_!erb;|K|DDB˦z ~+(*9qwKv;nU @E:hQ+Gr{NL;,3u} ; gHpJ?s_J)z ^F.f@·;vkԏY bOhv`2uĝ _'X]):6w/g{4z.vxDj^lw4UԒx'm͕̌Y{F9UsohǽӺ LÆn$ #3ESuf&[)ݵw׏s~ʬoԯٳ?wƲȎG%W#k;{J\%S#pvC6^բViwsxvA\:o~gGe>;ǫJGÿkaaAEty6Yc];=׵syJaf?~4k뻢?n>-QN^:3\w@ojޮUsW+B݀]ULnj3.wyWۋ8w$n@Qy9khнFŘz𛲺*d풠2T鼾Ӿ!}g֮s@zܝ_O.%e_9 ~.Rw:L`ӏ?=LnC֝|͹ם_㸻՜hÌ~Bke:ݫvhmw۳?ؖmɹYիo0n@8V0<l>);q},8g[oSc+;v+;lnC":wL*q;+wW 'Y&MYEʈ]7U.X+ݳ9frkK)E:1HrZ~U;wdn V _X;l݇uj;.'ejf3^|SxeTq]xk5#V=^m_r^ҸSabUg5cهY7Fڵv k'Jԃ7=x_<=}$=Y;'*d1#b#b@UƵkr ZKGv/ی^Vmv=(M5דoEZ?n݊i(ٚ4wZmq^S{5OE_W{6{\;1<#͇"xk@o5>ɠA)d4/RDzչ:7&U Oj{l&nf39k]~z&8Wf#-;2Æ=㼲Cڻ%Os͌8 5w׳jmdeeϞ6:*+;o튐,qݓO:s#!4uVN}ݑOXmMGT2YaFKQRG:VKyrJcbfAG&kWy./dCgu"e$C^#wY ުR"= &1{*Ϋv_֣pR]d^İa|  E5ڌ07V52Mǰ4N]ry}ˇ5 ;3c67w_~K$aUSvFfҕ_2NmD?qZ=O V!rJxgvh}>'՛ݖa&h6Jr)vȬ`>JXZ{vgU.GJ %o[Æ=:$Ґd闺ڍ{Lt"Z=#v m0ѐQa$zҖ>6m֣M k|w+/?.o! /˷ko~Iv$qC'N1m[krطO?#"uh Wwisz$Y;׫B{Ewkng]R.*(vvd -2''hn|=]Uτ]~ܪGm7og!ݡ>D}Dy7?>F|:&Bs&{FI%i.H9z9)fjN%׽~Bu:XXx@ppsw ]MGr9jBBh٨HGN]s2C|VVF^^t-11ODbuFddb#hh@5wK|6[u^QnI9nʧls^S5־fMjUPsmD s|LjK8 dY;aN-xf+?yi7N@UnhޒD'2eϾq]j&eaC >g|Y;R ׽Nݤwv~g{{˦JlTCC<srKo*S^"gF?kկ־SX|o?~Dd bޫɧW!qwT &}q;OgZ #VE] _ KLkCTYDF;#kҴN]NFio/7nlB 3uڨ-۴E+?Ov'Inb^g~L2o6c.کFw,?رuC_M{fغ!<ݔwldz5ouudiVpQ\ÓtSc3k+i풔]vvw{j=(O%wsC8E.kn%N!k?v_JVTvE;6 ?IٝUe+q7N\x63uv2)wk&2k'VKQ ]L֮?nOe^G/Hwâ&*gol?Of{wu*(<,zOݶHA[2&opíTx o3ulݐ5<'Wj?|Dq4ѤظIϢSf µ搵Kv V;oo4n֮:]2W)Ç#:>q{f8s+ю]5&}Id˱#:oKcfhR͞o96?b@3k:Бى2;N~YݗxݨN2I#Sd|3\Y;# Fޒ!kŁ|W-az -$#v(eʮ% :ތ_V7l;gtʮo)Ls9"qCbըHٙ٪`&rk˗`hԕ*[j8IwwhX}4?姎m,=.PРVЩL;M3jͼ8j';KΑT Ml:PSw]pg=tY;A~-Ȕ=*%*Sz2jg67%E,hW%tO9SWҎX{U\3 _L#W\gtܾslf11I{3n^{B޳ufT1% |&0#oz9ܾ} @yeгUAAT?v번fޮm = f.I`W k(>z2k7֫ 6wv_bSMf$n=^q5xA@ %$G64n3zLj*RQCOӽ*[ Q^ݨיf^{%@mU5)g߅7\&OU{KwNlͼd䘞m&,jWeuW'Eyܮ$ 00MI`M/wZ );Ϙ_rDnv YZݷq݂dx:¶ww5vnNKצ^*C>,| U}o݄k3KvCqtlJ}Dm*O?XiF]Ŀ5oͷ)%; 52XĞWҮeE <dnl3wu*ЧI3#/8x3Нz27J?c s'͎sn1t;? kO^S{5Om(eJX]UdYvNJ h?nYyjn5aO$CM͖6+{anUv@]4U9k"xkgqF:3˟=}Ŏa]?abʰ <<>UlO{w{ K i'l ss5q=qp$w׳H_|ni_!όt]b7)n3,Y;ӧՙ䟾Ild>&댏ߜӊٽG-O$%}5{5#jNom᰷0]|A#S] {ИT 6γWYIFPy8,V}oev1De8bvΠg_gαM9m1O?f;ݷKW@}lUеq@Ϥ;۴EáOً5?[h].6 [J2rga5G8a9$i>0$i۩qC.<3((~%=N;rk'݌Cɐډ:n;[m CkW5zז][ eڵNMܫBO>;RpMTt5/`n$&^vyCw33Ì$-#S="nWA*nDhq5a6CvidB^ %aN֮SٵvsNӴ,tb[LM:~|;ha>cУ'r_гUA_|ڱ|D`RdoĨi@vK^k3%hz&ݩ'ӻm'`vܮ&`ʎ kǦw֭[qNlTU& i7/m.+켸+JX;upNN$.yȄA2ʓT<`%۩8ݮT;gnFk`(zY Cdq2%m[;?~kW_'}Š mQȶa=HVD"| DVaڵٟ>gHf/$ޯ/(;vC7aݮ?kgx]MsbFy|ʮ&M7E_:g&|@ھ5GՓ^x^{{2+ F$ުF1Q@]{<:t}/t( ;CjWWT_J?!kr_qe& z略 )ww8cU_yczkFf=yQzlZ:Н KxnLN#cӡ;0n L-t_M!d5ܔ[;(WvγQ@Uywܙ?؟EPv3w_j%07N}. }7Qc6SmN*ݥ3n'_SCJt:95wSn:kwz&kVv m)̡e%hi>;WNI^eSofuU:^=(EWT:aUTyS+*d7#kn!zv.Lit['ulԳUWX#zDձy˲*Z{L[֮eV UdV=NhY{=lgms5|%>|fV%S#V!;܋\ݬP|P4[dx9#Oٻ ._3u65pvIO}n LY'x@݇FpܮL:@K<SʯpQ87mu@Ahזbծ`'nF;{קCڧWrJ̯'*aYW$=ܶ$ߡ(7cWs|S{=W7`򿿾YW|9>TsX<ս]36j?n/ӏ[ xǯɐW]kdv,׸dx; s`d32@n;}<^փ1ȸй[Bi[ %9f۵벲[{H2A?^YR̈́*>r7o}KkRv(WvWa`ַY #G"oʫ'=Zhοwff?n-_bEgnݡ#n/6*|>@zN}'=,Pu/RH5J2;X;lG9k ?#%ţnLn7?$־hΣjf֎͜0քAe!>I?f2e7J7+ݩM&X-}~~W-6]yk?Gծ2/e3k>v&*u;Oѻ];z/>f+]!ؙ Uc;a/W>̯ӧՙ>N/oBNu\iEtr%TvőJ!t`T=q{ɭoXk@֍U#݉O#ve26#pjmWvoqwWnl8d:Bw֖kexkg2j.GQYNm8vs;cqe а*[qvOFo"nw=Y\m܁UΑ|k?\n$cjzG(kv|*cxe"p ^WN{mW6wt6sƤ ׬Iifm ^$qƠȚs 6s&Cm셫a$S2<[rnQvŕP^yv9߹z]ғaFݝvڛ7v~Tk7 .{ w7mz'?6{ݝI Y{V^;,ngԌ O#3N;~z[hstM|d]ΫUz2(b,8BhNwrw#z;O-)XZSvqpHK1CwQvhԕn.i~}esk݈x}+wKZ"k't21j;tK~?ݦԙڷp پ9}ٖٵQ\U>2?EkC˒Eٺ0kg% ,<ɸQkgxLn=ڝ֖Y?t'[(*;onɓ5vRR5؟hA;YNS12kw%_f.9st϶.Q%?AaPX\ @&kl;Xإ6S|3/nm  wmW&K\:~/5z2 ! 3idмt]&m#DŏL3Cq9%޶*hw*\E.vWጸ\WV~P+Fypw]3%OV{ROCMdX=fNNew w߉')ЬfPލҷPTm@SΏI@%ѣOK2ӧ1sԢƇ(x)> ߝ_P]_ݞ u]j>cf{]!=FZ @&yQXp?akZT0ÍR݈=@VEu0n糶F8e^zZF _ Fwy!uYnu.o@fvv2]He ، vrے셵[trw=Re<}ߞߪ otr[5jHW-Ԭ!I+:>)kPndnW{25#w\ZF`fD{'.+j䠢TyU3v d˫kgzRs~/ݖ7$|ܐ%T<.D0-_k˼Y.AX©N%Tۙ13f("&x}]nӓaQ,tډgG3f/xm#cMG֬o+/~~mH'?ÂvX{E3fpk'z2CP,8x]nӝh3[2Z2G.:k72rk׈&[;O X&!w8SOsF2D/rU\R|@J?ENX]^{TTMfDఆEJ$CvQ^]n;AH<^Qo6ze9}_od,XӺ;n on`` K*l”}c#۴x[ ̅C]{oDnYs^$wѕ,dKgdV٭؉8.N]k HsInh@j0[2s8OY\d1#vyܮ=:ZZa=/WvTO)*AM 9nH8+.E; qHο=P˫2}7v`Dp+]m%9d%q;8kg%۵a!w >}K X2 ׁ~1`ZKFZh-PRЎre׸Y;E者})q끔|<׿ CDbz؝F"w>q^}+G; 8<݋Nkgȧc햼T+Zѥړ(^V,tW-ViPƍkݴοCw*A^ 3lbN|[+l@*vrv36ݒ +CׇdgtMY9M\Udu7Q#l_ijȥ&OeJ2N }^IT CwdH ]nWw:kQώPPܶmK-WyGlބ:0I~igvR_o7hY>K1j0K<[7F^ӦO[MiYe"njjVڙ#v֞foU廼.\v Iܮ1 ݒѸreP/fIRdF3̱G>jܐ"\rwO ݝoUyw?hr*ɰj{V^;GͯU)̘97? 3 C; 募ڵ_s=! BU,\+rF Կ_=ZZ->/w|>g)-<[_Rω{N\W{ƨĐ|.NH]"뒛a/bh#WS`Y\܋X][bnw(*tT۵1Fga!a"#[c纷ˢCgkPS8pژbH]6S$=М%{_&~(;(h+ŬV~5/дo)wgreo\/ZrNÄG'ЪQS:W.k/sXg?nJ|}e`qVRazCogpTf&~]P}=}۩Q@C:Y/ERSs+j.O#>i;ʹ#W_! WBE^DG؍-,tXG-z:y3fI kh.n[!v{2 Z z]e{&kX2wW,({H馳౗EQO*R# d%؀T%"Wv$_^i3f&#MCkT>rZ!µry5kZ!_KeKEu>^+[%[3`Xuy.VY]e>mgr\e Lc!kz"t$4JQJ8hD>L]7>ZnW%S@?@s`kCct;=_E[+YaKؐYOHH&!kWk5"m×dnWtΘ>m͌BwEeo\/:kWCXҰLvXv,s&669++ @j|#<,M`޼YOIz2v? -~;ܾRZ4s"]:6T)[|mSCV0Qy. hooZ=*֞_/#w{ug=Sw3ば߳t2Ϋ[4D)U85\]YC#g jނԕϦ4_}]k'̕dL[ў с,k'eaK؆Ee9$ِ!=1ŒXUU%Q5fUZN97r d"Y;Y{DDMv@;:s3@tlpEkGy~붭6nH'GG۶!a M{60eM(wGrkvp8z9 o>^~+= gg&l-v3?)Lj ݶ} eq~IRͥ0?SIDATXtVD̬bf=e4ׇoo (v JCݫkOHբ`^ܩ'MC{$&I(7wލZ$ԩBՆXC~H)KjL#wݿd_mw;X>m}vdyA3f&>: ȏ;㚾MVVm'5.vȭ@66 pvӁMfKoki7iel(mtٗ}Ej-:c3&`{l.k$Sq{gW,cʞwf{WR-Tk"T)kL&SV||Nk7YV.9ؿK}>lEz1zm6/o.\U,¨y2w8 5vFrV wM[9g/\kJIJ44Ƚ} @xD3JOTXU1Z+fL0}ڹ:%Εd,'_Gwhx]:XUdTuvz)t2vŸ' s}P*uc>yc]kid  k'm 1#FG4Z#4 _ -(3ft۱ӷOV1N.vԸ{Rc3ឍg;)L_v//[Nj}g3eOjTvm&s 8Y=']}>nC- ݝ2DUk-Yoyq[TkWsX|"HA;cM~@Ĥ(! Z!5H-wχ_V<;f3@vYbN>~ʊ f#â 50jv;^NY?gY>zGB|g#7;P}>2 7wc1sfj%LݺShr?[Q ?Y~jwabM41Jum6>e?.9ܝuf{xRVb twZKrDݻq̏־p-~tz]+ّ!G~wF'Tyy|-Xi[p~Ť- \22kɤm6~9_c/ZtSn"EEyѡMPBǑ9=q6{^8BQىM֒ȶM_-|=wa yfR-++}A1vCw g}tY;? ݗ>t'ж9{4H;eN7e.zw{Lq"LE؋qtNn7ehrk1m~B-Xq<%j0EBAju*{$\M>yci@**qY;c24=88?(tF9)kS(6uԸvwJ=]>DN x{@!bSSt#v-khul{݄&f)-+,Cqb/1 )SZ +쨧]aOW-i_\@nץ3[ZָWda0u9Cq ig H풋'%ĵY;8۬ׯ0fj !,Oruqka^K^o>G1Kwioé*@sycZ;?]Q@bpYPZ?,..=A92]jtxQf!D)iMb>}jiJ޳5T k};iG?gkɋ]6w9l;cfOgJʿSSkW;dT+77YYgLz6񢞗Qapnkj3_qZqD 鞋pJsqӽ:W'rk'Hey_+³ky͎묶Y{R뱥Kcԓ!Y'w5l_gd>}"^#ݚQWI٧6Y;Aq޾UyIul_qmk olk N葹Z.Qt'ڵ_8A;44Kj%p&~¹o/(,`FN <;lfqM-`E]:jYF$/,a#:|<0e0cf9oӧV,ZÐ!{%=} ` ^ z2<˲vj:FnA>"n7M{!~//w$c;;RwY)/eJ6vNcXϸ(2־j;~$wuL4h<ES6gWhzEﶕ1fC@sASNˣX?r WCeq;vc>oY?nxZF~_sLh0u VPEv 3nؾ1a:I;,մ3N &gwɔ}Eo-WlP֞WxQ1l}Fʩxӝf XP1FO-18"n7.ik Quj'#J2^XA B ݒ,Fھ##TiT9: I} JK}Р Aي~OB4*khu_oH)Fv;/ ɽWֈo<ik֮Wi)kg䶮kcb>ଽMeNlK-^=T%0d);16xS_  `ժbcGURyZ uOY]+UW!w"n7哬EU-b1Hxq380 5|G^[.`d5vkپ:q7+`TćC?"y)e[?@ll:CwiHyU ;WTYt73DEvEkxjkAi$H m!l؃*SZش/ܝnJPtw3_} Ҏ$ngz`c!=_~SW&1в6sଝdX^\D whm-0VsDP{ze2q<>UarwȺ*+ Eaa.QouvbhNHE^]%~?ٽq;ߖ ڌ2k^_d1& |Y]fOm?a?aO6_`kKvҀε =jFmsv!i>W^ɫiQykLW}Zz?EwqkȫcUM|fCK2)n'kWڡI6m]p@jX1tPsw! ]{ǤPIfъts1|Kh l*[;n4nٖn g, ߐ%&`-C碙Ž3}WNfLdT^2.GK0CsSikӤƌ'쯴Uq;f y/Jܝw޲ϭJ.w]Mwۣpmy!kR25J2zwK`sۙ[>E}ZԽywE/舵[-˖7Y=r]u\oxݮSKٵvhZP GRN;[gT?5S+f$FU\$ ym~}n_WHroW/lUe/^Q<[C 6 Tơz#!WvI&,7뮎Q![k6xq_:)qk,Uek3(&d3f0p:轭R+|/y\)Y6Gbj%LW[61k%.;k5mX;75$$>k\n0k1' >??;44fz^ۜaaMG: Mߊ%@g2 fڌ煴:q7ړIrh mXW*sJF+FzjkkVLv`[gg#v:Ӗ+ycik7ctoOta5yV`߹YZ;CcGRvwݍug7Y[Fڌ VEMpo&X>].y,dcR']z2KUuBm[;tD0k?|tۋ Ռ(=ɺ yZ O_\~'5 N56Mjȭ(vmD#ScmkS^nVhڜ Rz:}vu22V;opwNk;ߺ5/+BYΦ;o;֞`;ɜgoS7U(nK24{̴15[7ްti|֌;Gt=Ҋŕl@Q 5zF;dLXNY;t3FuWZ;oIƤROJ2FߙtKq;$֎j#%Ƹ_ܩY߿Lf~(—ߠ6_h?vSˡ9;4ɵNqEC[5CF|BqH7ݽJ=i#xkx~>Cnvǣw~u߲=֮AF h H.;_L8T#'~d+[>`߅!icjcr~uys )"t_mn$REmw'K:3w7ZQB~9VbP{*m s3o`L2u'R0NbWmpphw}dЪoջ~^IzƆ_Oٮy螐P w4unj `B%9SI(iT(DQ{w=hq$EvV= 8O뽴8 X mjoӐ' 8k٦yk W24SݽV|bv11 he_6/`qYI;)ns[WƟfYs]|vuc22S~W> `46UIZLr}1k~򚞋慔CG/>ABDG>k'ewSŪнX{'`6h,nnROvYyOF k7tܝ?4Oxw_*Pơ*=ЯN=W/ ١mS/OZ~rmlRY&ۏ_Q)ՙOm_.߯vQt~odq5'uoQȟҢKzkqWOab@]>{|B\e*w^T>ne?EuDxq6#vi yQj'{2vJ悔c0FtdLtdLiY5GχǺ8DeWb徾Coqj5iҗ1]cf/ɭٶiL3g?B68T;]vw QEgi#ϺqaP۷6aY-{Fi3mjIKJ bb,|889 @IIOK-!r={ UaQNY[Iy:hGbu/mZc@6udb~~~~Z;m S]M`8ܑv!nǛ50?Qء9kv _ϥj0=s+v"v'zSaΈ5M-/%vɼ|_'+V۝:u'M$=Zpo%T|HiYfsZOq 7o}DnޜbOd l@*ROd; swlz n ˳n\Rj쨾wS/R 4O54;Y#pհV̱`ZZ5p M{;;byIfŰsk/{# shZ׹K)WNyV9_kv'$:EE?zWvmیcEVu@GS~l\`F/Rո|K?a_-t `BER{ uQn핖-Dјn©YSKxs޴^$#GfߴvIOFRmw\?ҥ k]_ﶶ4J)>/^r__OWA w ڟ/DWȫ24;g7~\^wԪI]LNck31?lxh&aܼE*fz~ 1O>Jmo8U|uvھP ;"ԙ]Q?pjVa+ n9yec8rwѻUqGl0ɺ Wshg̀H &CJ#S d'nؾT~kz&k =|$tѿЁbЎS69X$ډ*{+dIkמ]НAq;Y;yפH(WvHN+5H׽'.^Ɗ9'3{IEY=.*J^n_]pRv6a6#{dΜ󯿵x;Չ)z󱰯]zMP5L@cl{1d%FU˷پQ H%kwpFy[/_ʶq'䙺Eh#w<{K|Z CdK> mOY 67yYWBwL+&l3 r̀H^Z8%e>sљJ2z]Y˩1+x)8H]*W]kd TUv#4U'ڄMN<7xwcOrzu>^.t/ԍZx'x!vҲo֜n~4zAç<9ij#*ddwX\Ў0+ѶA!GCg9r]k-]5Z i1rX !qw 번mxY#Lzi/3f1]9:,:,ڸk*ؽWM U5*N(Z;tKj{W_ӻ-ϹfDDŽT?>]QWzYݿXǙ9MPcS##42.1k0QG ȈP®X}ؚ-_\iA^]6_ST!e^Q8: ~G.?(9G-gdZ1a;p@:<<$͚3ko?Y%KK+E$\п e={8m'P=֕[ ?Fywc$ N-KƤn6$(,n*?ؠ 4Dpqo ffmHY۔'m/3lj?#"=~_@@gM|);zg36od$9#8y.{h e0__._~' lC}\.ƫ>Eff߫G )ӝ y_i?АpOF,ȡ7˭^I_Ӭz C{Nwl׼”>hۙ\\ij!ؘ1>&M4<[v:+>v?i:ʄ^2uLv6}oo|oǞAިo;do?Y|@ʄrG骮܊D|fŎ풒mg- =lYS*R~Alg7ڷtY),n׆ _hݥop$ȹm Ӟ}P/_HpaaʹH|ĪF.u乳v_{SbBEe'_^eɺ{1#S}tXjn gN/c7tŘX YJ2r2zOu[;{[,QIOӬGO_< Vf3k]u10$9Nܻ&O>3gy#«Mg^_ơBSd5m/7tz-+у̼Mg4O||hׇ՗&/~XV:W]QW)e'@օ=[H"_$չ/p>}jg/UYY.hUq{;=ZE;$#ww({~y @q.:|U P G1˦#|~˻~% hqyO ŕ^n0ڗmoԮ~zi؋1: ~p|3Y}JH|A{-YMP=L,JURxD3z*5BS\OaN /瀳%kl:Է-'qW f,d񏫃#ƍi9Bj堻K]rϿ:o}ݬfN;3[$ve:ק(+{ۆ~~)>2,p>HNk?ݟFe\wv&$Bw#e7^TktwJRv8ڛ%'zU+JyN4=4ҚWld8kҘ0o/[#o vv4l8#q(psቑP1h_:wY$~ mLJ'.xi^߯ \y%[^w-NhOϚ}"wϹ}~wI&a4>13X;Y2\묹;45dn[ /U]YwOSL^Gɔ2J.[ϿH I>OǤF'qg(Uy="(~zrdG}HAO{Q+ѥ=_8w"wO4 _0nH-kӖxv58w/87;-+9ቤ6kf?Oc*4h ]UY ,wƃm=4ǥc-$p|'x T]k{ u$%x{,ZFxIX6@ƟrӯLu7@_|o7 j>/OS?f11WVg}SvtKv.n{Tqщet/_G9 x"k@=߲K2r<}Ov_4h\ceA_mne~Q,nVK]*(nLN.) )LJᏁ詣˟ 9D|@xx?ߗ%;V߯kd} ;wxBu(0(9>]C2_aȭ}x|x{ڋ+ICsڧъZO x~kg^NȼgKm[nLo0 Û<:℈ ŹU yLEoOw %)tg7T4|?w)]WrН}yژW PPF kJ)d2GjHͯ†uk> l1sQu();ˮv &ݩ)4>6=.]@[`n=3t e= wϊT)kߑ Jf܅[譋S|fv흫xwkCiF,7=9hβ v` 4*--}$nŕJJ‚ڵJ>xi;Nq"G_y@ddm˨)߱}ڿ@6 ߢY)͹;ʷeʅK츚 ,yӠnҠcG{?);slQQ{==vNHB.}}Zxvb v_{_kjM JPQ`1F)~1hSL޼c71&{El"{{leAkdvyG;HdoS[|[RCyw;WmΥ2]aN^*ʙX(cyB22v:%*+eZۆ+0[3[H9DďYJkRYj`}N*1Mr@k"$N ┳^gwZzrVd׮^g(>_bH"?>}BҔVT +vjwn?ؚT9wZixBo??6\C[GfI̜3k`؝]{ e7@Tٛ74?Q {QeeV,B%1Y4a^8q^"žt"Nb{㮽49-:hMw^S,vVozCf)`Nd.nJ GGg%Je lh|QtUd-7Ra;%y}. t }(^ӣbj$N1݉~}Wc-SH\idgv7RvƋk F*K546XH%usXNFtSx}Cf2Kj^7ciCf鹰ޥPzA~"oسM9×m:=}Ew]D,߯;j!kޫjJ,`K-{ 2h<%ծh@Mwrs Ls|iN19K lR,mJ>4r6QHw/DiдD÷3"J";qGڃ1)ϘvbjnkVMwFk5IO SM@ ase0&}U*pxwCN7.;}w33[nT3(f|1cҩ]O]Hb<<4+jT)|-*^iEHTߥg&_cPQie!n2;5["|{2rL>/UhW9ӮN谷 _ v6rtt:pqdj~'(ڟ<+c[:#?-z}5;czݣ\ tQ'ύ }LWE23Eݎ!6#~'~#es8n )oL>9Q'Rm{垏UbQeJ72od6jk[]m \> oNxmis^Nc7Uտz.}w-YػV4HGE CiͤE\m YjzN3ж(2ڀ"jZƐ\x)6cjg%2^h]4ҩHzle2sj'Fv0*Sk9~4eIeډR[|]Pb֢khvsoeZݾ>'7ڡ9-6ްON\v[ۦf_&7a.ܲ 6UD0'Nl]#D b-lbo#K/vmt2:dJ9fv֛ 9wCInv;+qv7j aP,WkMw:";}ːdo΢ŀpZǗnvBGMcP{D,y6:,ZwBip,Q^.2L w ɴk=ȩO$uv;Mh|ewu;vR!B3m$ 5iZW;5sqΰ>'ǯp(}ʳlN{Evb1P;-]nNLc>h'ԾxW]rWկ93k̅8דrʠN}'M_znΞ}Mڛ}ޭ{nTZbL[`]mZf.&h4EZb8!v(o@7IJgwswBT wC*Sk_NAR{~^ZDv/;y{{j}RĄ&嗫4xI}^\TP$#oWQd K{(ŭ&Ri$_dBrzlUmP*qve\Co=pEOʿUYvҢJy]H*REE9ښܠE4J5Ň TArr]JE wAs^i?&Kʔnp3'c>ejLm5E!C96󑑀^gվ، wVd 7tv#II 1/[|dW{@߾Nvy'n\ ;_ڿ}F3'IjTϱۿ]Jy C:> g_A7,зj> j۟97KvbvLH%H 1gϵNN%Mf(1kƽ;"{זgǴBǖW2#~vR;S_-O_g3?_ȭq{}\_7N/>![R1+LyK>k%Cdwcܟ/ݬntUanl ].*p*Yҍ\:(]5hBXCsYWB}^}ZCD"ރC@4LCqPiDj'"ͺKJO9Uݻzr1\ #:pFpY˩hT/L;lh@=c\&pYٳȑ@Bf49(F̘O@wy'^X[ʹ8v;ZxݟGp?1yo̲}̬dW v7'@+ 9'wv|Q'RR$ @#_y_}HANoQΡv0!WZQfkɋ:wݷm<4]oەy{s^ޓHn[QpPLq$H}(]^|YN*wnN5m2] @&)Q)5=z7?q-?#ג9յٜ,Irľed>TAZR;S_o9(go|z^TaKvgM94ak}yϲ4*ޣ޸n@g" ML}[>cF+>GZ5o\Td!(𝲻2^/gL7{!&[ 7Olf(2eTtDm7'jYǮSOjIwce8~!xAWرԮQ"v;:uaUk/ ReKv ;NӘ[X`}s &fԉ&cZe>$'}:xHNF)~dwQlw܀"U]^zcZ }SQ}/I}B59.$C}{5r0kE62H,(E`}}UȵuiyEw)d&ԍ?9Շ8t|&ě\DXvֹ ɓl`6wfkup{g@O,Z/tO)Mwt=#zq;HRjOO_v1ݓk噙.㖮i8Y_ u [|yB] ?Rs02jͦs`-{kޤ۽G9 H ;Udx7HϖWoa3_(wpZO>Sgu'zVn<7Q۽\6{n>ZAwC2ST&IZ&flщj _ZQ^v3!UP2u qR*HP 9%KdwT_lF]H=51ݤ=Av#4 efmۨcC2΍$x H="| wF>X!#۾Jl s pY{MmQH\3h\pđCHShjwJOL9;v;)iNԥ{#zY+j''JΥ-*0kÞ6,`8J'٘Ѐ /@\ð~:Ne"`w u"Ԟ- /bq5ri,y܌c ܥ4v;s20_=| 7!W'T< 96*59b!1^Y 0=%;LeK ɨQ;]2qAxq#Rd']#n:73}'&bTD?Aޣ2J_mgͼLLXE]}QI ݵ}{K> fvR;k@jQMzL;9%fEݨqBa3G:ITa!q}VuK$$Cšm[oynIC"ӝ YpsB<cgݼWp6d2 뷶:; 8k+88u[*b5o6bU1IN?|QX'*:vwoGIf7c~.5}8αIZcw1+S_|#_l<A0ㇾwIOqNj>8LgJo./2$ijefIr2D撖9R"Q/vU{]Df4،`HFj(}r259 ?rr] <u9kڽF.SˢpgGv:?efXuis=G]O*,]>vV8Gi xǶS"(@A"xa׋]J98O gO"6ٲT)xX9 =8'$:Ty]֩N~sࢲQ0cJWEtg{on>okG!^vNFZέ7z83cD=:Vo<7Q~n#Y^}cP;Y=iI%Җu(j/E1dUIRݮݘuBFXjg%1 [MbאizXWv CA]l D;c3l@֜حy+%xu@'d$8Ց{^^mCw2p"<<Wnw] 4n1סp֟yQ&qv8v;I˰D%ޔ3ۃFS/2t$"}Pќڵvkq2o׺V2רTVfbsef!{HFQ{&j'*6YzE5R{3ZARdPFj?$ xʨvNaeÆa}_+r jnX dKwz4$:D!bv++צ7 ^׈;c3,>xB~W%|#JD/y![4r.@nrfzuy^y$g#W>][=SƾP' d7rr/a n?Y߈v/m<'ʯx4]ѐ]0Nkz "cm `LyM9ޭeHeWaZ QdLmjIDX=$Sv7q7A+ݨl#6F[GR0v;컢js*-Ng]ݰމP\ @mD]P_y--/㜝.(l'on)4WB kΤU^&.Wx#W<9w}|B$tԼm~ENm|lGy= @Tz庽t8;=p%3@ݮsZ I9=\,_Y[wgaśwg%!;B{Hxf̉{ !NNE]qU9VuTKzZ4YǷ )QPsViȡvbsZQB'W"ܨkv*wwex#QǪl;5PCݚp7|%iyTZjB9M*pnE,Z&#:3VР} @֩Wvi*e\w{w.۹ԭӈ8TχzZ|~* RM 7mdh+E_Vv)Ƚ?oiv$Oퟎ%Ԯf< `(*wt{L6#d];:j.UP޵;A?Jv)vV9!{I5_O]vt^6w9^;)Q؆vfsqJNRufw`}ؽwBUpUzs٨jYMuO5{nE˕H0f5m2j/JBTOO_ݵ۩>-+"{p2q>SOS8wR 8p%OkxxlOw)v{Fܩcc't ID1qv_Dv>oޒnX-`m~^׾݀2TSd꨽˨J$vTGCл8vYi-XVV9K?/n_yKD3;ovVUppl0ɤpzo<]0'ݵK`|WIFn#i^AÇױmt#;Qx<=}{}ګӼ'֔Y7},,r4C|$ΑnؚTRĽvf~LklVz%{.8۷$~rJ[N][͞ytoW K0ǽZe.ijIHRϾ} a rK6xlFǐLu%dLJ9?ԥKuh)Lo;jIW۳rA i!jҫSnZ瞝}9࿯:UIրn1n7"+4'CvqQv?%e/լn1wJEv۷<:t ӛ3 MJ˘;I*j$NaP]Ljϐ!Cl%s2&v*'߿֘.:Qdun%׹cP#q]HV.xd)v;Av_R_Rw[vDzfީEhۉ ,ٙ=EťTWn5a֯|:oVyȚ۶El8rśD;D1Me'c2ǮUX_P"iv.uV#?'̈́DvլH=ߝ@N!I"ȮgHPv9f%lC2ɪLbwd(8XU!QYݰ!ZJ<;X$߿֘ܺ.(]X}߷X:՗U,l<Û hSם[ .H!RLw%;xThγ DĤ;)Wm'Ϯpv݄Kl m~O촰 iܰhoǽEv_|}w;I Л}w6.RDⅪ,䯣Akw3b|4|C*tg{ k7ņ2JR 79gf,Xvd8Vm@1+NZhKioZk;ֻWB:-ɣCG츛Nd>;͓ڵS|.{W)U|]vW0I*'XדU{1Df2Gw)/F:kɼFr@^^b^^"TvuRnhsIJnսfhY*SI۹vZݱ=Fj#{z5߇=tO}ws冃1ݹѹ\F{,~h^˭& ]C45о,UD,5،VW<:tˮnԐ N^v{Mvw8K!p5Dڳn AYv^n.{CWTTX6{Qҿŗy݀4q_CY'wh'c=*J{T`d7QjW7%~ko--8)cJ/kk ̨uЮ߱79;!;e?%tp>A)Ө 唏,'Ei^Ϟo~nnMl9Ք@dMwThXvWԃ2k!>nn2`LwhcLmZ+m݀Nd :vm v{m)#=s0Wgi ߾.}]ņ}j@=߼& |'F{ƋM|؛ljufS;%v_|vP{|v0v;5L^/ kICD4஧'Ѯ3 vפerXTIH%vM\v=nG'-C?gN{PGZOu[ARv ,9{>Ip{iɏ)9/! &Bwub/l)]H&5ڣڽ`P[*kV?]M-**8ew/`47tnivݮ[Nڋ5мyI87ݩ^t4tMs;[[[(oDJ]vKs_6Vh_4Y=ɷw&)kݮ5<ȉ{xJyw*$HjۥՌL9@݈~.? -S(E8y-\VC" ؘb0!CFo_~vIv;AdNeIRubDjC2DݨΗJHFj')vsvE&֩*q&L=./| woDƪFYNSt3 ygp?{/{ܚ svIj ^W"=~ܐȵ"Q'8b[лo.o|s ]Ʉ2r58ȟ8=)/Wڻl1c_ߊ/|dicW.'-Z$;CWxo?~6^֭Lct `Ùȧxg+˔U5a5fqkzKs2"YcC|<*J][^Q&ZZ,}tgjͶ&JKpe'&Yfm Y[)#^GJQ&Y /+gM׎کko<;_P+,\TF|n&EbҪJ8U}0\1?%>@[ȴs,-NUjwWY)v_*w)w}w!>.PvԿ]PP;A=͗hw=t1݇=G&R"򬭭 8ȁW;;gvo =^dC R{VʔK2oKpkFj*r;@DaKx)~ 5TN#AR;#./0d:u4AMfϕ6-qn2:XU F &Y yQ04U/;nW5Dj7ZNι+:uGyhCtFTTDCƈ"=Չan"Ϥ%ȵ?.Rhǎ @NǵG,-VUկVwq 7v]2(C{dۉMwz|r0f5 :]]Nod0b_`mm ׷q1f^ `c8:XYC„et|l JΡ} R?U1Ƽ=!]%ζe̛آZ]l5Y}:P)?n7HM B2D!$Z2t7^C#!j\qjTN䀲b*'I~N$%6Jg#_wIHy9k>oh'$ڹȮi.j(HȾcde ?1vԵGfu@ouYuțC/JKG)e5݉NJTj;HLу~#bTd2lƂ,zzWb8:bMg%YՖtv.km[iYx}HNHEN kę["P8sGDx/~:i733ozy:^'I]l Y9}C2DRbKɘ}ݬ2Pog.I"؝څ{^-NqSlՙکDwڇ\cV BԞz<1Due1av,}FN}o p z#Dv"qיډmעIynū+\&qm fu:jрwq \u9ȞM%vȮn'X 1cQߝ4ttR&аa{kNY=<9V^^ɱ=I0#ݨ=ʫoB˂"eIA;;3e/]NLod' keX8uQrLw̛дa9̌etz،t׶ãFՔT?giXej4'URU6$ؤ?;]twmݘ9>헋t:^q@9_D-BVnvv|{@>Եۅ5 jޖ kشhuWw*.+( fE`hʐvAdcP>֟/.*/Ds+4L} k%aޫ$b>,7%jpfѤ%p,݂ɯ%E?cuCvt 7i۷piU8X'v(('xXPOtS^E'gۣd'ߎl#N#%%iܿV&=-7QG3{MwNnHF#;Guv;Gd2x)6I/E(zv.qZyxD&KhSӹF5sn+_T` {D}ʣW\]oOҡΧtrX%r+^SFXj(|_<.imm(=Om<MCB5bj8\IۉMw;qRtx}+U֑mގ燣%\LXv?x]͏'y]u9zcForb`ϿUt*:Go_Pg}8@ڨ.N֫~#mkRG,dJu05DU(H]Env!N{h:jw3&CiN3s]L @̉O^A ">4h(O5.&@d8}e%SNgVu/}|aWdvmP#mWymSh4U{W%KYuqd/.v).vINN.JAҨ3qVVV|qOnٹOʘV1O^5lĺNJn;^&uFuJ휉TI]3G}ƂC(^c4]פ=LPj`Qvg J}P|ݥUyZ}Xee?>-rv XvЙ ֻ-cP2qM* ݀v{%fQ5ʦeKY멝%ˤNe$j/EH]7j7fNFDʃ=E2AjP|`r}+ғYqf?h'vNU:|TRbHgRG#V-Sthv2x<ě :մ#Y[?]{ĊqF*qoN\霸RI+Un9!48w]]Pb NJ3zɯH`02*r3w77eƂ;kYYYgKR_S.^^ wi:zOF|OsP;B0g໶ 7Iz VOE)kPHfܟWNkNv-}&Ug?{CPnS) gh7 c&uPtlW.nCzaҰʹ~8 Rf=/!"|Pj2T.Z!"d'5[`YuLtֶ@s2:MfX7v":5{Wmh֫̓I .l;blKkk[kk% .N(96W~vrp:{} ]--J4=Ί~^uUv$[C(T /HƖ 8ͫȪ _{cFRԞ| k(?T ;EN2# 5cSjZ샕r(345Ƞj f#ajϖڍbۨWRct$1w2=TA h'cDDPJ}~Y3Ct6چ&9ΑR9*5|ݠG_{W/ɤB!u;Nó{tlY1??i۶L!>cAE6L({LN ;&k7UIwJewڛ _^ZSd'\nn:aASz5U[&r܍d?-cwͦ6fnMԞT(ګqԂi?3X^ 3drjn#jɨ3 ۫}HC[.L7"Rfzqr2>j\W0"8S|ͦi#?>ͬ,ĕ&Fs !ӣNp쮿鮿NgϜ7Rkxgl&Ϟj?:g׽XgGG~Adw|8ʡ[]Lp8m'N#nf7#hbw}m?}]'xqvר/-GvJվ~5nG]g͘Oקfܟc*0#h?Ԏ:]Gb#@Ƅ^;_Z{-hUk9[tfwfc:~孬}Ȭz[+W ӘIp,-N U;9$.ى4hFd˸w4#[`6=>HOKP`S֪۷شM w]d- /&+Y}kA&TWޭ. >֩/|nzvJ:jxĩSXNRvM-ۍQltpB˅Tae|pvs35KWy:R:j7Α&uTV#v;'~&u,LvGF;wf.;Er27vi^?5//l rEHwvҠ4!YF~UJvrgALwC_2Oqz̟Eo>nȶĎrS=ح׎RΣ`D^zL0w/eTVNwt?)Xsn ]?$";D|BH9cknPIIGueˀԮ,Sz|^Q!7컓xHVN:PF;8_S]?nvi^p:9@`yL%,tJI+V:J{S-czFX,FEϳ^{iU$]hWs r+t֧oK\ܤ;Gs~$aôo jTB;><*!:4@EԾ䮍pq;5 i=|zSىl%n2{ͷۉNLub^+:XC˦euv{:魜i~nAOO -Tqv?(Fɘ,.R* ?WXA=[osߍ%.K/w ZicXv=ڷ^ti66yQ+v/&}R{0km .9PqYXXd7g?rn@`bEX!8@[]._!U~Oj.MLJz P;=W&()q%Vm `[N3c3GGYݎI $qj`Avg[pD3n؂TVt'! K^5~]yԗG,:j'/,n'%Mg'>k gNUgN-3]ԧ&Q^%d2Mv9327/aFI:T톅Em}wTM߿䃑6X}R,s2h2Q;+P;gnei$֎za a@pFڻhkn=Z|W?;فƾn9?~x5K/ݛ˫6h dqv?Cϐ:G#NeW)?~|~:Oi.Qgvז]mkn4 #ҔҥtHt'+.-{:)2&,'c* T5C)Tw/UuvIlv#'ӹ֜OҳG I;5H]vNBV~2 jG=Wml{Ā#۠sDMU;0cz22OW~x7[>;.;OlLf_17+OH9)nnN|{eHZf"yasڥ;z׹ X>57(2ҥ~-tyџnl* H>{x1Bϖqjrq vs_Z{dĥ-IPgJi:TA~E}i@nū1 m Is2gj[`GrbPb Lл>Lֶ m3RکF}]9` 2ڻPf 5d'ѡysW_jK+El /;osX{=j$ZOK3= {p /<,ʊ_7pm_v"$CHT}|(Ev=U'bKvue"^RE)NR1DFc_>Ǧ;XvW-Y0^~5RLcNj aӛ~rSyP[ .]X)ֻV|l#(~Y'ISHoMs sZ3@||'{fK#r'C~!A; ґ<={v9|x瓛h<>9p..:`IVZdDiѪX˯hmiEYY¶o e aݔzJs.&Ku~m>mrS+d/k*hHu";vzˋ]^_r:d/.-DvLwfvULv)aF :HSeT(^iP;D9b"io:/ud˰Zy4W4ŷe}9逨Ъ(x%D ?>ΠyOvⲓґI+zȑ&ye$0xZ(C]y:~x>bxhv]z_r#O/rw}T\z+|Y}ցGΎ N{99)'ڹ-nטɲp#7u5)O as!y2v%)գB킑vt b1b-xSJjIe mZwyTLh}v=XSK ^g 5Ǝǰfxqߝ#:{x%v~pD1tw`gk#cX]Lv?IUmtc\D:]v;'?Tg"GމN5y$Cw!_P;b+fb'4E+ 6aD;KTy+9hK 4%TٺDhX鱝Y>م4HNNdDf-P=h:c[:|uǕuS3p@gNĐ.= |'/t9s G]'N6!}!ݜs 7VkCۗ(:S; nYS|JI;Tz7k@nDʭw1H!Cs2RɄ.i+3Kݕ1j]w.ٚ/e`jqnOw5ڍm#9ϩL1;}LwhV*FvAũ@cw16s);2t‹N~I^Kk` xoX½RT Q_٣ye|J:&x# "?;[(o:YT{ NO(~U$No*#g .Eʞ^YUBgC:TS m|$+;-8BMQ􅔓 awLxH}W9deq6ۭ>hW]nSzD4rC~Lw{.?q+ 4)'5:>iBI躠K}2[n;~2^S%깯RBU{tj/CL5ssv5v;-Iv"ɸ:,bOճ|}}w4Nz+h܄򫜎u,هx;wQIˆT۹jb+Rz!űgeJ:f^SvV~5)ԍ,3pc7>ͮ.GH,^ޓty'a^^-*(.f0qʼ)w<):< j'+da 7d,HKsDRh󙛕 縛^'F¾;޺v$d}%״;'FՆډX"̍MsߥJ~5? [Xq=&%-LOHS)z_{Z8o:EFdW2?W]ĕXh'E8?a^po)/|5Y:LOwbS*N6=>_TJuDpmuDq$-wŚ) ]!W]{D9>%x޻eMC?㻞A^k<۫e;;b09軟R1exp l>&'rIw}dY"u-_j*Ӟ|\-vwmY̿]oߌr=c<;S$ϸ'$0l3D*#&pזy%AܘS;+Av7[j]JvA}Fo2d4Yot(Y3QQ;.#|<786bM#y^p[PVJI8;$Xz*Amm=-ɵO8I.Y(;GJewz|V\VvbNo癴)kʎӞhA}y{_LeǪL3Ӿ}03iSt<H\T~+yi )YkCOwDǹ:ewbWL`/+wUC{|?ӗ[Zk[6 %XS~ <̌eۻ,jFjO瑜 d . ఻ق;].9iWk^ _{-mWvdp׶Ԏuv|pi^Ok >4܄K ^*)}ˁyS\-;RLu* w>wrn`gCrW,v0=v(cweOwWo5y=BN[\_(CADcwq~c9.w&+.AkPĺ*u!y!u/p'u{:#˞qԗUܳ7> b)Ц2zj>;HpYFmIBC|ז q7gjB1SN.jGvdj&4Ę;g2_ZQP;)*A-n>me<a|FJ?ю#Mr%+ ؄m:՛-ig,;p`|[ ,0'x%`/l̚#M|* ڇd]H(Ex}u[6@9D^x~UL[+GF{뤓 02=I|Ha:Ty]D;q5z߾c[7 ?X|?۫e`:!x)W}@aB:D޵-#ہGKvv.;\2.<NDR?fm;~>Ѿ%^6͚@ GIq7p3(F⎻\5tԲ;^G!n#;ti֧=Μ9 Әۅ)Yowu"10κռ*eW7Bhrn'z,P$dpK3G:Ӵ "4ݥ8f-wsZy%T3z`TS5t}),i*-Ro-{a^ȁzpp_; ;VNDC5P1nv;Q3uN] O l:j7CHvO.${sӼPpn3qwK%1?5֐,1,`wqJꐝ-oXgI/;Գ;βDpPRRB2{ZjkBӟ^i?w+(>f&Jf*tw B|⊊Og@mFDjp7 s4ȯޯ}sHIz/š'v;[4z[^n?QN}@QOv'eԢ66ΥyrsgRٞ(@\WVoX6ݿ z\"pZ D|BDn(p7̩us2yݍ@? Yxr%酩F+Q&FW v3 M 'NQRX)筄3q@yQx}.'M4|~hv"jk'v(ȖWtwX:ٸggزTSݫQj]?jByf.Ы S6vFj9x Y!v;}rSzEB믎-R ]YǝºbMwҺ勺J^pr%M/ ˟8F|4ݡw?sPVvwZw^hGF{22:hͼɩKlqi;=+X;zדiHxƒzhy'(/>99W,X]s(%ّms1DfhB/R977K-&@]t'hKi.hgg_wwoQ^?(/,9C0.;=pjYhSQ;̑Ct7n [ L&4NcHuT{E % 3oP,Y3҅.<j7ĩueꨝ!ĩ%w3q9hGxA>`-7s@:rRNۧ>zTqCpޜ- QJJJ(+gsz]ّ2YLV$K)}x}6U+Y.E5i܈שN Jc]UNg@bP;UqB"nQ: ~Ӡ![k{эEVRjo/ުSk˕K?JR_OKwq 0qwoQPpRg3/yQbcc ¥{YIO|q왋tv2܍:vWU{EbNk ktvz>OT{!g"Yj/Q^|dgo&}P F΀agf7? <}vnPPnǯ5&#c2|M'ĚPv*M$.jYdne^p`G4Ê ;;E}ޔUrf޽KJ-ciG10nv;ewߵP{LCbA92ۂ&,51.ZV~-Z+wNص Vg]kV\\x&3{^#wo j J7ݰ..Ũ2[j7DvF;QǐgiV'=Q^m""Ğzbw Ә"V@YYt0S1_}/>̩rd2vLk7ړEWFt3ޮ^ƍ-3T}H%u ewbCm;~ݬw>v+)z{dF8 '>Vs:%iW^y{v_[SkK+wn Fw+2EB)ֻr'^&hHƍ7\]ר^n.(1NԠQ[^=A;n Aze}˄;j:e.d|%h>3UM1.Q:gI%)y[*|0Ҧ{xeտr*!cim.q1{ĝϲF|W'،BU '.KTMH*=#FnQ=w}JT kqLw#c2f2T|ߝ]-eyGN}„?Ғ =H=Kn[$NilԭֳZUl' S}@e.Gots}ZC`+'Av[$"TO]zws0y- #v;iǽGLpse_9|٦Sk~L]t v{cw2{IRȠyv6|nC-ksy_J+e+X:FMw"vbawt_wAf4N}㹉=k'%ޫ5wz׬BF<̒ODDPȫJc3n_Xj/+σ/ۃ:8,t߫c9y捓B"!-fg޹/t*,nRKS0Yď#?.O Ԥzz);Ў# aw"AvFAur |yiOR$tGbE1kT]nZ ) d`nzi17JfEJV)8@&% wcpw}NFbZFK5D}wquq ϙL9 vc=ۓ=iXʥNLCdy4%ک;f$gc&ǡvNH:v=>ٴ nid4LT#+WhCٯ%_>;;WO鳏l'~̟asx I1D ըn]ͣٱH9VNZd 9(*0[.r SP CWw ̹Wݿ _+CWփ[қ7MKo>?!=Bמ^#aR8YBE`lM˰5 $v:j':[GGk|d )p!(S|aOyuܫIunx1vsA[JQQGҡ|vj+n ?NU6-iޥeۭ* K3ݡ\UEkW%_3cTY ۳caiɿmO(shfXv/6CD@tcPG*YaSCSqnJv|m\d슁 $'ُ'wrT dJgU𭂯8SvoOKT5کݞqC"[yf_wox|d )Ih ̂hG#:W1sQ6wns=q>nrӽI v6pQQz/mU]v{ze2Mgڣj/X]ݪrU>yj,S]b:\>saQg aK|Nރh/)zohm'6gwf*twߧ}m#J<$novɁ+**]\`Kjڨ++KB<kyVa5dɔ]wKȹ AhuVyP&F!vStv׶2U0Cv^\Ůsz7 rه,~l𓫕:1yo̲d^tbA7؍gtonvJD8Y,(@ 0l!>' osvs+T~ٹh;GC;ޕ⵷kAm)W[}^jVdL2 a ,F6@aݰ5TwɄfJY&ڣp/Tk1D) {A۫4e]v'|O+  ;DJαB"۶X[%+dý_y3 ;9S=CQj{Ұܪ>[^wd*nxzpn`U^vCP;Urz,PFY|r EveW0KNd{f2NoR͘pG>IΜW]uT޹-]7@`6%~H&/c=]{)dXj +; t#M oUSpWlǟ5/7rGcsc_qN&J=\mY=+Lv׈* lW: `R/ *sT!0SЪ `sGIuԮg.03CRUv;'Ѯz.v;nU$6ԧDUh0/_5;wIS,,8c(G{Oq5o?OB3^2V:%X'"'7p~u >ԠW[`wSdm#7X>p%c#TRq:ىP{} OԦDvBv̀ˢڽdC,{ w[ENjdivd;qeхXVϱRT9z͠qU_׻O9Ey`ҫɽ,ٖ2|C2YY>l3?W 땖BG8ֻ{F!꨽F+>_Juuh2ݮh'hk+wju%i'Yh.;Ets/T7ZVƀgSu\Z9+6{ǀC^ ]=xͣB^5Ί0; @#wU\^x%naקKu٩{d<&N8JcN !١&CTe3;=ݓaEB2nd7RYMd#o:]Yj'v]2WjOy=qc vquv2 gL6$2L?wLA-`w=w쐠qL:jWQ| 2 [ `Pn:e o!iVw(JTBINF ;AvunL94HG<Ƥ;tN];Y`ݻuN % dϣq`AXj'vJ<6S\x)P;bNv:l'x4?氻:mdP;)Q1\Cǀ\V8qFwS9TyO Y8I*)]sԱEٳ:2`^dwhDv*BZ)9SWOw28,Ljb(9K8E:SvP{͍ ?ʥNԄiK4LcKvs2T"%qwN`WL&Yd(; ϙղJo<7anybQd_qP(<%EO|-Ĕ^;Gݾ_z[X.:dgXrvWgYgwѮHXh8}d}ñ"^BEvb %a]B؉&AϦv{zzKv^+fͿb%ҾoC2m5i̋a Â{ -`hwPc5UK*@v%.Mo`됓!{Tyc3KTYwx MPrSdm`/kI00#٩7Adڷ!ⲋKIbo{ViS}z=q(/ U ^YYz^x\vu!*S|d'rɁWgϕ᭷s~7Χ.pYwፄjgv*nXz+wl%8ᦼ"vn gvO%";1I`dԁݕ&J/(xtυ&X]DL^, XR+CQvKWݍpY? bp!;^ CCnԎ&3:JCrFiO fj7[)v\-s-CoӝZD_,8c]]YY `ͽz :?w=?cMwDONGG}wdufoP IFMg*vAd';)T5]tt8~?Y#Sd!!ѭ1k}gOLı4m:༼ i<`C]">,`灶Cꅎ^Y$>ɷ7{h2;Qu{M7ݩ]!w)r&tg4NTMv;tp܍mӣPv;/8;updw]W?q٩N;,K'TjҸ?بk<ΡvbSj''̑C|`fϞ|}Ø;+s";Tk/?< zcA{w8g[[=#BVo^}g45=d pɷ؉&NDwm9eS1])y/Zc1~@6c+,R3}Bک5n$qFӽ;QﮟN|(92N?WWCvH쨎TUpq7ݮdۉYO̽H^7ZXo٣ڽo FFvt/*YYuԳZвUҽʲBdՇ]YpSK{ ҽqq],_Dnz7[rû0NMޱtձ- d]j߱hӜy/ӻp~P+[޼S'1"_$tzglH`WŇMw"A]ӝFvPxo=W`t_q/]BG/w.⸗HVđ{ut͢jRVWE1TNEr&ڨ=(R_ D2qjϯvmijۿi?&P JڣA|iWeJD3 ~N3PXmk뛙y73Mc|\Ρv;,Nn7Жډ9越vG/su2;l+gt?};wckz ݮESv2ɖorǢM%GLrBou NJJ->0GbL?4! Oy}Rqx ;w:aUħ'꨽4K/;o컡]r~HFsӐQj7 _`i9-ߵEOjOs8:H1h8th; gh9θh19N2,hgkkk I}Ѓo(bYv>^ (ϘO~߸I(wW $'szA4hER1DSvls̝'/Clؗ@A#+"|y99izss߽m2̀NL}[+zo&awjeAj'x""{A|k'+trj1sA\jjYkjU)\9~eNu+53:vpR-~MRxL-@vdj7 N|Ks"1od~;fAO+*n-Uy_I QN/XSYj^j'Hy n!>qxWSV{|Mn'ǿ!8 `07n܉=,J:*olj'[wdItLӇC2%²k\hvƸ^ӻo=Ǐ$;'Eh6uF RPhtsewo| d>Ԯnlv;Uz"0vQKiN&KQ{Ƙ7Rќv0.L˞rgGwf C-n9e;,y);KnN\v.."fزԗzH0&!@0?G['w 6B]v؋S;іSMMᨹ^.Gqw!^^~Y"wr%2$gBho\_':%xuz,.-3ŞO= ^3Ԯw2+jQ50;t04$g4ΜDo1D "~^kfQʕn:PvcrL hX{4etAd0 oj>d؞˱{.^-<=srsr4F `^S:c`rZQ;b3wb9 ]Gl˥K0kK[Ýhv(3js߽UU=d8wQ_%|WWW#;ډXv׈SAd-oxC[4&0ivvVl(7i\N:THw2)Y̥NYD dz!]t'.;kbٝetAd' j'v;!JvVMw*n&uՎױqKJqT o^dFjz6ډmӝEox` Ev:X0O"p l'%n!7r{hIW2e\3̀*':$d16wBe,_EdkA;;8pEiiA9S ~'=YZ% 3R.(8<;$ߟddX?X:EveWw侭7P{ RHNF+ӝJߏ%d47d'2 TAU7f|[D]vfzJZEW pU׉D}V"; Ys}-$GE3v{zvQzvi*7/sYyA؝#AlBVD-7;FZ~s)d PNdLVI]Cv~[Im)yk8+tb+ Jy?oT< LwR[_O;O|.FM}Iy=PO4.(= R;:>n; la]tiIjYHA.K]bƎ{@ũ+yꪔj@]]S3U-Ȯ7$l`v!M4'i&c(pOϖMs OKmf'ғw?Ź1-v{VVST<˳کFTCX3C$R]ITF|L";`;ENDE[yG|j?|nQ o?G5eWY>AW G +]H=֐$$@ݮy,)J_65]>Ir2wΜJ{2*y&PoR;qG(?.bSn;gogpF腛RMAH/= _v⬓JjQjϨvz7ډ Hh'뿬/wzfeeoee_YYO]NEئ; tډۖ߶Tw.Cc_}N9UIpˀ;pG$Bv>w׸E_?q J*U܋ě 0 C_^Ye眆i AXj} ;_$NɰmdLA5coSZ.Tv4v;QJb[=dy.T:R{IWKQ]d)K5`vPP{eQeeIeeS Iמ}he*;w&Ow DSa_gBVa̦ʘ8i@gLWCnq9qyAq*)d߯WԾ>`*33UU[Nw&>Orl;i5Ȁ Mi<'Mur}[tayg7657 J۩v Evnn^wSRyaw".F 9m͠B֩*oWsWђ]-u!FS;h{u,KNx%xݐ6q1Lw 8~+y6}wF j͎mXj'R+rnƴi P;a9tڬAe`1{n.!.'.IA*E9S=f.PC}ut,| `bϕ_b)H!>[ti~ O -ډvQ^SvX[OXm.>kPG]IGx 9iH9qW0dtr K.Ydߍi2G2YҽZx>:?W$T(R Tj=FG{Vu]OdojeYݮsNS~{*? E{?cͬw%եk"Iw-N}ߙ{V.h  3}Y=w ^ta>l{Ds/{?3οI9ȊwH0O;1W{>:R!^Qz yosh%ӿ\tZ{?zpZ5[}t|% ",tSw 1 Ʉ'|'ͫn˳]kgR;Iyt3Z/voV^'"^l΋SatӜ wTv >gȃ ºx^۫;0jFD1W3Z"(Q{h}5SΟ?i. v`=G1πOf .wvAyL?u(zr.ÊZN >XK/v`}wuCkȠGQ;U/!|%|>X饥bQJKKi`P{BC|(rdiҲ9?ݥE(AjcW'W?Q 9KvvV"Ԯt6݉."=wct^ Iw _lṱBuΗ:Q56$ߥ$$ӽMՂ:1_ WdvP kmmZndE;aT9F;v.QNvO7/[A CA,sL19"ȾfߣcVV_.%0gSHZk 2j_;Ơv 캉Ms-v"AꩽUsxf&u܍՞ncw3jߤ3)6R+ŨuZCPDE5ډYdcd⟴g|2po̓M77)w /n*UF;ɱ'nC؝#ODY|X`*-.b%$x`jOt~bHa+"J{tW>` 䟍_xs2@ UUqڶ 68$'"μDvvzy/;s =?Ɲ;/[+1npr|s>OӢ-.O*+J/Q𹻗nϙ:j;G,:XP2EvBys=X , lv!%\T"@~y9evtPcz4`'DzL̇u?Ĝv%rm=_nh!A;\KY8Y";9O =%ngE؝o-:}Jw٧Kg>OuNq/:QmU`"D;TNEёoK٭, ;՘~ǜ&eʀ\$ճ$=cIDZJU[vwsl&x.Qёu QxGʩ#M(w ^t֛ WPiC2˻l"N";a%Aj_sr/$d7,}7L|fiԻ9]zЍ'/!+l ؈ʋ׶|B}iٽk[9: DI z(meHyk+[4J*)haG=:r9=4'B_B,kv_8}\{TȵA3Wjn&v;ycw5jgEY+^[YU/nvP;Gv>5vWe6Л;2%kS7KRXZT(&89?q;qjhdSLNݒ] ;CImٛC:ȩ ;ܪIiX7"Ev'S =*~oG}Ϙn!=* T \\qH)R8N/fL10]XniTm?zz*KAv!v{L3v1$CJ7Kr6#n'"Ɠhs}.YښW)k٢QtYNB|`Ҳ*6!wh>rqvrw3Wd/Ytsd" -D K}Ԕd*Bx8m[ f鑐FwsDboҋnq?[Kډoj8\d|w?S`ҫn Ԝw8;&٣-\v GV|ĎԐV;nת$GMmYPd6:]ŌUP͆]j7]L]vQcY)tn.(_زE$d׹ G^֍ľ5wt'JN= ?v_O43,*aaɰ}{ø%$ƦY1[=92f1,Uy/qÕ;*lK 3K]ndMA()T@`ډc{'WUyIO߳۫o i?db!P(>iQ/rq;Q-FBw wN]7Xot)g>3(e Y~ `ŶOdi'àL@@P][7PS͙MOo:SXϨ̓1<^ Ug۫ ]-H-N ~Q9]Oyq6CDk ۼ e)ٌAAQyw#W.noWwY>H2|:f֮x=eC>򶱴Ԟ˟ؓAC}º6@aQ.^]~:u&OGg67 3zxh%fcxw_w9U kqAXc.lNk][a6c.Wv ͭ0neәAQ~ nR̀ 'ͯbhz+OSFbTa^SSYNwUvp^;R-}v- +tGQTﺱ˖oA̿^;辰T9-c?Kk+bY޳knjk rٍJJ>_:(iQlov4olOTzxyN-(@婬=pl^#kv(nSZo!Q3kSiqC<&wOPv+ad%ݓ4T~yԳ޻^i5(){ޜͻ'fšrv-POF;ZVjUCMx)ztɤWN I=y/)0J>53v+2 惯^_(Ee1QnKlE @O }E!= `ŋCCC dx4NQYj,nw{fqo>!5 (w.8h4^Wyb|E^Iq^S={~^el4dP.>&:1f|$px{ hvfKc1ʮ OuuELߒ:u@v:(qX+.uFtxԑ-c#3kv f)[7NtE7\*L3f$s!n$uQvOݣveO!E -4#Fi|DG9ٲTi{*{/턮ASR=줱F@O4aT wy'2Q Ee`*q:^c~ԷGpU{tNmS_\|_#ݧC[.v>>_f ktIݣѻi޼Ó6N)UތÑ?zɿ s~vMߒ͇f wr!О`JYܮgk6wL{jnmܮSCw#et);>]fz2 /ԾEИ#ut"ԔC;FOk>@yh`:|'Y;5fvN2PQ}mv϶ݤIKz[1ũ ^jxR'-W%6x@k/ '7xmYD7ϖ*y}aOsxso73dQ᱃lyλ'S3vɰZz2 ZEZQQco!"T4X1LDί*Z\,H(.?ݱ`ǾΣYo{k4Uhɀ޹]kf-XJ]WC:ʩ>Q[}bEOt @^4]baa~U:d풓k7ЊժUfيU*ɰaܮԣpMܝ!Y;ۖ/Qr%a<P${j䡔3cWl77hCqe,K)F6GKnUNY]bثʘoH3Ҳ_[ݰO2!Ȑ.~4@&[oؿL<[r-a #,}C|Cj ?WG()mPyk/  @%&3w h&.5f|$k'9q}MOמ>n{YOuwe;߇LǶG$g%s-Z<zT~Mme/S%1J`T' ?3 q;);zNBU湻HեAFh4X 33S]߈d>Р!we$;SRR`ٖbܸ3x a'z'91W;\BOsw%u]szcx/n4uOZ3X?8]`K=[-]Qb4)⮕3&eeo7,Ϟ@+g=m X}g~]~+OK)nFe'n7Н}SNҖyT]K|7N)k?Zۧ? 3﬉aI!vBzCwRv e5t-L3<8p&SvS˥ tp 0}|ybZذoދgOwJL^㭝v='>B=4&ڬ[([z2(q&u;D]1kr[F$pMo٦*ߚϾ콍ϚwO[.(9h d\aF_ά/w{]ܝݡNri#qb Rd- <c|}Օ}[qLk ݭUv _a񆫀K;r_7fӀ/STv:督-G,!֞u~Fҹ56Syvρce qwv<%jGó"zOSvx;ؕtw3_ opN%N>޾Ԕo@] |mAKj8I8lIh`EP*M]M nJ/Vt{|r++>4qw{~<6wQRV.Vv۟dre6y KbCսFx@㻚9_K[8qWsvg[;U9#p Pkw,n=3kSirnoL^!e)==1|Q^v;zdx6tfҵmiVϊ}v̛4;s*]]mIDATCw*;ߓᑄF8}|)>)~c|j1y²3?wUnP._G^ 3k`4pVʃ3.Ü41\ƨVC觍eۖfawwcw/]-a^`X[b񷍑l.DW)2Āҭd;!:v뼯HL #!#t;j[1a] e.H%h I>Ưd^7BoԴg?|//>$i0\_a%4u`n1QiWksu"{Lqw n h3m|c&ѻ7(RZZ No0k@+k~t-||f0d*twRίR<4g;D2d榡G^qcޱ/^</^? ?Y;k괃tLcTCw>no~nOՅ=LG|DxԴ 嗽/mxBmBwkY>bP;EgُNunݝ3nwuMqN3n/n@jTQg.#Ψ+ D ¹Ex}U6vEqjQ]Um66_aY<'@&~hsDŝk3^/>֯\#wy@Xm|x8oDN<:"{*%֞K∱O?dM.fB]ޓ'O-wka]aS뇎=!.+k 陑|ㅑcΏ_Q_o2twjNpuN&swA;z&Ơ ڭ] {N9AqovGn.D|j5Wu;C^"w;-R)l"z{>:BYWq3/Դ6{Inڙ8YT3@&S.tg8#w'kgA{~ަS7삃gywLTh*pϏ=Z99xCm`B& ^PvgbU/wmDA[-bS꒒aaF@=[a`/KeV`DJAe:Ru9gn Pk7;jG~oKԫUX$o{F.;A-:m$󥱒 z~xVoevt f4i3c%:vkS[F.vϦKh{B{]7)Z</!(6-FW~fk`ʞ)v<5ղ-3)43GO&e5 {&j{b|ZedTJ阬]? R'Y;jS5o:5.t\ 1zy^.}wo2F|y''~fDw Η[MR}z !kORcWfgz2}RQI:/$4kK)ۙwlK){d;gNNyMru֜1Lϸ56ٳv⧽m:D4m_ ݝxWxaf/dY[iP\yVb/ 1~.(vR5D `v۾Nwڟn `?ݳrс3jZo.~f߯3ʮH*r6~v  =Օ!6C5v%/ǧXn65~4ݝG3e=pWFzf٢Τn?2uka}wXk|݋.^!q;<*CŒә *4-uX @B\Sns;R"ѐΘfs&%wi'uuf$0k6魸Cr|δvkG8)cd}@j}Qfם|]?C|/_p!g,]uぁ WrT[U1 ]Gg̈́|a_DcbskME;H̅d;LwfZww{O?ج{fE5#7;kzU¤ӚԲ i`bU2)svk.vwϷvFwo^xd.GQ?Ԗ;odRK+ .!>nn.Ln#vBSk'vXIxu;֭n[uG}?y$q2[_(~E5ςD8}Wv{nU8{a__УNv.Q5lM*Xdڌew-T"kg,"ְ6~fg=V_nflY5͛_j&n@hk7Vvg{Y"ewV!\`qv2_xŦ֭A7hv amNHnJ.uRi|}[ӪS3h4WVɲ;ٱG ֫9Jhi^g^[vBDaI]W WMf%}ث9/w}ȌNxd C={2vзJU1l.(mhQvsw#Y iyw,Hu'F-Ive‹;\+r 3$6b̐ʺ7}>W.qAns'\ |b̽7oBǴTp%◡y!#ww}I;u͖ xYV__~fvک/QeuwInډX= )gt'Nv ow@5j)W@Q١coY ӁGC*Rvݝ/K=LukBKGvVq}# CU]CFDL5tVΛY9oиHJ_ k"rk:CW.qIFBs?cuw @7c5~4G ֿߟAŴ>]ރ]P"nSv(Y;M{Tl(ݪ~vw$#cJqwbh.{$[ vve$TmoQΦ@z2:ܝH rknAk-R#vHR_;:vMrLMG͎7EMcKR GTOַO**ʓz6Utwwgo:IʎY; ee=>|IAnͰ7';/]Xn| U-7*p{rn /9#GiN{^o•)*;LX;,\JX _\wbfpR%.A>dƼ%ڵuMzؠoNU7jJ_8_ZRBe͐ۦN.. z*n-Cw-qw67mI|bQ*O7zޫ*L߶hun_|){AqE|ߛNw껽@hxa)FDTܩy]u{Yq׵~?gU>n%$rxsI֟2R _mBC:^,= .}{p5a Puu卝~g%֐X;*=tpMHW{/*`tRhwc;B_sů@;$xeǝE 1Kh.w ld)^fMy~j2ec>h׸,陑XʆƘ\ɀH3֞k{+'}(.kg)J//ȉjSWw.2w`i`Pkv2l mU(R>T궉?Fk+:^0OAQ}l-a}K\M>ݮ>F;=^~sVMV20knv~MG'eu.Qe)IqؚI)^ kظޞ['VY;w yF3 *2敝\TBw6wJBؔo:<_r˭Z{9|}/=|ζs\Rr {R߹3L6m}txeTⲚG+u h ?OC (;=tЫ{ùIaf pk&x_g'#B[}/?֕ sF/DŀݧA' ΂a:(ܸ຤xtv]oseCwr_LJhTēCfZ3Z3+Ҝ5G( KzftWPʾ`Fm+Bq)DmE$@˝:HH+[ζIw(55]P5}(? `K?xxVVC );[;e<0PN[֒yxa_Wt>hp* >.\ Ŭ#w8TW_dO ;v˸ُ*s}ۦ֕gYO }k@ > Wņ$nI,CwײDY(q7Pmzɸ%>wvww'Yh!R4]vZ$˶Dʔ>>Fq1QZ~#L|z(_< k$W* :e8~M{nݕ)wf,55|||{VlPaHI1oifTKhPg]G$4[a[>aS0qְ'/ X8lO75䎙rO:~RWwWy{u75sQ۳၍b?{9ם/}|=־~;w@vS}2Ν;%j7+;KܿkYܝ 3>率'-=n -q;GN=]F3izʷPG yxk7"V6 )l_[4ʳGm8%Cf ЯSSش'Τ2Рnamk~BthQY{+~E(ٺaPO /tcxk7K20dzr䎙0kӢd$w?ӞR~v`cڀ@s/\nxuY}m+7V#ߡ3+;GЖ1c|kGswpwOvDKj8Ļ5Bӥ챭2 Mѐql阬ݰt!2c})]'eh׉t fXUy7_Q$ԕrG + Ƞ^ۗb2x^[Fj{N;tC8֬Cfj[]ܬv( Y;?6-CZWr#| >{]vkhTi~tk=r_Cxn=F\nٱ}@[銐w&0k}?>\q:Kx?ۖ|0|5k{2ȮsO6ޥݞ4g][ͻUag2kgVLk6k(НвhzwȵwloXJL͏&X;e7g"C֮3R%H 3_ }ΐصṽGwsƛ#iv}7>ddj?aC`QvE]ێKJؙU|ЎkN kgmEoMvvB93ѭ8v<h)tظݽN]Eix-]1sPT0S[3 ;v-zVr6ni^uӍi"_o a}u;?hSsw&$= @p^:E]3x^<-ؖ)>YԺcTepP'÷\/+Irw(-Wqjw}׷U>w'%A;XMWngSb*=oro˶LTD9BwS;El֞{de#0X^dhNSeL=#]e7CŒdYyq0w+{ w]uiKt`s/q:"_o"Dyܮb40~y=.Y;? Q<)>bvc+4U_coŒṁMLчeY;rHuȇo68CwW*];+wT4kGlUkoF<=3n]ȭms/s~~g&yɣ"%7gC`1lfѴZk򔽬vuk*(tZ,e[{M%;T)3}|(׊U9uDnAͻ.nuQw–j>ЎQuO-(~fQo6%uu66o|N^sNݧoOVu$۩p8 }6 CtY{k'n!/Ż8q}>~>>~Wt߫'& ZM+tMkR6_2:p1e#SLc捽yCmL,`کjŢ'vAA=ZP|AA11%CY;S^X\./..(ЯOuRGCwew~>R Z;ZH^3#+κ~"8잇U.5z;ske9K]rx _3:[f@c~Dž &\m [ k'4Sӊ +g!품.Yޓ '~L+VJ &k2hhUT-:ӻ>ژgR1k7լ \lpʰWh _̬7~8_PVL}w`#7GlF@*bPӧOЍ 'Н 2R?3n4[5{-B#ݫGThֲG:CXм*ɔVonH?n[yE.9׌({MRmJ'vl>=TYU [7_86mkFkVI}1s}NvrwwRRΌFJ t*=>˺7( EwoQY>kO,j={Ϩa럞`Խ[ٱ:-٣@`{H@Ml\v+w1Ǝ=>Ϗ e&`3);>A7l<[w=;FכA)wj gh,tϽpnNE{o܎f?UFi=ݽڡM%cP+D;%K+l2X}8hrpJ]m9yo W}~Cj>7 9umLM+,b'L:cX EwGC[ a*I& ԍvIE;E.z/S &)qmmmhhŋ2ڟ0$4X;EQvd,zä/w2<'Lj$qg(Ιx3{7ckg}hdmPvh4)k6ۨ>سvB!?pwX(oweTSdmJ;dDz4Y;pN;As;4OtHv|[ZWKv/:%k0wa_<=#Ĕ9:6nNݻh@aW'/Pv]Ee'~>Tݵ̂;];pC1q3qvkGw[؃);GqgO V{*$@Lm R+Bנᄀ-;~ket>@mmelD }H \/ q;>>Mb3,wjo0s̾y?x}E ̴mͮ;qv8kJoxǶt'OR>v\[[+Ǝʲ6mϋbC{yD:݃[[[:xf~uĽCxn=#ځage#IJ* qoݽBܭvaue ԓaR,n]j⵭)/;2=wK]rO[;숻 =^!v4{>ԙCZ^+ī\DbAONH>? KQb)ӿGyy zjkðkݍ;0H]b_jT-oäs>EBw[3X$Nk츻}sߍ+k.MZk@ &_.2 =']] qbG<&vyN({V§gK+;3uko̧kNWy *Ne|u^ܩ'Xw(;v3CqлX{3.G| A׉.(޸?#Wv4v,ngL]WC }SqxcLIY;|3uL3&d|N~NnXv ww($N޹DO|<#_ӥ@h+۟ckGK}؀7'JC1t7#hpߊ`LawWw^{C[p k0fC힊ĝ1,hWTv(Y;(qw1wwK;{2v03+zN^xg Oa?cxe'6m߾}O#7uyN޵;qUBp4]ݵ;2]WLy֮PWvݣ9ACkK.k:@%7)&Fs3eG06fo鸮vߡkv]Y;#5eFV¹ SSχn7OFHj|NbI L-m{@%nl]g^,?7ډv^ʞܛC]XyH|ߊ@"h:b׍@\ gBFdZ >ah 𺞌dTpw C3-(持Z.h׋ 3R(7-qwBޖa;t6g ie.B蠺l3;YЎnZD7/7wo!k5.*JD"hRbxuE\U1hTdtc$Y?b ݽ[xRN֗LNAqFz2풕<v32ϔ@޺9h'Ty<'CٵdxnYܝYmїS]\vd-0kKv+xs/T|)7'FP=f#v.vhQv={q; 3&OQy%֓z'TRuh,|mFV4!ӍɆُNʤEW)g.e+fCC vvXrM穩6h"ho{^WNHxvŘVq1:e,nX;mJw΋]{ a4zW'wUv_bA;);u! ^RԖ`;jDLnq7oZh;ݟU9Sٺݟ\` gd: >qqMv;=;ϧ}2)~@gq;v(d9'U|6G`55}|[ޞ`q~@ƫq̓?|7٨ʫ`o U6R0C^a V;S( Y=,nWMwhצo32ZC$ѱ\UXy\ch(!"h4J&qheh3kξ )$tgi(ZATR[m]/ڣwIú1U:EGŒ"J3ZC.rUa*xǛt3kofMS]˂T&]ғѲ,&F]m>n7zsɌ3Оo[[FCڛpeLUue{V!trod Iٛ<(mV<;~w/_ j3 k5w]ruD=F`Ĵ9zCwFLʺZ(@%%\5R:c05gݿ~Ɍ3yl.?܅}7V)<)3a&hx3ڳrwf>˺}RUIm x'%AY9o{y﹇|ુB19.6_P{gtRFg>)uɏ@˳vq7]wnv-ʝX|IL<-k\Edx; {kR%䜸^UFBAqz;Xzgty4=gjVB3zٙeTswvw ݳw. Z-f}e﹇*A\IMtX(X1e_72ݝ,+-!U#(tfۭyx͞Ĵ9Z 3G➌3{|c+LOge늦XΖۻXqMF軼9}?Tsm{ѐ[ݝcmjuKhJR+w1Jjԉ VY;.eZ; k7v{xu-MRU]qn~|fMn=5M_"wc%؟*cr=k/F_dCyߙVa*Ugddֱwbw>n rwW]Ee7ci!f1jƍk77[{ysݢu"hoi'W۝3̌oHi>֝[Ζۋ5dh((g˅iYp!BrMMվCk}gk)]~4rL<޹*'w.6hdkwx k7AEw'kL잌S]z2]1n׎Нq'@ݚ*ffޡ|e^̇v{!ac"}jtLp6[叧`Zkty/i!PW=9'E.0Mbe.WrYOƩI%q;=t.3Y^Ń{K<2RFђ >R霻ӦK}Ӣ04]}3& 6W=PVwQݳ55UZ#z-?Vug~޾+QWhr 4.xTANLrN^1Y'.hؘ\9 }o^!{q>< iɯpߙ%qwwa.G(@?{mCqyܨy2(/kϻ;eMN־I%f~w: w7xwr9fwhCfް޽TUQz @}v#Gu,j~Q|./$oZGxb%ar;W݅bڅ \[]=^ى[۶t!z7CA't ݙNIRpWVFh MZG#o۽}6ZuRݗm2|zԧvKp'J|}NaM0TOPvE,(F3,[wmV//[wnrjj+‡<pטد?Fuw%%)7f-]mFSw_ [>*(*W4yWm3 5ͯxrtR昙CSe\FFzr]Q:=v1]` U[){2s _`IOWn X0kgLN./L{۶h^=V (I<"9+-2c% ij?.`=uu)1?ˬ:>&^䯿MOhH21,vwaAB&qfz2ۮɟV톕19-0}jkiVjkLgF1kWNkjn},nuo^Tr+8d8)Ge~,#0u|zu;/aؘ:8~>*1e˿%D] *,kkׅv \/DHL<[x=Ouu1*.}ٺsl*ALuf0(DI/˔*1 ]8GX ?Ͻ[Iç[ܵp뻰v]4Wk.$|E=PLb:TJ "h O߄vg؜(*=g\WD8qNGơFu?.pS *SR]cOwO-mV1Su2`K{Ylm{"KB"#0uR0aBNB%=uq@e'SO;wg+;DG['qGw"6u]?ߢU pU>4k'q6~~ˁk՟"tE{bbҙ׶6~hTv]bM)eg / w 7#*nk׎yD.p>isԇ̨X*;d+S[+`.|Hꥨ^NM&!{<߫!fם1yŵ?3&-A;yo W_ ɉZWVÐ*nLlL;e]u#wñ k׎v \H޺&ewJ_!wOVvB1nz3=f%%]1t+f 3`%9`mŵB.y'X=7ȭ!e  Cڵ#1C[˿'t$+5ynw*֮a= \,;c|˚_p㕍s?@$bg.aKyW&4;tv wst/3<#]{Y7pUDYYr<ݩXS[)mؙt5l[Cew+Bdۛ|yeY9?1@Ή{ =jOթ(]̂vbZ )t/+4EWw p35]?_< 3wq;a tAq&&M $2R?v,nG H,Bu"qoV`B^!buv(f;15 %Frt_?\PdEu7- o]X>.1a_X1oCĝ_*Gon,n'潴onOVP.v f3xWjצֺzog;Y`ë]G=xܝ@XXK?uoФʪ&VgΦC:ues71na՟ Go9B~_VƯ!. څ ݭ ag$g/pwբmwܝ٤T'5Dfw cKd&noq,0xapO.|]Ќh설0@^k'3;9c_|VW&W0e{n ywg mcd$qw*"0[W[uAK:3ё*NLM;ְ=UowORƟIle7)?,fjwŒᕩz1rN*wWmFŘ, ]rDѧ][.hixBPTBT,} wWQv:}W~2CC ^n`eae$rwrwm֮-c$s=:SXckoAuA ]wy]x}'9 I.w5껢w3)l\w;a6lquOCTeZ4jQv4gk.5e'&EˢѠٜѨrT ^0v ^^y4}c6PvD$F]X1E\z[1Z`j3挢]o,zoZ. ݵLJԔZk6=q7l*mquG@)6Lv:څ p;Cy<9c8bWok<ES#yƂӧ|;ݡq'tf4ɬ^[a](W ] x|3MމUb`NZwJF,wB/f.AN͋+1pzgWIΟ:kYYe -.t:B@ _2HftgGdO9ya8|XXa5z-$uoSdݙ NO.3u[#H!|] C@  ޢR>:Tt~;0x^ܵ[Tb]㾔3Ξ=pC]e {: #] jxGNIN\;0e)\ߍ}.{+1]rWk<֮֩יC@B@]%btjϬ=g &=}wukwq%ưH"vRv8$\u yv}WةÔPwFxT#~ǀ۞hڅ < !@ hwyoqWkg0}ݝ&vWvW::a_=C}]]!|]* 9#M:yX]d!]Cߦ yx31V @cܮ*#] -{O|E%DX; {%j%ߑfJdk @w@ 'Y{DDW!NF回;(xOK"Wk%K"g?:}k\֟bv'WZqqw{铃F*r_7qb-/>INX5H;<\o`{3L #include #include "checkdgf.hh" using namespace Dune; int main(int argc, char ** argv) try { runDGFTest>(argc,argv); return 0; } catch( const Dune::Exception &e ) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 1; } dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/test-dgf-oned.cc000066400000000000000000000010711511655130300245610ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include "../dgfoned.hh" #include "checkdgf.hh" using namespace Dune; int main(int argc, char ** argv) try { runDGFTest(argc,argv); return 0; } catch( const Dune::Exception &e ) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 1; } dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/test-dgf-ug.cc000066400000000000000000000010661511655130300242530ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include "../dgfug.hh" #include "checkdgf.hh" using namespace Dune; int main(int argc, char ** argv) try { runDGFTest>(argc,argv); return 0; } catch( const Dune::Exception &e ) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 1; } dune-grid-2.11.0/dune/grid/io/file/dgfparser/test/test-dgf-yasp.cc000066400000000000000000000012641511655130300246140ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #include #include #include "../dgfyasp.hh" #include "checkdgf.hh" using namespace Dune; int main(int argc, char ** argv) try { #ifdef TESTCOORDINATES using Grid=YaspGrid<2,EquidistantOffsetCoordinates>; #else using Grid=YaspGrid<3>; #endif runDGFTest(argc,argv); return 0; } catch( const Dune::Exception &e ) { std::cerr << e << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 1; } dune-grid-2.11.0/dune/grid/io/file/dgfparser/utils/000077500000000000000000000000001511655130300217745ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/dgfparser/utils/CMakeLists.txt000066400000000000000000000012621511655130300245350ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(GRIDTYPE ONEDGRID) set(GRIDDIM 1) set(EXTRA_PROGRAMS dgf2dgf gmsh2dgf) foreach(exe ${EXTRA_PROGRAMS}) add_dgf_executable(${exe} EXCLUDE_FROM_ALL ${exe}.cc) target_link_libraries(${exe} PUBLIC dunegrid) endforeach(exe ${EXTRA_PROGRAMS}) if(dune-uggrid_FOUND) add_dgf_executable(gmsh2dgfugsimplex EXCLUDE_FROM_ALL gmsh2dgf.cc GRIDDIM 2 WORLDDIM 2 GRIDTYPE UGGRID) target_link_libraries(gmsh2dgfugsimplex PUBLIC dunegrid) set(EXTRA_PROGRAMS ${EXTRA_PROGRAMS} gmsh2dgfugsimplex) endif() dune-grid-2.11.0/dune/grid/io/file/dgfparser/utils/dgf2dgf.cc000066400000000000000000000044311511655130300236100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \author Matrin Nolte * \brief a small program converting a DGF file into a DGF file * * dgf2dgf is a small example program for the DGFWriter. It reads a DGF file * into any grid, optionally refining the grid * globally. The leaf grid is then written back as a DGF file. * * The program's usage is as follows: \code ./dgf2dgf [refinement level] \endcode * * While the program may seem completely useless, it has the following usages: * - Convert an interval block into a simplex or cube grid (depending on the * grid implementation used). * - Resolve the simplex generator block into a vertex and a simplex block, so * that it can be used without triangle or tetgen. * - Construct a refined macro grid, which is very useful when setting up * parallel computations with dune-ALUGrid. * . * * The source code of this program also demonstrates the easy use of the DGF * parser and the DGFWriter. */ #include #include using namespace Dune; int main ( int argc, char *argv[] ) try { typedef GridSelector::GridType Grid; Dune::MPIHelper::instance( argc, argv ); if( argc < 2 ) { std::cerr << "Usage: " << argv[ 0 ] << " [refinement level]" << std::endl; return 1; } const std::string dgfFileName( argv[ 1 ] ); const int level = (argc < 3 ? 0 : atoi( argv[ 2 ] )); GridPtr< Grid > gridptr( dgfFileName ); if( level > 0 ) gridptr->globalRefine( level ); typedef Grid::LeafGridView GridView; GridView gridView = gridptr->leafGridView(); DGFWriter< GridView > dgfWriter( gridView ); dgfWriter.write( std::cout ); const GridView::IndexSet &indexSet = gridView.indexSet(); std::cerr << "Grid successfully written: " << indexSet.size( Grid::dimension ) << " vertices, " << indexSet.size( 0 ) << " elements." << std::endl; return 0; } catch( const Exception &exception ) { std::cerr << exception << std::endl; return 1; } dune-grid-2.11.0/dune/grid/io/file/dgfparser/utils/gmsh2dgf.cc000066400000000000000000000034171511655130300240110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** \file * \author Matrin Nolte * \brief a small program converting a gmsh file into a DGF file * * gmsh2dgf is a small example program for the DGFWriter. It reads a gmsh file * into any grid (selected by gridtype.hh) and writes it back as a DGF file. * * The program's usage is as follows: \code ./gmsh2dgf \endcode */ #include #include #include #include using namespace Dune; int main ( int argc, char *argv[] ) try { Dune::MPIHelper::instance( argc, argv ); typedef Dune::GridSelector::GridType Grid; if( argc < 2 ) { std::cerr << "Usage: " << argv[ 0 ] << " " << std::endl; return 1; } const std::string gmshFileName( argv[ 1 ] ); std::string dgfFileName( gmshFileName ); dgfFileName.resize( dgfFileName.find_last_of( "." ) ); dgfFileName += ".dgf"; Grid *grid = GmshReader< Grid >::read( gmshFileName ); typedef Grid::LeafGridView GridView; GridView gridView = grid->leafGridView(); DGFWriter< GridView > dgfWriter( gridView ); dgfWriter.write( dgfFileName ); const GridView::IndexSet &indexSet = gridView.indexSet(); std::cerr << "Grid successfully written: " << indexSet.size( Grid::dimension ) << " vertices, " << indexSet.size( 0 ) << " elements." << std::endl; return 0; } catch( const Exception &exception ) { std::cerr << exception << std::endl; return 1; } dune-grid-2.11.0/dune/grid/io/file/gmsh/000077500000000000000000000000001511655130300176155ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/gmsh/CMakeLists.txt000066400000000000000000000007521511655130300223610ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception set(HEADERS filereader.hh gmsh2parser.hh gmsh4reader.hh gmsh4reader.impl.hh gridcreatorinterface.hh types.hh) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/gmsh) target_sources(dunegrid PRIVATE types.cc) add_subdirectory(gridcreators) add_subdirectory(utility) dune-grid-2.11.0/dune/grid/io/file/gmsh/filereader.hh000066400000000000000000000053641511655130300222500ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_FILEREADER_HH #define DUNE_GRID_IO_FILE_GMSH_FILEREADER_HH #include #include #include #include #include namespace Dune::Impl::Gmsh { template class FileReader { private: // type of underlying implementation, for internal use only using Implementation = FilerReaderImp; /// \brief An accessor class to call protected members of reader implementations. struct Accessor : public Implementation { template static std::unique_ptr createGridFromFileImpl (Args&&... args) { return Implementation::createGridFromFileImpl(std::forward(args)...); } template static void fillFactoryImpl (Args&&... args) { return Implementation::fillFactoryImpl(std::forward(args)...); } }; public: /// Reads the grid from a file with filename and returns a unique_ptr to the created grid. /// Redirects to concrete implementation of derived class. template static std::unique_ptr createGridFromFile (const std::string &filename, Args&&... args) { return Accessor::createGridFromFileImpl(filename, std::forward(args)...); } /// Reads the grid from a file with filename into a grid-factory. /// Redirects to concrete implementation of derived class. template static void fillFactory (GridFactory &factory, const std::string &filename, Args&&... args) { Accessor::fillFactoryImpl(factory, filename, std::forward(args)...); } protected: // default implementations // Default implementation, redirects to factory read implementation. template static std::unique_ptr createGridFromFileImpl (const std::string &filename, Args&&... args) { GridFactory factory; fillFactory(factory, filename, std::forward(args)...); return std::unique_ptr{ factory.createGrid() }; } // Default implementation for reading into grid-factory: produces a runtime-error. template static void fillFactoryImpl (GridFactory & /*factory*/, const std::string & /*filename*/, Args&&... /*args*/) { DUNE_THROW(NotImplemented, "GridReader using a factory argument not implemented for concrete reader implementation."); } }; } // end namespace Dune::Impl::Gmsh #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/gmsh2parser.hh000066400000000000000000000635051511655130300224040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_GMSH_GMSH2PARSER_HH #define DUNE_GRID_IO_FILE_GMSH_GMSH2PARSER_HH #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Dune::Impl::Gmsh { // arbitrary dimension, implementation is in specialization template< int dimension, int dimWorld = dimension > class GmshReaderQuadraticBoundarySegment { public: // empty function since this class does not implement anything static void registerFactory() {} }; // quadratic boundary segments in 1d /* Note the points (0) (alpha) (1) are mapped to the points in global coordinates p0 p2 p1 alpha is determined automatically from the given points. */ template< int dimWorld > struct GmshReaderQuadraticBoundarySegment< 2, dimWorld > : public Dune::BoundarySegment< 2, dimWorld > { typedef GmshReaderQuadraticBoundarySegment< 2, dimWorld > ThisType; typedef typename Dune::BoundarySegment< 2, dimWorld > :: ObjectStreamType ObjectStreamType; typedef Dune::FieldVector< double, dimWorld > GlobalVector; GmshReaderQuadraticBoundarySegment ( const GlobalVector &p0_, const GlobalVector &p1_, const GlobalVector &p2_) : p0(p0_), p1(p1_), p2(p2_) { init(); } GmshReaderQuadraticBoundarySegment( ObjectStreamType& in ) { // key is read before by the factory const int bytes = sizeof(double)*dimWorld; in.read( (char *) &p0[ 0 ], bytes ); in.read( (char *) &p1[ 0 ], bytes ); in.read( (char *) &p2[ 0 ], bytes ); init(); } static void registerFactory() { if( key() < 0 ) { key() = Dune::BoundarySegment< 2, dimWorld >::template registerFactory< ThisType >(); } } virtual GlobalVector operator() ( const Dune::FieldVector &local ) const { GlobalVector y; y = 0.0; y.axpy((local[0]-alpha)*(local[0]-1.0)/alpha,p0); y.axpy(local[0]*(local[0]-1.0)/(alpha*(alpha-1.0)),p1); y.axpy(local[0]*(local[0]-alpha)/(1.0-alpha),p2); return y; } void backup( ObjectStreamType& out ) const { // backup key to identify object out.write( (const char *) &key(), sizeof( int ) ); // backup data const int bytes = sizeof(double)*dimWorld; out.write( (const char*) &p0[ 0 ], bytes ); out.write( (const char*) &p1[ 0 ], bytes ); out.write( (const char*) &p2[ 0 ], bytes ); } protected: void init() { GlobalVector d1 = p1; d1 -= p0; GlobalVector d2 = p2; d2 -= p1; alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm()); if (alpha<1E-6 || alpha>1-1E-6) DUNE_THROW(Dune::IOError, "ration in quadratic boundary segment bad"); } static int& key() { static int k = -1; return k; } private: GlobalVector p0,p1,p2; double alpha; }; // quadratic boundary segments in 2d /* numbering of points corresponding to gmsh: 2 5 4 0 3 1 Note: The vertices 3, 4, 5 are not necessarily at the edge midpoints but can be placed with parameters alpha, beta , gamma at the following positions in local coordinates: 2 = (0,1) 5 = (0,beta) 4 = (1-gamma/sqrt(2),gamma/sqrt(2)) 0 = (0,0) 3 = (alpha,0) 1 = (1,0) The parameters alpha, beta, gamma are determined from the given vertices in global coordinates. */ template<> class GmshReaderQuadraticBoundarySegment< 3, 3 > : public Dune::BoundarySegment< 3 > { typedef GmshReaderQuadraticBoundarySegment< 3, 3 > ThisType; typedef typename Dune::BoundarySegment< 3 > :: ObjectStreamType ObjectStreamType; public: GmshReaderQuadraticBoundarySegment (Dune::FieldVector p0_, Dune::FieldVector p1_, Dune::FieldVector p2_, Dune::FieldVector p3_, Dune::FieldVector p4_, Dune::FieldVector p5_) : p0(p0_), p1(p1_), p2(p2_), p3(p3_), p4(p4_), p5(p5_) { init(); } GmshReaderQuadraticBoundarySegment( ObjectStreamType& in ) { const int bytes = sizeof(double)*3; in.read( (char *) &p0[ 0 ], bytes ); in.read( (char *) &p1[ 0 ], bytes ); in.read( (char *) &p2[ 0 ], bytes ); in.read( (char *) &p3[ 0 ], bytes ); in.read( (char *) &p4[ 0 ], bytes ); in.read( (char *) &p5[ 0 ], bytes ); init(); } static void registerFactory() { if( key() < 0 ) { key() = Dune::BoundarySegment< 3 >::template registerFactory< ThisType >(); } } virtual Dune::FieldVector operator() (const Dune::FieldVector& local) const { Dune::FieldVector y; y = 0.0; y.axpy(phi0(local),p0); y.axpy(phi1(local),p1); y.axpy(phi2(local),p2); y.axpy(phi3(local),p3); y.axpy(phi4(local),p4); y.axpy(phi5(local),p5); return y; } void backup( ObjectStreamType& out ) const { // backup key to identify object in factory out.write( (const char*) &key(), sizeof( int ) ); // backup data const int bytes = sizeof(double)*3; out.write( (const char*) &p0[ 0 ], bytes ); out.write( (const char*) &p1[ 0 ], bytes ); out.write( (const char*) &p2[ 0 ], bytes ); out.write( (const char*) &p3[ 0 ], bytes ); out.write( (const char*) &p4[ 0 ], bytes ); out.write( (const char*) &p5[ 0 ], bytes ); } protected: void init() { using std::sqrt; sqrt2 = sqrt(2.0); Dune::FieldVector d1,d2; d1 = p3; d1 -= p0; d2 = p1; d2 -= p3; alpha=d1.two_norm()/(d1.two_norm()+d2.two_norm()); if (alpha<1E-6 || alpha>1-1E-6) DUNE_THROW(Dune::IOError, "alpha in quadratic boundary segment bad"); d1 = p5; d1 -= p0; d2 = p2; d2 -= p5; beta=d1.two_norm()/(d1.two_norm()+d2.two_norm()); if (beta<1E-6 || beta>1-1E-6) DUNE_THROW(Dune::IOError, "beta in quadratic boundary segment bad"); d1 = p4; d1 -= p1; d2 = p2; d2 -= p4; gamma=sqrt2*(d1.two_norm()/(d1.two_norm()+d2.two_norm())); if (gamma<1E-6 || gamma>1-1E-6) DUNE_THROW(Dune::IOError, "gamma in quadratic boundary segment bad"); } static int& key() { static int k = -1; return k; } private: // The six Lagrange basis function on the reference element // for the points given above double phi0 (const Dune::FieldVector& local) const { return (alpha*beta-beta*local[0]-alpha*local[1])*(1-local[0]-local[1])/(alpha*beta); } double phi3 (const Dune::FieldVector& local) const { return local[0]*(1-local[0]-local[1])/(alpha*(1-alpha)); } double phi1 (const Dune::FieldVector& local) const { return local[0]*(gamma*local[0]-(sqrt2-gamma-sqrt2*alpha)*local[1]-alpha*gamma)/(gamma*(1-alpha)); } double phi5 (const Dune::FieldVector& local) const { return local[1]*(1-local[0]-local[1])/(beta*(1-beta)); } double phi4 (const Dune::FieldVector& local) const { return local[0]*local[1]/((1-gamma/sqrt2)*gamma/sqrt2); } double phi2 (const Dune::FieldVector& local) const { return local[1]*(beta*(1-gamma/sqrt2)-local[0]*(beta-gamma/sqrt2)-local[1]*(1-gamma/sqrt2))/((1-gamma/sqrt2)*(beta-1)); } Dune::FieldVector p0,p1,p2,p3,p4,p5; double alpha,beta,gamma,sqrt2; }; /** \brief A parser for the Version 2 ASCII Gmsh file format */ template class Gmsh2Parser { protected: // private data Dune::GridFactory& factory; bool verbose; bool insert_boundary_segments; unsigned int number_of_real_vertices; int boundary_element_count; int element_count; // read buffer char buf[512]; std::string fileName; // exported data std::vector boundary_id_to_physical_entity; std::vector element_index_to_physical_entity; std::vector physical_entity_names; // static data static const int dim = GridType::dimension; static const int dimWorld = GridType::dimensionworld; static_assert( (dimWorld <= 3), "GmshReader requires dimWorld <= 3." ); // typedefs typedef FieldVector< double, dimWorld > GlobalVector; // don't use something like // readfile(file, 1, "%s\n", buf); // to skip the rest of of the line -- that will only skip the next // whitespace-separated word! Use skipline() instead. void readfile(FILE * file, int cnt, const char * format, ...) #ifdef __GNUC__ __attribute__((format(scanf, 4, 5))) #endif { std::va_list ap; va_start(ap, format); auto pos = std::ftell(file); int c = std::vfscanf(file, format, ap); va_end(ap); if (c != cnt) DUNE_THROW(Dune::IOError, "Error parsing " << fileName << " " "file pos " << pos << ": Expected '" << format << "', only read " << c << " entries instead of " << cnt << "."); } // skip over the rest of the line, including the terminating newline void skipline(FILE * file) { int c; do { c = std::fgetc(file); } while(c != '\n' && c != EOF); } public: Gmsh2Parser(Dune::GridFactory& _factory, bool v, bool i) : factory(_factory), verbose(v), insert_boundary_segments(i) {} std::vector & boundaryIdMap() { return boundary_id_to_physical_entity; } //! Returns a map for the gmsh physical entity id (1-based index) for each entity of codim 0 std::vector & elementIndexMap() { return element_index_to_physical_entity; } //! Returns the names of the gmsh physical entities (0-based index) std::vector & physicalEntityNames() { return physical_entity_names; } void read (const std::string& f) { if (verbose) std::cout << "Reading " << dim << "d Gmsh grid..." << std::endl; // open file name, we use C I/O fileName = f; FILE* file = fopen(fileName.c_str(),"rb"); if (file==0) DUNE_THROW(Dune::IOError, "Could not open " << fileName); //========================================= // Header: Read vertices into vector // Check vertices that are needed //========================================= number_of_real_vertices = 0; boundary_element_count = 0; element_count = 0; // process header double version_number; int file_type, data_size; readfile(file,1,"%s\n",buf); if (strcmp(buf,"$MeshFormat")!=0) DUNE_THROW(Dune::IOError, "expected $MeshFormat in first line"); readfile(file,3,"%lg %d %d\n",&version_number,&file_type,&data_size); // 2.2 is not representable as float and leads to problems on i386 // Hence we use >= 2.00001. if( (version_number < 2.0) || (version_number >= 2.20001) ) // 2.2 is not representable as float and leads to problems on i386 DUNE_THROW(Dune::IOError, "can only read Gmsh version 2 files"); if (verbose) std::cout << "version " << version_number << " Gmsh file detected" << std::endl; readfile(file,1,"%s\n",buf); if (strcmp(buf,"$EndMeshFormat")!=0) DUNE_THROW(Dune::IOError, "expected $EndMeshFormat"); // physical name section physical_entity_names.clear(); readfile(file,1,"%s\n",buf); if (strcmp(buf,"$PhysicalNames")==0) { int number_of_names; readfile(file,1,"%d\n",&number_of_names); if (verbose) std::cout << "file contains " << number_of_names << " physical entities" << std::endl; physical_entity_names.resize(number_of_names); std::string buf_name; for( int i = 0; i < number_of_names; ++i ) { int edim, id; readfile(file,3, "%d %d %s\n", &edim, &id, buf); buf_name.assign(buf); auto begin = buf_name.find_first_of('\"') + 1; auto end = buf_name.find_last_of('\"') - begin; physical_entity_names[id-1].assign(buf_name.substr(begin, end)); } readfile(file,1,"%s\n",buf); if (strcmp(buf,"$EndPhysicalNames")!=0) DUNE_THROW(Dune::IOError, "expected $EndPhysicalNames"); readfile(file,1,"%s\n",buf); } // node section int number_of_nodes; if (strcmp(buf,"$Nodes")!=0) DUNE_THROW(Dune::IOError, "expected $Nodes"); readfile(file,1,"%d\n",&number_of_nodes); if (verbose) std::cout << "file contains " << number_of_nodes << " nodes" << std::endl; // read nodes // The '+1' is due to the fact that gmsh numbers node starting from 1 rather than from 0 std::vector< GlobalVector > nodes( number_of_nodes+1 ); { int id; double x[ 3 ]; for( int i = 1; i <= number_of_nodes; ++i ) { readfile(file,4, "%d %lg %lg %lg\n", &id, &x[ 0 ], &x[ 1 ], &x[ 2 ] ); if (id > number_of_nodes) { DUNE_THROW(Dune::IOError, "Only dense sequences of node indices are currently supported (node index " << id << " is invalid)."); } // just store node position for( int j = 0; j < dimWorld; ++j ) nodes[ id ][ j ] = x[ j ]; } readfile(file,1,"%s\n",buf); if (strcmp(buf,"$EndNodes")!=0) DUNE_THROW(Dune::IOError, "expected $EndNodes"); } // element section readfile(file,1,"%s\n",buf); if (strcmp(buf,"$Elements")!=0) DUNE_THROW(Dune::IOError, "expected $Elements"); int number_of_elements; readfile(file,1,"%d\n",&number_of_elements); if (verbose) std::cout << "file contains " << number_of_elements << " elements" << std::endl; //========================================= // Pass 1: Select and insert those vertices in the file that // actually occur as corners of an element. //========================================= auto section_element_offset = std::ftell(file); std::map renumber; for (int i=1; i<=number_of_elements; i++) { int id, elm_type, number_of_tags; readfile(file,3,"%d %d %d ",&id,&elm_type,&number_of_tags); for (int k=1; k<=number_of_tags; k++) { int blub; readfile(file,1,"%d ",&blub); // k == 1: physical entity // k == 2: elementary entity (not used here) // if version_number < 2.2: // k == 3: mesh partition 0 // else // k == 3: number of mesh partitions // k => 4: mesh partition k-4 } pass1HandleElement(file, elm_type, renumber, nodes); } if (verbose) std::cout << "number of real vertices = " << number_of_real_vertices << std::endl; if (verbose) std::cout << "number of boundary elements = " << boundary_element_count << std::endl; if (verbose) std::cout << "number of elements = " << element_count << std::endl; readfile(file,1,"%s\n",buf); if (strcmp(buf,"$EndElements")!=0) DUNE_THROW(Dune::IOError, "expected $EndElements"); boundary_id_to_physical_entity.resize(boundary_element_count); element_index_to_physical_entity.resize(element_count); //============================================== // Pass 2: Insert boundary segments and elements //============================================== std::fseek(file, section_element_offset, SEEK_SET); boundary_element_count = 0; element_count = 0; for (int i=1; i<=number_of_elements; i++) { int id, elm_type, number_of_tags; readfile(file,3,"%d %d %d ",&id,&elm_type,&number_of_tags); int physical_entity = -1; for (int k=1; k<=number_of_tags; k++) { int blub; readfile(file,1,"%d ",&blub); if (k==1) physical_entity = blub; } pass2HandleElement(file, elm_type, renumber, nodes, physical_entity); } readfile(file,1,"%s\n",buf); if (strcmp(buf,"$EndElements")!=0) DUNE_THROW(Dune::IOError, "expected $EndElements"); fclose(file); } /** \brief Process one element during the first pass through the list of all elements * * Mainly, the method inserts all vertices needed by the current element, * unless they have been inserted already for a previous element. */ void pass1HandleElement(FILE* file, const int elm_type, std::map & renumber, const std::vector< GlobalVector > & nodes) { // some data about gmsh elements const int nDofs[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10, -1, -1, -1, 1}; const int nVertices[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4, -1, -1, -1, 1}; const int elementDim[16] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3, -1, -1, -1, 0}; // test whether we support the element type if ( not (elm_type > 0 && elm_type <= 15 // index in suitable range? && (elementDim[elm_type] == dim || elementDim[elm_type] == (dim-1) ) ) ) // real element or boundary element? { skipline(file); // skip rest of line if element is unknown return; } // The format string for parsing is n times '%d' in a row std::string formatString = "%d"; for (int i=1; i elementDofs(10); readfile(file,nDofs[elm_type], formatString.c_str(), &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]), &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]), &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]), &(elementDofs[9])); // insert each vertex if it hasn't been inserted already for (int i=0; i void boundarysegment_insert( const V&, const E&, const V2& ) { DUNE_THROW(Dune::IOError, "tried to create a 3D boundary segment in a non-3D Grid"); } // 3d-case: template void boundarysegment_insert( const std::vector >& nodes, const E& elementDofs, const V& vertices ) { std::array, 6> v; for (int i=0; i<6; i++) for (int j=0; j* newBoundarySegment = (BoundarySegment*) new GmshReaderQuadraticBoundarySegment< 3, 3 >( v[0], v[1], v[2], v[3], v[4], v[5] ); factory.insertBoundarySegment( vertices, std::shared_ptr >(newBoundarySegment) ); } /** \brief Process one element during the second pass through the list of all elements * * This method actually inserts the element into the grid factory. */ virtual void pass2HandleElement(FILE* file, const int elm_type, std::map & renumber, const std::vector< GlobalVector > & nodes, const int physical_entity) { // some data about gmsh elements const int nDofs[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 3, 6, -1, 10, -1, -1, -1, 1}; const int nVertices[16] = {-1, 2, 3, 4, 4, 8, 6, 5, 2, 3, -1, 4, -1, -1, -1, 1}; const int elementDim[16] = {-1, 1, 2, 2, 3, 3, 3, 3, 1, 2, -1, 3, -1, -1, -1, 0}; // test whether we support the element type if ( not (elm_type > 0 && elm_type <= 15 // index in suitable range? && (elementDim[elm_type] == dim || elementDim[elm_type] == (dim-1) ) ) ) // real element or boundary element? { skipline(file); // skip rest of line if element is unknown return; } // The format string for parsing is n times '%d' in a row std::string formatString = "%d"; for (int i=1; i elementDofs(10); readfile(file,nDofs[elm_type], formatString.c_str(), &(elementDofs[0]),&(elementDofs[1]),&(elementDofs[2]), &(elementDofs[3]),&(elementDofs[4]),&(elementDofs[5]), &(elementDofs[6]),&(elementDofs[7]),&(elementDofs[8]), &(elementDofs[9])); // correct differences between gmsh and Dune in the local vertex numbering switch (elm_type) { case 3 : // 4-node quadrilateral std::swap(elementDofs[2],elementDofs[3]); break; case 5 : // 8-node hexahedron std::swap(elementDofs[2],elementDofs[3]); std::swap(elementDofs[6],elementDofs[7]); break; case 7 : // 5-node pyramid std::swap(elementDofs[2],elementDofs[3]); break; } // renumber corners to account for the explicitly given vertex // numbering in the file std::vector vertices(nVertices[elm_type]); for (int i=0; i, 3> v; for (int i=0; i* newBoundarySegment = (BoundarySegment*) new GmshReaderQuadraticBoundarySegment< 2, dimWorld >(v[0], v[1], v[2]); factory.insertBoundarySegment(vertices, std::shared_ptr >(newBoundarySegment)); break; } case 9 : { // 6-node triangle boundarysegment_insert(nodes, elementDofs, vertices); break; } default: { DUNE_THROW(Dune::IOError, "GmshReader does not support using element-type " << elm_type << " for boundary segments"); break; } } } } // count elements and boundary elements if (elementDim[elm_type] == dim) { element_index_to_physical_entity[element_count] = physical_entity; element_count++; } else { boundary_id_to_physical_entity[boundary_element_count] = physical_entity; boundary_element_count++; } } }; } // namespace Dune::Impl::Gmsh #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/gmsh4reader.hh000066400000000000000000000236551511655130300223560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_GMSH4READER_HH #define DUNE_GRID_IO_FILE_GMSH_GMSH4READER_HH #include #include #include #include #include #include #include // default GridCreator namespace Dune::Impl::Gmsh { /// File-Reader for GMsh unstructured .msh files /** * Reads .msh files version 4.x and constructs a grid from the cells stored in the file * Additionally, stored data can be read. * * \tparam Grid Type of the grid to construct. * \tparam GridCreator Policy type to control what to pass to a grid factory with * data given from the file. See \ref GridCreatorInterface * [ContinuousGridCreator] * \tparam SizeType Data type for indices in the .msh file. Should match in size * the `data_size` information in the header of the .msh file. * This type is used for the internal data in the caches. * [std::size_t] **/ template , class SizeType = std::size_t> class Gmsh4Reader : public FileReader > { // Sections visited during the file parsing enum class Sections { NO_SECTION = 0, MESH_FORMAT, PHYSICAL_NAMES, ENTITIES, PARTITIONED_ENTITIES, NODES, ELEMENTS, PERIODIC, GHOST_ELEMENTS, PARAMETRIZATION, NODE_DATA, ELEMENT_DATA, ELEMENT_NODE_DATA, INTERPOLATION_SCHEME }; using Entity = typename Grid::template Codim<0>::Entity; using GlobalCoordinate = typename Entity::Geometry::GlobalCoordinate; public: using size_type = SizeType; /// Constructor. Creates a new GridCreator with the passed factory template ::value,int> = 0> explicit Gmsh4Reader (Args&&... args) : creator_(std::make_shared(std::forward(args)...)) {} /// Constructor. Stores the references in a non-destroying shared_ptr explicit Gmsh4Reader (GridCreator& creator) : creator_(stackobject_to_shared_ptr(creator)) {} /// Constructor. Stores the shared_ptr explicit Gmsh4Reader (std::shared_ptr creator) : creator_(std::move(creator)) {} /// Read the grid from file with `filename` into the GridFactory stored in the GridCreator /** * \param filename The name of the input file * \param fillCreator If `false`, only fill internal data structures, * if `true`, also calls \ref fillGridCreator. [true] **/ void read (std::string const& filename, bool fillCreator = true); /// Advanced read methods /// @{ /// Read the grid from an input stream, referring to a .msh file, into the GridCreator /** * \param input A STL input stream to read the Gmsh file from. * \param fillCreator If `false`, only fill internal data structures, * if `true`, also calls \ref fillGridCreator. [true] **/ void readSerialFileFromStream (std::ifstream& input, bool fillCreator = true); /// Read the grid from and input stream, referring to a .pro file, into the GridCreator /** * \param input A STL input stream to read the Gmsh file from. * \param fillCreator If `false`, only fill internal data structures, * if `true`, also calls \ref fillGridCreator. [true] **/ void readParallelFileFromStream (std::ifstream& input, int rank, int size, bool fillCreator = true); /// Construct a grid using the GridCreator // NOTE: requires the internal data structures to be filled by an aforgoing call to read void fillGridCreator (bool insertPieces = true); /// @} /// Return the filenames of parallel pieces std::vector const& pieces () const { return pieces_; } #ifndef DOXYGEN /// Implementation of \ref FileReader interface static void fillFactoryImpl (GridFactory& factory, std::string const& filename) { Gmsh4Reader reader{factory}; reader.read(filename); } #endif private: template void readValueBinary(std::ifstream& input, T &v); void readMeshFormat (std::ifstream& input, double& version, int& file_type, int& data_size); void readPhysicalNames (std::ifstream& input); void readEntitiesAscii (std::ifstream& input); void readEntitiesBinary (std::ifstream& input); void readPartitionedEntitiesAscii (std::ifstream& input); void readPartitionedEntitiesBinary (std::ifstream& input); void readNodesAscii (std::ifstream& input); void readNodesBinary (std::ifstream& input); void readElementsAscii (std::ifstream& input); void readElementsBinary (std::ifstream& input); void readPeriodic (std::ifstream& input); void readGhostElements (std::ifstream& input); void readParametrization (std::ifstream& input); void readNodeData (std::ifstream& input); void readElementData (std::ifstream& input); void readElementNodeData (std::ifstream& input); void readInterpolationScheme (std::ifstream& input); // Test whether line belongs to section bool isSection (std::string line, std::string key, Sections current, Sections parent = Sections::NO_SECTION) const { bool result = line.substr(1, key.length()) == key; if (result && current != parent) DUNE_THROW(Dune::Exception , "<" << key << "> in wrong section." ); return result; } void readString(std::istream& /*stream*/, std::string& name) { DUNE_THROW(Dune::NotImplemented, "Method readString() not yet implemented"); name = ""; } // clear all vectors void clear () { pieces_.clear(); physicalNames_.clear(); points_.clear(); curves_.clear(); surfaces_.clear(); volumes_.clear(); numPartitions_ = 0; ghostEntities_.clear(); partitionedPoints_.clear(); partitionedCurves_.clear(); partitionedSurfaces_.clear(); partitionedVolumes_.clear(); numNodes_ = 0; minNodeTag_ = 0; maxNodeTag_ = 0; nodes_.clear(); numElements_ = 0; minElementTag_ = 0; maxElementTag_ = 0; elements_.clear(); periodic_.clear(); ghostElements_.clear(); parametrization_.clear(); nodeData_.clear(); elementData_.clear(); elementNodeData_.clear(); interpolationScheme_.clear(); } auto comm () const { return MPIHelper::getCommunication(); } private: // structures used to store data from file struct PhysicalNamesAttributes; struct PointAttributes; struct EntityAttributes; template struct PartitionedAttributes : public Attr { int parentDim; int parentTag; std::vector partitions; }; struct GhostAttributes; struct NodeAttributes; struct ElementAttributes; struct PeriodicAttributes; struct GhostElementAttributes {}; struct ParametrizationAttributes {}; struct NodeDataAttributes {}; struct ElementDataAttributes {}; struct ElementNodeDataAttributes {}; struct InterpolationSchemeAttributes {}; private: std::shared_ptr creator_ = nullptr; // swap will be true if a binary msh-file has different endianness as the user's system. bool swap = false; std::vector pieces_; // PhysicalNames section std::vector physicalNames_; // Entities section std::vector points_; std::vector curves_; std::vector surfaces_; std::vector volumes_; // PartitionedEntities section size_type numPartitions_ = 0; std::vector ghostEntities_; std::vector > partitionedPoints_; std::vector > partitionedCurves_; std::vector > partitionedSurfaces_; std::vector > partitionedVolumes_; size_type numNodes_ = 0; size_type minNodeTag_ = 0; size_type maxNodeTag_ = 0; std::vector nodes_; size_type numElements_ = 0; size_type minElementTag_ = 0; size_type maxElementTag_ = 0; std::vector elements_; std::vector periodic_; std::vector ghostElements_; std::vector parametrization_; std::vector nodeData_; std::vector elementData_; std::vector elementNodeData_; std::vector interpolationScheme_; /// Map the elementType number to number of nodes static std::map elementType_; // Associate a string with the corresponding Sections enum static std::map sections_; }; // deduction guides template Gmsh4Reader (GridFactory&) -> Gmsh4Reader >; template > Gmsh4Reader (GridCreator&) -> Gmsh4Reader; template > Gmsh4Reader (std::shared_ptr) -> Gmsh4Reader; } // end namespace Dune::Impl::Gmsh #include "gmsh4reader.impl.hh" #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/gmsh4reader.impl.hh000066400000000000000000001207211511655130300233060ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #include #include #include #include #include #include #include #include #include namespace Dune::Impl::Gmsh { template std::map Gmsh4Reader::elementType_ { {1, 2u}, // 2-node line. {2, 3u}, // 3-node triangle. {3, 4u}, // 4-node quadrangle. {4, 4u}, // 4-node tetrahedron. {5, 8u}, // 8-node hexahedron. {6, 6u}, // 6-node prism. {7, 5u}, // 5-node pyramid. {8, 3u}, // 3-node second order line. {9, 6u}, // 6-node second order triangle. {10, 9u}, // 9-node second order quadrangle. {11, 10u}, // 10-node second order tetrahedron. {12, 27u}, // 27-node second order hexahedron. {13, 18u}, // 18-node second order prism. {14, 14u}, // 14-node second order pyramid. {15, 1u}, // 1-node point. {16, 8u}, // 8-node second order quadrangle. {17, 20u}, // 20-node second order hexahedron. {18, 15u}, // 15-node second order prism. {19, 13u}, // 13-node second order pyramid. {20, 9u}, // 9-node third order incomplete triangle. {21, 10u}, // 10-node third order triangle. {22, 12u}, // 12-node fourth order incomplete triangle. {23, 15u}, // 15-node fourth order triangle. {24, 15u}, // 15-node fifth order incomplete triangle. {25, 21u}, // 21-node fifth order complete triangle. {26, 4u}, // 4-node third order line. {27, 5u}, // 5-node fourth order line. {28, 6u}, // 6-node fifth order line. {29, 20u}, // 20-node third order tetrahedron. {30, 35u}, // 35-node fourth order tetrahedron. {31, 56u}, // 56-node fifth order tetrahedron. {32, 22u}, // 22-node tetrahedron. {33, 28u}, // 28-node tetrahedron. //{34, ?}, // polygon. //{35, ?}, // polygon. {36, 16u}, // 16-node quadrangle. {37, 25u}, // 25-node quadrangle. {38, 36u}, // 36-node quadrangle. {39, 12u}, // 12-node quadrangle. {40, 16u}, // 16-node quadrangle (I). {41, 20u}, // 20-node quadrangle. {42, 28u}, // 28-node triangle. {43, 36u}, // 36-node triangle. {44, 45u}, // 45-node triangle. {45, 55u}, // 55-node triangle. {46, 66u}, // 66-node triangle. {47, 49u}, // 49-node quadrangle. {48, 64u}, // 64-node quadrangle. {49, 81u}, // 81-node quadrangle. {50, 100u}, // 100-node quadrangle. {51, 121u}, // 121-node quadrangle. {52, 18u}, // 18-node triangle. {53, 21u}, // 21-node triangle (I). {54, 24u}, // 24-node triangle. {55, 27u}, // 27-node triangle. {56, 30u}, // 30-node triangle. {57, 24u}, // 24-node quadrangle. {58, 28u}, // 28-node quadrangle. {59, 32u}, // 32-node quadrangle. {60, 36u}, // 36-node quadrangle (I). {61, 40u}, // 40-node quadrangle. {62, 7u}, // 7-node line. {63, 8u}, // 8-node line. {64, 9u}, // 9-node line. {65, 10u}, // 10-node line. {66, 11u}, // 11-node line. //{67, ?}, // line. //{68, ?}, // triangle. //{69, ?}, // polygon. //{70, ?}, // line. {71, 84u}, // 84-node tetrahedron. {72, 120u}, // 120-node tetrahedron. {73, 165u}, // 165-node tetrahedron. {74, 220u}, // 220-node tetrahedron. {75, 286u}, // 286-node tetrahedron. {79, 34u}, // 34-node incomplete tetrahedron. {80, 40u}, // 40-node incomplete tetrahedron. {81, 46u}, // 46-node incomplete tetrahedron. {82, 52u}, // 52-node incomplete tetrahedron. {83, 58u}, // 58-node incomplete tetrahedron. {84, 1u}, // 1-node line. {85, 1u}, // 1-node triangle. {86, 1u}, // 1-node quadrangle. {87, 1u}, // 1-node tetrahedron. {88, 1u}, // 1-node hexahedron. {89, 1u}, // 1-node prism. {90, 40u}, // 40-node prism. {91, 75u}, // 75-node prism. {92, 64u}, // 64-node third order hexahedron. {93, 125u}, // 125-node fourth order hexahedron. {94, 216u}, // 216-node hexahedron. {95, 343u}, // 343-node hexahedron. {96, 512u}, // 512-node hexahedron. {97, 729u}, // 729-node hexahedron. {98, 1000u},// 1000-node hexahedron. {99, 32u}, // 32-node incomplete hexahedron. {100, 44u}, // 44-node incomplete hexahedron. {101, 56u}, // 56-node incomplete hexahedron. {102, 68u}, // 68-node incomplete hexahedron. {103, 80u}, // 80-node incomplete hexahedron. {104, 92u}, // 92-node incomplete hexahedron. {105, 104u},// 104-node incomplete hexahedron. {106, 126u},// 126-node prism. {107, 196u},// 196-node prism. {108, 288u},// 288-node prism. {109, 405u},// 405-node prism. {110, 550u},// 550-node prism. {111, 24u}, // 24-node incomplete prism. {112, 33u}, // 33-node incomplete prism. {113, 42u}, // 42-node incomplete prism. {114, 51u}, // 51-node incomplete prism. {115, 60u}, // 60-node incomplete prism. {116, 69u}, // 69-node incomplete prism. {117, 78u}, // 78-node incomplete prism. {118, 30u}, // 30-node pyramid. {119, 55u}, // 55-node pyramid. {120, 91u}, // 91-node pyramid. {121, 140u},// 140-node pyramid. {122, 204u},// 204-node pyramid. {123, 285u},// 285-node pyramid. {124, 385u},// 385-node pyramid. {125, 21u}, // 21-node incomplete pyramid. {126, 29u}, // 29-node incomplete pyramid. {127, 37u}, // 37-node incomplete pyramid. {128, 45u}, // 45-node incomplete pyramid. {129, 53u}, // 53-node incomplete pyramid. {130, 61u}, // 61-node incomplete pyramid. {131, 69u}, // 69-node incomplete pyramid. {132, 1u}, // 1-node pyramid. //{133, ?}, // point. //{134, ?}, // line. //{135, ?}, // triangle. //{136, ?}, // tetrahedron. {137, 16u}, // 16-node tetrahedron. //{138, ?}, // triangle (mini). //{139, ?}, // tetrahedron (mini). {140, 4u}, // 4-node triangle. }; template std::map::Sections> Gmsh4Reader::sections_ { {"MeshFormat", Sections::MESH_FORMAT}, {"PhysicalNames", Sections::PHYSICAL_NAMES}, {"Entities", Sections::ENTITIES}, {"PartitionedEntities", Sections::PARTITIONED_ENTITIES}, {"Nodes", Sections::NODES}, {"Elements", Sections::ELEMENTS}, {"Periodic", Sections::PERIODIC}, {"GhostElements", Sections::GHOST_ELEMENTS}, {"Parametrization", Sections::PARAMETRIZATION}, {"NodeData", Sections::NODE_DATA}, {"ElementData", Sections::ELEMENT_DATA}, {"ElementNodeData", Sections::ELEMENT_NODE_DATA}, {"InterpolationScheme", Sections::INTERPOLATION_SCHEME} }; template struct Gmsh4Reader::PhysicalNamesAttributes { int dim; int tag; std::string name; }; template struct Gmsh4Reader::PointAttributes { int tag; std::array xyz; std::vector physicalTags; }; template struct Gmsh4Reader::EntityAttributes { int tag; std::array min_xyz; std::array max_xyz; std::vector physicalTags; std::vector boundingEntities; }; template struct Gmsh4Reader::GhostAttributes { int tag; int partition; }; template struct Gmsh4Reader::NodeAttributes { struct Node { size_type tag; std::array xyz; std::array uvw; }; int entityDim; int entityTag; int parametric; std::vector nodes; }; template struct Gmsh4Reader::ElementAttributes { struct Element { size_type tag; std::vector nodes; }; int entityDim; int entityTag; int elementType; std::vector elements; }; template struct Gmsh4Reader::PeriodicAttributes { struct Association { size_type tag; size_type tagMaster; }; int entityDim; int entityTag; int entityTagMaster; std::vector affine; std::vector correspondingNodes; }; template template void Gmsh4Reader::readValueBinary(std::ifstream& input, T &v) { const std::size_t size = sizeof(T); input.read(reinterpret_cast(&v), size); if (swap) { char* vBinary = reinterpret_cast(&v); for (std::size_t i=0; i void Gmsh4Reader::read (std::string const& filename, bool fillCreator) { const std::filesystem::path filePath(filename); // check whether file exists! if (!std::filesystem::exists(filePath)) DUNE_THROW(IOError, "File " << filename << " does not exist!"); std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); GMSH4_ASSERT(input.is_open()); const std::string ext = filePath.extension().string(); if (ext == ".msh") { // Get first line std::string line; std::getline(input, line); ltrim(line); // Read the mesh format section -- it must make up the first two lines GMSH4_ASSERT_MSG((line=="$MeshFormat"), "First line of file is not $MeshFormat!"); double version = 0.0; int file_type = 0; int data_size = 0; readMeshFormat(input, version, file_type, data_size); // Test whether version is supported GMSH4_ASSERT_MSG((version >= 4.0 && version < 5.0), "Can only read gmsh files versions >= 4.0 and < 5.0"); // Further sanity checking GMSH4_ASSERT_MSG(file_type == 0 || file_type == 1, "Invalid file-type: 0 for ASCII mode, 1 for binary mode"); GMSH4_ASSERT_MSG(data_size >= 4 && data_size <= 16, "Invalid data-size range: should be in {4, 16}"); GMSH4_ASSERT_MSG(file_type != 1 || data_size == sizeof(size_type), "Invalid data-size: must be sizeof(size_t)"); // Rewind the stream, so readSerialFileFromStream can start from the top again input.clear(); input.seekg(0, std::ios::beg); readSerialFileFromStream(input, fillCreator); pieces_.push_back(filename); } else if (ext == ".pro") { readParallelFileFromStream(input, comm().rank(), comm().size(), fillCreator); } else { DUNE_THROW(IOError, "File has unknown file-extension '" << ext << "'. Allowed are only '.msh' and '.pro'."); } } template void Gmsh4Reader::readSerialFileFromStream (std::ifstream& input, bool fillCreator) { clear(); // MeshFormat section int file_type = 0; int data_size = 0; Sections section = Sections::NO_SECTION; for (std::string line; std::getline(input, line); ) { ltrim(line); // detect current section for (auto const& s : sections_) { if (isSection(line, s.first, section)) { section = s.second; break; } else if (isSection(line, "End" + s.first, section, s.second)) { section = Sections::NO_SECTION; break; } } switch (section) { case Sections::MESH_FORMAT: { double version = 0.0; readMeshFormat(input, version, file_type, data_size); break; } case Sections::PHYSICAL_NAMES: readPhysicalNames(input); break; case Sections::ENTITIES: if(file_type == 0) readEntitiesAscii(input); else readEntitiesBinary(input); break; case Sections::PARTITIONED_ENTITIES: if(file_type == 0) readPartitionedEntitiesAscii(input); else readPartitionedEntitiesBinary(input); break; case Sections::NODES: if(file_type == 0) readNodesAscii(input); else readNodesBinary(input); break; case Sections::ELEMENTS: if(file_type == 0) readElementsAscii(input); else readElementsBinary(input); break; case Sections::PERIODIC: readPeriodic(input); break; case Sections::GHOST_ELEMENTS: readGhostElements(input); break; case Sections::PARAMETRIZATION: readParametrization(input); break; case Sections::NODE_DATA: readNodeData(input); break; case Sections::ELEMENT_DATA: readElementData(input); break; case Sections::ELEMENT_NODE_DATA: readElementNodeData(input); break; case Sections::INTERPOLATION_SCHEME: readInterpolationScheme(input); break; default: // do nothing break; } } if (fillCreator) fillGridCreator(); } template void Gmsh4Reader::readParallelFileFromStream (std::ifstream& input, int commRank, int commSize, bool fillCreator) { clear(); DUNE_THROW(Dune::NotImplemented, "Reading parallel .pro files not yet implemented."); if (fillCreator) fillGridCreator(); } template void Gmsh4Reader::readMeshFormat (std::ifstream& input, double& version, int& file_type, int& data_size) { std::string line; std::getline(input, line); std::istringstream stream(line); stream >> version >> file_type >> data_size; if (file_type != 0) { int one; input.read(reinterpret_cast(&one), sizeof(int)); if (one != 1) swap = true; std::getline(input, line); } } template void Gmsh4Reader::readPhysicalNames (std::ifstream& input) { int numPhysicalNames = 0; std::string line; std::getline(input, line); { std::istringstream stream(line); stream >> numPhysicalNames; } for (int i = 0; i < numPhysicalNames; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); PhysicalNamesAttributes attr; stream >> attr.dim >> attr.tag; readString(stream, attr.name); physicalNames_.push_back(attr); } } template void Gmsh4Reader::readEntitiesAscii (std::ifstream& input) { size_type numPoints = 0, numCurves = 0, numSurfaces = 0, numVolumes = 0; std::string line; std::getline(input, line); { std::istringstream stream(line); stream >> numPoints >> numCurves >> numSurfaces >> numVolumes; } // points points_.reserve(numPoints); for (size_type i = 0; i < numPoints; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); PointAttributes attr; stream >> attr.tag >> attr.xyz[0] >> attr.xyz[1] >> attr.xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; points_.push_back(attr); } GMSH4_ASSERT(points_.size() == numPoints); // curves curves_.reserve(numCurves); for (size_type i = 0; i < numCurves; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); EntityAttributes attr; stream >> attr.tag >> attr.min_xyz[0] >> attr.min_xyz[1] >> attr.min_xyz[2] >> attr.max_xyz[0] >> attr.max_xyz[1] >> attr.max_xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; size_type numBoundingPoints = 0; stream >> numBoundingPoints; attr.boundingEntities.resize(numBoundingPoints); for (size_type j = 0; j < numBoundingPoints; ++j) stream >> attr.boundingEntities[j]; curves_.push_back(attr); } GMSH4_ASSERT(curves_.size() == numCurves); // surfaces surfaces_.reserve(numSurfaces); for (size_type i = 0; i < numSurfaces; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); EntityAttributes attr; stream >> attr.tag >> attr.min_xyz[0] >> attr.min_xyz[1] >> attr.min_xyz[2] >> attr.max_xyz[0] >> attr.max_xyz[1] >> attr.max_xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; size_type numBoundingCurves = 0; stream >> numBoundingCurves; attr.boundingEntities.resize(numBoundingCurves); for (size_type j = 0; j < numBoundingCurves; ++j) stream >> attr.boundingEntities[j]; surfaces_.push_back(attr); } GMSH4_ASSERT(surfaces_.size() == numSurfaces); // volumes volumes_.reserve(numVolumes); for (size_type i = 0; i < numVolumes; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); EntityAttributes attr; stream >> attr.tag >> attr.min_xyz[0] >> attr.min_xyz[1] >> attr.min_xyz[2] >> attr.max_xyz[0] >> attr.max_xyz[1] >> attr.max_xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; size_type numBoundingSurfaces = 0; stream >> numBoundingSurfaces; attr.boundingEntities.resize(numBoundingSurfaces); for (size_type j = 0; j < numBoundingSurfaces; ++j) stream >> attr.boundingEntities[j]; volumes_.push_back(attr); } GMSH4_ASSERT(volumes_.size() == numVolumes); } template void Gmsh4Reader::readEntitiesBinary (std::ifstream& input) { size_type numPoints = 0, numCurves = 0, numSurfaces = 0, numVolumes = 0; readValueBinary(input, numPoints); readValueBinary(input, numCurves); readValueBinary(input, numSurfaces); readValueBinary(input, numVolumes); // points points_.reserve(numPoints); for (size_type i = 0; i < numPoints; ++i) { PointAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.xyz[0]); readValueBinary(input, attr.xyz[1]); readValueBinary(input, attr.xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); points_.push_back(attr); } GMSH4_ASSERT(points_.size() == numPoints); // curves curves_.reserve(numCurves); for (size_type i = 0; i < numCurves; ++i) { EntityAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.min_xyz[0]); readValueBinary(input, attr.min_xyz[1]); readValueBinary(input, attr.min_xyz[2]); readValueBinary(input, attr.max_xyz[0]); readValueBinary(input, attr.max_xyz[1]); readValueBinary(input, attr.max_xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); size_type numBoundingPoints = 0; readValueBinary(input, numBoundingPoints); attr.boundingEntities.resize(numBoundingPoints); for (size_type j = 0; j < numBoundingPoints; ++j) readValueBinary(input, attr.boundingEntities[j]); curves_.push_back(attr); } GMSH4_ASSERT(curves_.size() == numCurves); // surfaces surfaces_.reserve(numSurfaces); for (size_type i = 0; i < numSurfaces; ++i) { EntityAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.min_xyz[0]); readValueBinary(input, attr.min_xyz[1]); readValueBinary(input, attr.min_xyz[2]); readValueBinary(input, attr.max_xyz[0]); readValueBinary(input, attr.max_xyz[1]); readValueBinary(input, attr.max_xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); size_type numBoundingCurves = 0; readValueBinary(input, numBoundingCurves); attr.boundingEntities.resize(numBoundingCurves); for (size_type j = 0; j < numBoundingCurves; ++j) readValueBinary(input, attr.boundingEntities[j]); surfaces_.push_back(attr); } GMSH4_ASSERT(surfaces_.size() == numSurfaces); // volumes volumes_.reserve(numVolumes); for (size_type i = 0; i < numVolumes; ++i) { EntityAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.min_xyz[0]); readValueBinary(input, attr.min_xyz[1]); readValueBinary(input, attr.min_xyz[2]); readValueBinary(input, attr.max_xyz[0]); readValueBinary(input, attr.max_xyz[1]); readValueBinary(input, attr.max_xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); size_type numBoundingSurfaces = 0; readValueBinary(input, numBoundingSurfaces); attr.boundingEntities.resize(numBoundingSurfaces); for (size_type j = 0; j < numBoundingSurfaces; ++j) readValueBinary(input, attr.boundingEntities[j]); volumes_.push_back(attr); } GMSH4_ASSERT(volumes_.size() == numVolumes); std::string line; std::getline(input, line); } template void Gmsh4Reader::readPartitionedEntitiesAscii (std::ifstream& input) { size_type numGhostEntities = 0; size_type numPoints = 0, numCurves = 0, numSurfaces = 0, numVolumes = 0; std::string line; std::getline(input, line); { std::istringstream stream(line); stream >> numPartitions_; } std::getline(input, line); { std::istringstream stream(line); stream >> numGhostEntities; // ghost entities ghostEntities_.reserve(numGhostEntities); for (size_type i = 0; i < numGhostEntities; ++i) { GhostAttributes attr; stream >> attr.tag >> attr.partition; ghostEntities_.push_back(attr); } GMSH4_ASSERT(ghostEntities_.size() == numGhostEntities); } std::getline(input, line); { std::istringstream stream(line); stream >> numPoints >> numCurves >> numSurfaces >> numVolumes; } // points partitionedPoints_.reserve(numPoints); for (size_type i = 0; i < numPoints; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); PartitionedAttributes attr; stream >> attr.tag >> attr.parentDim >> attr.parentTag; size_type numPartitions = 0; stream >> numPartitions; attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) stream >> attr.partitions[j]; stream >> attr.xyz[0] >> attr.xyz[1] >> attr.xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; partitionedPoints_.push_back(attr); } GMSH4_ASSERT(partitionedPoints_.size() == numPoints); // curves partitionedCurves_.reserve(numCurves); for (size_type i = 0; i < numCurves; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); PartitionedAttributes attr; stream >> attr.tag >> attr.parentDim >> attr.parentTag; size_type numPartitions = 0; stream >> numPartitions; attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) stream >> attr.partitions[j]; stream >> attr.min_xyz[0] >> attr.min_xyz[1] >> attr.min_xyz[2] >> attr.max_xyz[0] >> attr.max_xyz[1] >> attr.max_xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; size_type numBoundingPoints = 0; stream >> numBoundingPoints; attr.boundingEntities.resize(numBoundingPoints); for (size_type j = 0; j < numBoundingPoints; ++j) stream >> attr.boundingEntities[j]; partitionedCurves_.push_back(attr); } GMSH4_ASSERT(partitionedCurves_.size() == numCurves); // surfaces partitionedSurfaces_.reserve(numSurfaces); for (size_type i = 0; i < numSurfaces; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); PartitionedAttributes attr; stream >> attr.tag >> attr.parentDim >> attr.parentTag; size_type numPartitions = 0; stream >> numPartitions; attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) stream >> attr.partitions[j]; stream >> attr.min_xyz[0] >> attr.min_xyz[1] >> attr.min_xyz[2] >> attr.max_xyz[0] >> attr.max_xyz[1] >> attr.max_xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; size_type numBoundingCurves = 0; stream >> numBoundingCurves; attr.boundingEntities.resize(numBoundingCurves); for (size_type j = 0; j < numBoundingCurves; ++j) stream >> attr.boundingEntities[j]; partitionedSurfaces_.push_back(attr); } GMSH4_ASSERT(partitionedSurfaces_.size() == numSurfaces); // volumes partitionedVolumes_.reserve(numVolumes); for (size_type i = 0; i < numVolumes; ++i) { if (!std::getline(input,line)) break; std::istringstream stream(line); PartitionedAttributes attr; stream >> attr.tag >> attr.parentDim >> attr.parentTag; size_type numPartitions = 0; stream >> numPartitions; attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) stream >> attr.partitions[j]; stream >> attr.min_xyz[0] >> attr.min_xyz[1] >> attr.min_xyz[2] >> attr.max_xyz[0] >> attr.max_xyz[1] >> attr.max_xyz[2]; size_type numPhysicalTags = 0; stream >> numPhysicalTags; attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) stream >> attr.physicalTags[j]; size_type numBoundingSurfaces = 0; stream >> numBoundingSurfaces; attr.boundingEntities.resize(numBoundingSurfaces); for (size_type j = 0; j < numBoundingSurfaces; ++j) stream >> attr.boundingEntities[j]; partitionedVolumes_.push_back(attr); } GMSH4_ASSERT(partitionedVolumes_.size() == numVolumes); } template void Gmsh4Reader::readPartitionedEntitiesBinary (std::ifstream& input) { size_type numGhostEntities = 0; size_type numPoints = 0, numCurves = 0, numSurfaces = 0, numVolumes = 0; readValueBinary(input, numPartitions_); // ghost entities readValueBinary(input, numGhostEntities); ghostEntities_.reserve(numGhostEntities); for (size_type i = 0; i < numGhostEntities; ++i) { GhostAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.partition); ghostEntities_.push_back(attr); } GMSH4_ASSERT(ghostEntities_.size() == numGhostEntities); readValueBinary(input, numPoints); readValueBinary(input, numCurves); readValueBinary(input, numSurfaces); readValueBinary(input, numVolumes); // points partitionedPoints_.reserve(numPoints); for (size_type i = 0; i < numPoints; ++i) { PartitionedAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.parentDim); readValueBinary(input, attr.parentTag); size_type numPartitions = 0; readValueBinary(input, numPartitions); attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) readValueBinary(input, attr.partitions[j]); readValueBinary(input, attr.xyz[0]); readValueBinary(input, attr.xyz[1]); readValueBinary(input, attr.xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); partitionedPoints_.push_back(attr); } GMSH4_ASSERT(partitionedPoints_.size() == numPoints); // curves partitionedCurves_.reserve(numCurves); for (size_type i = 0; i < numCurves; ++i) { PartitionedAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.parentDim); readValueBinary(input, attr.parentTag); size_type numPartitions = 0; readValueBinary(input, numPartitions); attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) readValueBinary(input, attr.partitions[j]); readValueBinary(input, attr.min_xyz[0]); readValueBinary(input, attr.min_xyz[1]); readValueBinary(input, attr.min_xyz[2]); readValueBinary(input, attr.max_xyz[0]); readValueBinary(input, attr.max_xyz[1]); readValueBinary(input, attr.max_xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); size_type numBoundingPoints = 0; readValueBinary(input, numBoundingPoints); attr.boundingEntities.resize(numBoundingPoints); for (size_type j = 0; j < numBoundingPoints; ++j) readValueBinary(input, attr.boundingEntities[j]); partitionedCurves_.push_back(attr); } GMSH4_ASSERT(partitionedCurves_.size() == numCurves); // surfaces partitionedSurfaces_.reserve(numSurfaces); for (size_type i = 0; i < numSurfaces; ++i) { PartitionedAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.parentDim); readValueBinary(input, attr.parentTag); size_type numPartitions = 0; readValueBinary(input, numPartitions); attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) readValueBinary(input, attr.partitions[j]); readValueBinary(input, attr.min_xyz[0]); readValueBinary(input, attr.min_xyz[1]); readValueBinary(input, attr.min_xyz[2]); readValueBinary(input, attr.max_xyz[0]); readValueBinary(input, attr.max_xyz[1]); readValueBinary(input, attr.max_xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); size_type numBoundingCurves = 0; readValueBinary(input, numBoundingCurves); attr.boundingEntities.resize(numBoundingCurves); for (size_type j = 0; j < numBoundingCurves; ++j) readValueBinary(input, attr.boundingEntities[j]); partitionedSurfaces_.push_back(attr); } GMSH4_ASSERT(partitionedSurfaces_.size() == numSurfaces); // volumes partitionedVolumes_.reserve(numVolumes); for (size_type i = 0; i < numVolumes; ++i) { PartitionedAttributes attr; readValueBinary(input, attr.tag); readValueBinary(input, attr.parentDim); readValueBinary(input, attr.parentTag); size_type numPartitions = 0; readValueBinary(input, numPartitions); attr.partitions.resize(numPartitions); for (size_type j = 0; j < numPartitions; ++j) readValueBinary(input, attr.partitions[j]); readValueBinary(input, attr.min_xyz[0]); readValueBinary(input, attr.min_xyz[1]); readValueBinary(input, attr.min_xyz[2]); readValueBinary(input, attr.max_xyz[0]); readValueBinary(input, attr.max_xyz[1]); readValueBinary(input, attr.max_xyz[2]); size_type numPhysicalTags = 0; readValueBinary(input, numPhysicalTags); attr.physicalTags.resize(numPhysicalTags); for (size_type j = 0; j < numPhysicalTags; ++j) readValueBinary(input, attr.physicalTags[j]); size_type numBoundingSurfaces = 0; readValueBinary(input, numBoundingSurfaces); attr.boundingEntities.resize(numBoundingSurfaces); for (size_type j = 0; j < numBoundingSurfaces; ++j) readValueBinary(input, attr.boundingEntities[j]); partitionedVolumes_.push_back(attr); } GMSH4_ASSERT(partitionedVolumes_.size() == numVolumes); std::string line; std::getline(input, line); } template void Gmsh4Reader::readNodesAscii (std::ifstream& input) { size_type numEntityBlocks = 0; std::string line; std::getline(input, line); { std::istringstream stream(line); stream >> numEntityBlocks >> numNodes_ >> minNodeTag_ >> maxNodeTag_; } nodes_.resize(numEntityBlocks); for (size_type i = 0; i < numEntityBlocks; ++i) { if (!std::getline(input,line)) break; auto& entityBlock = nodes_[i]; size_type numNodesInBlock = 0; std::istringstream stream(line); stream >> entityBlock.entityDim >> entityBlock.entityTag >> entityBlock.parametric >> numNodesInBlock; entityBlock.nodes.resize(numNodesInBlock); for (size_type j = 0; j < numNodesInBlock; ++j) { if (!std::getline(input,line)) break; char* end; entityBlock.nodes[j].tag = std::strtoul(line.data(), &end, 10); } for (size_type j = 0; j < numNodesInBlock; ++j) { if (!std::getline(input,line)) break; auto& node = entityBlock.nodes[j]; std::istringstream stream(line); stream >> node.xyz[0] >> node.xyz[1] >> node.xyz[2]; if (entityBlock.parametric && entityBlock.entityDim >= 1) stream >> node.uvw[0]; if (entityBlock.parametric && entityBlock.entityDim >= 2) stream >> node.uvw[1]; if (entityBlock.parametric && entityBlock.entityDim == 3) stream >> node.uvw[2]; } } } template void Gmsh4Reader::readNodesBinary (std::ifstream& input) { size_type numEntityBlocks = 0; readValueBinary(input, numEntityBlocks); readValueBinary(input, numNodes_); readValueBinary(input, minNodeTag_); readValueBinary(input, maxNodeTag_); nodes_.resize(numEntityBlocks); for (size_type i = 0; i < numEntityBlocks; ++i) { auto& entityBlock = nodes_[i]; size_type numNodesInBlock = 0; readValueBinary(input, entityBlock.entityDim); readValueBinary(input, entityBlock.entityTag); readValueBinary(input, entityBlock.parametric); readValueBinary(input, numNodesInBlock); entityBlock.nodes.resize(numNodesInBlock); for (size_type j = 0; j < numNodesInBlock; ++j) readValueBinary(input, entityBlock.nodes[j].tag); for (size_type j = 0; j < numNodesInBlock; ++j) { auto& node = entityBlock.nodes[j]; readValueBinary(input, node.xyz[0]); readValueBinary(input, node.xyz[1]); readValueBinary(input, node.xyz[2]); if (entityBlock.parametric && entityBlock.entityDim >= 1) readValueBinary(input, node.uvw[0]); if (entityBlock.parametric && entityBlock.entityDim >= 2) readValueBinary(input, node.uvw[1]); if (entityBlock.parametric && entityBlock.entityDim == 3) readValueBinary(input, node.uvw[2]); } } std::string line; std::getline(input, line); } template void Gmsh4Reader::readElementsAscii (std::ifstream& input) { size_type numEntityBlocks = 0; size_type numElementsInBlock = 0; std::string line; std::getline(input, line); { std::istringstream stream(line); stream >> numEntityBlocks >> numElements_ >> minElementTag_ >> maxElementTag_; } elements_.resize(numEntityBlocks); for (size_type i = 0; i < numEntityBlocks; ++i) { if (!std::getline(input,line)) break; auto& entityBlock = elements_[i]; std::istringstream stream(line); stream >> entityBlock.entityDim >> entityBlock.entityTag >> entityBlock.elementType >> numElementsInBlock; size_type numNodes = elementType_[entityBlock.elementType]; entityBlock.elements.resize(numElementsInBlock); for (size_type j = 0; j < numElementsInBlock; ++j) { if (!std::getline(input,line)) break; auto& element = entityBlock.elements[j]; std::istringstream stream(line); stream >> element.tag; element.nodes.resize(numNodes); for (size_type k = 0; k < numNodes; ++k) stream >> element.nodes[k]; } } } template void Gmsh4Reader::readElementsBinary (std::ifstream& input) { size_type numEntityBlocks = 0; size_type numElementsInBlock = 0; readValueBinary(input, numEntityBlocks); readValueBinary(input, numElements_); readValueBinary(input, minElementTag_); readValueBinary(input, maxElementTag_); elements_.resize(numEntityBlocks); for (size_type i = 0; i < numEntityBlocks; ++i) { auto& entityBlock = elements_[i]; readValueBinary(input, entityBlock.entityDim); readValueBinary(input, entityBlock.entityTag); readValueBinary(input, entityBlock.elementType); readValueBinary(input, numElementsInBlock); size_type numNodes = elementType_[entityBlock.elementType]; entityBlock.elements.resize(numElementsInBlock); for (size_type j = 0; j < numElementsInBlock; ++j) { auto& element = entityBlock.elements[j]; readValueBinary(input, element.tag); element.nodes.resize(numNodes); for (size_type k = 0; k < numNodes; ++k) readValueBinary(input, element.nodes[k]); } } std::string line; std::getline(input, line); } template void Gmsh4Reader::readPeriodic (std::ifstream& /*input*/) { std::cout << "WARNING: readPeriodic() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::readGhostElements (std::ifstream& /*input*/) { std::cout << "WARNING: readGhostElements() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::readParametrization (std::ifstream& /*input*/) { std::cout << "WARNING: readParametrization() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::readNodeData (std::ifstream& /*input*/) { std::cout << "WARNING: readNodeData() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::readElementData (std::ifstream& /*input*/) { std::cout << "WARNING: readElementData() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::readElementNodeData (std::ifstream& /*input*/) { std::cout << "WARNING: readElementNodeData() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::readInterpolationScheme (std::ifstream& /*input*/) { std::cout << "WARNING: readInterpolationScheme() is not yet implemented. Section will be ignored." << std::endl; } template void Gmsh4Reader::fillGridCreator (bool insertPieces) { if (!nodes_.empty()) creator_->insertVertices(numNodes_, {minNodeTag_, maxNodeTag_}, nodes_); if (!elements_.empty()) { std::set boundaryEntities; creator_->insertElements(numElements_, {minElementTag_, maxElementTag_}, elements_, boundaryEntities); } if (insertPieces) creator_->insertPieces(pieces_); } } // end namespace Dune::Impl::Gmsh dune-grid-2.11.0/dune/grid/io/file/gmsh/gridcreatorinterface.hh000066400000000000000000000070201511655130300243230ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_GRIDCREATORINTERFACE_HH #define DUNE_GRID_IO_FILE_GMSH_GRIDCREATORINTERFACE_HH #include #include #include #include #include namespace Dune::Impl::Gmsh { /// Base class for grid creators in a CRTP style. /** * Construct a grid from data read from Gmsh files. * * \tparam GridView Model of Dune::GridView * \tparam Derived Implementation of a concrete GridCreator. **/ template class GridCreatorInterface { public: using Grid = G; using GlobalCoordinate = typename Grid::template Codim<0>::Entity::Geometry::GlobalCoordinate; public: /// Constructor. Stores a reference to the passed GridFactory GridCreatorInterface (GridFactory& factory) : factory_(&factory) {} /// Insert all points as vertices into the factory template void insertVertices (std::size_t numNodes, std::pair nodeTagRange, std::vector const& entityBlocks) { asDerived().insertVerticesImpl(numNodes, nodeTagRange, entityBlocks); } /// Create elements based on type and connectivity description template void insertElements (std::size_t numElements, std::pair elementTagRange, std::vector const& entityBlocks, BoundaryEntities const& boundaryEntities) { asDerived().insertElementsImpl(numElements, elementTagRange, entityBlocks, boundaryEntities); } /// Insert part of a grid stored in file into factory void insertPieces (std::vector const& pieces) { asDerived().insertPiecesImpl(pieces); } /// Return the associated GridFactory GridFactory& factory () { return *factory_; } /// Return the associated (const) GridFactory GridFactory const& factory () const { return *factory_; } /// Return the mpi collective communicator auto comm () const { return MPIHelper::getCommunication(); } protected: // cast to derived type Derived& asDerived () { return static_cast(*this); } const Derived& asDerived () const { return static_cast(*this); } public: // default implementations template void insertVerticesImpl (std::size_t numNodes, std::pair nodeTagRange, std::vector const& entityBlocks) { /* do nothing */ } template void insertElementsImpl (std::size_t numElements, std::pair elementTagRange, std::vector const& entityBlocks, BoundaryEntities const& boundaryEntities) { /* do nothing */ } void insertPiecesImpl (std::vector const&) { /* do nothing */; } protected: GridFactory* factory_; }; } // end namespace Dune::Impl::Gmsh #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/gridcreators/000077500000000000000000000000001511655130300223055ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/gmsh/gridcreators/CMakeLists.txt000066400000000000000000000004531511655130300250470ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later install(FILES continuousgridcreator.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/gmsh/gridcreators) dune-grid-2.11.0/dune/grid/io/file/gmsh/gridcreators/continuousgridcreator.hh000066400000000000000000000075331511655130300272720ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_GRIDCREATORS_CONTINUOUSGRIDCREATOR_HH #define DUNE_GRID_IO_FILE_GMSH_GRIDCREATORS_CONTINUOUSGRIDCREATOR_HH #include #include #include #include #include #include #include #include #include #include namespace Dune::Impl::Gmsh { // Create a grid where the input points and connectivity is already // connected correctly. template struct ContinuousGridCreator : public GridCreatorInterface > { using Super = GridCreatorInterface >; using GlobalCoordinate = typename Super::GlobalCoordinate; using Nodes = std::vector; public: using Super::Super; using Super::factory; template void insertVerticesImpl (std::size_t numNodes, std::pair nodeTagRange, std::vector const& entityBlocks) { vertexMap_.resize(nodeTagRange.second - nodeTagRange.first + 1); vertexShift_ = nodeTagRange.first; nodes_.resize(numNodes); GlobalCoordinate p; size_t vertexIndex = 0; for (auto const& entityBlock : entityBlocks) { for (auto const& node : entityBlock.nodes) { for (std::size_t j = 0; j < p.size(); ++j) p[j] = node.xyz[j]; nodes_[vertexIndex] = p; vertexMap_[node.tag - vertexShift_] = vertexIndex++; } } } template void insertElementsImpl (std::size_t /*numElements*/, std::pair /*elementTagRange*/, std::vector const& entityBlocks, BoundaryEntities const& /*boundaryEntities*/) { std::vector connectivity; std::size_t cornerIndex = 0; std::vector cornerVertices(nodes_.size(), -1); for (auto const& entityBlock : entityBlocks) { if (entityBlock.entityDim < Grid::dimension-1) continue; auto type = gmshNumberToGeometryType(entityBlock.elementType); CellType cell{type}; if (entityBlock.entityDim == Grid::dimension) { //element auto refElem = referenceElement(cell.type()); connectivity.resize(refElem.size(Grid::dimension)); for (auto const& element : entityBlock.elements) { GMSH4_ASSERT(element.nodes.size() >= connectivity.size()); for (std::size_t j = 0; j < connectivity.size(); ++j) { auto index = vertexMap_[element.nodes[j] - vertexShift_]; auto& vertex = cornerVertices.at(index); if (vertex < 0) { factory().insertVertex(nodes_.at(index)); vertex = cornerIndex++; } connectivity[cell.gmshVertexToDuneVertex(j)] = vertex; } factory().insertElement(cell.type(), connectivity); } } } nodes_.clear(); } private: /// All point coordinates including the higher-order Lagrange points Nodes nodes_; std::vector vertexMap_; std::size_t vertexShift_ = 0; }; // deduction guides template ContinuousGridCreator(GridFactory&) -> ContinuousGridCreator; } // end namespace Dune::Impl::Gmsh #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/types.cc000066400000000000000000000175541511655130300213040ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #include #include namespace Dune::Impl::Gmsh { GeometryType gmshNumberToGeometryType (int elementType) { switch (elementType) { case 1: return GeometryTypes::line; case 2: return GeometryTypes::triangle; case 3: return GeometryTypes::quadrilateral; case 4: return GeometryTypes::tetrahedron; case 5: return GeometryTypes::hexahedron; case 6: return GeometryTypes::prism; case 7: return GeometryTypes::pyramid; case 8: return GeometryTypes::line; case 9: return GeometryTypes::triangle; case 10: return GeometryTypes::quadrilateral; case 11: return GeometryTypes::tetrahedron; case 12: return GeometryTypes::hexahedron; case 13: return GeometryTypes::prism; case 14: return GeometryTypes::pyramid; case 15: return GeometryTypes::vertex; case 16: return GeometryTypes::quadrilateral; case 17: return GeometryTypes::hexahedron; case 18: return GeometryTypes::prism; case 19: return GeometryTypes::pyramid; case 20: return GeometryTypes::triangle; case 21: return GeometryTypes::triangle; case 22: return GeometryTypes::triangle; case 23: return GeometryTypes::triangle; case 24: return GeometryTypes::triangle; case 25: return GeometryTypes::triangle; case 26: return GeometryTypes::line; case 27: return GeometryTypes::line; case 28: return GeometryTypes::line; case 29: return GeometryTypes::tetrahedron; case 30: return GeometryTypes::tetrahedron; case 31: return GeometryTypes::tetrahedron; case 32: return GeometryTypes::tetrahedron; case 33: return GeometryTypes::tetrahedron; //case 34: return polygon; //case 35: return polygon; case 36: return GeometryTypes::quadrilateral; case 37: return GeometryTypes::quadrilateral; case 38: return GeometryTypes::quadrilateral; case 39: return GeometryTypes::quadrilateral; case 40: return GeometryTypes::quadrilateral; case 41: return GeometryTypes::quadrilateral; case 42: return GeometryTypes::triangle; case 43: return GeometryTypes::triangle; case 44: return GeometryTypes::triangle; case 45: return GeometryTypes::triangle; case 46: return GeometryTypes::triangle; case 47: return GeometryTypes::quadrilateral; case 48: return GeometryTypes::quadrilateral; case 49: return GeometryTypes::quadrilateral; case 50: return GeometryTypes::quadrilateral; case 51: return GeometryTypes::quadrilateral; case 52: return GeometryTypes::triangle; case 53: return GeometryTypes::triangle; case 54: return GeometryTypes::triangle; case 55: return GeometryTypes::triangle; case 56: return GeometryTypes::triangle; case 57: return GeometryTypes::quadrilateral; case 58: return GeometryTypes::quadrilateral; case 59: return GeometryTypes::quadrilateral; case 60: return GeometryTypes::quadrilateral; case 61: return GeometryTypes::quadrilateral; case 62: return GeometryTypes::line; case 63: return GeometryTypes::line; case 64: return GeometryTypes::line; case 65: return GeometryTypes::line; case 66: return GeometryTypes::line; //case 67: return GeometryTypes::line; //case 68: return GeometryTypes::triangle; //case 69: return polygon; //case 70: return line; case 71: return GeometryTypes::tetrahedron; case 72: return GeometryTypes::tetrahedron; case 73: return GeometryTypes::tetrahedron; case 74: return GeometryTypes::tetrahedron; case 75: return GeometryTypes::tetrahedron; case 79: return GeometryTypes::tetrahedron; case 80: return GeometryTypes::tetrahedron; case 81: return GeometryTypes::tetrahedron; case 82: return GeometryTypes::tetrahedron; case 83: return GeometryTypes::tetrahedron; case 84: return GeometryTypes::line; case 85: return GeometryTypes::triangle; case 86: return GeometryTypes::quadrilateral; case 87: return GeometryTypes::tetrahedron; case 88: return GeometryTypes::hexahedron; case 89: return GeometryTypes::prism; case 90: return GeometryTypes::prism; case 91: return GeometryTypes::prism; case 92: return GeometryTypes::hexahedron; case 93: return GeometryTypes::hexahedron; case 94: return GeometryTypes::hexahedron; case 95: return GeometryTypes::hexahedron; case 96: return GeometryTypes::hexahedron; case 97: return GeometryTypes::hexahedron; case 98: return GeometryTypes::hexahedron; case 99: return GeometryTypes::hexahedron; case 100: return GeometryTypes::hexahedron; case 101: return GeometryTypes::hexahedron; case 102: return GeometryTypes::hexahedron; case 103: return GeometryTypes::hexahedron; case 104: return GeometryTypes::hexahedron; case 105: return GeometryTypes::hexahedron; case 106: return GeometryTypes::prism; case 107: return GeometryTypes::prism; case 108: return GeometryTypes::prism; case 109: return GeometryTypes::prism; case 110: return GeometryTypes::prism; case 111: return GeometryTypes::prism; case 112: return GeometryTypes::prism; case 113: return GeometryTypes::prism; case 114: return GeometryTypes::prism; case 115: return GeometryTypes::prism; case 116: return GeometryTypes::prism; case 117: return GeometryTypes::prism; case 118: return GeometryTypes::pyramid; case 119: return GeometryTypes::pyramid; case 120: return GeometryTypes::pyramid; case 121: return GeometryTypes::pyramid; case 122: return GeometryTypes::pyramid; case 123: return GeometryTypes::pyramid; case 124: return GeometryTypes::pyramid; case 125: return GeometryTypes::pyramid; case 126: return GeometryTypes::pyramid; case 127: return GeometryTypes::pyramid; case 128: return GeometryTypes::pyramid; case 129: return GeometryTypes::pyramid; case 130: return GeometryTypes::pyramid; case 131: return GeometryTypes::pyramid; case 132: return GeometryTypes::pyramid; //case 133: return GeometryTypes::vertex; //case 134: return GeometryTypes::line; //case 135: return GeometryTypes::triangle; //case 136: return GeometryTypes::tetrahedron; case 137: return GeometryTypes::tetrahedron; //case 138: return GeometryTypes::triangle; //case 139: return GeometryTypes::tetrahedron; case 140: return GeometryTypes::triangle; default: DUNE_THROW(RangeError, "CellType does not map to GeometryType."); std::abort(); } } CellType::CellType (GeometryType const& t) : identityPermutation_(true) { if (t.isVertex()) { type_ = GeometryTypes::vertex; permutation_ = {0}; } else if (t.isLine()) { type_ = GeometryTypes::line; permutation_ = {0,1}; } else if (t.isTriangle()) { type_ = GeometryTypes::triangle; permutation_ = {0,1,2}; } else if (t.isQuadrilateral()) { type_ = GeometryTypes::quadrilateral; permutation_ = {0,1,3,2}; identityPermutation_ = false; } else if (t.isTetrahedron()) { type_ = GeometryTypes::tetrahedron; permutation_ = {0,1,2,3}; } else if (t.isHexahedron()) { type_ = GeometryTypes::hexahedron; permutation_ = {0,1,3,2,4,5,7,6}; identityPermutation_ = false; } else if (t.isPrism()) { type_ = GeometryTypes::prism; permutation_ = {0,2,1,3,5,4}; identityPermutation_ = false; } else if (t.isPyramid()) { type_ = GeometryTypes::pyramid; permutation_ = {0,1,3,2,4}; identityPermutation_ = false; } else if (t.isNone() && t.dim() == 1) { type_ = GeometryTypes::line; permutation_ = {0,1}; } else { std::cerr << "Geometry Type not supported by Gmsh4!\n"; std::abort(); } } } // end namespace Dune::Impl::Gmsh dune-grid-2.11.0/dune/grid/io/file/gmsh/types.hh000066400000000000000000000023761511655130300213120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_TYPES_HH #define DUNE_GRID_IO_FILE_GMSH_TYPES_HH #include #include #include #include #include #include namespace Dune::Impl::Gmsh { /// Get the Dune GeometryType corresponding to a Gmsh entity number GeometryType gmshNumberToGeometryType (int elementType); /// Mapping of Dune geometry types to Gmsh cell types class CellType { public: CellType (GeometryType const& t); /// Return Gmsh Cell type GeometryType type () const { return type_; } /// Return the Dune local number of a cell's vertex given in Gmsh numbering int gmshVertexToDuneVertex (int idx) const { return permutation_[idx]; } /// Return true if Dune and Gmsh use the same vertex numbering for this element type bool identityPermutation () const { return identityPermutation_; } private: GeometryType type_; std::vector permutation_; bool identityPermutation_; }; } // end namespace Dune::Impl::Gmsh #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/utility/000077500000000000000000000000001511655130300213205ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/gmsh/utility/CMakeLists.txt000066400000000000000000000004601511655130300240600ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later install(FILES errors.hh string.hh version.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/gmsh/utility) dune-grid-2.11.0/dune/grid/io/file/gmsh/utility/errors.hh000066400000000000000000000021351511655130300231560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_UTILITY_ERRORS_HH #define DUNE_GRID_IO_FILE_GMSH_UTILITY_ERRORS_HH #include /** * \file * \brief Macro for wrapping error checks and throwing exceptions */ namespace Dune::Impl::Gmsh { class Gmsh4Error : public Exception {}; } /** * \brief check if condition \a cond holds; otherwise, throw a Gmsh4Error with a message. */ #define GMSH4_ASSERT_MSG(cond, text) \ do { \ if (!(cond)) \ DUNE_THROW(Dune::Impl::Gmsh::Gmsh4Error, text); \ } while (false) /** * \brief check if condition \a cond holds; otherwise, throw a Gmsh4Error. */ #define GMSH4_ASSERT(cond) \ do { \ if (!(cond)) \ DUNE_THROW(Dune::Impl::Gmsh::Gmsh4Error, #cond); \ } while (false) #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/utility/string.hh000066400000000000000000000026541511655130300231560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_UTILITY_STRING_HH #define DUNE_GRID_IO_FILE_GMSH_UTILITY_STRING_HH #include #include #include #include #include namespace Dune::Impl::Gmsh { /// trim a string from the left inline std::string& ltrim(std::string& str) { auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace(ch, std::locale::classic()); }); str.erase(str.begin() , it); return str; } /// trim a string from the right inline std::string& rtrim(std::string& str) { auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace(ch, std::locale::classic()); }); str.erase(it.base(), str.end()); return str; } /// trim a string from both sides inline std::string& trim(std::string& str) { return ltrim(rtrim(str)); } template void split(InputIter first, InputIter end, T const& t, Func f) { if (first == end) return; while (true) { InputIter found = std::find(first, end, t); f(first, found); if (found == end) break; first = ++found; } } } // end namespace Dune::Impl::Gmsh #endif dune-grid-2.11.0/dune/grid/io/file/gmsh/utility/version.hh000066400000000000000000000027301511655130300233300ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later #ifndef DUNE_GRID_IO_FILE_GMSH_UTILITY_VERSION_HH #define DUNE_GRID_IO_FILE_GMSH_UTILITY_VERSION_HH #include #include #include #include #include #include "string.hh" namespace Dune::Impl::Gmsh { /// Return a version tuple identifying the .msh file format version inline std::vector fileVersion(std::string filename) { std::ifstream file(filename, std::ios_base::in); std::string section; file >> section; if (section != "$MeshFormat") DUNE_THROW(Dune::IOError, "Invalid header of msh file."); std::string version; int file_type = -1; int data_size = -1; file >> version >> file_type >> data_size; if (std::stod(version) <= 0.0) DUNE_THROW(Dune::IOError, "Invalid version number in msh file."); if (file_type != 0 and file_type != 1) DUNE_THROW(Dune::IOError, "Invalid file-type: 0 for ASCII mode, 1 for binary mode."); if (data_size < 4 || data_size > 16) DUNE_THROW(Dune::IOError, "Invalid data-size range: should be in {4, 16}"); std::vector version_tuple; split(version.begin(), version.end(), '.', [&](auto first, auto last) { version_tuple.push_back(std::stoi(std::string{first,last})); }); return version_tuple; } } #endif dune-grid-2.11.0/dune/grid/io/file/gmshreader.hh000066400000000000000000000531611511655130300213270ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_GMSHREADER_HH #define DUNE_GRID_IO_FILE_GMSHREADER_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \ingroup Gmsh \{ */ /** \brief Options for read operation * * \deprecated The class is deprecated, because it looks like it should be used * in the GmshReader implementation, but it is not actually used anywhere. */ struct [[deprecated]] GmshReaderOptions { enum GeometryOrder { /** @brief edges are straight lines. */ firstOrder, /** @brief quadratic boundary approximation. */ secondOrder }; }; namespace Gmsh { /** \ingroup Gmsh \brief Options for the Gmsh mesh file reader \note Two or more options can be composed using the binary "|"-operator **/ enum class ReaderOptions { verbose = 1, insertBoundarySegments = 2, readElementData = 4, readBoundaryData = 8 }; //! composition operator for reader options constexpr ReaderOptions operator | (ReaderOptions a, ReaderOptions b) { return static_cast( static_cast(a) | static_cast(b) ); } //! query operator for reader options (is b set in a) constexpr bool operator & (ReaderOptions a, ReaderOptions b) { return static_cast(a) & static_cast(b); } } // end namespace Gmsh /** \brief The GmshReaderParser class has been renamed and moved to the Impl::Gmsh namespace * * With its new location, the class is now officially not part of the public interface. * Please complain if you disagree. * * \deprecated The name GmshReaderParser remains for backward compatibility, * and will be removed eventually. * * \since dune-grid 2.11 */ template struct [[deprecated("Public interface of the GmshReaderParser has been deprecated since dune 2.11.")]] GmshReaderParser : Impl::Gmsh::Gmsh2Parser { using Impl::Gmsh::Gmsh2Parser::Gmsh2Parser; }; /** \ingroup Gmsh \brief Read Gmsh mesh file Read a .msh (version 2) file generated using Gmsh and construct a grid using the grid factory interface. The file format used by gmsh can hold grids that are more general than the simplex grids that the gmsh grid generator is able to construct. We try to read as many grids as possible, as long as they are valid files. You can test this by checking whether gmsh will load the file and display its content. All grids in a gmsh file live in three-dimensional Euclidean space. If the world dimension of the grid type that you are reading the file into is less than three, the remaining coordinates are simply ignored. */ template class GmshReader { //! internal general reading method /** * This method does all the highlevel steering of the reader: * - it will register the GmshReader boundary segment implementation with * the factory * - it will ensure the reader is called on all ranks (debug mode only) * - proceed to construct a parser (rank 0 only) * - use the parser to read the grid into the factory (rank 0 only) * - move entity and boundary data from the parser into the data vector * arguments, or clear the data vector arguments, depending on rank * * \note That the parser always reads the data vectors from the files. * However, if insertBoundarySegments is false, no boundary segments * are inserted into the factory, and thus there will be no correct * indexing of the boundarySegmentToPhysicalEntity vector possible. * For this reason, this method is not exposed to the user, and the * interface methods are responsible to ensure that * boundarySegmentToPhysicalEntity is discarded if boundary segments * are not inserted. */ static void doRead(Dune::GridFactory &factory, const std::string &fileName, std::vector& boundarySegmentToPhysicalEntity, std::vector& elementToPhysicalEntity, bool verbose, bool insertBoundarySegments) { // register boundary segment to boundary segment factory for possible load balancing // this needs to be done on all cores since the type might not be known otherwise Impl::Gmsh::GmshReaderQuadraticBoundarySegment< Grid::dimension, Grid::dimensionworld >::registerFactory(); #ifndef NDEBUG // check that this method is called on all cores factory.comm().barrier(); #endif // create parse object and read grid on process 0 if (factory.comm().rank() == 0) { Impl::Gmsh::Gmsh2Parser parser(factory,verbose,insertBoundarySegments); parser.read(fileName); boundarySegmentToPhysicalEntity = std::move(parser.boundaryIdMap()); elementToPhysicalEntity = std::move(parser.elementIndexMap()); } else { boundarySegmentToPhysicalEntity = {}; elementToPhysicalEntity = {}; } } //! pass a discarded lvalue argument to a function /** * This method is intended to be used in function calls that require * lvalue arguments, when the caller just wants to pass in temporary * variable that is immediately discarded after the return of the * function. It expects an rvalue argument, that is turned into an * lvalue. For instance: * ```c++ * doRead(factory, fileName, discarded(std::vector{}), * discarded(std::vector{})); * ``` * Here, the vectors are constructed as rvalues, passed through * `discarded()` which turns them into lvalues, so they can be arguments * to `doRead()`. `doRead()` will fill them with some data, and they * will be destroyed at the end of the full-expression containing the * function call. * * \note It is very likely an error to use this outside a function call * argument. */ template static T &discarded(T &&value) { return static_cast(value); } struct DataArg { std::vector *data_ = nullptr; DataArg(std::vector &data) : data_(&data) {} DataArg(const decltype(std::ignore)&) {} DataArg() = default; }; struct DataFlagArg : DataArg { bool flag_ = false; using DataArg::DataArg; DataFlagArg(bool flag) : flag_(flag) {} }; public: typedef GridType Grid; /** \todo doc me */ static std::unique_ptr read (const std::string& fileName, bool verbose = true, bool insertBoundarySegments=true) { // make a grid factory Dune::GridFactory factory; read(factory, fileName, verbose, insertBoundarySegments); return factory.createGrid(); } /** * \brief Read Gmsh file, possibly with data * \param fileName Name of the file to read from. * \param boundarySegmentToPhysicalEntity Container to fill with boundary segment * physical entity data (if insertBoundarySegments=true) * \param elementToPhysicalEntity Container to fill with element physical entity data * \param verbose Whether to be chatty * \param insertBoundarySegments Whether boundary segments are inserted into the factory * * \note When insertBoundarySegments=false there is no way to correctly use the values returned * in boundarySegmentToPhysicalEntity. Make sure to set insertBoundarySegments=true if you * intent to do this. An alternative is to use the other overloads which provide compile-time * checking of the provided parameter combinations. * * \warning The following does not work when the file is in Version 4 Gmsh format: * Filling the boundarySegmentToPhysicalEntity and elementToPhysicalEntity fields, * controlling verbosity, and inserting boundary segments. * * \todo This interface is error-prone and should not be exposed to the user. However, the * compile-time overloads may not provide sufficient runtime flexibility in all cases. * Therefore this interface is kept until a better interface can be agreed on. * See https://gitlab.dune-project.org/core/dune-grid/-/issues/107 */ static std::unique_ptr read (const std::string& fileName, std::vector& boundarySegmentToPhysicalEntity, std::vector& elementToPhysicalEntity, bool verbose = true, bool insertBoundarySegments=true) { // make a grid factory Dune::GridFactory factory; if (Impl::Gmsh::fileVersion(fileName)[0]==4) { Impl::Gmsh::Gmsh4Reader::fillFactory(factory, fileName); return factory.createGrid(); } doRead( factory, fileName, boundarySegmentToPhysicalEntity, elementToPhysicalEntity, verbose, insertBoundarySegments ); return factory.createGrid(); } /** \brief Read Gmsh grid file into a `GridFactory` object * * \warning Controlling verbosity, and inserting boundary segments does not work * when the file is in Version 4 Gmsh format. */ static void read (Dune::GridFactory& factory, const std::string& fileName, bool verbose = true, bool insertBoundarySegments=true) { if (Impl::Gmsh::fileVersion(fileName)[0]==4) { Impl::Gmsh::Gmsh4Reader::fillFactory(factory, fileName); return; } doRead( factory, fileName, discarded(std::vector{}), discarded(std::vector{}), verbose, insertBoundarySegments ); } //! read Gmsh file, possibly with data /** * \param factory The GridFactory to fill. * \param fileName Name of the file to read from. * \param boundarySegmentData Container to fill with boundary segment * physical entity data, or `std::ignore`, or a * `bool` value. Boundary segments are * inserted when a container or `true` is * given, otherwise they are not inserted. * \param elementData Container to fill with element physical * entity data, or `std::ignore`. * \param verbose Whether to be chatty. * * Containers to fill with data must be `std::vector` lvalues. * Element data is indexed by the insertion index of the element, * boundarySegment data is indexed by the insertion index of the boundary * intersection. These can be obtained from the `factory`, and are lost * once the grid gets modified (refined or load-balanced). * * \warning The following does not work when the file is in Version 4 Gmsh format: * Filling the boundarySegmentData and elementData fields, and controlling verbosity. * * \note At the moment the data containers are still filled internally, * even if they are ignored. So not having to pass them is more of * a convenience feature and less of an optimization. This may * however change in the future. */ static void read (Dune::GridFactory &factory, const std::string &fileName, DataFlagArg boundarySegmentData, DataArg elementData, bool verbose=true) { if (Impl::Gmsh::fileVersion(fileName)[0]==4) { Impl::Gmsh::Gmsh4Reader::fillFactory(factory, fileName); return; } doRead( factory, fileName, boundarySegmentData.data_ ? *boundarySegmentData.data_ : discarded(std::vector{}), elementData.data_ ? *elementData.data_ : discarded(std::vector{}), verbose, boundarySegmentData.flag_ || boundarySegmentData.data_ ); } /** * \brief Read Gmsh file, possibly with data * \param factory The GridFactory to fill. * \param fileName Name of the file to read from. * \param boundarySegmentToPhysicalEntity Container to fill with boundary segment * physical entity data (if insertBoundarySegments=true) * \param elementToPhysicalEntity Container to fill with element physical entity data * \param verbose Whether to be chatty * \param insertBoundarySegments Whether boundary segments are inserted into the factory * * \note When insertBoundarySegments=false there is no way to correctly use the values returned * in boundarySegmentToPhysicalEntity. Make sure to set insertBoundarySegments=true if you * intent to do this. An alternative is to use the other overloads which provide compile-time * checking of the provided parameter combinations. * * \warning The following does not work when the file is in Version 4 Gmsh format: * Filling the boundarySegmentToPhysicalEntity and elementToPhysicalEntity fields, * controlling verbosity, and inserting boundary segments. * * \todo This interface is error-prone and should not be exposed to the user. However, the * compile-time overloads may not provide sufficient runtime flexibility in all cases. * Therefore this interface is kept until a better interface can be agreed on. * See https://gitlab.dune-project.org/core/dune-grid/-/issues/107 */ static void read (Dune::GridFactory& factory, const std::string& fileName, std::vector& boundarySegmentToPhysicalEntity, std::vector& elementToPhysicalEntity, bool verbose, bool insertBoundarySegments) { if (Impl::Gmsh::fileVersion(fileName)[0]==4) { Impl::Gmsh::Gmsh4Reader::fillFactory(factory, fileName); return; } doRead( factory, fileName, boundarySegmentToPhysicalEntity, elementToPhysicalEntity, verbose, insertBoundarySegments ); } //! Dynamic Gmsh reader interface //\{ using Opts = Gmsh::ReaderOptions; static constexpr Opts defaultOpts = Opts::verbose | Opts::insertBoundarySegments | Opts::readElementData | Opts::readBoundaryData; //! Construct a Gmsh reader object (alternatively use one of the static member functions) /** * \brief Construct a Gmsh reader object from a file name * \param fileName Name of the file to read from. * \param options Options of the type `Dune::Gmsh::ReaderOptions` * * To pass several options, combine them with the |-operator like this * \code using Opt = Dune::Gmsh::ReaderOptions; auto reader = Dune::GmshReader("grid.msh", Opt::verbose | Opt::readElementData) \endcode * * Per default the reader has enabled the following options - Dune::Gmsh::ReaderOptions::verbose - Dune::Gmsh::ReaderOptions::insertBoundarySegments - Dune::Gmsh::ReaderOptions::readBoundaryData - Dune::Gmsh::ReaderOptions::readElementData * * Passing any option to the interface will overwrite these defaults. * * A Dune grid object can be obtained via the `createGrid()` member * * \warning All options are automatically `false` when the file is in Version 4 Gmsh format. */ GmshReader(const std::string& fileName, Gmsh::ReaderOptions options = defaultOpts) { gridFactory_ = std::make_unique>(); readGridFile(fileName, *gridFactory_, options); } /** * \brief Construct a Gmsh reader object from a file name and a grid factory * \param fileName Name of the file to read from. * \param options Options of the type `Dune::Gmsh::ReaderOptions` * * Use this constructor if you need access to the grid factory after the grid * has been read, e.g., for obtaining boundary segment insertion indices. */ GmshReader(const std::string& fileName, GridFactory& factory, Gmsh::ReaderOptions options = defaultOpts) { readGridFile(fileName, factory, options); } //! Access element data (maps element index to Gmsh physical entity) const std::vector& elementData () const { checkElementData(); return elementIndexToGmshPhysicalEntity_; } //! Access boundary data (maps boundary segment index to Gmsh physical entity) const std::vector& boundaryData () const { checkBoundaryData(); return boundarySegmentIndexToGmshPhysicalEntity_; } /** * \brief If element data is available * \note This is false if no such data was requested */ bool hasElementData () const { return hasElementData_ && !extractedElementData_; } /** * \brief If boundary data is available * \note This is false if no such data was requested */ bool hasBoundaryData () const { return hasBoundaryData_ && !extractedBoundaryData_; } //! Erase element data from reader and return the data std::vector extractElementData () { checkElementData(); extractedElementData_ = true; return std::move(elementIndexToGmshPhysicalEntity_); } //! Erase boundary data from reader and return the data std::vector extractBoundaryData () { checkBoundaryData(); extractedBoundaryData_ = true; return std::move(boundarySegmentIndexToGmshPhysicalEntity_); } //! Create the grid std::unique_ptr createGrid () { if (!gridFactory_) DUNE_THROW(Dune::InvalidStateException, "This GmshReader has been constructed with a Dune::GridFactory. " << "This grid factory has been filled with all information to create a grid. " << "Please use this factory to create the grid by calling factory.createGrid(). " << "Alternatively use the constructor without passing the factory in combination with this member function." ); return gridFactory_->createGrid(); } //\} private: void checkElementData () const { if (!hasElementData_) DUNE_THROW(Dune::InvalidStateException, "This GmshReader has been constructed without the option 'readElementData'. " << "Please enable reading element data by passing the option 'Gmsh::ReaderOpts::readElementData' " << "to the constructor of this class." ); if (extractedElementData_) DUNE_THROW(Dune::InvalidStateException, "The element data has already been extracted from this GmshReader " << "via a function call to reader.extractElementData(). Use the extracted data or " << "read the grid data from file again by constructing a new reader." ); } void checkBoundaryData () const { if (!hasBoundaryData_) DUNE_THROW(Dune::InvalidStateException, "This GmshReader has been constructed without the option 'readBoundaryData'. " << "Please enable reading boundary data by passing the option 'Gmsh::ReaderOpts::readBoundaryData' " << "to the constructor of this class." ); if (extractedBoundaryData_) DUNE_THROW(Dune::InvalidStateException, "The boundary data has already been extracted from this GmshReader " << "via a function call to reader.extractBoundaryData(). Use the extracted data or " << "read the grid data from file again by constructing a new reader." ); } void readGridFile (const std::string& fileName, GridFactory& factory, Gmsh::ReaderOptions options) { if (Impl::Gmsh::fileVersion(fileName)[0]==4) { Impl::Gmsh::Gmsh4Reader::fillFactory(factory, fileName); return; } const bool verbose = options & Opts::verbose; const bool insertBoundarySegments = options & Opts::insertBoundarySegments; const bool readBoundaryData = options & Opts::readBoundaryData; const bool readElementData = options & Opts::readElementData; doRead( factory, fileName, boundarySegmentIndexToGmshPhysicalEntity_, elementIndexToGmshPhysicalEntity_, verbose, readBoundaryData || insertBoundarySegments ); // clear unwanted data if (!readBoundaryData) boundarySegmentIndexToGmshPhysicalEntity_ = std::vector{}; if (!readElementData) elementIndexToGmshPhysicalEntity_ = std::vector{}; hasElementData_ = readElementData; hasBoundaryData_ = readBoundaryData; } std::unique_ptr> gridFactory_; std::vector elementIndexToGmshPhysicalEntity_; std::vector boundarySegmentIndexToGmshPhysicalEntity_; bool hasElementData_ = false; bool hasBoundaryData_ = false; // for better error messages, we keep track of these separately bool extractedElementData_ = false; bool extractedBoundaryData_ = false; }; /** \} */ } // namespace Dune #endif dune-grid-2.11.0/dune/grid/io/file/gmshwriter.hh000066400000000000000000000236501511655130300214010ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_GRID_IO_FILE_GMSHWRITER_HH #define DUNE_GRID_IO_FILE_GMSHWRITER_HH #include #include #include #include #include #include #include #include #include #include namespace Dune { /** \ingroup Gmsh \brief Write Gmsh mesh file Write a grid using the given GridView as an ASCII Gmsh file of version 2.0. If the grid contains an element type not supported by gmsh an IOError exception is thrown. All grids in a gmsh file live in three-dimensional Euclidean space. If the world dimension of the grid type that you are writing is less than three, the remaining coordinates are set to zero. */ template class GmshWriter { private: const GridView gv; int precision; static const unsigned int dim = GridView::dimension; static const unsigned int dimWorld = GridView::dimensionworld; static_assert( (dimWorld <= 3), "GmshWriter requires dimWorld <= 3." ); /** \brief Returns index of i-th vertex of an element, plus 1 (for gmsh numbering) */ template std::size_t nodeIndexFromEntity(const Entity& entity, int i) const { return gv.indexSet().subIndex(entity, i, dim)+1; } /** \brief Translate GeometryType to corresponding Gmsh element type number * \throws IOError if there is no equivalent type in Gmsh */ static std::size_t translateDuneToGmshType(const GeometryType& type) { std::size_t element_type; if (type.isLine()) element_type = 1; else if (type.isTriangle()) element_type = 2; else if (type.isQuadrilateral()) element_type = 3; else if (type.isTetrahedron()) element_type = 4; else if (type.isHexahedron()) element_type = 5; else if (type.isPrism()) element_type = 6; else if (type.isPyramid()) element_type = 7; else if (type.isVertex()) element_type = 15; else DUNE_THROW(Dune::IOError, "GeometryType " << type << " is not supported by gmsh."); return element_type; } /** \brief Writes all the elements of a grid line by line * * Each line has the format * element-number element-type number-of-tags node-number-list * Counting of the element numbers starts by "1". * * If `physicalEntities` is not empty, each element has a tag representing its physical id. * * If `physicalBoundaries` is not empty, also the boundaries are written to the file with * the corresponding physical value. * * The physicalBoundaries vector need to be sorted according to the intersection * boundary segment index. */ void outputElements(std::ofstream& file, const std::vector& physicalEntities, const std::vector& physicalBoundaries) const { MultipleCodimMultipleGeomTypeMapper elementMapper(gv, mcmgElementLayout()); std::size_t counter(1); for (const auto& entity : elements(gv)) { // Check whether the type is compatible. If not, close file and rethrow exception. try { std::size_t element_type = translateDuneToGmshType(entity.type()); file << counter << " " << element_type; // If present, set the first tag to the physical entity if (!physicalEntities.empty()) file << " " << 1 << " " << physicalEntities[elementMapper.index(entity)]; else file << " " << 0; // "0" for "I do not use any tags." // Output list of nodes. // 3, 5 and 7 got different vertex numbering compared to Dune if (3 == element_type) file << " " << nodeIndexFromEntity(entity, 0) << " " << nodeIndexFromEntity(entity, 1) << " " << nodeIndexFromEntity(entity, 3) << " " << nodeIndexFromEntity(entity, 2); else if (5 == element_type) file << " " << nodeIndexFromEntity(entity, 0) << " " << nodeIndexFromEntity(entity, 1) << " " << nodeIndexFromEntity(entity, 3) << " " << nodeIndexFromEntity(entity, 2) << " " << nodeIndexFromEntity(entity, 4) << " " << nodeIndexFromEntity(entity, 5) << " " << nodeIndexFromEntity(entity, 7) << " " << nodeIndexFromEntity(entity, 6); else if (7 == element_type) file << " " << nodeIndexFromEntity(entity, 0) << " " << nodeIndexFromEntity(entity, 1) << " " << nodeIndexFromEntity(entity, 3) << " " << nodeIndexFromEntity(entity, 2) << " " << nodeIndexFromEntity(entity, 4); else { for (int k = 0; k < entity.geometry().corners(); ++k) file << " " << nodeIndexFromEntity(entity, k); } ++counter; file << std::endl; // Write boundaries if (!physicalBoundaries.empty()) { auto refElement = referenceElement(entity.type()); for(const auto& intersection : intersections(gv, entity)) { if(intersection.boundary()) { const auto faceLocalIndex(intersection.indexInInside()); file << counter << " " << translateDuneToGmshType(intersection.type()) << " " << 1 << " " << physicalBoundaries[intersection.boundarySegmentIndex()]; for (int k = 0; k < intersection.geometry().corners(); ++k) { const auto vtxLocalIndex(refElement.subEntity(faceLocalIndex, 1, k, dim)); file << " " << nodeIndexFromEntity(entity, vtxLocalIndex); } ++counter; file << std::endl; } } } } catch(Exception& e) { file.close(); throw; } } } /** \brief Writes all the vertices of a grid line by line * * Each line has the format * node-number x-coord y-coord z-coord * The node-numbers will most certainly not have the arrangement "1, 2, 3, ...". */ void outputNodes(std::ofstream& file) const { for (const auto& vertex : vertices(gv)) { const auto globalCoord = vertex.geometry().center(); const auto nodeIndex = gv.indexSet().index(vertex)+1; // Start counting indices by "1". if (1 == dimWorld) file << nodeIndex << " " << globalCoord[0] << " " << 0 << " " << 0 << std::endl; else if (2 == dimWorld) file << nodeIndex << " " << globalCoord[0] << " " << globalCoord[1] << " " << 0 << std::endl; else // (3 == dimWorld) file << nodeIndex << " " << globalCoord[0] << " " << globalCoord[1] << " " << globalCoord[2] << std::endl; } } public: /** * \brief Constructor expecting GridView of Grid to be written. * \param gridView GridView that will be written. * \param numDigits Number of digits to use. */ GmshWriter(const GridView& gridView, int numDigits=6) : gv(gridView), precision(numDigits) {} /** * \brief Set the number of digits to be used when writing the vertices. By default is 6. * \brief numDigits Number of digits to use. */ void setPrecision(int numDigits) { precision = numDigits; } /** * \brief Write given grid in Gmsh 2.0 compatible ASCII file. * \param fileName Path of file. This method does not attach a ".msh"-extension by itself. * \param physicalEntities Physical entities for each element (optional). * \param physicalBoundaries Physical boundaries (optional). * * Opens the file with given name and path, stores the element data of the grid * and closes the file when done. * * If the optional parameter `physicalEntities` is provided, each element is written with * a tag representing its physical id. * * If the optional parameter `physicalBoundaries` is provided, also the boundaries * are written on file with the corresponding physical value. * * The physicalBoundaries vector need to be sorted according to the intersection boundary * segment index. * * Throws an IOError if file could not be opened or an unsupported element type is * encountered. */ void write(const std::string& fileName, const std::vector& physicalEntities=std::vector(), const std::vector& physicalBoundaries=std::vector()) const { // Open file std::ofstream file(fileName.c_str()); if (!file.is_open()) DUNE_THROW(Dune::IOError, "Could not open " << fileName << " with write access."); // Set precision file << std::setprecision( precision ); // Output Header file << "$MeshFormat" << std::endl << "2.0 0 " << sizeof(double) << std::endl // "2.0" for "version 2.0", "0" for ASCII << "$EndMeshFormat" << std::endl; // Output Nodes file << "$Nodes" << std::endl << gv.size(dim) << std::endl; outputNodes(file); file << "$EndNodes" << std::endl; // Output Elements; int boundariesSize(0); if(!physicalBoundaries.empty()) for(const auto& entity : elements(gv)) for(const auto& intersection : intersections(gv, entity)) if(intersection.boundary()) ++boundariesSize; file << "$Elements" << std::endl << gv.size(0) + boundariesSize<< std::endl; outputElements(file, physicalEntities, physicalBoundaries); file << "$EndElements" << std::endl; } }; } // namespace Dune #endif // DUNE_GRID_IO_FILE_GMSHWRITER_HH dune-grid-2.11.0/dune/grid/io/file/gnuplot.hh000066400000000000000000000065031511655130300206740ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_IO_GNUPLOT_HH #define DUNE_IO_GNUPLOT_HH /** @file @author Christian Engwer @brief Provides gnuplot output for 1D Grids */ #include #include #include #include #include #include namespace Dune { /** \brief Writer for 1D grids in gnuplot format \ingroup Gnuplot \tparam GridType the grid \tparam GridView Level- or LeafGridView */ template class GnuplotWriter { typedef typename GridView::Grid::ctype ctype; constexpr static int dimworld = GridView::dimensionworld; public: GnuplotWriter (const GridView & gv) : _is(gv.indexSet()), _gv(gv) { static_assert(dimworld==1 || dimworld==2, "GnuPlot export only works for worlddim==1 and worlddim==2"); // allocate _data buffer _data.resize(_is.size(0)*2); } /** \brief Add cell data \param data An ISTL compliant vector type \param name associated with the data */ template void addCellData(const DataContainer& data, const std::string & name) { if (dimworld!=1) DUNE_THROW(IOError, "Gnuplot cell data writing is only supported for grids in a 1d world!"); addData(cellData, data, name); } /** \brief Add vertex data \param data An ISTL compliant vector type \param name associated with the data */ template void addVertexData(const DataContainer& data, const std::string & name) { addData(vertexData, data, name); } /** \brief Write Gnuplot file to disk \param filename Name of the file to write to */ void write(const std::string& filename) const; private: enum DataType { vertexData, cellData }; const typename GridView::IndexSet & _is; const GridView _gv; std::vector< std::vector< float > > _data; std::vector< std::string > _names; template void addData(DataType t, const DataContainer& data, const std::string & name); void writeRow(std::ostream & file, const FieldVector& position, const std::vector & data) const; }; /** \brief GnuplotWriter on the leaf grid \ingroup Gnuplot */ template class LeafGnuplotWriter : public GnuplotWriter { public: /** \brief Construct a Gnuplot writer for the leaf level of a given grid */ LeafGnuplotWriter (const G& grid) : GnuplotWriter(grid.leafGridView()) {} }; /** \brief GnuplotWriter on a given level grid \ingroup Gnuplot */ template class LevelGnuplotWriter : public GnuplotWriter { public: /** \brief Construct a Gnuplot writer for a certain level of a given grid */ LevelGnuplotWriter (const G& grid, int level) : GnuplotWriter(grid.levelGridView(level)) {} }; } #include "gnuplot/gnuplot.cc" #endif // DUNE_IO_GNUPLOT_HH dune-grid-2.11.0/dune/grid/io/file/gnuplot/000077500000000000000000000000001511655130300203475ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/gnuplot/CMakeLists.txt000066400000000000000000000004131511655130300231050ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception install(FILES gnuplot.cc DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/grid/io/file/gnuplot) dune-grid-2.11.0/dune/grid/io/file/gnuplot/gnuplot.cc000066400000000000000000000066551511655130300223620ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: /** @file @author Christian Engwer @brief Implementation of gnuplot output for 1D and 2D grids */ #include "../gnuplot.hh" namespace Dune { /** \brief Write Gnuplot file to disk \param filename Name of the file to write to */ template void GnuplotWriter::write(const std::string& filename) const { // open file std::ofstream file(filename.c_str()); // write all column names file << "# coord\t"; for (size_t i=0; i<_names.size(); i++) file << _names[i] << "\t"; file << "\n"; if (dimworld==1) { #if !NDEBUG int counter = 0; #endif typedef typename GridView::template Codim<0>::Iterator CellIterator; CellIterator it = _gv.template begin<0>(); CellIterator end = _gv.template end<0>(); for (; it != end; ++it) { int i = _is.index(*it); // check that the elements are numbered consecutively assert (i == counter++); // calc positions assert(it->geometry().corners() == 2); const FieldVector& left = it->geometry().corner(0); const FieldVector& right = it->geometry().corner(1); assert(left[0] < right[0]); // write gnuplot rows for left & right vertex writeRow(file, left, _data[2*i]); writeRow(file, right, _data[2*i+1]); } } else { typedef typename GridView::template Codim::Iterator VertexIterator; VertexIterator it = _gv.template begin(); VertexIterator end = _gv.template end(); for (; it != end; ++it) { // write gnuplot rows for vertex writeRow(file, it->geometry().corner(0), _data[_is.index(*it)]); } } } template void GnuplotWriter::writeRow(std::ostream & file, const FieldVector& position, const std::vector & data) const { assert (data.size() == _names.size()); // write position file << position << "\t"; // write all data columns for (size_t j=0; j template void GnuplotWriter::addData(DataType t, const DataContainer& data, const std::string & name) { assert((t == cellData && _is.size(0) == data.size()) || (t == vertexData && _is.size(GridView::dimension) == data.size()) ); _names.push_back(name); // copy data to new container if (dimworld==1) { // data is transformed to nonconforming vertex data int c = 0; int shift = (t==vertexData ? 1 : 0); for (size_t i=0; i<_is.size(0); i++) { _data[c++].push_back(data[i]); _data[c++].push_back(data[i+shift]); }; } else { // 2d: only vertex data is allowed for (size_t i=0; i<_is.size(dimworld); i++) _data[i].push_back(data[i]); } } } dune-grid-2.11.0/dune/grid/io/file/printgrid.hh000066400000000000000000000214471511655130300212120ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_PRINTGRID_HH #define DUNE_PRINTGRID_HH #include #include #include #include #include namespace Dune { namespace { template struct ElementDataLayout { bool contains (Dune::GeometryType gt) { return gt.dim()==dim; } }; template struct NodeDataLayout { bool contains (Dune::GeometryType gt) { return gt.dim()==0; } }; // Move a point closer to basegeo's center by factor scale (used for drawing relative to the element) template C centrify (const B& basegeo, const C& coords, const double scale) { C ret = coords; ret -= basegeo.center(); ret *= scale; ret += basegeo.center(); return ret; } // Add a line to the plotfile from p1 to p2 template void draw_line (std::ofstream &plotfile, const Coord &p1, const Coord &p2, std::string options) { plotfile << "set object poly from "; plotfile << p1[0] << "," << p1[1] << " to "; plotfile << p2[0] << "," << p2[1] << " to "; plotfile << p1[0] << "," << p1[1]; plotfile << " " << options << std::endl; } } /** \brief Print a grid as a gnuplot for testing and development * \tparam GridType the type of grid to work with * \param grid the grid to print * \param output_file the base of the output filename * \param size size of the plot in pixels; increase if plot is too cramped * \param execute_plot whether to execute gnuplot automatically * \param png whether to use PNG or SVG as the output format * \param local_corner_indices whether to show local corner indices * \param local_intersection_indices whether to show local intersection indices * \param outer_normals whether to show outer normals of intersections * Creates a gnuplot showing the grid structure with indices, intersection types etc. */ template void printGrid (const GridType& grid, std::string output_file, int size = 2000, bool execute_plot = true, bool png = true, bool local_corner_indices = true, bool local_intersection_indices = true, bool outer_normals = true) { // Create output file std::string plot_file_name = output_file + ".gnuplot"; std::ofstream plotfile (plot_file_name, std::ios::out | std::ios::trunc); if (!plotfile.is_open()) { DUNE_THROW(Dune::IOError, "Could not create plot file " << output_file << "!"); return; } // Basic plot settings plotfile << "set size ratio -1" << std::endl; if (png) { plotfile << "set terminal png size " << size << "," << size << std::endl; plotfile << "set output '" << output_file << ".png'" << std::endl; } else { plotfile << "set terminal svg size " << size << "," << size << " enhanced background rgb 'white'" << std::endl; plotfile << "set output '" << output_file << ".svg'" << std::endl; } // Get GridView typedef typename GridType::LeafGridView GV; const GV gv = grid.leafGridView(); // Create mappers used to retrieve indices typedef typename Dune::MultipleCodimMultipleGeomTypeMapper Mapper; const Mapper elementmapper(gv, mcmgElementLayout()); const Mapper nodemapper(gv, mcmgVertexLayout()); // Create iterators typedef typename GV::template Codim<0 >::Iterator LeafIterator; typedef typename GV::IntersectionIterator IntersectionIterator; LeafIterator it = gv.template begin<0>(); // Will contain min/max coordinates. Needed for scaling of the plot Dune::FieldVector max_coord (it->geometry().center()), min_coord (max_coord); // Iterate over elements for (; it != gv.template end<0>(); ++it) { const auto& entity = *it; auto geo = entity.geometry(); // Plot element index int element_id = elementmapper.index(entity); plotfile << "set label at " << geo.center()[0] << "," << geo.center()[1] << " '" << element_id << "' center" << std::endl; for (int i = 0; i < geo.corners(); ++i) { // Plot corner indices const int globalNodeNumber1 = nodemapper.subIndex(entity, i, 2); auto labelpos = centrify (geo, geo.corner(i), 0.7); plotfile << "set label at " << labelpos[0] << "," << labelpos[1] << " '" << globalNodeNumber1; if (local_corner_indices) plotfile << "(" << i << ")"; plotfile << "' center" << std::endl; // Adapt min / max coordinates for (int dim = 0; dim < 2; ++dim) { if (geo.corner(i)[dim] < min_coord[dim]) min_coord[dim] = geo.corner(i)[dim]; else if (geo.corner(i)[dim] > max_coord[dim]) max_coord[dim] = geo.corner(i)[dim]; } } // Iterate over intersections for (IntersectionIterator is = gv.ibegin(entity); is != gv.iend(entity); ++is) { const auto& intersection = *is; auto igeo = intersection.geometry(); // Draw intersection line draw_line (plotfile, igeo.corner(0), igeo.corner(1), "fs empty border 1"); // Plot local intersection index if (local_intersection_indices) { auto label_pos = centrify (geo, igeo.center(), 0.8); plotfile << "set label at " << label_pos[0] << "," << label_pos[1] << " '" << intersection.indexInInside() << "' center" << std::endl; } // Plot outer normal if (outer_normals) { auto intersection_pos = igeo.center(); auto normal = intersection.centerUnitOuterNormal(); normal *= 0.15 * igeo.volume(); auto normal_end = intersection_pos + normal; plotfile << "set arrow from " << intersection_pos[0] << "," << intersection_pos[1] << " to " << normal_end[0] << "," << normal_end[1] << " lt rgb \"gray\"" << std::endl; } // Get corners for inner intersection representation auto inner_corner1 = centrify (geo, igeo.corner(0), 0.5); auto inner_corner2 = centrify (geo, igeo.corner(1), 0.5); // Thick line in case of boundary() if (intersection.boundary()) draw_line (plotfile, inner_corner1, inner_corner2, "fs empty border 3 lw 4"); // Thin line with color according to neighbor() if (intersection.neighbor()) draw_line (plotfile, inner_corner1, inner_corner2, "fs empty border 2"); else draw_line (plotfile, inner_corner1, inner_corner2, "fs empty border 1"); } } // Finish plot, pass extend of the grid Dune::FieldVector extend (max_coord - min_coord); extend *= 0.2; min_coord -= extend; max_coord += extend; plotfile << "plot [" << min_coord[0] << ":" << max_coord[0] << "] [" << min_coord[1] << ":" << max_coord[1] << "] NaN notitle" << std::endl; plotfile.close(); if (execute_plot) { std::string cmd = "gnuplot -p '" + plot_file_name + "'"; if (std::system (cmd.c_str()) != 0) DUNE_THROW(Dune::Exception,"Error running GNUPlot: " << cmd); } } /** \brief Print a grid as a gnuplot for testing and development * \tparam GridType the type of grid to work with * \param grid the grid to print * \param helper an MPIHelper to create unique output file names in parallel case * \param output_file the base of the output filename * \param size size of the plot in pixels; increase if plot is too cramped * \param execute_plot whether to execute gnuplot automatically * \param png whether to use PNG or SVG as the output format * \param local_corner_indices whether to show local corner indices * \param local_intersection_indices whether to show local intersection indices * \param outer_normals whether to show outer normals of intersections * Creates a gnuplot (one per process if parallel) showing the grid structure with indices, intersection types etc. */ template void printGrid (const GridType& grid, const Dune::MPIHelper& helper, std::string output_file = "printgrid", int size = 2000, bool execute_plot = true, bool png = true, bool local_corner_indices = true, bool local_intersection_indices = true, bool outer_normals = true) { printGrid(grid, output_file + "_" + std::to_string(helper.rank()), size, execute_plot, png, local_corner_indices, local_intersection_indices, outer_normals); } } #endif // #ifndef DUNE_PRINTGRID_HH dune-grid-2.11.0/dune/grid/io/file/starcdreader.hh000066400000000000000000000154561511655130300216560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_STARCD_READER_HH #define DUNE_STARCD_READER_HH #include #include #include #include #include #include namespace Dune { /** @ingroup StarCD * \brief File reader for the Star-CD format. * * Reads grid data described by the Star-CD format and fills * an empty grid with the data. Uses the grid creation methods * described in * * "How to Write a File Reader for UGGrid Objects". * * Two files \a fileName.vrt and \a fileName.cel have to be present. The file fileName.vrt contains the * coordinates of the nodes, each row having the format \code idx x-coordinate y-coordinate z-coordinate \endcode * * The file fileName.cel contains the data of the volume and possibly the boundary elements, each * row having the format \code idx node1 node2 ... node8 material/boundaryId flag1 flag2 \endcode * The flags flag1 and flag2 appear to be always identical to 1 in case of a volume element * and to 4 in case of a boundary element. The element types simplex, pyramid, prism, and * cube are supported: * * - For cubes, the indices node1 ... node8 are what you expect them to be. * - For simplices, node3 and node4 are identical, as well as node5 ... node8. * - For pyramids, node5 ... node8 are identical. * - For prisms, node3 and node4 are identical, as well as node7 and node8. * * This reader only supports three-dimensional grids. * * Currently no boundary element data is passed to \a grid. */ template class StarCDReader { public: /** \brief Read grid from a Star-CD file * \return Pointer to the grid * \param fileName The base file name of the Star-CD files * \param verbose Tlag to set whether information should be printed * * \return The return type is a special pointer type that casts into * std::unique_ptr, and std::shared_ptr. It is scheduled * to be replaced by std::unique_ptr eventually. */ static std::unique_ptr read(const std::string& fileName, bool verbose = true) { // extract the grid dimension const int dim = GridType::dimension; // currently only dim = 3 is implemented if (dim != 3) DUNE_THROW(Dune::NotImplemented, "Reading Star-CD format is not implemented for dimension " << dim); // set up the grid factory GridFactory factory; // set the name of the vertex file std::string vertexFileName = fileName + ".vrt"; // set the vertex input stream std::ifstream vertexFile(vertexFileName.c_str()); if (!vertexFile) DUNE_THROW(Dune::IOError, "Could not open " << vertexFileName); // read the vertices int dummyIdx; int numberOfVertices = 0; while (vertexFile >> dummyIdx) { numberOfVertices++; Dune::FieldVector position; for (int k = 0; k < dim; k++) vertexFile >> position[k]; factory.insertVertex(position); } if (verbose) std::cout << numberOfVertices << " vertices read." << std::endl; // set the name of the element file std::string elementFileName = fileName + ".cel"; // set the element input stream std::ifstream elementFile(elementFileName.c_str()); if (!elementFile) DUNE_THROW(Dune::IOError, "Could not open " << elementFileName); // read the elements int numberOfElements = 0; int numberOfSimplices = 0; int numberOfPyramids = 0; int numberOfPrisms = 0; int numberOfCubes = 0;; int maxNumberOfVertices = (int)pow(2, dim); int isVolume = 1; while (elementFile >> dummyIdx) { std::vector vertices(maxNumberOfVertices); for (int k = 0; k < maxNumberOfVertices; k++) elementFile >> vertices[k]; int boundaryId; elementFile >> boundaryId; int volumeOrSurface[2]; elementFile >> volumeOrSurface[0] >> volumeOrSurface[1]; if (volumeOrSurface[0] == isVolume) { numberOfElements++; if (vertices[2] == vertices[3]) { // simplex or prism if (vertices[4] == vertices[5]) { // simplex numberOfSimplices++; std::vector simplexVertices(4); for (int k = 0; k < 3; k++) simplexVertices[k] = vertices[k] - 1; simplexVertices[3] = vertices[4] - 1; factory.insertElement(Dune::GeometryTypes::tetrahedron, simplexVertices); } else { // prism numberOfPrisms++; std::vector prismVertices(6); for (int k = 0; k < 3; k++) prismVertices[k] = vertices[k] - 1; for (int k = 3; k < 6; k++) prismVertices[k] = vertices[k+1] - 1; factory.insertElement(Dune::GeometryTypes::prism, prismVertices); } } else { // cube or pyramid if (vertices[4] == vertices[5]) { // pyramid numberOfPyramids++; std::vector pyramidVertices(5); for (int k = 0; k < 5; k++) pyramidVertices[k] = vertices[k] - 1; factory.insertElement(Dune::GeometryTypes::pyramid, pyramidVertices); } else { // cube numberOfCubes++; std::vector cubeVertices(8); for (int k = 0; k < 8; k++) cubeVertices[k] = vertices[k] - 1; std::swap(cubeVertices[2], cubeVertices[3]); std::swap(cubeVertices[6], cubeVertices[7]); factory.insertElement(Dune::GeometryTypes::hexahedron, cubeVertices); } } } } if (verbose) std::cout << numberOfElements << " elements read: " << numberOfSimplices << " simplices, " << numberOfPyramids << " pyramids, " << numberOfPrisms << " prisms, " << numberOfCubes << " cubes." << std::endl; // finish off the construction of the grid object if (verbose) std::cout << "Starting createGrid() ... " << std::flush; return factory.createGrid(); } }; } #endif dune-grid-2.11.0/dune/grid/io/file/test/000077500000000000000000000000001511655130300176365ustar00rootroot00000000000000dune-grid-2.11.0/dune/grid/io/file/test/CMakeLists.txt000066400000000000000000000102651511655130300224020ustar00rootroot00000000000000# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root # SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception # TODO when porting this file to dune_add_test, the GMSH test needed to be adapted. # It previously relied on the flags added to the executable to switch different grid types. # I have adapted it quickly by adding a preprocessor variable. This could be and should # be done more nicely. # # Link all test targets in this directory against Dune::Grid link_libraries(Dune::Grid) dune_add_test(SOURCES conformvolumevtktest.cc) dune_add_test(SOURCES gnuplottest.cc) dune_add_test(SOURCES nonconformboundaryvtktest.cc) dune_add_test(SOURCES printgridtest.cc) # If VTK is found in venv, use that interpreter to run the tests # otherwise use the interpreter of Python3::Python unset(VTK_INTERPRETER_LOCATION) option(DUNE_GRID_SKIP_VTK_PYTHON_TESTS "Skip tests that require VTK Python bindings.\n On some systems (e.g. Ubuntu, Debian) the VTK package, it is known that it cannot read binary files due to a security patch.\n See https://gitlab.dune-project.org/core/dune-grid/-/merge_requests/784" OFF) if((TARGET Python3::Python) AND (NOT ${DUNE_GRID_SKIP_VTK_PYTHON_TESTS})) if(DUNE_PYTHON_VIRTUALENV_EXECUTABLE) dune_python_find_package(PACKAGE vtk RESULT DUNE_PYTHON_VTK_FOUND INTERPRETER ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE}) if(DUNE_PYTHON_VTK_FOUND) set(VTK_INTERPRETER_LOCATION ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE}) endif() endif() if(NOT VTK_INTERPRETER_LOCATION) get_target_property(VTK_INTERPRETER_LOCATION Python3::Interpreter LOCATION) endif() endif() # Note that an empty PYTHON_INTERPRETER will result in an skipped test unset(VTK_COMPILE_DEFINITIONS) if(VTK_INTERPRETER_LOCATION) message(STATUS "Using VTK interpreter at ${VTK_INTERPRETER_LOCATION} for tests") set(VTK_COMPILE_DEFINITIONS $<$:PYTHON_INTERPRETER=L"${VTK_INTERPRETER_LOCATION}">) endif() dune_add_test(NAME subsamplingvtktest LINK_LIBRARIES ${DUNE_LIBS} $ SOURCES subsamplingvtktest.cc test-linking.cc TIMEOUT 600 COMPILE_DEFINITIONS ${VTK_COMPILE_DEFINITIONS}) dune_add_test(SOURCES vtktest.cc LINK_LIBRARIES ${DUNE_LIBS} $ MPI_RANKS 1 2 TIMEOUT 1200 COMPILE_DEFINITIONS ${VTK_COMPILE_DEFINITIONS}) dune_add_test(SOURCES vtksequencetest.cc LINK_LIBRARIES ${DUNE_LIBS} $ COMPILE_DEFINITIONS ${VTK_COMPILE_DEFINITIONS}) dune_add_test(SOURCES starcdreadertest.cc COMPILE_DEFINITIONS DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\" CMAKE_GUARD dune-uggrid_FOUND) # the gmsh tests dune_add_test(NAME gmshtest-onedgrid SOURCES gmshtest.cc COMPILE_DEFINITIONS GMSH_ONEDGRID DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\") dune_add_test(NAME gmshtest-uggrid SOURCES gmshtest.cc COMPILE_DEFINITIONS GMSH_UGGRID DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\" CMAKE_GUARD dune-uggrid_FOUND) dune_add_test(NAME gmsh4readertest SOURCES gmsh4readertest.cc COMPILE_DEFINITIONS DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\" CMAKE_GUARD dune-uggrid_FOUND) if(Alberta_FOUND) add_executable(gmshtest-alberta2d gmshtest.cc) add_dune_alberta_flags(gmshtest-alberta2d WORLDDIM 2) target_compile_definitions(gmshtest-alberta2d PUBLIC GMSH_ALBERTAGRID DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\") dune_add_test(TARGET gmshtest-alberta2d) add_executable(gmshtest-alberta3d gmshtest.cc) add_dune_alberta_flags(gmshtest-alberta3d WORLDDIM 3) target_compile_definitions(gmshtest-alberta3d PUBLIC GMSH_ALBERTAGRID DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\") dune_add_test(TARGET gmshtest-alberta3d) endif() dune-grid-2.11.0/dune/grid/io/file/test/checkvtkfile.hh000066400000000000000000000110651511655130300226240ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception #ifndef DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH #define DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PYTHON_INTERPRETER #include #endif namespace Dune { namespace Impl { // quote so the result can be used inside '...' in python // quotes not included in the result inline std::string pyq(const std::string &s) { std::ostringstream result; for(std::size_t i = 0; i < s.size(); ++i) { char c = s[i]; switch(c) { case '\'': result << "\\'"; break; case '\\': result << "\\\\"; break; case '\n': result << "\\n"; break; default: if(c < 32 || c >= 127) result << "\\x" << std::hex << std::setfill('0') << std::setw(2) << static_cast(c); else result << c; } } return result.str(); } inline int runPython(const std::string &code) { #ifdef PYTHON_INTERPRETER #if (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION >= 8) PyConfig config; PyConfig_InitPythonConfig(&config); PyConfig_SetString(&config, &config.program_name, PYTHON_INTERPRETER); PyStatus status = Py_InitializeFromConfig(&config); PyConfig_Clear(&config); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); return PyStatus_IsExit(status) ? status.exitcode : EXIT_FAILURE; } #else Py_SetProgramName(PYTHON_INTERPRETER); Py_Initialize(); #endif int exitcode = PyRun_SimpleString(code.c_str()); int finalizecode = Py_FinalizeEx(); return (exitcode + finalizecode) ? EXIT_FAILURE : EXIT_SUCCESS; #else return EXIT_FAILURE; #endif // PYTHON_INTERPRETER } inline bool is_suffix(const std::string &s, const std::string &suffix) { return s.size() >= suffix.size() && s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0; } inline bool havePythonVTK() { static const bool result = [] { // This check is invoked only once, even in a multithreading environment, // since it is invoked in the initializer of a static variable. if(runPython("from vtk import *") == EXIT_SUCCESS) return true; std::cerr << "warning: python or python vtk module not available. This " << "will result in skipped tests, since we cannot check that " << "vtk can read the files we wrote." << std::endl; return false; } (); return result; } inline std::string pythonVTKReader(const std::string& filename) { if (is_suffix(filename, ".vtu")) return "vtkXMLUnstructuredGridReader"; else if(is_suffix(filename, ".pvtu")) return "vtkXMLPUnstructuredGridReader"; else if(is_suffix(filename, ".vtp")) return "vtkXMLPolyDataReader"; else if(is_suffix(filename, ".pvtp")) return "vtkXMLPPolyDataReader"; else DUNE_THROW(Dune::NotImplemented, "Unknown vtk file extension: " << filename); } } /* namespace Impl */ class VTKChecker { public: void push(const std::string& file) { auto res = files_.insert(file); if (not res.second) { testSuite_.check(false, "VTKChecker") << "'" << file << "' was added multiple times"; } } int check() { if (not Impl::havePythonVTK()) { return 77; } else if (not files_.empty()) { const int result = Impl::runPython(generatePythonCode()); testSuite_.check(result == EXIT_SUCCESS); } return testSuite_.exit(); } const TestSuite& testSuite() const { return testSuite_; } private: std::string generatePythonCode() const { std::stringstream code; code << "from vtk import *\n" << "import sys\n" << "passed = True\n"; for (const auto& file : files_) { code << "reader = " << Impl::pythonVTKReader(file) << "()\n" << "reader.SetFileName('" << Impl::pyq(file) << "')\n" << "reader.Update()\n" << "if (not (reader.GetOutput().GetNumberOfCells() > 0)):\n" << " print('ERROR in {}'.format('" << Impl::pyq(file) << "'))\n" << " passed = False\n"; } code << "sys.exit(0 if passed else 1)\n"; return code.str(); } std::set< std::string > files_; TestSuite testSuite_; }; } /* namespace Dune */ #endif // DUNE_GRID_IO_FILE_TEST_CHECKVTKFILE_HH dune-grid-2.11.0/dune/grid/io/file/test/conformvolumevtktest.cc000066400000000000000000000112171511655130300244670ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 template< class GridView > class VTKVectorFunction : public Dune::VTK::ConformingVolumeWriter::VTKFunction { // extract types constexpr static int n = GridView :: dimension; constexpr static int w = GridView :: dimensionworld; typedef typename GridView :: Grid :: ctype DT; typedef typename GridView :: template Codim< 0 > :: Entity Entity; const char *type; public: /** @brief Make a new VTKVectorFunction * * @param type_ Type of the function for use in its name (hint: "cell" or * "vertex") */ VTKVectorFunction(const char *type_) : type(type_) { } //! return number of components virtual int ncomps () const { return n; } //! evaluate single component comp in the entity e at local coordinates xi /*! Evaluate the function in an entity at local coordinates. @param[in] comp number of component to be evaluated @param[in] e reference to grid entity of codimension 0 @param[in] xi point in local coordinates of the reference element of e \return value of the component */ virtual double evaluate (int comp, [[maybe_unused]] const Entity& e, [[maybe_unused]] const Dune::FieldVector& xi) const { return comp*0.1; } // get name virtual std::string name () const { char _name[256]; snprintf(_name, 256, "%s-vector-%iD", type, ncomps()); return std::string(_name); } }; template< class GridView > void doWrite( const GridView &gridView ) { constexpr static int dim = GridView :: dimension; const typename GridView :: IndexSet &is = gridView.indexSet(); std::vector vertexdata(is.size(dim),dim); std::vector celldata(is.size(0),0); Dune::VTK::ConformingVolumeWriter< GridView > vtk( gridView ); vtk.addVertexData(vertexdata,"vertexData"); vtk.addCellData(celldata,"cellData"); vtk.addVertexData(std::make_shared< VTKVectorFunction >("vertex")); vtk.addCellData(std::make_shared< VTKVectorFunction >("cell")); char name[256]; snprintf(name,256,"conformvolumevtktest-%iD-ascii", dim); vtk.write(name, Dune::VTK::ascii); snprintf(name,256,"conformvolumevtktest-%iD-base64", dim); vtk.write(name, Dune::VTK::base64); snprintf(name,256,"conformvolumevtktest-%iD-appendedraw", dim); vtk.write(name, Dune::VTK::appendedraw); snprintf(name,256,"conformvolumevtktest-%iD-appendedbase64", dim); vtk.write(name, Dune::VTK::appendedbase64); } template void vtkCheck(Dune::FieldVector& length, std::array elements) { std::cout << "vtkCheck dim=" << dim << std::endl; Dune::YaspGrid grid(length, elements); grid.globalRefine(1); doWrite( grid.leafGridView() ); doWrite( grid.levelGridView( 0 ) ); doWrite( grid.levelGridView( grid.maxLevel() ) ); } int main(int argc, char **argv) { try { const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); if(mpiHelper.rank() == 0) std::cout << "subsamplingvtktest: MPI_Comm_size == " << mpiHelper.size() << std::endl; { const unsigned int dim = 1; Dune::FieldVector length(1.0); std::array elements; std::fill(elements.begin(), elements.end(), 5); vtkCheck(length, elements); } { const unsigned int dim = 2; Dune::FieldVector length(1.0); length[1] = 2.0; std::array elements; std::fill(elements.begin(), elements.end(), 5); vtkCheck(length, elements); } { const unsigned int dim = 3; Dune::FieldVector length(1.0); length[1] = 2.0; length[2] = 3.0; std::array elements; std::fill(elements.begin(), elements.end(), 5); vtkCheck(length, elements); } } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/io/file/test/gmsh4readertest.cc000066400000000000000000000025421511655130300232550ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later // -*- 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 #include #include #include #include using namespace Dune; int main(int argc, char** argv) { MPIHelper::instance(argc, argv); const std::string path = DUNE_GRID_EXAMPLE_GRIDS_PATH "gmsh/"; { // Read a 2d ASCII test grid auto grid = Impl::Gmsh::Gmsh4Reader >::createGridFromFile(path + "hybrid-testgrid-2d-v4-ascii.msh"); gridcheck(*grid); } { // Read a 2d binary test grid auto grid = Impl::Gmsh::Gmsh4Reader >::createGridFromFile(path + "hybrid-testgrid-2d-v4-binary.msh"); gridcheck(*grid); } { // Read a 3d ASCII test grid auto grid = Impl::Gmsh::Gmsh4Reader >::createGridFromFile(path + "hybrid-testgrid-3d-v4-ascii.msh"); gridcheck(*grid); } { // Read a 3d binary test grid auto grid = Impl::Gmsh::Gmsh4Reader >::createGridFromFile(path + "hybrid-testgrid-3d-v4-ascii.msh"); gridcheck(*grid); } return 0; } dune-grid-2.11.0/dune/grid/io/file/test/gmshtest.cc000066400000000000000000000251441511655130300220110ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 // dune grid includes #include #if HAVE_DUNE_UGGRID #include #endif #if HAVE_ALBERTA #include #endif // alberta related stuff #ifndef ALBERTA_DIM #define ALBERTA_DIM 2 #endif #ifndef GRIDDIM #define GRIDDIM ALBERTA_DIM #endif #include #if GMSH_ONEDGRID #include #endif #include #include #include #include #include using namespace Dune; #if HAVE_ALBERTA template< int dim, int dimworld > struct EnableLevelIntersectionIteratorCheck< Dune::AlbertaGrid< dim, dimworld > > { static const bool v = false; }; #endif template using read_gf_result_t = decltype(GmshReader::read(std::declval&>(), std::string{}, std::declval()...)); template void testReadingAndWritingGrid( const std::string& path, const std::string& gridName, const std::string& gridManagerName, int refinements, bool expectsElementData = true, bool expectsBoundarySegments = false) { // Read the grid std::cout<<"Using "< gridFactory; const std::string inputName(path+gridName+".msh"); std::cout<<"Reading mesh file "<(inputName, gridFactory); auto grid = gridFactory.createGrid(); // Version 4 file apparently do not always have element data auto elementsIDs = (expectsElementData) ? reader.extractElementData() : std::vector{}; auto boundaryIDs = (expectsBoundarySegments) ? reader.extractBoundaryData() : std::vector{}; // Reorder boundary IDs according to the insertion index const auto leafGridView(grid->leafGridView()); if(!boundaryIDs.empty()) { std::vector tempIDs(boundaryIDs.size(),0); for(const auto& entity:elements(leafGridView)) for(const auto& intersection:intersections(leafGridView,entity)) if(intersection.boundary()) tempIDs[intersection.boundarySegmentIndex()]=boundaryIDs[gridFactory.insertionIndex(intersection)]; boundaryIDs=std::move(tempIDs); } else if (expectsBoundarySegments) DUNE_THROW(Dune::IOError, "Expected boundary segment markers found none!"); // Load balancing and refinement grid->loadBalance(); if ( refinements > 0 ) grid->globalRefine( refinements ); // Do some tests to make sure the grid has been properly read gridcheck(*grid); // Write MSH Dune::GmshWriter writer( leafGridView ); writer.setPrecision(10); const std::string outputName(gridName+"-"+gridManagerName+"-gmshtest-write.msh"); writer.write(outputName); if(!elementsIDs.empty()) { const std::string outputNameEntity(gridName+"-"+gridManagerName+"-gmshtest-write-entity.msh"); writer.write(outputNameEntity,elementsIDs); } if((!boundaryIDs.empty())&&(!elementsIDs.empty())) { const std::string outputNameBoundary(gridName+"-"+gridManagerName+"-gmshtest-write-boundary.msh"); writer.write(outputNameBoundary,elementsIDs,boundaryIDs); } // Write VTK std::ostringstream vtkName; vtkName << gridName << "-gmshtest-" << refinements; VTKWriter vtkWriter( leafGridView ); vtkWriter.write( vtkName.str() ); std::cout<::read(inputName); } // test deprecated reading without gridfactory but with data { auto read = [&] (auto... args) { std::vector boundaryData; std::vector elementData; DUNE_NO_DEPRECATED_BEGIN auto gridp = GmshReader::read(inputName, elementData, boundaryData, args...); DUNE_NO_DEPRECATED_END static_assert(std::is_same, GridType>::value, "GmshReader::read() return type is wrong"); }; read(); read(false); read(false, false); read(false, true); read(true); read(true, false); read(true, true); } // test reading with gridfactory but without data { auto read = [&] (auto... args) { GridFactory factory; GmshReader::read(factory, inputName, args...); }; read(); read(false); read(false, false); read(false, true); read(true); read(true, false); read(true, true); } // test reading with gridfactory and data { auto read = [&] (auto &&... args) { GridFactory gridFactory{}; return GmshReader::read(gridFactory, inputName, std::forward(args)...); }; std::vector boundarySegmentToPhysicalEntity; std::vector elementToPhysicalEntity; // boundary data provided, element data provided read(boundarySegmentToPhysicalEntity, elementToPhysicalEntity); read(boundarySegmentToPhysicalEntity, elementToPhysicalEntity, false); read(boundarySegmentToPhysicalEntity, elementToPhysicalEntity, true); // boundary data provided, element data omitted read(boundarySegmentToPhysicalEntity, std::ignore); read(boundarySegmentToPhysicalEntity, std::ignore, false); read(boundarySegmentToPhysicalEntity, std::ignore, true); // boundary data omitted, segment insertion omitted, element data provided read(std::ignore, elementToPhysicalEntity); read(std::ignore, elementToPhysicalEntity, false); read(std::ignore, elementToPhysicalEntity, true); // boundary data omitted, segment insertion omitted, element data omitted read(std::ignore, std::ignore); read(std::ignore, std::ignore, false); read(std::ignore, std::ignore, true); // boundary data omitted, segment insertion omitted, element data provided read(false, elementToPhysicalEntity); read(false, elementToPhysicalEntity, false); read(false, elementToPhysicalEntity, true); // boundary data omitted, segment insertion omitted, element data omitted read(false, std::ignore); read(false, std::ignore, false); read(false, std::ignore, true); // boundary data omitted, segment insertion done, element data provided read(true, elementToPhysicalEntity); read(true, elementToPhysicalEntity, false); read(true, elementToPhysicalEntity, true); // boundary data omitted, segment insertion done, element data omitted read(true, std::ignore); read(true, std::ignore, false); read(true, std::ignore, true); // check that certain signatures are rejected static_assert(!Std::is_detected_v, std::vector&>, "rvalue boundary data should be rejected"); static_assert(!Std::is_detected_v&, std::vector>, "rvalue element data should be rejected"); } // test reading with gridfactory and data (deprecated signatures) { auto read = [&] (bool verbose, bool insertBoundarySegments) { std::vector boundaryData; std::vector elementData; GridFactory factory; DUNE_NO_DEPRECATED_BEGIN GmshReader::read(factory, inputName, boundaryData, elementData, verbose, insertBoundarySegments); DUNE_NO_DEPRECATED_END }; read(false, false); read(false, true); read(true, false); read(true, true); } } int main( int argc, char** argv ) try { MPIHelper::instance( argc, argv ); const int refinements = ( argc > 1 ) ? atoi( argv[1] ) : 0; const std::string path(static_cast(DUNE_GRID_EXAMPLE_GRIDS_PATH)+"gmsh/"); #if GMSH_UGGRID // Test reading Version 2 Gmsh files testReadingAndWritingGrid >( path, "curved2d", "UGGrid-2D", refinements ); testReadingAndWritingGrid >( path, "circle2ndorder", "UGGrid-2D", refinements ); testReadingAndWritingGrid >( path, "unitsquare_quads_2x2", "UGGrid-2D", refinements ); testReadingAndWritingGrid >( path, "hybrid-testgrid-2d", "UGGrid-2D", refinements ); testReadingAndWritingGrid >( path, "pyramid", "UGGrid-3D", refinements ); testReadingAndWritingGrid >( path, "pyramid2ndorder", "UGGrid-3D", refinements ); testReadingAndWritingGrid >( path, "hybrid-testgrid-3d", "UGGrid-3D", refinements ); testReadingAndWritingGrid >( path, "unitcube", "UGGrid-3D", refinements ); // Test reading Version 4 Gmsh files testReadingAndWritingGrid >( path, "hybrid-testgrid-2d-v4-ascii", "UGGrid-2D", refinements, false, false ); testReadingAndWritingGrid >( path, "hybrid-testgrid-2d-v4-binary", "UGGrid-2D", refinements, false, false ); testReadingAndWritingGrid >( path, "hybrid-testgrid-3d-v4-ascii", "UGGrid-3D", refinements, false, false ); testReadingAndWritingGrid >( path, "hybrid-testgrid-3d-v4-binary", "UGGrid-3D", refinements, false, false ); #endif #if GMSH_ALBERTAGRID #if ALBERTA_DIM==2 testReadingAndWritingGrid >( path, "curved2d", "AlbertaGrid-2D", refinements ); #endif #if ALBERTA_DIM==3 testReadingAndWritingGrid >( path, "sphere", "AlbertaGrid-2D", refinements ); testReadingAndWritingGrid >( path, "pyramid", "AlbertaGrid-3D", refinements ); #endif #endif #if GMSH_ONEDGRID testReadingAndWritingGrid( path, "oned-testgrid", "OneDGrid", refinements, true); #endif return 0; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch ( ... ) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/io/file/test/gnuplottest.cc000066400000000000000000000030571511655130300225420ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include #include template void testIO(const GV & gridView, std::string fname) { // create data buffer std::vector celldata; std::vector vertexdata; for (size_t i=0; i gnuplot(gridView); // register data gnuplot.template addVertexData< std::vector >(vertexdata, std::string("vertexdata")); gnuplot.addCellData(celldata, std::string("celldata")); // write data gnuplot.write(fname); } int main(int argc, char** argv) { try { Dune::MPIHelper::instance(argc, argv); const unsigned int dim = 1; Dune::FieldVector length(1.0); std::array elements; elements[0] = 10; Dune::YaspGrid<1> grid(length, elements); testIO(grid.leafGridView(), "grid-leaf.data"); testIO(grid.levelGridView(0), "grid-level.data"); } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/io/file/test/nonconformboundaryvtktest.cc000066400000000000000000000074401511655130300255210ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 template< class GridView > class ScalarFunction { public: typedef Dune::VTK::SkeletonFunctionTraits Traits; //! return number of components unsigned dimRange() const { return 1; } void evaluate(const typename Traits::Cell& c, const typename Traits::Domain& xl, typename Traits::Range& result) const { result.resize(1, c.geometry().global(xl).two_norm()); } }; template< class GridView > class VectorFunction { public: typedef Dune::VTK::SkeletonFunctionTraits Traits; //! return number of components unsigned dimRange() const { return GridView::dimensionworld; } void evaluate(const typename Traits::Cell& c, const typename Traits::Domain& xl, typename Traits::Range& result) const { const Dune::FieldVector& normal = c.unitOuterNormal(xl); result.assign(normal.begin(), normal.end()); } }; template< class GridView > void doWrite( const GridView &gridView ) { constexpr static int dim = GridView :: dimension; Dune::VTK::NonConformingBoundaryWriter< GridView > vtk( gridView ); std::shared_ptr > scalarFunc (new ScalarFunction); vtk.addCellData(scalarFunc, "cellScalar"); vtk.addPointData(scalarFunc, "pointScalar"); std::shared_ptr > vectorFunc (new VectorFunction); vtk.addCellData(vectorFunc, "cellVector"); vtk.addPointData(vectorFunc, "pointVector"); char name[256]; snprintf(name,256,"nonconformboundaryvtktest-%iD-ascii", dim); vtk.write(name, Dune::VTK::ascii); snprintf(name,256,"nonconformboundaryvtktest-%iD-base64", dim); vtk.write(name, Dune::VTK::base64); snprintf(name,256,"nonconformboundaryvtktest-%iD-appendedraw", dim); vtk.write(name, Dune::VTK::appendedraw); snprintf(name,256,"nonconformboundaryvtktest-%iD-appendedbase64", dim); vtk.write(name, Dune::VTK::appendedbase64); } template void vtkCheck(const std::array& n, const Dune::FieldVector& h) { std::cout << std::endl << "vtkCheck dim=" << dim << std::endl << std::endl; Dune::YaspGrid grid(h, n); grid.globalRefine(1); doWrite( grid.leafGridView() ); doWrite( grid.levelGridView( 0 ) ); doWrite( grid.levelGridView( grid.maxLevel() ) ); } int main(int argc, char **argv) { try { const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); if(mpiHelper.rank() == 0) std::cout << "subsamplingvtktest: MPI_Comm_size == " << mpiHelper.size() << std::endl; { std::array n = { { 5, 5 } }; Dune::FieldVector h = { 1.0, 2.0 }; vtkCheck<2>(n,h); } { std::array n = { { 5, 5, 5 } }; Dune::FieldVector h = { 1.0, 2.0, 3.0 }; vtkCheck<3>(n,h); } } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } return 0; } dune-grid-2.11.0/dune/grid/io/file/test/printgridtest.cc000066400000000000000000000027261511655130300230560ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil -*- // Based on: Boilerplate tutorial poisson_uniform.cc #include #include #include #include int main(int argc, char **argv) { if (std::system("gnuplot --version") != 0) { std::cerr << "GNUplot was not found." << std::endl; std::exit(77); } try { // initialize MPI, finalize is done automatically on exit Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc,argv); // make grid const int dim = 2; Dune::FieldVector L(1.0); std::array N; std::fill(N.begin(), N.end(), 4); std::bitset periodic (false); periodic[0] = true; int overlap = 1; Dune::YaspGrid grid(L,N,periodic, overlap); // write .plt files (one for png, one for svg) without executing gnuplot on them Dune::printGrid (grid, helper, "printgridtest_yasp_svg", 4000, true, false); Dune::printGrid (grid, helper, "printgridtest_yasp_png", 4000, true); } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } // done return 0; } dune-grid-2.11.0/dune/grid/io/file/test/starcdreadertest.cc000066400000000000000000000030521511655130300235100ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 template void readGrid (const std::string& baseName) { // read the grid std::unique_ptr grid = Dune::StarCDReader::read(baseName); std::cout << "Starting grid tests ." << std::flush; // check macro grid gridcheck(*grid); std::cout << " passed." << std::endl; std::shared_ptr gridShared = Dune::StarCDReader::read(baseName); } int main (int argc , char **argv) try { // initialize MPI if necessary Dune::MPIHelper::instance(argc, argv); std::string gridDirectory = std::string(DUNE_GRID_EXAMPLE_GRIDS_PATH) + "starcd/"; // Currently, Star-CD only works for UGGrid readGrid >(gridDirectory + "star"); readGrid >(gridDirectory + "tets"); readGrid >(gridDirectory + "withprism"); readGrid >(gridDirectory + "withpyramid"); return 0; } catch (Dune::Exception& e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } dune-grid-2.11.0/dune/grid/io/file/test/subsamplingvtktest.cc000066400000000000000000000153201511655130300241170ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 template< class GridView > class VTKVectorFunction : public Dune :: VTKWriter< GridView > :: VTKFunction { // extract types constexpr static int n = GridView :: dimension; typedef typename GridView :: Grid :: ctype DT; typedef typename GridView :: template Codim< 0 > :: Entity Entity; const std::string type_; public: /** @brief Make a new VTKVectorFunction * * @param type_ Type of the function for use in its name (hint: "cell" or * "vertex") */ VTKVectorFunction(std::string type) : type_(type) { } //! return number of components virtual int ncomps () const { return n; } //! evaluate single component comp in the entity e at local coordinates xi /*! Evaluate the function in an entity at local coordinates. @param[in] comp number of component to be evaluated @param[in] e reference to grid entity of codimension 0 @param[in] xi point in local coordinates of the reference element of e \return value of the component */ virtual double evaluate ([[maybe_unused]] int comp, const Entity& e, const Dune::FieldVector& xi) const { Dune::FieldVector global = e.geometry().global( xi ); return global.two_norm2(); } // get name virtual std::string name () const { std::ostringstream os; os << type_ << "-vector-" << ncomps() << "D"; return os.str(); } }; // accumulate exit status void acc(int &accresult, int result) { if(accresult == 0 || (accresult == 77 && result != 0)) accresult = result; } struct Acc { int operator()(int v1, int v2) const { acc(v1, v2); return v1; } }; template< class GridView > int doWrite( Dune::VTKChecker& vtkChecker, const std::string& gridViewName, const GridView &gridView, bool coerceToSimplex, const std::string &refinementName, Dune::RefinementIntervals intervals ) { constexpr static int dim = GridView :: dimension; Dune :: SubsamplingVTKWriter< GridView > vtk( gridView, intervals, coerceToSimplex); // disabled due to FS#676: // const typename GridView :: IndexSet &is = gridView.indexSet(); // std::vector vertexdata(is.size(dim),dim); // std::vector celldata(is.size(0),0); // vtk.addVertexData(vertexdata,"vertexData"); // vtk.addCellData(celldata,"cellData"); vtk.addVertexData(std::make_shared< VTKVectorFunction >("vertex")); vtk.addCellData(std::make_shared< VTKVectorFunction >("cell")); int result = 0; std::string name; std::ostringstream prefix; prefix << "subsamplingvtktest-" << dim << "D-" << gridViewName << "-" << (coerceToSimplex ? "simplex" : "natural") << "-" << refinementName; int rank = gridView.comm().rank(); name = vtk.write(prefix.str() + "-ascii"); if(rank == 0) vtkChecker.push(name); name = vtk.write(prefix.str() + "-appendedraw", Dune::VTK::appendedraw); if(rank == 0) vtkChecker.push(name); return result; } template int vtkCheck(Dune::VTKChecker& vtkChecker, const std::array& elements, const Dune::FieldVector& upperRight) { using Dune::refinementIntervals; using Dune::refinementLevels; Dune::YaspGrid g(upperRight, elements); if(g.comm().rank() == 0) std::cout << std::endl << "subsamplingVTKCheck dim=" << dim << std::endl << std::endl; g.globalRefine(1); int result = 0; auto leafview = g.leafGridView(); auto coarselevelview = g.levelGridView( 0 ); auto finelevelview = g.levelGridView( g.maxLevel() ); acc(result, doWrite( vtkChecker, "leafview", leafview, true, "intervals3", refinementIntervals(3))); acc(result, doWrite( vtkChecker, "coarselevelview", coarselevelview, true, "intervals3", refinementIntervals(3))); acc(result, doWrite( vtkChecker, "finelevelview", finelevelview, true, "intervals3", refinementIntervals(3))); acc(result, doWrite( vtkChecker, "leafview", leafview, true, "levels1", refinementLevels(1))); acc(result, doWrite( vtkChecker, "coarselevelview", coarselevelview, true, "levels1", refinementLevels(1))); acc(result, doWrite( vtkChecker, "finelevelview", finelevelview, true, "levels1", refinementLevels(1))); acc(result, doWrite( vtkChecker, "leafview", leafview, false, "intervals3", refinementIntervals(3))); acc(result, doWrite( vtkChecker, "coarselevelview", coarselevelview, false, "intervals3", refinementIntervals(3))); acc(result, doWrite( vtkChecker, "finelevelview", finelevelview, false, "intervals3", refinementIntervals(3))); acc(result, doWrite( vtkChecker, "leafview", leafview, false, "levels1", refinementLevels(1))); acc(result, doWrite( vtkChecker, "coarselevelview", coarselevelview, false, "levels1", refinementLevels(1))); acc(result, doWrite( vtkChecker, "finelevelview", finelevelview, false, "levels1", refinementLevels(1))); return result; } int main(int argc, char **argv) { try { const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); if(mpiHelper.rank() == 0) std::cout << "subsamplingvtktest: MPI_Comm_size == " << mpiHelper.size() << std::endl; int result = 0; // pass by default Dune::VTKChecker vtkChecker; acc(result, vtkCheck<1>(vtkChecker, std::array{5}, {1.0})); acc(result, vtkCheck<2>(vtkChecker, std::array{5, 5}, {1.0, 2.0})); acc(result, vtkCheck<3>(vtkChecker, std::array{5, 5, 5}, {1.0, 2.0, 3.0})); acc(result, vtkChecker.check()); mpiHelper.getCommunication().allreduce(&result, 1); return result; } catch (Dune::Exception &e) { std::cerr << e << std::endl; return 1; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Generic exception!" << std::endl; return 2; } } dune-grid-2.11.0/dune/grid/io/file/test/test-linking.cc000066400000000000000000000011011511655130300225460ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #include #include #include /* #include "gridcheck.cc" #include "checkgeometryinfather.cc" #include "checkintersectionit.cc" #include "checkpartition.cc" */ template void test(Grid& grid) {} dune-grid-2.11.0/dune/grid/io/file/test/vtksequencetest.cc000066400000000000000000000137021511655130300234050ustar00rootroot00000000000000// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception // -*- 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 // dune headers #include #include #include // check that the files have equal amount of lines void checkFileEqualNumLines(const std::string& name1, const std::string& name2) { std::ifstream pvdFile1(name1); std::ifstream pvdFile2(name2); if (pvdFile1.fail()) DUNE_THROW(Dune::Exception, "File " << name1 << " could not be opened!"); if (pvdFile2.fail()) DUNE_THROW(Dune::Exception, "File " << name2 << " could not be opened!"); std::string line; unsigned int lines1 = 0, lines2 = 0; while (std::getline(pvdFile1, line)) ++lines1; while (std::getline(pvdFile2, line)) ++lines2; if (lines1 != lines2) DUNE_THROW(Dune::Exception, "Not the same number of lines (comparing " << name1 << " and " << name2 << ")"); } std::string VTKDataMode(Dune::VTK::DataMode dm) { switch(dm) { case Dune::VTK::conforming : return "conforming"; case Dune::VTK::nonconforming : return "nonconforming"; } return ""; } template< class GridView > class VTKVectorFunction : public Dune :: VTKWriter< GridView > :: VTKFunction { // extract types constexpr static int n = GridView :: dimension; constexpr static int w = GridView :: dimensionworld; typedef typename GridView :: Grid :: ctype DT; typedef typename GridView :: template Codim< 0 > :: Entity Entity; double time_; public: VTKVectorFunction() : time_(0) {} void setTime(double time) { time_ = time; } //! return number of components virtual int ncomps () const { return n; } //! evaluate single component comp in the entity e at local coordinates xi /*! Evaluate the function in an entity at local coordinates. @param[in] comp number of component to be evaluated @param[in] e reference to grid entity of codimension 0 @param[in] xi point in local coordinates of the reference element of e \return value of the component */ virtual double evaluate (int comp, [[maybe_unused]] const Entity& e, [[maybe_unused]] const Dune::FieldVector& xi) const { return comp*0.1*sin(time_*2.*Dune::MathematicalConstants