diff --git a/dumux/discretization/cellcentered/mpfa/CMakeLists.txt b/dumux/discretization/cellcentered/mpfa/CMakeLists.txt index 74af590a45f2b5e6d037d176d406526cfac016e3..4390abd49b98bdfd050568567b3d9ba78ffedd0f 100644 --- a/dumux/discretization/cellcentered/mpfa/CMakeLists.txt +++ b/dumux/discretization/cellcentered/mpfa/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory("omethod") install(FILES +computetransmissibility connectivitymap.hh darcyslaw.hh dualgridindexset.hh @@ -18,6 +19,8 @@ helper.hh interactionvolumebase.hh interactionvolumedatahandle.hh interactionvolume.hh +localassembler.hh +localfacedata.hh methods.hh properties.hh subcontrolvolumeface.hh diff --git a/dumux/discretization/cellcentered/mpfa/computetransmissibility.hh b/dumux/discretization/cellcentered/mpfa/computetransmissibility.hh new file mode 100644 index 0000000000000000000000000000000000000000..aad8b5474d042f1def6e79476efc1ad0557987db --- /dev/null +++ b/dumux/discretization/cellcentered/mpfa/computetransmissibility.hh @@ -0,0 +1,100 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * 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, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup CCMpfaDiscretization + * \brief This file contains free functions to evaluate the transmissibilities + * associated with flux evaluations across sub-control volume faces + * in the context of cell-centered Mpfa schemes. + */ +#ifndef DUMUX_DISCRETIZATION_CC_MPFA_COMPUTE_TRANSMISSIBILITY_HH +#define DUMUX_DISCRETIZATION_CC_MPFA_COMPUTE_TRANSMISSIBILITY_HH + +#include <dune/common/typetraits.hh> +#include <dune/common/fvector.hh> + +#include <dumux/common/math.hh> + +namespace Dumux +{ + +/*! + * \ingroup CCMpfaDiscretization + * \brief Free function to evaluate the Mpfa transmissibility associated + * with the flux (in the form of flux = T*gradU) across a + * sub-control volume face stemming from a given sub-control + * volume with corresponding tensor T. + * + * \param scv The iv-local sub-control volume + * \param scvf The grid sub-control volume face + * \param T The tensor living in the scv + * \param extrusionFactor The extrusion factor of the scv + */ +template<class Scv, class Scvf, class Tensor> +Dune::FieldVector< typename Tensor::field_type, Scv::myDimension > +computeMpfaTransmissibility(const Scv& scv, + const Scvf& scvf, + const Tensor& T, + typename Scv::ctype extrusionFactor) +{ + Dune::FieldVector< typename Tensor::field_type, Scv::myDimension > wijk; + for (unsigned int dir = 0; dir < Scv::myDimension; ++dir) + wijk[dir] = vtmv(scvf.unitOuterNormal(), T, scv.nu(dir)); + + wijk *= scvf.area()*extrusionFactor; + wijk /= scv.detX(); + + return wijk; +} + +/*! + * \ingroup CCMpfaDiscretization + * \brief Free function to evaluate the Mpfa transmissibility associated + * with the flux (in the form of flux = T*gradU) across a + * sub-control volume face stemming from a given sub-control + * volume with corresponding tensor T, where T is a scalar. + * + * \param scv The iv-local sub-control volume + * \param scvf The grid sub-control volume face + * \param t the scalar quantity living in the scv + * \param extrusionFactor The extrusion factor of the scv + */ +template< class Scv, + class Scvf, + class Tensor, + std::enable_if_t< Dune::IsNumber<Tensor>::value, int > = 1 > +Dune::FieldVector<Tensor, Scv::myDimension> +computeMpfaTransmissibility(const Scv& scv, + const Scvf& scvf, + Tensor t, + typename Scv::ctype extrusionFactor) +{ + Dune::FieldVector<Tensor, Scv::myDimension> wijk; + for (unsigned int dir = 0; dir < Scv::myDimension; ++dir) + wijk[dir] = vtmv(scvf.unitOuterNormal(), t, scv.nu(dir)); + + wijk *= scvf.area()*extrusionFactor; + wijk /= scv.detX(); + + return wijk; +} + +} // end namespace Dumux + +#endif diff --git a/dumux/discretization/cellcentered/mpfa/connectivitymap.hh b/dumux/discretization/cellcentered/mpfa/connectivitymap.hh index 3c7152e75b9f48069ee935a476535f5718dffda8..95073ed462527cc3659b57b2d5fa9d4694790fc3 100644 --- a/dumux/discretization/cellcentered/mpfa/connectivitymap.hh +++ b/dumux/discretization/cellcentered/mpfa/connectivitymap.hh @@ -18,8 +18,11 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief Stores the face indices corresponding to the neighbors of an element - * that contribute to the derivative calculation + * that contribute to the derivative calculation. Depending on if an + * mpfa scheme leads to a symmetric/unsymmetric sparsity pattern, the + * adequate implementation of the connectiviy map is chosen. */ #ifndef DUMUX_CC_MPFA_CONNECTIVITY_MAP_HH #define DUMUX_CC_MPFA_CONNECTIVITY_MAP_HH @@ -35,15 +38,15 @@ namespace Dumux template<class TypeTag, MpfaMethods method> class CCMpfaConnectivityMapImplementation; -// //! The Assembly map for models using mpfa methods +//! The Assembly map for models using mpfa methods template<class TypeTag> using CCMpfaConnectivityMap = CCMpfaConnectivityMapImplementation<TypeTag, GET_PROP_VALUE(TypeTag, MpfaMethod)>; -//! The default is the general assembly map for mpfa schemes +//! The default is the general assembly map for mpfa schemes (non-symmetric schemes) template<class TypeTag, MpfaMethods method> class CCMpfaConnectivityMapImplementation : public CCMpfaGeneralConnectivityMap<TypeTag> {}; -//! The o-method can use the simple assembly map +//! The o-method can use the simple (symmetric) assembly map template<class TypeTag> class CCMpfaConnectivityMapImplementation<TypeTag, MpfaMethods::oMethod> : public CCSimpleConnectivityMap<TypeTag> {}; } diff --git a/dumux/discretization/cellcentered/mpfa/darcyslaw.hh b/dumux/discretization/cellcentered/mpfa/darcyslaw.hh index 7aa203b3367c276ae4b0569c307d7454e746ae9d..487f56ca2189ec27292ae7727cf021938cef4677 100644 --- a/dumux/discretization/cellcentered/mpfa/darcyslaw.hh +++ b/dumux/discretization/cellcentered/mpfa/darcyslaw.hh @@ -18,27 +18,31 @@ *****************************************************************************/ /*! * \file - * \brief This file contains the class which is required to calculate - * volume and mass fluxes of fluid phases over a face of a finite volume by means - * of the Darcy approximation. This specializations is for cell-centered schemes - * using multi-point flux approximation. + * \ingroup CCMpfaDiscretization + * \brief Darcy's Law for cell-centered finite volume schemes + * with multi-point flux approximation. */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_DARCYS_LAW_HH #define DUMUX_DISCRETIZATION_CC_MPFA_DARCYS_LAW_HH +#include <dune/common/densevector.hh> +#include <dune/common/densematrix.hh> + #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> #include <dumux/discretization/methods.hh> +#include <dumux/discretization/methods.hh> + namespace Dumux { -// forward declarations +//! forward declaration of the method-specific implementation template<class TypeTag, DiscretizationMethods discMethod> class DarcysLawImplementation; /*! - * \ingroup Mpfa - * \brief Specialization of Darcy's Law for the CCMpfa method. + * \ingroup CCMpfaDiscretization + * \brief Darcy's law for cell-centered finite volume schemes with multi-point flux approximation. */ template <class TypeTag> class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> @@ -47,21 +51,13 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache); using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); - // Always use the dynamic type for vectors (compatibility with the boundary) - using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using CoefficientVector = typename PrimaryInteractionVolume::Traits::DynamicVector; - using DataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; - - static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); - static constexpr int dim = GridView::dimension; - static constexpr int dimWorld = GridView::dimensionworld; - //! Class that fills the cache corresponding to mpfa Darcy's Law class MpfaDarcysLawCacheFiller { @@ -77,14 +73,16 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> const SubControlVolumeFace& scvf, const FluxVariablesCacheFiller& fluxVarsCacheFiller) { - // get interaction volume from the flux vars cache filler & upate the cache + // get interaction volume related data from the filler class & upate the cache if (fvGeometry.fvGridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex())) scvfFluxVarsCache.updateAdvection(fluxVarsCacheFiller.secondaryInteractionVolume(), - fluxVarsCacheFiller.dataHandle(), + fluxVarsCacheFiller.secondaryIvLocalFaceData(), + fluxVarsCacheFiller.secondaryIvDataHandle(), scvf); else scvfFluxVarsCache.updateAdvection(fluxVarsCacheFiller.primaryInteractionVolume(), - fluxVarsCacheFiller.dataHandle(), + fluxVarsCacheFiller.primaryIvLocalFaceData(), + fluxVarsCacheFiller.primaryIvDataHandle(), scvf); } }; @@ -92,54 +90,137 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> //! The cache used in conjunction with the mpfa Darcy's Law class MpfaDarcysLawCache { - // We always use the dynamic types here to be compatible on the boundary - using Stencil = typename PrimaryInteractionVolume::Traits::DynamicGlobalIndexContainer; - using DirichletDataContainer = typename PrimaryInteractionVolume::DirichletDataContainer; + static constexpr int dim = GridView::dimension; + static constexpr int dimWorld = GridView::dimensionworld; + static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); + using GridIndexType = typename GridView::IndexSet::IndexType; + + // In the current implementation of the flux variables cache we cannot + // make a disctinction between dynamic (mpfa-o) and static (mpfa-l) + // matrix and vector types, as currently the cache class can only be templated + // by a type tag (and there can only be one). We use a dynamic vector here to + // make sure it works in case one of the two used interaction volume types uses + // dynamic types performance is thus lowered for schemes using static types. + // TODO: this has to be checked thoroughly as soon as a scheme using static types + // is implemented. One idea to overcome the performance drop could be only + // storing the iv-local index here and obtain tij always from the datahandle + // of the fluxVarsCacheContainer + using Vector = Dune::DynamicVector< Scalar >; + using Matrix = Dune::DynamicMatrix< Scalar >; + using Stencil = std::vector< GridIndexType >; + + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using PrimaryIvVector = typename PrimaryInteractionVolume::Traits::Vector; + using PrimaryIvMatrix = typename PrimaryInteractionVolume::Traits::Matrix; + using PrimaryStencil = typename PrimaryInteractionVolume::Traits::Stencil; + + static_assert( std::is_convertible<PrimaryIvVector*, Vector*>::value, + "The vector type used in primary interaction volumes is not convertible to Dune::DynamicVector!" ); + static_assert( std::is_convertible<PrimaryIvMatrix*, Matrix*>::value, + "The matrix type used in primary interaction volumes is not convertible to Dune::DynamicMatrix!" ); + static_assert( std::is_convertible<PrimaryStencil*, Stencil*>::value, + "The stencil type used in primary interaction volumes is not convertible to std::vector<GridIndexType>!" ); + + using SecondaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); + using SecondaryIvVector = typename SecondaryInteractionVolume::Traits::Vector; + using SecondaryIvMatrix = typename SecondaryInteractionVolume::Traits::Matrix; + using SecondaryStencil = typename SecondaryInteractionVolume::Traits::Stencil; + + static_assert( std::is_convertible<SecondaryIvVector*, Vector*>::value, + "The vector type used in secondary interaction volumes is not convertible to Dune::DynamicVector!" ); + static_assert( std::is_convertible<SecondaryIvMatrix*, Matrix*>::value, + "The matrix type used in secondary interaction volumes is not convertible to Dune::DynamicMatrix!" ); + static_assert( std::is_convertible<SecondaryStencil*, Stencil*>::value, + "The stencil type used in secondary interaction volumes is not convertible to std::vector<GridIndexType>!" ); public: // export the filler type using Filler = MpfaDarcysLawCacheFiller; - //! update cached objects - template<class InteractionVolume> - void updateAdvection(const InteractionVolume& iv, const DataHandle& dataHandle, const SubControlVolumeFace &scvf) + /*! + * \brief Update cached objects (transmissibilities and gravity) + * + * \tparam InteractionVolume The (mpfa scheme-specific) interaction volume + * \tparam LocalFaceData The object used to store iv-local info on an scvf + * \tparam DataHandle The object used to store transmissibility matrices etc. + * + * \param iv The interaction volume this scvf is embedded in + * \param localFaceData iv-local info on this scvf + * \param dataHandle Transmissibility matrix & gravity data of this iv + * \param scvf The sub-control volume face + */ + template< class InteractionVolume, class LocalFaceData, class DataHandle > + void updateAdvection(const InteractionVolume& iv, + const LocalFaceData& localFaceData, + const DataHandle& dataHandle, + const SubControlVolumeFace &scvf) { - const auto& localFaceData = iv.getLocalFaceData(scvf); + stencil_ = &iv.stencil(); + switchFluxSign_ = localFaceData.isOutside(); + + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + pj_[pIdx] = &dataHandle.pressures(pIdx); - // update the quantities that are equal for all phases - advectionSwitchFluxSign_ = localFaceData.isOutside(); - advectionVolVarsStencil_ = &dataHandle.volVarsStencil(); - advectionDirichletData_ = &dataHandle.dirichletData(); + static const bool enableGravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); + const auto ivLocalIdx = localFaceData.ivLocalScvfIndex(); - // the transmissibilities on surface grids have to be obtained from the outside + // standard grids if (dim == dimWorld) - advectionTij_ = &dataHandle.T()[localFaceData.ivLocalScvfIndex()]; + { + Tij_ = &dataHandle.advectionT()[ivLocalIdx]; + + if (enableGravity) + for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + g_[phaseIdx] = dataHandle.gravity(phaseIdx)[ivLocalIdx]; + } + + // surface grids else - advectionTij_ = localFaceData.isOutside() ? - &dataHandle.outsideTij()[localFaceData.ivLocalOutsideScvfIndex()] : - &dataHandle.T()[localFaceData.ivLocalScvfIndex()]; + { + if (!localFaceData.isOutside()) + { + Tij_ = &dataHandle.advectionT()[ivLocalIdx]; + + if (enableGravity) + for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + g_[phaseIdx] = dataHandle.gravity(phaseIdx)[ivLocalIdx]; + } + else + { + const auto idxInOutsideFaces = localFaceData.scvfLocalOutsideScvfIndex(); + Tij_ = &dataHandle.advectionTout()[ivLocalIdx][idxInOutsideFaces]; + + if (enableGravity) + for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) + g_[phaseIdx] = dataHandle.gravityOutside(phaseIdx)[ivLocalIdx][idxInOutsideFaces]; + } + } } - //! Returns the stencil for advective scvf flux computation - const Stencil& advectionVolVarsStencil() const { return *advectionVolVarsStencil_; } + //! The stencil corresponding to the transmissibilities + const Stencil& advectionStencil() const { return *stencil_; } + + //! Coefficients for the cell (& Dirichlet) unknowns in flux expressions + const Vector& advectionTij() const { return *Tij_; } - //! Returns the transmissibilities associated with the volume variables - //! All phases flow through the same rock, thus, tij are equal for all phases - const CoefficientVector& advectionTij() const { return *advectionTij_; } + //! The cell (& Dirichlet) pressures within this interaction volume + const Vector& pressures(unsigned int phaseIdx) const { return *pj_[phaseIdx]; } - //! On faces that are "outside" w.r.t. a face in the interaction volume, - //! we have to take the negative value of the fluxes, i.e. multiply by -1.0 - bool advectionSwitchFluxSign() const { return advectionSwitchFluxSign_; } + //! The gravitational acceleration for a phase on this scvf + Scalar gravity(unsigned int phaseIdx) const { return g_[phaseIdx]; } - //! Returns the data on dirichlet boundary conditions affecting - //! the flux computation on this face - const DirichletDataContainer& advectionDirichletData() const { return *advectionDirichletData_; } + //! In the interaction volume-local system of eq we have one unknown per face. + //! On scvfs on this face, but in "outside" (neighbor) elements of it, we have + //! to take the negative value of the fluxes due to the flipped normal vector. + //! This function returns whether or not this scvf is an "outside" face in the iv. + bool advectionSwitchFluxSign() const { return switchFluxSign_; } private: - bool advectionSwitchFluxSign_; - const Stencil* advectionVolVarsStencil_; - const CoefficientVector* advectionTij_; - const DirichletDataContainer* advectionDirichletData_; + bool switchFluxSign_; + const Stencil* stencil_; //!< The stencil, i.e. the grid indices j + const Vector* Tij_; //!< The transmissibilities such that f = Tij*pj + std::array< Scalar, numPhases > g_; //!< Gravitational flux contribution on this face + std::array<const Vector*, numPhases> pj_; //!< The interaction-volume wide phase pressures pj }; public: @@ -149,6 +230,7 @@ public: // export the type for the corresponding cache using Cache = MpfaDarcysLawCache; + //! Compute the advective flux across an scvf static Scalar flux(const Problem& problem, const Element& element, const FVElementGeometry& fvGeometry, @@ -157,78 +239,23 @@ public: const unsigned int phaseIdx, const ElementFluxVariablesCache& elemFluxVarsCache) { - static const bool gravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); - - // Calculate the interface density for gravity evaluation - const auto rho = interpolateDensity(elemVolVars, scvf, phaseIdx); - - // prepare computations - unsigned int i = 0; - Scalar scvfFlux(0.0); const auto& fluxVarsCache = elemFluxVarsCache[scvf]; const auto& tij = fluxVarsCache.advectionTij(); + const auto& pj = fluxVarsCache.pressures(phaseIdx); - // add contributions from cell-centered unknowns - for (const auto volVarIdx : fluxVarsCache.advectionVolVarsStencil()) - { - const auto& volVars = elemVolVars[volVarIdx]; - Scalar h = volVars.pressure(phaseIdx); - - // if gravity is enabled, add gravitational acceleration - if (gravity) - { - // gravitational acceleration in the center of the actual element - const auto x = fvGeometry.scv(volVarIdx).center(); - const auto g = problem.gravityAtPos(x); - h -= rho*(g*x); - } - - scvfFlux += tij[i++]*h; - } - - // add contributions from possible dirichlet boundary conditions - for (const auto& d : fluxVarsCache.advectionDirichletData()) - { - const auto& volVars = elemVolVars[d.volVarIndex()]; - Scalar h = volVars.pressure(phaseIdx); - - // maybe add gravitational acceleration - if (gravity) - { - const auto x = d.ipGlobal(); - const auto g = problem.gravityAtPos(x); - h -= rho*(g*x); - } + // compute t_ij*p_j + Scalar scvfFlux = tij*pj; - scvfFlux += tij[i++]*h; - } + // maybe add gravitational acceleration + static const bool enableGravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); + if (enableGravity) + scvfFlux += fluxVarsCache.gravity(phaseIdx); - // return the flux (maybe adjust the sign) - return fluxVarsCache.advectionSwitchFluxSign() ? -scvfFlux : scvfFlux; - } + // switch the sign if necessary + if (fluxVarsCache.advectionSwitchFluxSign()) + scvfFlux *= -1.0; -private: - static Scalar interpolateDensity(const ElementVolumeVariables& elemVolVars, - const SubControlVolumeFace& scvf, - const unsigned int phaseIdx) - { - static const bool gravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); - - if (!gravity) - return Scalar(0.0); - else - { - // use arithmetic mean of the densities around the scvf - if (!scvf.boundary()) - { - Scalar rho = elemVolVars[scvf.insideScvIdx()].density(phaseIdx); - for (const auto outsideIdx : scvf.outsideScvIndices()) - rho += elemVolVars[outsideIdx].density(phaseIdx); - return rho/(scvf.outsideScvIndices().size()+1); - } - else - return elemVolVars[scvf.outsideScvIdx()].density(phaseIdx); - } + return scvfFlux; } }; diff --git a/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh b/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh index d6e54463fd3a3fe7a51f615be072e9e33dd95c3f..d1bc781ab88ab6589e7b4dc24d18843abfcde3bb 100644 --- a/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh +++ b/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh @@ -18,39 +18,40 @@ *****************************************************************************/ /*! * \file - * \brief Base class for the index sets of the dual grid in mpfa schemes. + * \ingroup CCMpfaDiscretization + * \brief Class for the index sets of the dual grid in mpfa schemes. */ -#ifndef DUMUX_DISCRETIZATION_MPFA_DUALGRID_INDEXSET_BASE_HH -#define DUMUX_DISCRETIZATION_MPFA_DUALGRID_INDEXSET_BASE_HH - -#include <dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh> +#ifndef DUMUX_DISCRETIZATION_MPFA_DUALGRID_INDEX_SET_HH +#define DUMUX_DISCRETIZATION_MPFA_DUALGRID_INDEX_SET_HH namespace Dumux { /*! - * \ingroup Mpfa - * \brief Nodal index set for the dual grid of mpfa schemes. + * \ingroup CCMpfaDiscretization + * \brief Nodal index set for mpfa schemes, constructed + * around grid vertices. + * + * \tparam GI The type used for indices on the grid + * \tparam LI The type used for indexing in interaction volumes + * \tparam dim The dimension of the grid */ -template<class TypeTag> +template< class GI, class LI, int dim > class DualGridNodalIndexSet { - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; - using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using LocalIndexType = typename PrimaryInteractionVolume::Traits::LocalIndexType; - using LocalIndexContainer = typename PrimaryInteractionVolume::Traits::DynamicLocalIndexContainer; - using GlobalIndexContainer = typename PrimaryInteractionVolume::Traits::DynamicGlobalIndexContainer; +public: + using GridIndexType = GI; + using LocalIndexType = LI; - static const int dim = GridView::dimension; + // we use dynamic containers to store indices here + using GridIndexContainer = std::vector<GridIndexType>; + using LocalIndexContainer = std::vector<LocalIndexType>; -public: - //! constructor + //! Constructor DualGridNodalIndexSet() : numBoundaryScvfs_(0) {} - // Inserts data for a given scvf. This should only called once per scvf! + //! Inserts data for a given scvf + template<typename SubControlVolumeFace> void insert(const SubControlVolumeFace& scvf) { insert(scvf.boundary(), @@ -59,20 +60,21 @@ public: scvf.outsideScvIndices()); } - // Inserts data for a given scvf. This should only called once per scvf! + //! Inserts scvf data void insert(const bool boundary, - const IndexType scvfIdx, - const IndexType insideScvIdx, - const std::vector<IndexType>& outsideScvIndices) + const GridIndexType scvfIdx, + const GridIndexType insideScvIdx, + const std::vector<GridIndexType>& outsideScvIndices) { - // this should always be called only once - assert( std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx ) == scvfIndices_.end() && "scvf has already been inserted!"); + // this should always be called only once per scvf + assert(std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx ) == scvfIndices_.end() + && "scvf has already been inserted!"); // the local index of the scvf data about to be inserted const LocalIndexType curScvfLocalIdx = scvfIndices_.size(); - // add global scvf data - GlobalIndexContainer scvIndices; + // add grid scvf data + GridIndexContainer scvIndices; scvIndices.reserve(outsideScvIndices.size()+1); scvIndices.push_back(insideScvIdx); scvIndices.insert(scvIndices.end(), outsideScvIndices.begin(), outsideScvIndices.end()); @@ -86,7 +88,7 @@ public: scvfIsOnBoundary_.push_back(boundary); scvfNeighborScvIndices_.emplace_back( std::move(scvIndices) ); - // if entry for the inside scv exists append scvf local index, create otherwise + // if entry for the inside scv exists, append scvf local index, create otherwise auto it = std::find( scvIndices_.begin(), scvIndices_.end(), insideScvIdx ); if (it != scvIndices_.end()) localScvfIndicesInScv_[ std::distance(scvIndices_.begin(), it) ].push_back(curScvfLocalIdx); @@ -100,105 +102,96 @@ public: } } - //! returns the number of scvs + //! returns the number of scvs around the node std::size_t numScvs() const { return scvIndices_.size(); } - //! returns the number of scvfs + //! returns the number of scvfs around the node std::size_t numScvfs() const { return scvfIndices_.size(); } - //! returns the number of boundary scvfs + //! returns the number of boundary scvfs around the node std::size_t numBoundaryScvfs() const { return numBoundaryScvfs_; } //! returns the global scv indices connected to this dual grid node - const GlobalIndexContainer& globalScvIndices() const { return scvIndices_; } + const GridIndexContainer& globalScvIndices() const { return scvIndices_; } //! returns the global scvf indices connected to this dual grid node - const GlobalIndexContainer& globalScvfIndices() const { return scvfIndices_; } + const GridIndexContainer& globalScvfIndices() const { return scvfIndices_; } + + //! returns whether or not the i-th scvf is on a domain boundary + bool scvfIsOnBoundary(unsigned int i) const { return scvfIsOnBoundary_[i]; } //! returns the global scv idx of the i-th scv - IndexType scvIdxGlobal(unsigned int i) const { return scvIndices_[i]; } + GridIndexType scvIdxGlobal(unsigned int i) const { return scvIndices_[i]; } //! returns the index of the i-th scvf - IndexType scvfIdxGlobal(unsigned int i) const { return scvfIndices_[i]; } + GridIndexType scvfIdxGlobal(unsigned int i) const { return scvfIndices_[i]; } //! returns the global index of the j-th scvf embedded in the i-th scv - IndexType scvfIdxGlobal(unsigned int i, unsigned int j) const + GridIndexType scvfIdxGlobal(unsigned int i, unsigned int j) const { assert(j < dim); // only dim faces can be embedded in an scv return scvfIndices_[ localScvfIndicesInScv_[i][j] ]; } - //! returns the nodel-local index of the j-th scvf embedded in the i-th scv - IndexType scvfIdxLocal(unsigned int i, unsigned int j) const + //! returns the node-local index of the j-th scvf embedded in the i-th scv + LocalIndexType scvfIdxLocal(unsigned int i, unsigned int j) const { assert(j < dim); // only dim faces can be embedded in an scv return localScvfIndicesInScv_[i][j]; } - //! returns whether or not the i-th scvf touches the boundary - bool scvfIsOnBoundary(unsigned int i) const { return scvfIsOnBoundary_[i]; } - //! returns the indices of the neighboring scvs of the i-th scvf - const GlobalIndexContainer& neighboringScvIndices(unsigned int i) const + const GridIndexContainer& neighboringScvIndices(unsigned int i) const { return scvfNeighborScvIndices_[i]; } private: - //! the indices of the scvs around a dual grid node - GlobalIndexContainer scvIndices_; - //! maps to each scv a list of scvf indices embedded in it - std::vector<LocalIndexContainer> localScvfIndicesInScv_; - - //! the indices of the scvfs around a dual grid node - GlobalIndexContainer scvfIndices_; - //! maps to each scvf a boolean to indicate if it is on the boundary - std::vector<bool> scvfIsOnBoundary_; - //! maps to each scvf a list of neighbouring scv indices - //! ordering: 0 - inside scv idx; 1..n - outside scv indices - std::vector<GlobalIndexContainer> scvfNeighborScvIndices_; - //! stores how many boundary scvfs are embedded in this dual grid node - std::size_t numBoundaryScvfs_; + GridIndexContainer scvIndices_; //!< The indices of the scvs around a dual grid node + std::vector<LocalIndexContainer> localScvfIndicesInScv_; //!< Maps to each scv a list of scvf indices embedded in it + + GridIndexContainer scvfIndices_; //!< the indices of the scvfs around a dual grid node + std::vector<bool> scvfIsOnBoundary_; //!< Maps to each scvf a boolean to indicate if it is on the boundary + std::vector<GridIndexContainer> scvfNeighborScvIndices_; //!< The neighboring scvs for the scvfs (order: 0 - inside, 1..n - outside) + std::size_t numBoundaryScvfs_; //!< stores how many boundary scvfs are embedded in this dual grid node }; /*! - * \ingroup Mpfa + * \ingroup CCMpfaDiscretization * \brief Class for the index sets of the dual grid in mpfa schemes. + * + * \tparam GridIndexType The type used for indices on the grid + * \tparam LocalIndexType The type used for indexing in interaction volumes + * \tparam dim The dimension of the grid */ -template<class TypeTag> +template< class GridIndexType, class LocalIndexType, int dim > class CCMpfaDualGridIndexSet { - using ParentType = std::vector<DualGridNodalIndexSet<TypeTag>>; - - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - - static const int dim = GridView::dimension; - public: - using NodalIndexSet = DualGridNodalIndexSet<TypeTag>; + using NodalIndexSet = DualGridNodalIndexSet< GridIndexType, LocalIndexType, dim >; - //! default constructor + //! Default constructor should not be used CCMpfaDualGridIndexSet() = delete; - //! constructor - explicit CCMpfaDualGridIndexSet(const GridView& gridView) : nodalIndexSets_(gridView.size(dim)) {} + //! Constructor taking a grid view + template< class GridView > + CCMpfaDualGridIndexSet(const GridView& gridView) : nodalIndexSets_(gridView.size(dim)) {} - //! access with an scvf + //! Access with an scvf + template< class SubControlVolumeFace > const NodalIndexSet& operator[] (const SubControlVolumeFace& scvf) const { return nodalIndexSets_[scvf.vertexIndex()]; } + + template< class SubControlVolumeFace > NodalIndexSet& operator[] (const SubControlVolumeFace& scvf) { return nodalIndexSets_[scvf.vertexIndex()]; } - //! access with an index - const NodalIndexSet& operator[] (IndexType i) const - { return nodalIndexSets_[i]; } - NodalIndexSet& operator[] (IndexType i) - { return nodalIndexSets_[i]; } + //! Access with an index + const NodalIndexSet& operator[] (GridIndexType i) const { return nodalIndexSets_[i]; } + NodalIndexSet& operator[] (GridIndexType i) { return nodalIndexSets_[i]; } private: std::vector<NodalIndexSet> nodalIndexSets_; }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/elementfluxvariablescache.hh b/dumux/discretization/cellcentered/mpfa/elementfluxvariablescache.hh index 7e9281db78d17988fd21656319d4f718e491b07e..313cf34659b7ecd614d60f39fd8e517a13672483 100644 --- a/dumux/discretization/cellcentered/mpfa/elementfluxvariablescache.hh +++ b/dumux/discretization/cellcentered/mpfa/elementfluxvariablescache.hh @@ -18,14 +18,17 @@ *****************************************************************************/ /*! * \file - * \brief The local object of flux var caches + * \ingroup CCMpfaDiscretization + * \brief The element-local object of flux variables caches */ #ifndef DUMUX_DISCRETIZATION_CCMPFA_ELEMENT_FLUXVARSCACHE_HH #define DUMUX_DISCRETIZATION_CCMPFA_ELEMENT_FLUXVARSCACHE_HH #include <dune/common/exceptions.hh> + #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> + #include "fluxvariablescachefiller.hh" #include "methods.hh" @@ -33,56 +36,61 @@ namespace Dumux { /*! - * \ingroup ImplicitModel - * \brief Base class for the local flux variables cache. - * Prepares the cache on all the faces in the stencil. + * \ingroup CCMpfaDiscretization + * \brief The flux variables caches for an element + * \note The class is specialized for a version with and without caching. + * If grid caching is enabled the flux caches are stored for the whole + * gridview in the corresponding GridFluxVariablesCache. This is memory + * intensive but faster. For caching disabled, the flux caches are locally + * computed for each element whenever needed. */ template<class TypeTag, bool EnableGridFluxVariablesCache> class CCMpfaElementFluxVariablesCache; /*! - * \ingroup ImplicitModel - * \brief Spezialization when caching globally + * \ingroup CCMpfaDiscretization + * \brief The flux variables caches for an element with caching enabled */ template<class TypeTag> class CCMpfaElementFluxVariablesCache<TypeTag, true> { - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; using Element = typename GridView::template Codim<0>::Entity; + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); using GridFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, GridFluxVariablesCache); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + public: + //! The constructor CCMpfaElementFluxVariablesCache(const GridFluxVariablesCache& global) : gridFluxVarsCachePtr_(&global) {} - // Specialization for the global caching being enabled - do nothing here + //! Specialization for the global caching being enabled - do nothing here void bindElement(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) {} - // Specialization for the global caching being enabled - do nothing here + //! Specialization for the global caching being enabled - do nothing here void bind(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) {} - // Specialization for the global caching being enabled - do nothing here + //! Specialization for the global caching being enabled - do nothing here void bindScvf(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, const SubControlVolumeFace& scvf) {} - // Specialization for the global caching being enabled - do nothing here + //! Specialization for the global caching being enabled - do nothing here void update(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) {} - // access operators in the case of caching + //! access operators in the case of caching const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const { return (*gridFluxVarsCachePtr_)[scvf]; } @@ -95,54 +103,55 @@ private: }; /*! - * \ingroup ImplicitModel - * \brief Spezialization when not using global caching + * \ingroup CCMpfaDiscretization + * \brief The flux variables caches for an element with caching disabled */ template<class TypeTag> class CCMpfaElementFluxVariablesCache<TypeTag, false> { - // the flux variables cache filler needs to be friend to fill - // the interaction volumes and data handles - friend CCMpfaFluxVariablesCacheFiller<TypeTag>; - - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; + using GridIndexType = typename GridView::IndexSet::IndexType; using Element = typename GridView::template Codim<0>::Entity; + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); using GridFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, GridFluxVariablesCache); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using FluxVariablesCacheFiller = CCMpfaFluxVariablesCacheFiller<TypeTag>; - using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using PrimaryIvDataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; using SecondaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); - using DataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; - - static constexpr int dim = GridView::dimension; + using SecondaryIvDataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; public: CCMpfaElementFluxVariablesCache(const GridFluxVariablesCache& global) : gridFluxVarsCachePtr_(&global) {} - // This function has to be called prior to flux calculations on the element. - // Prepares the transmissibilities of the scv faces in an element. The FvGeometry is assumed to be bound. + /*! + * \brief Prepares the transmissibilities of the scv faces in an element + * \note the fvGeometry is assumed to be bound to the same element + * \note this function has to be called prior to flux calculations on the element. + */ void bindElement(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) { - // TODO + // For mpfa schemes we will have to prepare the caches of all scvfs that are + // embedded in the interaction volumes in which the element-local scvfs are embedded DUNE_THROW(Dune::NotImplemented, "Local element binding of the flux variables cache in mpfa schemes"); } - // This function is called by the CCLocalResidual before flux calculations during assembly. - // Prepares the transmissibilities of the scv faces in the stencil. The FvGeometries are assumed to be bound. + /*! + * \brief Prepares the transmissibilities of the scv faces in the stencil of an element + * \note the fvGeometry is assumed to be bound to the same element + * \note this function has to be called prior to flux calculations on the element. + */ void bind(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) { - // clear data clear_(); // some references for convenience @@ -202,22 +211,31 @@ public: } } + /*! + * \brief Prepares the transmissibilities of a single scv face + * \note the fvGeometry is assumed to be bound to the same element + * \note this function has to be called prior to flux calculations on this scvf. + */ void bindScvf(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, const SubControlVolumeFace& scvf) { - // TODO - DUNE_THROW(Dune::NotImplemented, "Local element binding of the flux variables cache in mpfa schemes"); + // For mpfa schemes we will have to prepare the caches of all + // scvfs that are embedded in the interaction volumes this scvf is embedded + DUNE_THROW(Dune::NotImplemented, "Scvf-local binding of the flux variables cache in mpfa schemes"); } - // This function is used to update the transmissibilities if the volume variables have changed - // Results in undefined behaviour if called before bind() or with a different element + /*! + * \brief Update the transmissibilities if the volume variables have changed + * \note Results in undefined behaviour if called before bind() or with a different element + */ void update(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) { - // update only if transmissibilities are solution-dependent + // Update only if the filler puts + // solution-dependent stuff into the caches if (FluxVariablesCacheFiller::isSolDependent) { const auto& problem = gridFluxVarsCache().problem(); @@ -253,19 +271,54 @@ public: } } - // access operators in the case of no caching + //! access operators in the case of no caching const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const { return fluxVarsCache_[getLocalScvfIdx_(scvf.index())]; } - const FluxVariablesCache& operator [](const IndexType scvfIdx) const + //! access operators in the case of no caching + const FluxVariablesCache& operator [](const GridIndexType scvfIdx) const { return fluxVarsCache_[getLocalScvfIdx_(scvfIdx)]; } + //! access operators in the case of no caching FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) { return fluxVarsCache_[getLocalScvfIdx_(scvf.index())]; } - FluxVariablesCache& operator [](const IndexType scvfIdx) + //! access operators in the case of no caching + FluxVariablesCache& operator [](const GridIndexType scvfIdx) { return fluxVarsCache_[getLocalScvfIdx_(scvfIdx)]; } + //! access to the stored interaction volumes + const std::vector<PrimaryInteractionVolume>& primaryInteractionVolumes() const + { return primaryInteractionVolumes_; } + + //! access to the stored interaction volumes + std::vector<PrimaryInteractionVolume>& primaryInteractionVolumes() + { return primaryInteractionVolumes_; } + + //! access to the stored data handles + const std::vector<PrimaryIvDataHandle>& primaryDataHandles() const + { return primaryIvDataHandles_; } + + //! access to the stored data handles + std::vector<PrimaryIvDataHandle>& primaryDataHandles() + { return primaryIvDataHandles_; } + + //! access to the stored interaction volumes + const std::vector<SecondaryInteractionVolume>& secondaryInteractionVolumes() const + { return secondaryInteractionVolumes_; } + + //! access to the stored interaction volumes + std::vector<SecondaryInteractionVolume>& secondaryInteractionVolumes() + { return secondaryInteractionVolumes_; } + + //! access to the stored data handles + const std::vector<SecondaryIvDataHandle>& secondaryDataHandles() const + { return secondaryIvDataHandles_; } + + //! access to the stored data handles + std::vector<SecondaryIvDataHandle>& secondaryDataHandles() + { return secondaryIvDataHandles_; } + //! The global object we are a restriction of const GridFluxVariablesCache& gridFluxVarsCache() const { return *gridFluxVarsCachePtr_; } @@ -273,6 +326,7 @@ public: private: const GridFluxVariablesCache* gridFluxVarsCachePtr_; + //! clears all containers void clear_() { fluxVarsCache_.clear(); @@ -283,35 +337,27 @@ private: secondaryIvDataHandles_.clear(); } - // get number of interaction volumes that are going to be required + //! get estimate of interaction volumes that are going to be required template<class AssemblyMap> std::size_t getNoInteractionVolumesEstimate_(const Element& element, const AssemblyMap& assemblyMap) { - // TODO: uncomment as soon as methods are re-implemented // if statements are optimized away by the compiler - if (GET_PROP_VALUE(TypeTag, MpfaMethod) == MpfaMethods::oMethod /*|| method == MpfaMethods::oMethodFps*/) + if (GET_PROP_VALUE(TypeTag, MpfaMethod) == MpfaMethods::oMethod) { - //! Reserve memory for the case of each facet having neighbors being 4 levels higher. Memory limitations - //! do not play an important role here as global caching is disabled. In the unlikely case you want - //! to use higher local differences in element levels set a higher value for the parameter below - //! in your input file (note that some grids might only support levels differences of one anyway) + // Reserve memory for the case of each facet having neighbors being 4 levels higher. Memory limitations + // do not play an important role here as global caching is disabled. In the unlikely case you want + // to use higher local differences in element levels set a higher value for the parameter below + // in your input file (note that some grids might only support levels differences of one anyway) static const unsigned int maxDiff = getParamFromGroup<unsigned int>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Grid.MaxLocalElementLevelDifference", 4); - return element.subEntities(dim)*maxDiff; + return element.subEntities(GridView::dimension)*maxDiff; } - /* else if (method == MpfaMethods::lMethod) - { - std::size_t numInsideScvfs = MpfaHelper::getNumLocalScvfs(element.geometry().type()); - std::size_t numOutsideScvf = 0; - for (const auto& dataJ : assemblyMap) numOutsideScvf += dataJ.scvfsJ.size(); - return numOutsideScvf - numInsideScvfs; - }*/ else DUNE_THROW(Dune::NotImplemented, "number of interaction volumes estimate for chosen mpfa scheme"); } - // get index of an scvf in the local container + //! get index of an scvf in the local container unsigned int getLocalScvfIdx_(const int scvfIdx) const { auto it = std::find(globalScvfIndices_.begin(), globalScvfIndices_.end(), scvfIdx); @@ -320,15 +366,15 @@ private: } - // the local flux vars caches and the index set + // the local flux vars caches and corresponding indices std::vector<FluxVariablesCache> fluxVarsCache_; - std::vector<IndexType> globalScvfIndices_; + std::vector<GridIndexType> globalScvfIndices_; - // store the interaction volumes and handles + // stored interaction volumes and handles std::vector<PrimaryInteractionVolume> primaryInteractionVolumes_; std::vector<SecondaryInteractionVolume> secondaryInteractionVolumes_; - std::vector<DataHandle> primaryIvDataHandles_; - std::vector<DataHandle> secondaryIvDataHandles_; + std::vector<PrimaryIvDataHandle> primaryIvDataHandles_; + std::vector<SecondaryIvDataHandle> secondaryIvDataHandles_; }; } // end namespace diff --git a/dumux/discretization/cellcentered/mpfa/elementvolumevariables.hh b/dumux/discretization/cellcentered/mpfa/elementvolumevariables.hh index c1098567c841bec79bad303b4d5ce3965f2c1e9d..6269dd5ca43d74fe8bfef2bc84ffc33fd6722a98 100644 --- a/dumux/discretization/cellcentered/mpfa/elementvolumevariables.hh +++ b/dumux/discretization/cellcentered/mpfa/elementvolumevariables.hh @@ -18,6 +18,7 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief The local (stencil) volume variables class for cell centered mpfa models */ #ifndef DUMUX_DISCRETIZATION_CCMPFA_ELEMENT_VOLUMEVARIABLES_HH @@ -26,55 +27,60 @@ #include <utility> #include <dumux/common/properties.hh> -namespace Dumux { +namespace Dumux +{ /*! - * \ingroup ImplicitModel - * \brief Base class for the local volume variables vector + * \ingroup CCMpfaDiscretization + * \brief The local (stencil) volume variables class for cell centered mpfa models + * \note The class is specilized for versions with and without caching */ template<class TypeTag, bool enableGridVolVarsCache> -class CCMpfaElementVolumeVariables -{}; +class CCMpfaElementVolumeVariables; -// specialization in case of storing the volume variables globally +/*! + * \ingroup CCMpfaDiscretization + * \brief The local (stencil) volume variables class for cell centered mpfa models with caching + * \note the volume variables are stored for the whole grid view in the corresponding GridVolumeVariables class + */ template<class TypeTag> class CCMpfaElementVolumeVariables<TypeTag, /*enableGridVolVarsCache*/true> { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Element = typename GridView::template Codim<0>::Entity; + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables); using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); - using IndexType = typename GridView::IndexSet::IndexType; - - static const int dim = GridView::dimension; - using Element = typename GridView::template Codim<0>::Entity; + using GridIndexType = typename GridView::IndexSet::IndexType; public: //! Constructor CCMpfaElementVolumeVariables(const GridVolumeVariables& gridVolVars) : gridVolVarsPtr_(&gridVolVars) {} + //! operator for the access with an scv const VolumeVariables& operator [](const SubControlVolume& scv) const { return gridVolVars().volVars(scv.dofIndex()); } - // operator for the access with an index - // needed for cc methods for the access to the boundary volume variables - const VolumeVariables& operator [](const IndexType scvIdx) const + //! operator for the access with an index + const VolumeVariables& operator [](const GridIndexType scvIdx) const { return gridVolVars().volVars(scvIdx); } - // For compatibility reasons with the case of not storing the vol vars. - // function to be called before assembling an element, preparing the vol vars within the stencil + //! precompute all volume variables in a stencil of an element - do nothing volVars: are cached void bind(const Element& element, const FVElementGeometry& fvGeometry, - const SolutionVector& sol) {} + const SolutionVector& sol) + {} - // function to prepare the vol vars within the element + //! precompute the volume variables of an element - do nothing: volVars are cached void bindElement(const Element& element, const FVElementGeometry& fvGeometry, - const SolutionVector& sol) {} + const SolutionVector& sol) + {} //! The global volume variables object we are a restriction of const GridVolumeVariables& gridVolVars() const @@ -85,36 +91,38 @@ private: }; -// Specialization when the current volume variables are not stored +/*! + * \ingroup CCMpfaDiscretization + * \brief The local (stencil) volume variables class for cell centered tpfa models with caching + */ template<class TypeTag> class CCMpfaElementVolumeVariables<TypeTag, /*enableGridVolVarsCache*/false> { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); + using Element = typename GridView::template Codim<0>::Entity; + using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); using ElementSolution = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector); using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables); using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using IndexType = typename GridView::IndexSet::IndexType; + using GridIndexType = typename GridView::IndexSet::IndexType; - static const int dim = GridView::dimension; - using Element = typename GridView::template Codim<0>::Entity; public: - //! Constructor CCMpfaElementVolumeVariables(const GridVolumeVariables& gridVolVars) : gridVolVarsPtr_(&gridVolVars) {} - // Binding of an element, prepares the volume variables within the element stencil - // called by the local jacobian to prepare element assembly + //! Prepares the volume variables within the element stencil void bind(const Element& element, const FVElementGeometry& fvGeometry, const SolutionVector& sol) { + clear(); + const auto& problem = gridVolVars().problem(); const auto& fvGridGeometry = fvGeometry.fvGridGeometry(); const auto& gridIvIndexSets = fvGridGeometry.gridInteractionVolumeIndexSets(); @@ -151,7 +159,7 @@ public: ++localIdx; } - // eventually prepare boundary volume variables + // maybe prepare boundary volume variables const auto maxNumBoundaryVolVars = maxNumBoundaryVolVars_(fvGeometry); if (maxNumBoundaryVolVars > 0) { @@ -167,7 +175,8 @@ public: const auto bcTypes = problem.boundaryTypes(element, scvf); - // on dirichlet boundaries use dirichlet values + // Only proceed on dirichlet boundaries. Fluxes across Neumann + // boundaries are never computed - the user-defined flux is taken. if (bcTypes.hasOnlyDirichlet()) { // boundary volume variables @@ -180,12 +189,6 @@ public: volumeVariables_.emplace_back(std::move(dirichletVolVars)); volVarIndices_.push_back(scvf.outsideScvIdx()); } - // use the inside volume variables for neumann boundaries - else - { - volumeVariables_.emplace_back(volumeVariables_[0]); - volVarIndices_.push_back(scvf.outsideScvIdx()); - } } // Update boundary volume variables in the neighbors @@ -194,16 +197,13 @@ public: if (fvGridGeometry.vertexUsesPrimaryInteractionVolume(scvf.vertexIndex())) { const auto& nodalIndexSet = gridIvIndexSets.primaryIndexSet(scvf).nodalIndexSet(); - // if present, insert boundary vol vars if (nodalIndexSet.numBoundaryScvfs() > 0) addBoundaryVolVars_(problem, fvGeometry, nodalIndexSet); - } else { const auto& nodalIndexSet = gridIvIndexSets.secondaryIndexSet(scvf).nodalIndexSet(); - // if present, insert boundary vol vars if (nodalIndexSet.numBoundaryScvfs() > 0) addBoundaryVolVars_(problem, fvGeometry, nodalIndexSet); @@ -235,11 +235,13 @@ public: // } } - // Binding of an element, prepares only the volume variables of the element + //! Prepares the volume variables of an element void bindElement(const Element& element, const FVElementGeometry& fvGeometry, const SolutionVector& sol) { + clear(); + auto eIdx = fvGeometry.fvGridGeometry().elementMapper().index(element); volumeVariables_.resize(1); volVarIndices_.resize(1); @@ -253,29 +255,40 @@ public: volVarIndices_[0] = scv.dofIndex(); } + //! access operator with scv const VolumeVariables& operator [](const SubControlVolume& scv) const { return volumeVariables_[getLocalIdx_(scv.dofIndex())]; } + //! access operator with scv VolumeVariables& operator [](const SubControlVolume& scv) { return volumeVariables_[getLocalIdx_(scv.dofIndex())]; } - const VolumeVariables& operator [](IndexType scvIdx) const + //! access operator with scv index + const VolumeVariables& operator [](GridIndexType scvIdx) const { return volumeVariables_[getLocalIdx_(scvIdx)]; } - VolumeVariables& operator [](IndexType scvIdx) + //! access operator with scv index + VolumeVariables& operator [](GridIndexType scvIdx) { return volumeVariables_[getLocalIdx_(scvIdx)]; } //! The global volume variables object we are a restriction of const GridVolumeVariables& gridVolVars() const { return *gridVolVarsPtr_; } + //! Clear all local storage + void clear() + { + volVarIndices_.clear(); + volumeVariables_.clear(); + } + private: const GridVolumeVariables* gridVolVarsPtr_; - //! Computes how many boundary vol vars come into play for flux calculations - //! on this element. This number is probably almost always higher than the actually - //! needed number of volume variables. However, memory is not an issue for the global - //! caching being deactivated and we want to make sure we reserve enough memory here. + // Computes how many boundary vol vars come into play for flux calculations + // on this element. This number here is probably always higher than the actually + // needed number of volume variables. However, memory is not an issue for the global + // caching being deactivated and we want to make sure we reserve enough memory here. // TODO: What about non-symmetric schemes? Is there a better way for estimating this? std::size_t maxNumBoundaryVolVars_(const FVElementGeometry& fvGeometry) { @@ -311,10 +324,10 @@ private: const auto insideElement = fvGeometry.fvGridGeometry().element(insideScvIdx); const auto bcTypes = problem.boundaryTypes(insideElement, ivScvf); - // on dirichlet boundaries use dirichlet values + // Only proceed on dirichlet boundaries. Fluxes across Neumann + // boundaries are never computed - the user-defined flux is taken. if (bcTypes.hasOnlyDirichlet()) { - // boundary volume variables VolumeVariables dirichletVolVars; const auto& ivScv = fvGeometry.scv(insideScvIdx); dirichletVolVars.update(ElementSolution(problem.dirichlet(insideElement, ivScvf)), @@ -325,15 +338,10 @@ private: volumeVariables_.emplace_back(std::move(dirichletVolVars)); volVarIndices_.push_back(ivScvf.outsideScvIdx()); } - // use the inside volume variables for neumann boundaries - else - { - volumeVariables_.emplace_back((*this)[insideScvIdx]); - volVarIndices_.push_back(ivScvf.outsideScvIdx()); - } } } + //! map a global scv index to the local storage index int getLocalIdx_(const int volVarIdx) const { auto it = std::find(volVarIndices_.begin(), volVarIndices_.end(), volVarIdx); @@ -341,7 +349,7 @@ private: return std::distance(volVarIndices_.begin(), it); } - std::vector<IndexType> volVarIndices_; + std::vector<GridIndexType> volVarIndices_; std::vector<VolumeVariables> volumeVariables_; }; diff --git a/dumux/discretization/cellcentered/mpfa/fickslaw.hh b/dumux/discretization/cellcentered/mpfa/fickslaw.hh index e94332d2ec47e2eddbaed466444740628bf519a4..d3b2d0cc857850c97ccaf277d159ecaf6ccce5d5 100644 --- a/dumux/discretization/cellcentered/mpfa/fickslaw.hh +++ b/dumux/discretization/cellcentered/mpfa/fickslaw.hh @@ -18,9 +18,8 @@ *****************************************************************************/ /*! * \file - * \brief This file contains the class which is required to calculate - * molar and mass fluxes of a component in a fluid phase over a face of a finite volume by means - * of Fick's Law for cell-centered MPFA models. + * \ingroup CCMpfaDiscretization + * \brief Fick's law for cell-centered finite volume schemes with multi-point flux approximation */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_FICKS_LAW_HH #define DUMUX_DISCRETIZATION_CC_MPFA_FICKS_LAW_HH @@ -29,15 +28,15 @@ #include <dumux/common/properties.hh> #include <dumux/discretization/methods.hh> -namespace Dumux { - -// forward declaration +namespace Dumux +{ +//! forward declaration of the method-specific implemetation template<class TypeTag, DiscretizationMethods discMethod> class FicksLawImplementation; /*! - * \ingroup Mpfa - * \brief Specialization of Fick's Law for the CCMpfa method. + * \ingroup CCMpfaDiscretization + * \brief Fick's law for cell-centered finite volume schemes with multi-point flux approximation */ template <class TypeTag> class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> @@ -46,6 +45,7 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); @@ -54,14 +54,6 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); using BalanceEqOpts = typename GET_PROP_TYPE(TypeTag, BalanceEqOpts); - // Always use the dynamic type for vectors (compatibility with the boundary) - using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using CoefficientVector = typename PrimaryInteractionVolume::Traits::DynamicVector; - using DataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; - - static constexpr int dim = GridView::dimension; - static constexpr int dimWorld = GridView::dimensionworld; - static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); static constexpr int numComponents = GET_PROP_VALUE(TypeTag,NumComponents); using ComponentFluxVector = Dune::FieldVector<Scalar, numComponents>; @@ -81,78 +73,127 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> const SubControlVolumeFace& scvf, const FluxVariablesCacheFiller& fluxVarsCacheFiller) { - // get interaction volume from the flux vars cache filler & upate the cache - if (fvGeometry.fvGridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex())) - scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.secondaryInteractionVolume(), - fluxVarsCacheFiller.dataHandle(), - scvf, phaseIdx, compIdx); - else - scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.primaryInteractionVolume(), - fluxVarsCacheFiller.dataHandle(), - scvf, phaseIdx, compIdx); + // get interaction volume related data from the filler class & upate the cache + if (fvGeometry.fvGridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex())) + scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.secondaryInteractionVolume(), + fluxVarsCacheFiller.secondaryIvLocalFaceData(), + fluxVarsCacheFiller.secondaryIvDataHandle(), + scvf, phaseIdx, compIdx); + else + scvfFluxVarsCache.updateDiffusion(fluxVarsCacheFiller.primaryInteractionVolume(), + fluxVarsCacheFiller.primaryIvLocalFaceData(), + fluxVarsCacheFiller.primaryIvDataHandle(), + scvf, phaseIdx, compIdx); } }; //! The cache used in conjunction with the mpfa Fick's Law class MpfaFicksLawCache { - // We always use the dynamic types here to be compatible on the boundary - using Stencil = typename PrimaryInteractionVolume::Traits::DynamicGlobalIndexContainer; - using DirichletDataContainer = typename PrimaryInteractionVolume::DirichletDataContainer; + // In the current implementation of the flux variables cache we cannot + // make a disctinction between dynamic (mpfa-o) and static (mpfa-l) + // matrix and vector types, as currently the cache class can only be templated + // by a type tag (and there can only be one). We use a dynamic vector here to + // make sure it works in case one of the two used interaction volume types uses + // dynamic types performance is thus lowered for schemes using static types. + // TODO: this has to be checked thoroughly as soon as a scheme using static types + // is implemented. One idea to overcome the performance drop could be only + // storing the iv-local index here and obtain tij always from the datahandle + // of the fluxVarsCacheContainer + using GridIndexType = typename GridView::IndexSet::IndexType; + using Vector = Dune::DynamicVector< Scalar >; + using Matrix = Dune::DynamicMatrix< Scalar >; + using Stencil = std::vector< GridIndexType >; + + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using PrimaryIvVector = typename PrimaryInteractionVolume::Traits::Vector; + using PrimaryIvMatrix = typename PrimaryInteractionVolume::Traits::Matrix; + using PrimaryStencil = typename PrimaryInteractionVolume::Traits::Stencil; + + static_assert( std::is_convertible<PrimaryIvVector*, Vector*>::value, + "The vector type used in primary interaction volumes is not convertible to Dune::DynamicVector!" ); + static_assert( std::is_convertible<PrimaryIvMatrix*, Matrix*>::value, + "The matrix type used in primary interaction volumes is not convertible to Dune::DynamicMatrix!" ); + static_assert( std::is_convertible<PrimaryStencil*, Stencil*>::value, + "The stencil type used in primary interaction volumes is not convertible to std::vector<GridIndexType>!" ); + + using SecondaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); + using SecondaryIvVector = typename SecondaryInteractionVolume::Traits::Vector; + using SecondaryIvMatrix = typename SecondaryInteractionVolume::Traits::Matrix; + using SecondaryStencil = typename SecondaryInteractionVolume::Traits::Stencil; + + static_assert( std::is_convertible<SecondaryIvVector*, Vector*>::value, + "The vector type used in secondary interaction volumes is not convertible to Dune::DynamicVector!" ); + static_assert( std::is_convertible<SecondaryIvMatrix*, Matrix*>::value, + "The matrix type used in secondary interaction volumes is not convertible to Dune::DynamicMatrix!" ); + static_assert( std::is_convertible<SecondaryStencil*, Stencil*>::value, + "The stencil type used in secondary interaction volumes is not convertible to std::vector<GridIndexType>!" ); + + static constexpr int dim = GridView::dimension; + static constexpr int dimWorld = GridView::dimensionworld; + static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); public: // export filler type using Filler = MpfaFicksLawCacheFiller; - // update cached objects for the diffusive fluxes - template<class InteractionVolume> + /*! + * \brief Update cached objects (transmissibilities) + * + * \tparam InteractionVolume The (mpfa scheme-specific) interaction volume + * \tparam LocalFaceData The object used to store iv-local info on an scvf + * \tparam DataHandle The object used to store transmissibility matrices etc. + * + * \param iv The interaction volume this scvf is embedded in + * \param localFaceData iv-local info on this scvf + * \param dataHandle Transmissibility matrix & gravity data of this iv + * \param scvf The sub-control volume face + */ + template<class InteractionVolume, class LocalFaceData, class DataHandle> void updateDiffusion(const InteractionVolume& iv, + const LocalFaceData& localFaceData, const DataHandle& dataHandle, const SubControlVolumeFace &scvf, unsigned int phaseIdx, unsigned int compIdx) { - const auto& localFaceData = iv.getLocalFaceData(scvf); + stencil_[phaseIdx][compIdx] = &iv.stencil(); + switchFluxSign_[phaseIdx][compIdx] = localFaceData.isOutside(); - // update the quantities that are equal for all phases - diffusionSwitchFluxSign_[phaseIdx][compIdx] = localFaceData.isOutside(); - diffusionVolVarsStencil_[phaseIdx][compIdx] = &dataHandle.volVarsStencil(); - diffusionDirichletData_[phaseIdx][compIdx] = &dataHandle.dirichletData(); + // store pointer to the mole fraction vector of this iv + xj_[phaseIdx][compIdx] = &dataHandle.moleFractions(phaseIdx, compIdx); - // the transmissibilities on surface grids have to be obtained from the outside + const auto ivLocalIdx = localFaceData.ivLocalScvfIndex(); if (dim == dimWorld) - diffusionTij_[phaseIdx][compIdx] = &dataHandle.T()[localFaceData.ivLocalScvfIndex()]; + Tij_[phaseIdx][compIdx] = &dataHandle.diffusionT()[ivLocalIdx]; else - diffusionTij_[phaseIdx][compIdx] = localFaceData.isOutside() ? - &dataHandle.outsideTij()[localFaceData.ivLocalOutsideScvfIndex()] : - &dataHandle.T()[localFaceData.ivLocalScvfIndex()]; + Tij_[phaseIdx][compIdx] = localFaceData.isOutside() ? &dataHandle.diffusionTout()[ivLocalIdx][localFaceData.scvfLocalOutsideScvfIndex()] + : &dataHandle.diffusionT()[ivLocalIdx]; } - //! Returns the volume variables indices necessary for diffusive flux - //! computation. This includes all participating boundary volume variables - //! and it can be different for the phases & components. - const Stencil& diffusionVolVarsStencil(unsigned int phaseIdx, unsigned int compIdx) const - { return *diffusionVolVarsStencil_[phaseIdx][compIdx]; } - - //! On faces that are "outside" w.r.t. a face in the interaction volume, - //! we have to take the negative value of the fluxes, i.e. multiply by -1.0 + //! In the interaction volume-local system of eq we have one unknown per face. + //! On scvfs on this face, but in "outside" (neighbor) elements of it, we have + //! to take the negative value of the fluxes due to the flipped normal vector. + //! This function returns whether or not this scvf is an "outside" face in the iv. bool diffusionSwitchFluxSign(unsigned int phaseIdx, unsigned int compIdx) const - { return diffusionSwitchFluxSign_[phaseIdx][compIdx]; } + { return switchFluxSign_[phaseIdx][compIdx]; } + + //! Coefficients for the cell (& Dirichlet) unknowns in flux expressions + const Vector& diffusionTij(unsigned int phaseIdx, unsigned int compIdx) const + { return *Tij_[phaseIdx][compIdx]; } - //! Returns the transmissibilities associated with the volume variables - //! This can be different for the phases & components. - const CoefficientVector& diffusionTij(unsigned int phaseIdx, unsigned int compIdx) const - { return *diffusionTij_[phaseIdx][compIdx]; } + //! The cell (& Dirichlet) mole fractions within this interaction volume + const Vector& moleFractions(unsigned int phaseIdx, unsigned int compIdx) const + { return *xj_[phaseIdx][compIdx]; } - //! Returns the data on dirichlet boundary conditions affecting - //! the flux computation on this face - const DirichletDataContainer& diffusionDirichletData(unsigned int phaseIdx, unsigned int compIdx) const - { return *diffusionDirichletData_[phaseIdx][compIdx]; } + //! The stencils corresponding to the transmissibilities + const Stencil& diffusionStencil(unsigned int phaseIdx, unsigned int compIdx) const + { return *stencil_[phaseIdx][compIdx]; } private: - std::array< std::array<bool, numComponents>, numPhases> diffusionSwitchFluxSign_; - std::array< std::array<const Stencil*, numComponents>, numPhases> diffusionVolVarsStencil_; - std::array< std::array<const DirichletDataContainer*, numComponents>, numPhases> diffusionDirichletData_; - std::array< std::array<const CoefficientVector*, numComponents>, numPhases> diffusionTij_; + std::array< std::array<bool, numComponents>, numPhases > switchFluxSign_; + std::array< std::array<const Stencil*, numComponents>, numPhases > stencil_; //!< The stencils, i.e. the grid indices j + std::array< std::array<const Vector*, numComponents>, numPhases > Tij_; //!< The transmissibilities such that f = Tij*xj + std::array< std::array<const Vector*, numComponents>, numPhases > xj_; //!< The interaction-volume wide mole fractions xj }; public: @@ -162,13 +203,14 @@ public: // state the type for the corresponding cache and its filler using Cache = MpfaFicksLawCache; - static ComponentFluxVector flux (const Problem& problem, - const Element& element, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - const SubControlVolumeFace& scvf, - const int phaseIdx, - const ElementFluxVariablesCache& elemFluxVarsCache) + //! Compute the diffusive flux across an scvf + static ComponentFluxVector flux(const Problem& problem, + const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolumeFace& scvf, + const int phaseIdx, + const ElementFluxVariablesCache& elemFluxVarsCache) { ComponentFluxVector componentFlux(0.0); for (int compIdx = 0; compIdx < numComponents; compIdx++) @@ -187,20 +229,16 @@ public: const auto rho = interpolateDensity(elemVolVars, scvf, phaseIdx); // prepare computations - Scalar flux(0.0); - unsigned int i = 0; const auto& fluxVarsCache = elemFluxVarsCache[scvf]; const auto& tij = fluxVarsCache.diffusionTij(phaseIdx, compIdx); + const auto& xj = fluxVarsCache.moleFractions(phaseIdx, compIdx); // calculate Tij*xj - for (const auto volVarIdx : fluxVarsCache.diffusionVolVarsStencil(phaseIdx, compIdx)) - flux += tij[i++]*elemVolVars[volVarIdx].moleFraction(phaseIdx, compIdx); - - // add contributions from dirichlet BCs - for (const auto& d : fluxVarsCache.diffusionDirichletData(phaseIdx, compIdx)) - flux += tij[i++]*elemVolVars[d.volVarIndex()].moleFraction(phaseIdx, compIdx); + Scalar flux = tij*xj; + if (fluxVarsCache.diffusionSwitchFluxSign(phaseIdx, compIdx)) + flux *= -1.0; - componentFlux[compIdx] = fluxVarsCache.diffusionSwitchFluxSign(phaseIdx, compIdx) ? -1.0*flux*rho*effFactor : flux*rho*effFactor; + componentFlux[compIdx] = flux*rho*effFactor; } // accumulate the phase component flux @@ -212,6 +250,7 @@ public: } private: + //! compute the density at branching facets for network grids as arithmetic mean static Scalar interpolateDensity(const ElementVolumeVariables& elemVolVars, const SubControlVolumeFace& scvf, const unsigned int phaseIdx) diff --git a/dumux/discretization/cellcentered/mpfa/fluxvariablescachefiller.hh b/dumux/discretization/cellcentered/mpfa/fluxvariablescachefiller.hh index 29935706928e45b69c71899ad44039ec5846f9ce..452d0f6883b512869aea2cd05b1e4239bc03f622 100644 --- a/dumux/discretization/cellcentered/mpfa/fluxvariablescachefiller.hh +++ b/dumux/discretization/cellcentered/mpfa/fluxvariablescachefiller.hh @@ -16,37 +16,50 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * *****************************************************************************/ -/*! + /*! * \file - * \brief The flux variables cache filler class + * \ingroup CCMpfaDiscretization + * \brief A helper class to fill the flux variable caches used in the flux constitutive laws */ #ifndef DUMUX_DISCRETIZATION_CCMPFA_FLUXVARSCACHE_FILLER_HH #define DUMUX_DISCRETIZATION_CCMPFA_FLUXVARSCACHE_FILLER_HH +#include <dumux/common/properties.hh> +#include <dumux/common/parameters.hh> + #include <dumux/discretization/methods.hh> #include <dumux/discretization/cellcentered/mpfa/tensorlambdafactory.hh> +#include <dumux/discretization/cellcentered/mpfa/localassembler.hh> namespace Dumux { /*! - * \ingroup ImplicitModel - * \brief Helper class to fill the flux var caches + * \ingroup CCMpfaDiscretization + * \brief Helper class to fill the flux variables caches within + * the interaction volume around a given sub-control volume face. */ template<class TypeTag> class CCMpfaFluxVariablesCacheFiller { using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Element = typename GridView::template Codim<0>::Entity; + using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using PrimaryDataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; + using PrimaryLocalFaceData = typename PrimaryInteractionVolume::Traits::LocalFaceData; using SecondaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); - using DataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; + using SecondaryDataHandle = typename SecondaryInteractionVolume::Traits::DataHandle; + using SecondaryLocalFaceData = typename SecondaryInteractionVolume::Traits::LocalFaceData; - using Element = typename GridView::template Codim<0>::Entity; + static constexpr int dim = GridView::dimension; + static constexpr int dimWorld = GridView::dimensionworld; static constexpr bool doAdvection = GET_PROP_VALUE(TypeTag, EnableAdvection); static constexpr bool doDiffusion = GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion); @@ -57,11 +70,12 @@ class CCMpfaFluxVariablesCacheFiller static constexpr bool soldependentHeatConduction = GET_PROP_VALUE(TypeTag, SolutionDependentHeatConduction); public: - static constexpr bool isSolDependent = (doAdvection && soldependentAdvection) || - (doDiffusion && soldependentDiffusion) || - (doHeatConduction && soldependentHeatConduction); + //! This cache filler is always solution-dependent, as it updates the + //! vectors of cell unknowns with which the transmissibilities have to be + //! multiplied in order to obtain the fluxes. + static constexpr bool isSolDependent = true; - //! The constructor. Sets the problem pointer + //! The constructor. Sets problem pointer. CCMpfaFluxVariablesCacheFiller(const Problem& problem) : problemPtr_(&problem) {} /*! @@ -71,7 +85,7 @@ public: * \param scvfFluxVarsCache The flux var cache to be updated corresponding to the given scvf * \param element The finite element * \param fvGeometry The finite volume geometry - * \param elemVolVars The element volume variables + * \param elemVolVars The element volume variables (primary/secondary variables) * \param scvf The corresponding sub-control volume face * \param forceUpdateAll if true, forces all caches to be updated (even the solution-independent ones) */ @@ -96,30 +110,30 @@ public: if (forceUpdateAll) { // the local index of the interaction volume to be created in its container - const auto ivIndexInContainer = fluxVarsCacheContainer.secondaryInteractionVolumes_.size(); + const auto ivIndexInContainer = fluxVarsCacheContainer.secondaryInteractionVolumes().size(); // prepare the locally cached boundary interaction volume const auto& indexSet = fvGridGeometry.gridInteractionVolumeIndexSets().secondaryIndexSet(scvf); - fluxVarsCacheContainer.secondaryInteractionVolumes_.emplace_back(); - secondaryIv_ = &fluxVarsCacheContainer.secondaryInteractionVolumes_.back(); + fluxVarsCacheContainer.secondaryInteractionVolumes().emplace_back(); + secondaryIv_ = &fluxVarsCacheContainer.secondaryInteractionVolumes().back(); secondaryIv_->setUpLocalScope(indexSet, problem(), fvGeometry); // prepare the corresponding data handle - fluxVarsCacheContainer.secondaryIvDataHandles_.emplace_back(); - ivDataHandle_ = &fluxVarsCacheContainer.secondaryIvDataHandles_.back(); - secondaryIv_->prepareDataHandle(*ivDataHandle_); + fluxVarsCacheContainer.secondaryDataHandles().emplace_back(); + secondaryIvDataHandle_ = &fluxVarsCacheContainer.secondaryDataHandles().back(); + secondaryIvDataHandle_->resize(*secondaryIv_); // fill the caches for all the scvfs in the interaction volume - fillCachesInInteractionVolume_(fluxVarsCacheContainer, *secondaryIv_, *ivDataHandle_, ivIndexInContainer, true); + fillCachesInInteractionVolume_(fluxVarsCacheContainer, *secondaryIv_, *secondaryIvDataHandle_, ivIndexInContainer, true); } else { const auto ivIndexInContainer = scvfFluxVarsCache.ivIndexInContainer(); - secondaryIv_ = &fluxVarsCacheContainer.secondaryInteractionVolumes_[ivIndexInContainer]; - ivDataHandle_ = &fluxVarsCacheContainer.secondaryIvDataHandles_[ivIndexInContainer]; + secondaryIv_ = &fluxVarsCacheContainer.secondaryInteractionVolumes()[ivIndexInContainer]; + secondaryIvDataHandle_ = &fluxVarsCacheContainer.secondaryDataHandles()[ivIndexInContainer]; // fill the caches for all the scvfs in the interaction volume - fillCachesInInteractionVolume_(fluxVarsCacheContainer, *secondaryIv_, *ivDataHandle_, ivIndexInContainer); + fillCachesInInteractionVolume_(fluxVarsCacheContainer, *secondaryIv_, *secondaryIvDataHandle_, ivIndexInContainer); } } else @@ -127,61 +141,69 @@ public: if (forceUpdateAll) { // the local index of the interaction volume to be created in its container - const auto ivIndexInContainer = fluxVarsCacheContainer.primaryInteractionVolumes_.size(); + const auto ivIndexInContainer = fluxVarsCacheContainer.primaryInteractionVolumes().size(); // prepare the locally cached boundary interaction volume const auto& indexSet = fvGridGeometry.gridInteractionVolumeIndexSets().primaryIndexSet(scvf); - fluxVarsCacheContainer.primaryInteractionVolumes_.emplace_back(); - primaryIv_ = &fluxVarsCacheContainer.primaryInteractionVolumes_.back(); + fluxVarsCacheContainer.primaryInteractionVolumes().emplace_back(); + primaryIv_ = &fluxVarsCacheContainer.primaryInteractionVolumes().back(); primaryIv_->setUpLocalScope(indexSet, problem(), fvGeometry); // prepare the corresponding data handle - fluxVarsCacheContainer.primaryIvDataHandles_.emplace_back(); - ivDataHandle_ = &fluxVarsCacheContainer.primaryIvDataHandles_.back(); - primaryIv_->prepareDataHandle(*ivDataHandle_); + fluxVarsCacheContainer.primaryDataHandles().emplace_back(); + primaryIvDataHandle_ = &fluxVarsCacheContainer.primaryDataHandles().back(); + primaryIvDataHandle_->resize(*primaryIv_); // fill the caches for all the scvfs in the interaction volume - fillCachesInInteractionVolume_(fluxVarsCacheContainer, *primaryIv_, *ivDataHandle_, ivIndexInContainer, true); + fillCachesInInteractionVolume_(fluxVarsCacheContainer, *primaryIv_, *primaryIvDataHandle_, ivIndexInContainer, true); } else { const auto ivIndexInContainer = scvfFluxVarsCache.ivIndexInContainer(); - primaryIv_ = &fluxVarsCacheContainer.primaryInteractionVolumes_[ivIndexInContainer]; - ivDataHandle_ = &fluxVarsCacheContainer.primaryIvDataHandles_[ivIndexInContainer]; + primaryIv_ = &fluxVarsCacheContainer.primaryInteractionVolumes()[ivIndexInContainer]; + primaryIvDataHandle_ = &fluxVarsCacheContainer.primaryDataHandles()[ivIndexInContainer]; // fill the caches for all the scvfs in the interaction volume - fillCachesInInteractionVolume_(fluxVarsCacheContainer, *primaryIv_, *ivDataHandle_, ivIndexInContainer); + fillCachesInInteractionVolume_(fluxVarsCacheContainer, *primaryIv_, *primaryIvDataHandle_, ivIndexInContainer); } } } + //! returns the stored interaction volume pointer const PrimaryInteractionVolume& primaryInteractionVolume() const { return *primaryIv_; } + //! returns the stored interaction volume pointer const SecondaryInteractionVolume& secondaryInteractionVolume() const { return *secondaryIv_; } - const DataHandle& dataHandle() const - { return *ivDataHandle_; } + //! returns the stored data handle pointer + const PrimaryDataHandle& primaryIvDataHandle() const + { return *primaryIvDataHandle_; } -private: + //! returns the stored data handle pointer + const SecondaryDataHandle& secondaryIvDataHandle() const + { return *secondaryIvDataHandle_; } - const Problem& problem() const - { return *problemPtr_; } + //! returns the currently stored iv-local face data object + const PrimaryLocalFaceData& primaryIvLocalFaceData() const + { return *primaryLocalFaceData_; } - const Element& element() const - { return *elementPtr_; } + //! returns the currently stored iv-local face data object + const SecondaryLocalFaceData& secondaryIvLocalFaceData() const + { return *secondaryLocalFaceData_; } - const FVElementGeometry& fvGeometry() const - { return *fvGeometryPtr_; } +private: - const ElementVolumeVariables& elemVolVars() const - { return *elemVolVarsPtr_; } + const Problem& problem() const { return *problemPtr_; } + const Element& element() const { return *elementPtr_; } + const FVElementGeometry& fvGeometry() const { return *fvGeometryPtr_; } + const ElementVolumeVariables& elemVolVars() const { return *elemVolVarsPtr_; } //! Method to fill the flux var caches within an interaction volume - template<class FluxVariablesCacheContainer, class InteractionVolumeType> - void fillCachesInInteractionVolume_(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, + template<class FluxVarsCacheContainer, class InteractionVolume, class DataHandle> + void fillCachesInInteractionVolume_(FluxVarsCacheContainer& fluxVarsCacheContainer, + InteractionVolume& iv, DataHandle& handle, unsigned int ivIndexInContainer, bool forceUpdateAll = false) @@ -205,31 +227,21 @@ private: i++; } - if (forceUpdateAll) - { - fillAdvection(fluxVarsCacheContainer, iv, handle, ivScvfs, ivFluxVarCaches); - fillDiffusion(fluxVarsCacheContainer, iv, handle, ivScvfs, ivFluxVarCaches); - fillHeatConduction(fluxVarsCacheContainer, iv, handle, ivScvfs, ivFluxVarCaches); - } - else - { - if (doAdvection && soldependentAdvection) - fillAdvection(fluxVarsCacheContainer, iv, handle, ivScvfs, ivFluxVarCaches); - if (doDiffusion && soldependentDiffusion) - fillDiffusion(fluxVarsCacheContainer, iv, handle, ivScvfs, ivFluxVarCaches); - if (doHeatConduction && soldependentHeatConduction) - fillHeatConduction(fluxVarsCacheContainer, iv, handle, ivScvfs, ivFluxVarCaches); - } + fillAdvection(iv, handle, ivScvfs, ivFluxVarCaches, forceUpdateAll); + fillDiffusion(iv, handle, ivScvfs, ivFluxVarCaches, forceUpdateAll); + fillHeatConduction(iv, handle, ivScvfs, ivFluxVarCaches, forceUpdateAll); } - //! method to fill the advective quantities - template<class FluxVariablesCacheContainer, class InteractionVolumeType, bool advectionEnabled = doAdvection> - typename std::enable_if<advectionEnabled>::type - fillAdvection(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, - DataHandle& handle, - const std::vector<const SubControlVolumeFace*>& ivScvfs, - const std::vector<FluxVariablesCache*>& ivFluxVarCaches) + //! fills the advective quantities (enabled advection) + template< class InteractionVolume, + class DataHandle, + bool enableAdvection = doAdvection, + typename std::enable_if_t<enableAdvection, int> = 0 > + void fillAdvection(InteractionVolume& iv, + DataHandle& handle, + const std::vector<const SubControlVolumeFace*>& ivScvfs, + const std::vector<FluxVariablesCache*>& ivFluxVarCaches, + bool forceUpdateAll = false) { using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType); using AdvectionFiller = typename AdvectionType::Cache::Filler; @@ -237,15 +249,98 @@ private: static constexpr auto AdvectionMethod = AdvectionType::myDiscretizationMethod; using LambdaFactory = TensorLambdaFactory<TypeTag, AdvectionMethod>; - // set the advection context in the data handle - handle.setAdvectionContext(); - - // maybe solve the local system subject to K (if AdvectionType uses mpfa) + // skip the following if advection doesn't use mpfa if (AdvectionMethod == DiscretizationMethods::CCMpfa) - iv.solveLocalSystem(LambdaFactory::getAdvectionLambda(), problem(), fvGeometry(), elemVolVars(), handle); + { + // get instance of the interaction volume-local assembler + using IvLocalAssembler = InteractionVolumeAssembler< InteractionVolume >; + IvLocalAssembler localAssembler(problem(), fvGeometry(), elemVolVars()); + + // Use different assembly if gravity is enabled + static const bool enableGravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); + + // Assemble T only if permeability is sol-dependent or if update is forced + if (forceUpdateAll || soldependentAdvection) + { + // distinguish between normal/surface grids (optimized away by compiler) + if (dim < dimWorld) + { + if (enableGravity) + localAssembler.assembleWithGravity( handle.advectionTout(), + handle.advectionT(), + handle.gravityOutside(), + handle.gravity(), + handle.advectionCA(), + handle.advectionA(), + iv, + LambdaFactory::getAdvectionLambda() ); + + else + localAssembler.assemble( handle.advectionTout(), + handle.advectionT(), + iv, + LambdaFactory::getAdvectionLambda() ); + } + + // normal grids + else + { + if (enableGravity) + localAssembler.assembleWithGravity( handle.advectionT(), + handle.gravity(), + handle.advectionCA(), + iv, + LambdaFactory::getAdvectionLambda() ); + else + localAssembler.assemble( handle.advectionT(), + iv, + LambdaFactory::getAdvectionLambda() ); + } + } + + // (maybe) only reassemble gravity vector + else if (enableGravity) + { + if (dim == dimWorld) + localAssembler.assembleGravity( handle.gravity(), + iv, + handle.advectionCA(), + LambdaFactory::getAdvectionLambda() ); + else + localAssembler.assembleGravity( handle.gravity(), + handle.gravityOutside(), + iv, + handle.advectionCA(), + handle.advectionA(), + LambdaFactory::getAdvectionLambda() ); + } + + // assemble pressure vectors + for (unsigned int pIdx = 0; pIdx < GET_PROP_VALUE(TypeTag, NumPhases); ++pIdx) + { + const auto& evv = &elemVolVars(); + auto getPressure = [&evv, pIdx] (auto volVarIdx) { return (evv->operator[](volVarIdx)).pressure(pIdx); }; + localAssembler.assemble(handle.pressures(pIdx), iv, getPressure); + } + } // fill advection caches for (unsigned int i = 0; i < iv.localFaceData().size(); ++i) + { + // set pointer to current local face data object + // ifs are evaluated at compile time and are optimized away + if (std::is_same<PrimaryInteractionVolume, SecondaryInteractionVolume>::value) + { + // we cannot make a disctinction, thus we set both pointers + primaryLocalFaceData_ = &(iv.localFaceData()[i]); + secondaryLocalFaceData_ = &(iv.localFaceData()[i]); + } + else if (std::is_same<InteractionVolume, PrimaryInteractionVolume>::value) + primaryLocalFaceData_ = &(iv.localFaceData()[i]); + else + secondaryLocalFaceData_ = &(iv.localFaceData()[i]); + + // fill this scvfs cache AdvectionFiller::fill(*ivFluxVarCaches[i], problem(), iv.element(iv.localFaceData()[i].ivLocalInsideScvIndex()), @@ -253,25 +348,31 @@ private: elemVolVars(), *ivScvfs[i], *this); + } } //! do nothing if advection is not enabled - template<class FluxVariablesCacheContainer, class InteractionVolumeType, bool advectionEnabled = doAdvection> - typename std::enable_if<!advectionEnabled>::type - fillAdvection(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, - DataHandle& handle, - const std::vector<const SubControlVolumeFace*>& ivScvfs, - const std::vector<FluxVariablesCache*>& ivFluxVarCaches) {} - - //! method to fill the diffusive quantities - template<class FluxVariablesCacheContainer, class InteractionVolumeType, bool diffusionEnabled = doDiffusion> - typename std::enable_if<diffusionEnabled>::type - fillDiffusion(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, - DataHandle& handle, - const std::vector<const SubControlVolumeFace*>& ivScvfs, - const std::vector<FluxVariablesCache*>& ivFluxVarCaches) + template< class InteractionVolume, + class DataHandle, + bool enableAdvection = doAdvection, + typename std::enable_if_t<!enableAdvection, int> = 0 > + void fillAdvection(InteractionVolume& iv, + DataHandle& handle, + const std::vector<const SubControlVolumeFace*>& ivScvfs, + const std::vector<FluxVariablesCache*>& ivFluxVarCaches, + bool forceUpdateAll = false) + {} + + //! fills the diffusive quantities (diffusion enabled) + template< class InteractionVolume, + class DataHandle, + bool enableDiffusion = doDiffusion, + typename std::enable_if_t<enableDiffusion, int> = 0 > + void fillDiffusion(InteractionVolume& iv, + DataHandle& handle, + const std::vector<const SubControlVolumeFace*>& ivScvfs, + const std::vector<FluxVariablesCache*>& ivFluxVarCaches, + bool forceUpdateAll = false) { using DiffusionType = typename GET_PROP_TYPE(TypeTag, MolecularDiffusionType); using DiffusionFiller = typename DiffusionType::Cache::Filler; @@ -282,6 +383,10 @@ private: static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); static constexpr int numComponents = GET_PROP_VALUE(TypeTag, NumComponents); + // get instance of the interaction volume-local assembler + using IvLocalAssembler = InteractionVolumeAssembler< InteractionVolume >; + IvLocalAssembler localAssembler(problem(), fvGeometry(), elemVolVars()); + for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) { for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx) @@ -289,15 +394,51 @@ private: if (phaseIdx == compIdx) continue; - // set the diffusion context in the data handle - handle.setDiffusionContext(phaseIdx, compIdx); - // solve the local system subject to the diffusion tensor (if uses mpfa) if (DiffusionMethod == DiscretizationMethods::CCMpfa) - iv.solveLocalSystem(LambdaFactory::getDiffusionLambda(phaseIdx, compIdx), problem(), fvGeometry(), elemVolVars(), handle); + { + // update the context in handle + handle.setPhaseIndex(phaseIdx); + handle.setComponentIndex(compIdx); + + // assemble T + if (forceUpdateAll || soldependentDiffusion) + { + if (dim < dimWorld) + localAssembler.assemble( handle.diffusionTout(), + handle.diffusionT(), + iv, + LambdaFactory::getDiffusionLambda(phaseIdx, compIdx) ); + else + localAssembler. assemble( handle.diffusionT(), + iv, + LambdaFactory::getDiffusionLambda(phaseIdx, compIdx) ); + } + + // assemble vector of mole fractions + const auto& evv = &elemVolVars(); + auto getMoleFraction = [&evv, phaseIdx, compIdx] (auto volVarIdx) + { return (evv->operator[](volVarIdx)).moleFraction(phaseIdx, compIdx); }; + localAssembler.assemble(handle.moleFractions(phaseIdx, compIdx), iv, getMoleFraction); + } // fill diffusion caches for (unsigned int i = 0; i < iv.localFaceData().size(); ++i) + { + // set pointer to current local face data object + // ifs are evaluated at compile time and are optimized away + if (std::is_same<PrimaryInteractionVolume, SecondaryInteractionVolume>::value) + { + // we cannot make a disctinction, thus we set both pointers + primaryLocalFaceData_ = &(iv.localFaceData()[i]); + secondaryLocalFaceData_ = &(iv.localFaceData()[i]); + } + else if (std::is_same<InteractionVolume, PrimaryInteractionVolume>::value) + primaryLocalFaceData_ = &(iv.localFaceData()[i]); + else + secondaryLocalFaceData_ = &(iv.localFaceData()[i]); + + // fill this scvfs cache DiffusionFiller::fill(*ivFluxVarCaches[i], phaseIdx, compIdx, @@ -307,27 +448,33 @@ private: elemVolVars(), *ivScvfs[i], *this); + } } } } //! do nothing if diffusion is not enabled - template<class FluxVariablesCacheContainer, class InteractionVolumeType, bool diffusionEnabled = doDiffusion> - typename std::enable_if<!diffusionEnabled>::type - fillDiffusion(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, - DataHandle& handle, - const std::vector<const SubControlVolumeFace*>& ivScvfs, - const std::vector<FluxVariablesCache*>& ivFluxVarCaches) {} - - //! method to fill the quantities related to heat conduction - template<class FluxVariablesCacheContainer, class InteractionVolumeType, bool heatConductionEnabled = doHeatConduction> - typename std::enable_if<heatConductionEnabled>::type - fillHeatConduction(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, + template< class InteractionVolume, + class DataHandle, + bool enableDiffusion = doDiffusion, + typename std::enable_if_t<!enableDiffusion, int> = 0 > + void fillDiffusion(InteractionVolume& iv, DataHandle& handle, const std::vector<const SubControlVolumeFace*>& ivScvfs, - const std::vector<FluxVariablesCache*>& ivFluxVarCaches) + const std::vector<FluxVariablesCache*>& ivFluxVarCaches, + bool forceUpdateAll = false) + {} + + //! fills the quantities related to heat conduction (heat conduction enabled) + template< class InteractionVolume, + class DataHandle, + bool enableHeatConduction = doHeatConduction, + typename std::enable_if_t<enableHeatConduction, int> = 0 > + void fillHeatConduction(InteractionVolume& iv, + DataHandle& handle, + const std::vector<const SubControlVolumeFace*>& ivScvfs, + const std::vector<FluxVariablesCache*>& ivFluxVarCaches, + bool forceUpdateAll = false) { using HeatConductionType = typename GET_PROP_TYPE(TypeTag, HeatConductionType); using HeatConductionFiller = typename HeatConductionType::Cache::Filler; @@ -335,15 +482,49 @@ private: static constexpr auto HeatConductionMethod = HeatConductionType::myDiscretizationMethod; using LambdaFactory = TensorLambdaFactory<TypeTag, HeatConductionMethod>; - // set the advection context in the data handle - handle.setHeatConductionContext(); - // maybe solve the local system subject to fourier coefficient if (HeatConductionMethod == DiscretizationMethods::CCMpfa) - iv.solveLocalSystem(LambdaFactory::getHeatConductionLambda(), problem(), fvGeometry(), elemVolVars(), handle); + { + // get instance of the interaction volume-local assembler + using IvLocalAssembler = InteractionVolumeAssembler< InteractionVolume >; + IvLocalAssembler localAssembler(problem(), fvGeometry(), elemVolVars()); + + if (forceUpdateAll || soldependentAdvection) + { + if (dim < dimWorld) + localAssembler.assemble( handle.heatConductionTout(), + handle.heatConductionT(), + iv, + LambdaFactory::getHeatConductionLambda() ); + else + localAssembler.assemble( handle.heatConductionT(), + iv, + LambdaFactory::getHeatConductionLambda() ); + } + + // assemble vector of temperatures + const auto& evv = &elemVolVars(); + auto getMoleFraction = [&evv] (auto volVarIdx) { return (evv->operator[](volVarIdx)).temperature(); }; + localAssembler.assemble(handle.temperatures(), iv, getMoleFraction); + } // fill heat conduction caches for (unsigned int i = 0; i < iv.localFaceData().size(); ++i) + { + // set pointer to current local face data object + // ifs are evaluated at compile time and are optimized away + if (std::is_same<PrimaryInteractionVolume, SecondaryInteractionVolume>::value) + { + // we cannot make a disctinction, thus we set both pointers + primaryLocalFaceData_ = &(iv.localFaceData()[i]); + secondaryLocalFaceData_ = &(iv.localFaceData()[i]); + } + else if (std::is_same<InteractionVolume, PrimaryInteractionVolume>::value) + primaryLocalFaceData_ = &(iv.localFaceData()[i]); + else + secondaryLocalFaceData_ = &(iv.localFaceData()[i]); + + // fill this scvfs cache HeatConductionFiller::fill(*ivFluxVarCaches[i], problem(), iv.element(iv.localFaceData()[i].ivLocalInsideScvIndex()), @@ -351,16 +532,20 @@ private: elemVolVars(), *ivScvfs[i], *this); + } } //! do nothing if heat conduction is disabled - template<class FluxVariablesCacheContainer, class InteractionVolumeType, bool heatConductionEnabled = doHeatConduction> - typename std::enable_if<!heatConductionEnabled>::type - fillHeatConduction(FluxVariablesCacheContainer& fluxVarsCacheContainer, - InteractionVolumeType& iv, - DataHandle& handle, - const std::vector<const SubControlVolumeFace*>& ivScvfs, - const std::vector<FluxVariablesCache*>& ivFluxVarCaches) {} + template< class InteractionVolume, + class DataHandle, + bool enableHeatConduction = doHeatConduction, + typename std::enable_if_t<!enableHeatConduction, int> = 0 > + void fillHeatConduction(InteractionVolume& iv, + DataHandle& handle, + const std::vector<const SubControlVolumeFace*>& ivScvfs, + const std::vector<FluxVariablesCache*>& ivFluxVarCaches, + bool forceUpdateAll = false) + {} const Problem* problemPtr_; const Element* elementPtr_; @@ -374,9 +559,17 @@ private: SecondaryInteractionVolume* secondaryIv_; // pointer to the current interaction volume data handle - DataHandle* ivDataHandle_; + PrimaryDataHandle* primaryIvDataHandle_; + SecondaryDataHandle* secondaryIvDataHandle_; + + // We do an interaction volume-wise filling of the caches + // While filling, we store a pointer to the current localScvf + // face data object of the IV so that the individual caches + // can access it and don't have to retrieve it again + const PrimaryLocalFaceData* primaryLocalFaceData_; + const SecondaryLocalFaceData* secondaryLocalFaceData_; }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/fourierslaw.hh b/dumux/discretization/cellcentered/mpfa/fourierslaw.hh index 14bb0fee6547a7abd637613d429799791899a469..308d6fa395dd1ea47433a1294616fab2a71e51f3 100644 --- a/dumux/discretization/cellcentered/mpfa/fourierslaw.hh +++ b/dumux/discretization/cellcentered/mpfa/fourierslaw.hh @@ -18,8 +18,8 @@ *****************************************************************************/ /*! * \file - * \brief This file contains the class which is required to calculate - * heat conduction fluxes with Fourier's law for cell-centered MPFA models. + * \ingroup CCMpfaDiscretization + * \brief Fourier's law for cell-centered finite volume schemes with multi-point flux approximation */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_FOURIERS_LAW_HH #define DUMUX_DISCRETIZATION_CC_MPFA_FOURIERS_LAW_HH @@ -27,16 +27,18 @@ #include <dumux/common/properties.hh> #include <dumux/discretization/methods.hh> +#include <dumux/discretization/methods.hh> + namespace Dumux { -// forward declaration +//! forward declaration of the method-specific implementation template<class TypeTag, DiscretizationMethods discMethod> class FouriersLawImplementation; /*! - * \ingroup Mpfa - * \brief Specialization of Fourier's Law for the CCMpfa method. - */ +* \ingroup CCMpfaDiscretization +* \brief Fourier's law for cell-centered finite volume schemes with two-point flux approximation +*/ template <class TypeTag> class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> { @@ -51,15 +53,6 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); using ThermalConductivityModel = typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel); - // Always use the dynamic type for vectors (compatibility with the boundary) - using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using CoefficientVector = typename PrimaryInteractionVolume::Traits::DynamicVector; - using DataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; - - static constexpr int dim = GridView::dimension; - static constexpr int dimWorld = GridView::dimensionworld; - static constexpr int energyEqIdx = GET_PROP_TYPE(TypeTag, Indices)::energyEqIdx; - //! Class that fills the cache corresponding to mpfa Darcy's Law class MpfaFouriersLawCacheFiller { @@ -78,11 +71,13 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> // get interaction volume from the flux vars cache filler & upate the cache if (fvGeometry.fvGridGeometry().vertexUsesSecondaryInteractionVolume(scvf.vertexIndex())) scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.secondaryInteractionVolume(), - fluxVarsCacheFiller.dataHandle(), + fluxVarsCacheFiller.secondaryIvLocalFaceData(), + fluxVarsCacheFiller.secondaryIvDataHandle(), scvf); else scvfFluxVarsCache.updateHeatConduction(fluxVarsCacheFiller.primaryInteractionVolume(), - fluxVarsCacheFiller.dataHandle(), + fluxVarsCacheFiller.primaryIvLocalFaceData(), + fluxVarsCacheFiller.primaryIvDataHandle(), scvf); } }; @@ -90,52 +85,104 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCMpfa> //! The cache used in conjunction with the mpfa Fourier's Law class MpfaFouriersLawCache { - // We always use the dynamic types here to be compatible on the boundary - using Stencil = typename PrimaryInteractionVolume::Traits::DynamicGlobalIndexContainer; - using DirichletDataContainer = typename PrimaryInteractionVolume::DirichletDataContainer; + // In the current implementation of the flux variables cache we cannot + // make a disctinction between dynamic (mpfa-o) and static (mpfa-l) + // matrix and vector types, as currently the cache class can only be templated + // by a type tag (and there can only be one). We use a dynamic vector here to + // make sure it works in case one of the two used interaction volume types uses + // dynamic types performance is thus lowered for schemes using static types. + // TODO: this has to be checked thoroughly as soon as a scheme using static types + // is implemented. One idea to overcome the performance drop could be only + // storing the iv-local index here and obtain tij always from the datahandle + // of the fluxVarsCacheContainer + using GridIndexType = typename GridView::IndexSet::IndexType; + using Vector = Dune::DynamicVector< Scalar >; + using Matrix = Dune::DynamicMatrix< Scalar >; + using Stencil = std::vector< GridIndexType >; + + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using PrimaryIvVector = typename PrimaryInteractionVolume::Traits::Vector; + using PrimaryIvMatrix = typename PrimaryInteractionVolume::Traits::Matrix; + using PrimaryStencil = typename PrimaryInteractionVolume::Traits::Stencil; + + static_assert( std::is_convertible<PrimaryIvVector*, Vector*>::value, + "The vector type used in primary interaction volumes is not convertible to Dune::DynamicVector!" ); + static_assert( std::is_convertible<PrimaryIvMatrix*, Matrix*>::value, + "The matrix type used in primary interaction volumes is not convertible to Dune::DynamicMatrix!" ); + static_assert( std::is_convertible<PrimaryStencil*, Stencil*>::value, + "The stencil type used in primary interaction volumes is not convertible to std::vector<GridIndexType>!" ); + + using SecondaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); + using SecondaryIvVector = typename SecondaryInteractionVolume::Traits::Vector; + using SecondaryIvMatrix = typename SecondaryInteractionVolume::Traits::Matrix; + using SecondaryStencil = typename SecondaryInteractionVolume::Traits::Stencil; + + static_assert( std::is_convertible<SecondaryIvVector*, Vector*>::value, + "The vector type used in secondary interaction volumes is not convertible to Dune::DynamicVector!" ); + static_assert( std::is_convertible<SecondaryIvMatrix*, Matrix*>::value, + "The matrix type used in secondary interaction volumes is not convertible to Dune::DynamicMatrix!" ); + static_assert( std::is_convertible<SecondaryStencil*, Stencil*>::value, + "The stencil type used in secondary interaction volumes is not convertible to std::vector<GridIndexType>!" ); + + static constexpr int dim = GridView::dimension; + static constexpr int dimWorld = GridView::dimensionworld; + public: // export filler type using Filler = MpfaFouriersLawCacheFiller; - // update cached objects for heat conduction - template<class InteractionVolume> - void updateHeatConduction(const InteractionVolume& iv, const DataHandle& dataHandle, const SubControlVolumeFace &scvf) + /*! + * \brief Update cached objects (transmissibilities) + * + * \tparam InteractionVolume The (mpfa scheme-specific) interaction volume + * \tparam LocalFaceData The object used to store iv-local info on an scvf + * \tparam DataHandle The object used to store transmissibility matrices etc. + * + * \param iv The interaction volume this scvf is embedded in + * \param localFaceData iv-local info on this scvf + * \param dataHandle Transmissibility matrix & gravity data of this iv + * \param scvf The sub-control volume face + */ + template<class InteractionVolume, class LocalFaceData, class DataHandle> + void updateHeatConduction(const InteractionVolume& iv, + const LocalFaceData& localFaceData, + const DataHandle& dataHandle, + const SubControlVolumeFace &scvf) { - const auto& localFaceData = iv.getLocalFaceData(scvf); + stencil_ = &iv.stencil(); + switchFluxSign_ = localFaceData.isOutside(); - // update the quantities that are equal for all phases - heatConductionSwitchFluxSign_ = localFaceData.isOutside(); - heatConductionVolVarsStencil_ = &dataHandle.volVarsStencil(); - heatConductionDirichletData_ = &dataHandle.dirichletData(); + // store pointer to the temperature vector of this iv + Tj_ = &dataHandle.temperatures(); - // the transmissibilities on surface grids have to be obtained from the outside + const auto ivLocalIdx = localFaceData.ivLocalScvfIndex(); if (dim == dimWorld) - heatConductionTij_ = &dataHandle.T()[localFaceData.ivLocalScvfIndex()]; + Tij_ = &dataHandle.heatConductionT()[ivLocalIdx]; else - heatConductionTij_ = localFaceData.isOutside() ? - &dataHandle.outsideTij()[localFaceData.ivLocalOutsideScvfIndex()] : - &dataHandle.T()[localFaceData.ivLocalScvfIndex()]; + Tij_ = localFaceData.isOutside() ? &dataHandle.heatConductionTout()[ivLocalIdx][localFaceData.scvfLocalOutsideScvfIndex()] + : &dataHandle.heatConductionT()[ivLocalIdx]; } - //! Returns the stencil for heat conduction flux computation on an scvf - const Stencil& heatConductionVolVarsStencil() const { return *heatConductionVolVarsStencil_; } + //! Coefficients for the cell (& Dirichlet) unknowns in flux expressions + const Vector& heatConductionTij() const { return *Tij_; } - //! Returns the transmissibilities associated with the volume variables - const CoefficientVector& heatConductionTij() const { return *heatConductionTij_; } + //! The stencil corresponding to the transmissibilities + const Stencil& heatConductionStencil() const { return *stencil_; } - //! On faces that are "outside" w.r.t. a face in the interaction volume, - //! we have to take the negative value of the fluxes, i.e. multiply by -1.0 - bool heatConductionSwitchFluxSign() const { return heatConductionSwitchFluxSign_; } + //! In the interaction volume-local system of eq we have one unknown per face. + //! On scvfs on this face, but in "outside" (neighbor) elements of it, we have + //! to take the negative value of the fluxes due to the flipped normal vector. + //! This function returns whether or not this scvf is an "outside" face in the iv. + bool heatConductionSwitchFluxSign() const { return switchFluxSign_; } - //! Returns the data on dirichlet boundary conditions affecting - //! the flux computation on this face - const DirichletDataContainer& heatConductionDirichletData() const { return *heatConductionDirichletData_; } + //! The cell (& Dirichlet) temperatures within this interaction volume + const Vector& temperatures() const { return *Tj_; } private: - bool heatConductionSwitchFluxSign_; - const Stencil* heatConductionVolVarsStencil_; - const CoefficientVector* heatConductionTij_; - const DirichletDataContainer* heatConductionDirichletData_; + bool switchFluxSign_; + const Stencil* stencil_; //!< The stencil, i.e. the grid indices j + const Vector* Tij_; //!< The transmissibilities such that f = Tij*Tj + const Vector* Tj_; //!< The interaction-volume wide temperature Tj }; public: @@ -145,6 +192,7 @@ public: // state the type for the corresponding cache and its filler using Cache = MpfaFouriersLawCache; + //! Compute the conductive flux across an scvf static Scalar flux(const Problem& problem, const Element& element, const FVElementGeometry& fvGeometry, @@ -152,22 +200,16 @@ public: const SubControlVolumeFace& scvf, const ElementFluxVarsCache& elemFluxVarsCache) { - // prepare computations - Scalar flux(0.0); - unsigned int i = 0; const auto& fluxVarsCache = elemFluxVarsCache[scvf]; const auto& tij = fluxVarsCache.heatConductionTij(); + const auto& Tj = fluxVarsCache.temperatures(); - // calculate Tij*tj - for (const auto volVarIdx : fluxVarsCache.heatConductionVolVarsStencil()) - flux += tij[i++]*elemVolVars[volVarIdx].temperature(); - - // add contributions from dirichlet BCs - for (const auto& d : fluxVarsCache.heatConductionDirichletData()) - flux += tij[i++]*elemVolVars[d.volVarIndex()].temperature(); + // compute Tij*tj + Scalar flux = tij*Tj; + if (fluxVarsCache.heatConductionSwitchFluxSign()) + flux *= -1.0; - // return overall resulting flux - return fluxVarsCache.heatConductionSwitchFluxSign() ? -flux : flux; + return flux; } }; diff --git a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh index bb707613a506bbed39d7788007ca04cf8fe69fa0..fc4cdb07a16fd8f6b155a6daf26ac4b82ab8ff7c 100644 --- a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh @@ -18,13 +18,15 @@ *****************************************************************************/ /*! * \file - * \brief Base class for a local finite volume geometry for cell-centered MPFA models + * \ingroup CCMpfaDiscretization + * \brief Stencil-local finite volume geometry (scvs and scvfs) for cell-centered mpfa models * This builds up the sub control volumes and sub control volume faces * for each element in the local scope we are restricting to, e.g. stencil or element. */ #ifndef DUMUX_DISCRETIZATION_CCMPFA_FV_ELEMENT_GEOMETRY_HH #define DUMUX_DISCRETIZATION_CCMPFA_FV_ELEMENT_GEOMETRY_HH +#include <dune/common/exceptions.hh> #include <dune/common/iteratorrange.hh> #include <dune/geometry/referenceelements.hh> @@ -35,30 +37,35 @@ namespace Dumux { /*! - * \ingroup ImplicitModel - * \brief Base class for the finite volume geometry vector for cell-centered MPFA models + * \ingroup CCMpfaDiscretization + * \brief Stencil-local finite volume geometry (scvs and scvfs) for cell-centered mpfa models * This builds up the sub control volumes and sub control volume faces - * for each element. + * for each element in the local scope we are restricting to, e.g. stencil or element. + * \note This class is specialized for versions with and without caching the fv geometries on the grid view */ template<class TypeTag, bool EnableFVGridGeometryCache> -class CCMpfaFVElementGeometry -{}; +class CCMpfaFVElementGeometry; -//! specialization in case the FVElementGeometries are stored globally -//! In this case we just forward internally to the global object +/*! + * \ingroup CCMpfaDiscretization + * \brief Stencil-local finite volume geometry (scvs and scvfs) for cell-centered mpfa models + * Specialization for grid caching enabled + * \note The finite volume geometries are stored in the corresponding FVGridGeometry + */ template<class TypeTag> class CCMpfaFVElementGeometry<TypeTag, true> { using ThisType = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; + using Element = typename GridView::template Codim<0>::Entity; + + using GridIndexType = typename GridView::IndexSet::IndexType; using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using Element = typename GridView::template Codim<0>::Entity; using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::vector<IndexType>, ThisType>; - using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<IndexType>, ThisType>; + using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::vector<GridIndexType>, ThisType>; + using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>; public: //! Constructor @@ -66,20 +73,20 @@ public: : fvGridGeometryPtr_(&fvGridGeometry) {} //! Get an element sub control volume with a global scv index - const SubControlVolume& scv(IndexType scvIdx) const + const SubControlVolume& scv(GridIndexType scvIdx) const { return fvGridGeometry().scv(scvIdx); } //! Get an element sub control volume face with a global scvf index - const SubControlVolumeFace& scvf(IndexType scvfIdx) const + const SubControlVolumeFace& scvf(GridIndexType scvfIdx) const { return fvGridGeometry().scvf(scvfIdx); } - //! Get an element sub control volume face with a global scvf index - //! We separate element and neighbor scvfs to speed up mapping - const SubControlVolumeFace& flipScvf(IndexType scvfIdx, unsigned int outsideScvIdx = 0) const + //! Get the scvf on the same face but from the other side + //! Note that e.g. the normals might be different in the case of surface grids + const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx, unsigned int outsideScvIdx = 0) const { return fvGridGeometry().flipScvf(scvfIdx, outsideScvIdx); } @@ -131,7 +138,7 @@ public: //! Bind only element-local void bindElement(const Element& element) { - scvIndices_ = std::vector<IndexType>({fvGridGeometry().elementMapper().index(element)}); + scvIndices_ = std::vector<GridIndexType>({fvGridGeometry().elementMapper().index(element)}); } //! The global finite volume geometry we are a restriction of @@ -140,11 +147,15 @@ public: private: - std::vector<IndexType> scvIndices_; + std::vector<GridIndexType> scvIndices_; const FVGridGeometry* fvGridGeometryPtr_; }; -//! specialization in case the FVElementGeometries are not stored +/*! + * \ingroup CCMpfaDiscretization + * \brief Stencil-local finite volume geometry (scvs and scvfs) for cell-centered TPFA models + * Specialization for grid caching disabled + */ template<class TypeTag> class CCMpfaFVElementGeometry<TypeTag, false> { @@ -152,15 +163,16 @@ class CCMpfaFVElementGeometry<TypeTag, false> using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; + using Element = typename GridView::template Codim<0>::Entity; + using GridIndexType = typename GridView::IndexSet::IndexType; + using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using Element = typename GridView::template Codim<0>::Entity; using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::vector<IndexType>, ThisType>; - using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<IndexType>, ThisType>; + using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::vector<GridIndexType>, ThisType>; + using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>; static const int dim = GridView::dimension; static const int dimWorld = GridView::dimensionworld; @@ -175,7 +187,7 @@ public: //! Get an elment sub control volume with a global scv index //! We separate element and neighbor scvs to speed up mapping - const SubControlVolume& scv(IndexType scvIdx) const + const SubControlVolume& scv(GridIndexType scvIdx) const { if (scvIdx == scvIndices_[0]) return scvs_[0]; @@ -185,7 +197,7 @@ public: //! Get an element sub control volume face with a global scvf index //! We separate element and neighbor scvfs to speed up mapping - const SubControlVolumeFace& scvf(IndexType scvfIdx) const + const SubControlVolumeFace& scvf(GridIndexType scvfIdx) const { auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx); if (it != scvfIndices_.end()) @@ -194,9 +206,9 @@ public: return neighborScvfs_[findLocalIndex(scvfIdx, neighborScvfIndices_)]; } - //! Get an element sub control volume face with a global scvf index - //! We separate element and neighbor scvfs to speed up mapping - const SubControlVolumeFace& flipScvf(IndexType scvfIdx, unsigned int outsideScvIdx = 0) const + //! Get the scvf on the same face but from the other side + //! Note that e.g. the normals might be different in the case of surface grids + const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx, unsigned int outsideScvIdx = 0) const { auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx); if (it != scvfIndices_.end()) @@ -207,7 +219,7 @@ public: else { const auto neighborScvfIdxLocal = findLocalIndex(scvfIdx, neighborScvfIndices_); - auto&& scvf = neighborScvfs_[neighborScvfIdxLocal]; + const auto& scvf = neighborScvfs_[neighborScvfIdxLocal]; if (scvf.outsideScvIdx(outsideScvIdx) == scvIndices_[0]) return scvfs_[neighborFlipScvfIndices_[neighborScvfIdxLocal][outsideScvIdx]]; @@ -252,6 +264,7 @@ public: //! called by the local assembler to prepare element assembly void bind(const Element& element) { + // make inside geometries bindElement(element); // get some references for convenience @@ -308,11 +321,11 @@ public: private: //! Computes the number of neighboring scvfs that have to be prepared - template<class DataJ> - unsigned int numNeighborScvfs_(const std::vector<DataJ>& dataJVector) + template<class DataJContainer> + std::size_t numNeighborScvfs_(const DataJContainer& dataJContainer) { - unsigned int numNeighborScvfs = 0; - for (const auto& dataJ : dataJVector) + std::size_t numNeighborScvfs = 0; + for (const auto& dataJ : dataJContainer) numNeighborScvfs += dataJ.scvfsJ.size() + dataJ.additionalScvfs.size(); return numNeighborScvfs; } @@ -329,7 +342,7 @@ private: const auto& scvFaceIndices = fvGridGeometry().scvfIndicesOfScv(eIdx); const auto& neighborVolVarIndices = fvGridGeometry().neighborVolVarIndices(eIdx); - // the quadrature point to be used on the scvf + // the quadrature point parameterizaion to be used on scvfs static const Scalar q = getParamFromGroup<Scalar>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Mpfa.Q"); // reserve memory for the scv faces @@ -402,7 +415,7 @@ private: //! create the scv and necessary scvfs of a neighboring element template<typename IndexVector> void makeNeighborGeometries(const Element& element, - IndexType eIdxGlobal, + GridIndexType eIdxGlobal, const IndexVector& scvfIndices, const IndexVector& additionalScvfs) { @@ -414,7 +427,7 @@ private: const auto& scvFaceIndices = fvGridGeometry().scvfIndicesOfScv(eIdxGlobal); const auto& neighborVolVarIndices = fvGridGeometry().neighborVolVarIndices(eIdxGlobal); - // the quadrature point to be used on the scvf + // the quadrature point parameterizaion to be used on scvfs static const Scalar q = getParamFromGroup<Scalar>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Mpfa.Q"); // for network grids we only want to do one scvf per half facet @@ -583,14 +596,16 @@ private: } } - const IndexType findLocalIndex(const IndexType idx, - const std::vector<IndexType>& indices) const + //! map a global index to the local storage index + const unsigned int findLocalIndex(const GridIndexType idx, + const std::vector<GridIndexType>& indices) const { auto it = std::find(indices.begin(), indices.end(), idx); assert(it != indices.end() && "Could not find the scv/scvf! Make sure to properly bind this class!"); return std::distance(indices.begin(), it); } + //! clear all containers void clear() { scvIndices_.clear(); @@ -602,24 +617,27 @@ private: neighborScvfIndices_.clear(); neighborScvs_.clear(); neighborScvfs_.clear(); + + flipScvfIndices_.clear(); + neighborFlipScvfIndices_.clear(); } const FVGridGeometry* fvGridGeometryPtr_; // local storage after binding an element - std::vector<IndexType> scvIndices_; - std::vector<IndexType> scvfIndices_; + std::vector<GridIndexType> scvIndices_; + std::vector<GridIndexType> scvfIndices_; std::vector<SubControlVolume> scvs_; std::vector<SubControlVolumeFace> scvfs_; - std::vector<IndexType> neighborScvIndices_; - std::vector<IndexType> neighborScvfIndices_; + std::vector<GridIndexType> neighborScvIndices_; + std::vector<GridIndexType> neighborScvfIndices_; std::vector<SubControlVolume> neighborScvs_; std::vector<SubControlVolumeFace> neighborScvfs_; - // flip index sets - std::vector< std::vector<IndexType> > flipScvfIndices_; - std::vector< std::vector<IndexType> > neighborFlipScvfIndices_; + // flip scvf index sets + std::vector< std::vector<GridIndexType> > flipScvfIndices_; + std::vector< std::vector<GridIndexType> > neighborFlipScvfIndices_; }; } // end namespace diff --git a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh index 858b4fec5b3484794142284dd80309d22b457220..6570faf63e0fefc9bdc36783619684bc6250d49a 100644 --- a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh +++ b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh @@ -18,9 +18,10 @@ *****************************************************************************/ /*! * \file - * \brief Base class for the finite volume geometry vector for mpfa models + * \ingroup CCMpfaDiscretization + * \brief The finite volume geometry (scvs and scvfs) for cell-centered mpfa models on a grid view * This builds up the sub control volumes and sub control volume faces - * for each element. + * for each element of the grid partition. */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_HH #define DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_HH @@ -28,6 +29,9 @@ #include <dune/geometry/multilineargeometry.hh> #include <dune/geometry/referenceelements.hh> +#include <dumux/common/properties.hh> +#include <dumux/common/parameters.hh> + #include <dumux/discretization/basefvgridgeometry.hh> #include <dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh> #include <dumux/discretization/cellcentered/mpfa/connectivitymap.hh> @@ -37,129 +41,106 @@ namespace Dumux { /*! - * \ingroup Mpfa - * \brief Base class for the finite volume geometry vector for mpfa models + * \ingroup CCMpfaDiscretization + * \brief The finite volume geometry (scvs and scvfs) for cell-centered mpfa models on a grid view * This builds up the sub control volumes and sub control volume faces - * for each element. + * \note This class is specialized for versions with and without caching the fv geometries on the grid view */ template<class TypeTag, bool EnableFVElementGeometryCache> -class CCMpfaFVGridGeometry -{}; +class CCMpfaFVGridGeometry; -// specialization in case the finite volume grid geometries are stored +/*! + * \ingroup CCMpfaDiscretization + * \brief The finite volume geometry (scvs and scvfs) for cell-centered mpfa models on a grid view + * This builds up the sub control volumes and sub control volume faces + * \note For caching enabled we store the fv geometries for the whole grid view which is memory intensive but faster + */ template<class TypeTag> class CCMpfaFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag> { using ParentType = BaseFVGridGeometry<TypeTag>; using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using ElementMapper = typename GET_PROP_TYPE(TypeTag, ElementMapper); + using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using GridIVIndexSets = CCMpfaGridInteractionVolumeIndexSets<TypeTag>; - using ConnectivityMap = CCMpfaConnectivityMap<TypeTag>; using GridView = typename GET_PROP_TYPE(TypeTag, GridView); static constexpr int dim = GridView::dimension; static constexpr int dimWorld = GridView::dimensionworld; + using Element = typename GridView::template Codim<0>::Entity; using Vertex = typename GridView::template Codim<dim>::Entity; using Intersection = typename GridView::Intersection; using CoordScalar = typename GridView::ctype; - using IndexType = typename GridView::IndexSet::IndexType; + using GridIndexType = typename GridView::IndexSet::IndexType; + using LocalIndexType = typename PrimaryInteractionVolume::Traits::LocalIndexType; + + using GridIVIndexSets = CCMpfaGridInteractionVolumeIndexSets<TypeTag>; + using ConnectivityMap = CCMpfaConnectivityMap<TypeTag>; - using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>; using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>; public: - using SecondaryIvIndicator = std::function<bool(const Element&, const Intersection&, bool)>; + using SecondaryIvIndicatorType = std::function<bool(const Element&, const Intersection&, bool)>; //! Constructor without indicator function for secondary interaction volumes //! Per default, we use the secondary IVs at branching points & boundaries - explicit CCMpfaFVGridGeometry(const GridView& gridView) - : ParentType(gridView) - , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching) - { return is.boundary() || isBranching; } ) - {} - - //! Constructor with user-defined indicator function for secondary interaction volumes - explicit CCMpfaFVGridGeometry(const GridView& gridView, const SecondaryIvIndicator& indicator) - : ParentType(gridView) - , secondaryIvIndicator_(indicator) - {} + CCMpfaFVGridGeometry(const GridView& gridView) + : ParentType(gridView) + , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching) + { return is.boundary() || isBranching; } ) + {} + + //! Constructor with user-defined indicator function for secondary interaction volumes + CCMpfaFVGridGeometry(const GridView& gridView, const SecondaryIvIndicatorType& indicator) + : ParentType(gridView) + , secondaryIvIndicator_(indicator) + {} //! the element mapper is the dofMapper //! this is convenience to have better chance to have the same main files for box/tpfa/mpfa... - const ElementMapper& dofMapper() const - { return this->elementMapper(); } + const ElementMapper& dofMapper() const { return this->elementMapper(); } + + //! The total number of sub control volumes + std::size_t numScv() const { return scvs_.size(); } + + //! The total number of sub control volume faces + std::size_t numScvf() const { return scvfs_.size(); } + + //! The total number of boundary sub control volume faces + std::size_t numBoundaryScvf() const { return numBoundaryScvf_; } + + //! The total number of degrees of freedom + std::size_t numDofs() const { return this->gridView().size(0); } - /*! - * \brief Returns the total number of sub control volumes. - */ - std::size_t numScv() const - { return scvs_.size(); } - - /*! - * \brief Returns the total number of sub control volume faces. - */ - std::size_t numScvf() const - { return scvfs_.size(); } - - /*! - * \brief Returns the number of scvfs on the domain boundary. - */ - std::size_t numBoundaryScvf() const - { return numBoundaryScvf_; } - - /*! - * \brief Returns the total number of degrees of freedom. - */ - std::size_t numDofs() const - { return this->gridView().size(0); } - - /*! - * \brief Gets an element from a global element index. - */ - Element element(IndexType eIdx) const - { return this->elementMap()[eIdx]; } - - /*! - * \brief Gets an element from a sub control volume contained in it. - */ - Element element(const SubControlVolume& scv) const - { return this->elementMap()[scv.elementIndex()]; } - - /*! - * \brief Returns true if primary interaction volumes are used around a given vertex, - * false otherwise. - */ + //! Get an element from a global element index + Element element(GridIndexType eIdx) const { return this->elementMap()[eIdx]; } + + //! Get an element from a sub control volume contained in it + Element element(const SubControlVolume& scv) const { return this->elementMap()[scv.elementIndex()]; } + + //! Returns true if primary interaction volumes are used around a given vertex. bool vertexUsesPrimaryInteractionVolume(const Vertex& v) const { return primaryInteractionVolumeVertices_[this->vertexMapper().index(v)]; } - /*! - * \brief Returns true if primary interaction volumes are used around a given vertex index, - * false otherwise. - */ - bool vertexUsesPrimaryInteractionVolume(IndexType vIdxGlobal) const + //!Returns true if primary interaction volumes are used around a vertex (index). + bool vertexUsesPrimaryInteractionVolume(GridIndexType vIdxGlobal) const { return primaryInteractionVolumeVertices_[vIdxGlobal]; } - /*! - * \brief Returns if primary interaction volumes are used around a given vertex. - */ + //! Returns if primary interaction volumes are used around a given vertex. bool vertexUsesSecondaryInteractionVolume(const Vertex& v) const { return secondaryInteractionVolumeVertices_[this->vertexMapper().index(v)]; } - /*! - * \brief Returns true if primary interaction volumes are used around a given vertex index, - * false otherwise. - */ - bool vertexUsesSecondaryInteractionVolume(IndexType vIdxGlobal) const + //! Returns true if primary interaction volumes are used around a given vertex index. + bool vertexUsesSecondaryInteractionVolume(GridIndexType vIdxGlobal) const { return secondaryInteractionVolumeVertices_[vIdxGlobal]; } - /*! - * \brief Updates all finite volume geometries of the grid. Hhas to be called again after grid adaptation. - */ + //! update all fvElementGeometries (do this again after grid adaption) void update() { ParentType::update(); @@ -189,10 +170,10 @@ public: const auto isGhostVertex = MpfaHelper::findGhostVertices(this->gridView(), this->vertexMapper()); // instantiate the dual grid index set (to be used for construction of interaction volumes) - CCMpfaDualGridIndexSet<TypeTag> dualIdSet(this->gridView()); + CCMpfaDualGridIndexSet<GridIndexType, LocalIndexType, dim> dualIdSet(this->gridView()); // Build the SCVs and SCV faces - IndexType scvfIdx = 0; + GridIndexType scvfIdx = 0; numBoundaryScvf_ = 0; for (const auto& element : elements(this->gridView())) { @@ -202,12 +183,12 @@ public: auto elementGeometry = element.geometry(); // The local scvf index set - std::vector<IndexType> scvfIndexSet; + std::vector<GridIndexType> scvfIndexSet; scvfIndexSet.reserve(MpfaHelper::getNumLocalScvfs(elementGeometry.type())); // for network grids there might be multiple intersections with the same geometryInInside // we indentify those by the indexInInside for now (assumes conforming grids at branching facets) - std::vector<std::vector<IndexType>> outsideIndices; + std::vector<std::vector<GridIndexType>> outsideIndices; if (dim < dimWorld) { outsideIndices.resize(element.subEntities(1)); @@ -269,7 +250,7 @@ public: secondaryInteractionVolumeVertices_[vIdxGlobal] = true; } - // the quadrature point to be used on the scvfs + // the quadrature point parameterizarion to be used on scvfs static const Scalar q = getParamFromGroup<Scalar>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Mpfa.Q"); // make the scv face (for non-boundary scvfs on network grids, use precalculated outside indices) @@ -278,15 +259,15 @@ public: if (!boundary) { return dim == dimWorld ? - std::vector<IndexType>({this->elementMapper().index(is.outside())}) : + std::vector<GridIndexType>({this->elementMapper().index(is.outside())}) : outsideIndices[indexInInside]; } else { // compute boundary scv idx and increment counter - const IndexType bIdx = numScvs + numBoundaryScvf_; + const GridIndexType bIdx = numScvs + numBoundaryScvf_; numBoundaryScvf_++; - return std::vector<IndexType>(1, bIdx); + return std::vector<GridIndexType>(1, bIdx); } } (); @@ -368,43 +349,27 @@ public: std::cout << "Initializing of the connectivity map took " << timer.elapsed() << " seconds." << std::endl; } - /*! - * \brief Returns a sub control volume for a given global scv index. - */ - const SubControlVolume& scv(IndexType scvIdx) const - { return scvs_[scvIdx]; } - - /*! - * \brief Returns a sub control volume face for a given global scvf index. - */ - const SubControlVolumeFace& scvf(IndexType scvfIdx) const - { return scvfs_[scvfIdx]; } - - /*! - * \brief Returns the "flipped" scvf, i.e. the correspongin scvf in an outside element. - * The second argument is optional and only comes into play on network/surface grids. - */ - const SubControlVolumeFace& flipScvf(IndexType scvfIdx, unsigned int outsideScvfIdx = 0) const - { return scvfs_[flipScvfIndices_[scvfIdx][outsideScvfIdx]]; } + //! Get a sub control volume with a global scv index + const SubControlVolume& scv(GridIndexType scvIdx) const { return scvs_[scvIdx]; } - /*! - * \brief Returns the sub control volume face indices of an scv by global index. - */ - const std::vector<IndexType>& scvfIndicesOfScv(IndexType scvIdx) const - { return scvfIndicesOfScv_[scvIdx]; } + //! Get a sub control volume face with a global scvf index + const SubControlVolumeFace& scvf(GridIndexType scvfIdx) const { return scvfs_[scvfIdx]; } + + //! Returns the connectivity map of which dofs + //! have derivatives with respect to a given dof. + const ConnectivityMap& connectivityMap() const { return connectivityMap_; } - /*! - * \brief Returns the connectivity map of which dofs have derivatives with respect - * to a given dof. - */ - const ConnectivityMap& connectivityMap() const - { return connectivityMap_; } + //! Returns the grid interaction volume seeds class. + const GridIVIndexSets& gridInteractionVolumeIndexSets() const { return ivIndexSets_; } - /*! - * \brief Returns the grit interaction volume seeds class. - */ - const GridIVIndexSets& gridInteractionVolumeIndexSets() const - { return ivIndexSets_; } + //! Get the scvf on the same face but from the other side + //! Note that e.g. the normals might be different in the case of surface grids + const SubControlVolumeFace& flipScvf(GridIndexType scvfIdx, unsigned int outsideScvfIdx = 0) const + { return scvfs_[flipScvfIndices_[scvfIdx][outsideScvfIdx]]; } + + //! Get the sub control volume face indices of an scv by global index + const std::vector<GridIndexType>& scvfIndicesOfScv(GridIndexType scvIdx) const + { return scvfIndicesOfScv_[scvIdx]; } private: // connectivity map for efficient assembly @@ -415,45 +380,56 @@ private: std::vector<SubControlVolumeFace> scvfs_; // containers storing the global data - std::vector<std::vector<IndexType>> scvfIndicesOfScv_; + std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_; std::vector<bool> primaryInteractionVolumeVertices_; std::vector<bool> secondaryInteractionVolumeVertices_; std::size_t numBoundaryScvf_; // needed for embedded surface and network grids (dim < dimWorld) - std::vector<std::vector<IndexType>> flipScvfIndices_; + std::vector<std::vector<GridIndexType>> flipScvfIndices_; // The grid interaction volume index set GridIVIndexSets ivIndexSets_; // Indicator function on where to use the secondary IVs - SecondaryIvIndicator secondaryIvIndicator_; + SecondaryIvIndicatorType secondaryIvIndicator_; }; -// specialization in case the FVElementGeometries are not stored +/*! + * \ingroup CCMpfaDiscretization + * \brief The finite volume geometry (scvs and scvfs) for cell-centered mpfa models on a grid view + * This builds up the sub control volumes and sub control volume faces + * \note For caching disabled we store only some essential index maps to build up local systems on-demand in + * the corresponding FVElementGeometry + */ template<class TypeTag> class CCMpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag> { using ParentType = BaseFVGridGeometry<TypeTag>; using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using ElementMapper = typename GET_PROP_TYPE(TypeTag, ElementMapper); + using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using GridIVIndexSets = CCMpfaGridInteractionVolumeIndexSets<TypeTag>; - using ConnectivityMap = CCMpfaConnectivityMap<TypeTag>; using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using ElementMapper = typename GET_PROP_TYPE(TypeTag, ElementMapper); static constexpr int dim = GridView::dimension; static constexpr int dimWorld = GridView::dimensionworld; + using Element = typename GridView::template Codim<0>::Entity; using Vertex = typename GridView::template Codim<dim>::Entity; using Intersection = typename GridView::Intersection; using CoordScalar = typename GridView::ctype; - using IndexType = typename GridView::IndexSet::IndexType; + using GridIndexType = typename GridView::IndexSet::IndexType; + using LocalIndexType = typename PrimaryInteractionVolume::Traits::LocalIndexType; + + using GridIVIndexSets = CCMpfaGridInteractionVolumeIndexSets<TypeTag>; + using ConnectivityMap = CCMpfaConnectivityMap<TypeTag>; - using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>; using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>; public: @@ -461,102 +437,64 @@ public: //! Constructor without indicator function for secondary interaction volumes //! Per default, we use the secondary IVs at branching points & boundaries - explicit CCMpfaFVGridGeometry(const GridView& gridView) - : ParentType(gridView) - , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching) - { return is.boundary() || isBranching; } ) - {} - - //! Constructor with user-defined indicator function for secondary interaction volumes - explicit CCMpfaFVGridGeometry(const GridView& gridView, const SecondaryIvIndicator& indicator) - : ParentType(gridView) - , secondaryIvIndicator_(indicator) - {} + CCMpfaFVGridGeometry(const GridView& gridView) + : ParentType(gridView) + , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching) + { return is.boundary() || isBranching; } ) + {} + + //! Constructor with user-defined indicator function for secondary interaction volumes + CCMpfaFVGridGeometry(const GridView& gridView, const SecondaryIvIndicator& indicator) + : ParentType(gridView) + , secondaryIvIndicator_(indicator) + {} //! the element mapper is the dofMapper //! this is convenience to have better chance to have the same main files for box/tpfa/mpfa... const ElementMapper& dofMapper() const { return this->elementMapper(); } - /*! - * \brief Returns the total number of sub control volumes. - */ - std::size_t numScv() const - { return numScvs_; } - - /*! - * \brief Returns the total number of sub control volume faces. - */ - std::size_t numScvf() const - { return numScvf_; } - - /*! - * \brief Returns the number of scvfs on the domain boundary. - */ - std::size_t numBoundaryScvf() const - { return numBoundaryScvf_; } - - /*! - * \brief Returns the total number of degrees of freedom. - */ - std::size_t numDofs() const - { return this->gridView().size(0); } - - /*! - * \brief Gets an element from a global element index. - */ - Element element(IndexType eIdx) const - { return this->elementMap()[eIdx]; } - - /*! - * \brief Gets an element from a sub control volume contained in it. - */ - Element element(const SubControlVolume& scv) const - { return this->elementMap()[scv.elementIndex()]; } - - /*! - * \brief Returns true if primary interaction volumes are used around a given vertex, - * false otherwise. - */ + //! Returns the total number of sub control volumes. + std::size_t numScv() const { return numScvs_; } + + //! Returns the total number of sub control volume faces. + std::size_t numScvf() const { return numScvf_; } + + //! Returns the number of scvfs on the domain boundary. + std::size_t numBoundaryScvf() const { return numBoundaryScvf_; } + + //! Returns the total number of degrees of freedom. + std::size_t numDofs() const { return this->gridView().size(0); } + + //! Gets an element from a global element index. + Element element(GridIndexType eIdx) const { return this->elementMap()[eIdx]; } + + //! Gets an element from a sub control volume contained in it. + Element element(const SubControlVolume& scv) const { return this->elementMap()[scv.elementIndex()]; } + + //! Returns true if primary interaction volumes are used around a given vertex. bool vertexUsesPrimaryInteractionVolume(const Vertex& v) const { return primaryInteractionVolumeVertices_[this->vertexMapper().index(v)]; } - /*! - * \brief Returns true if primary interaction volumes are used around a given vertex index, - * false otherwise. - */ - bool vertexUsesPrimaryInteractionVolume(IndexType vIdxGlobal) const + //! Returns true if primary interaction volumes are used around a given vertex (index). + bool vertexUsesPrimaryInteractionVolume(GridIndexType vIdxGlobal) const { return primaryInteractionVolumeVertices_[vIdxGlobal]; } - /*! - * \brief Returns if primary interaction volumes are used around a given vertex. - */ + //! Returns if primary interaction volumes are used around a given vertex. bool vertexUsesSecondaryInteractionVolume(const Vertex& v) const { return secondaryInteractionVolumeVertices_[this->vertexMapper().index(v)]; } - /*! - * \brief Returns true if primary interaction volumes are used around a given vertex index, - * false otherwise. - */ - bool vertexUsesSecondaryInteractionVolume(IndexType vIdxGlobal) const + //! Returns true if primary interaction volumes are used around a given vertex (index). + bool vertexUsesSecondaryInteractionVolume(GridIndexType vIdxGlobal) const { return secondaryInteractionVolumeVertices_[vIdxGlobal]; } - /*! - * \brief Returns true if a given vertex lies on a processor boundary inside a ghost element. - */ - bool isGhostVertex(const Vertex& v) const - { return isGhostVertex_[this->vertexMapper().index(v)]; } - - /*! - * \brief Returns true if the vertex corresponding to a given vertex index lies on a - * processor boundary inside a ghost element. - */ - bool isGhostVertex(IndexType vIdxGlobal) const - { return isGhostVertex_[vIdxGlobal]; } - - /*! - * \brief Updates all finite volume geometries of the grid. Has to be called again after grid adaption. - */ + //! Returns true if a given vertex lies on a processor boundary inside a ghost element. + bool isGhostVertex(const Vertex& v) const { return isGhostVertex_[this->vertexMapper().index(v)]; } + + //! Returns true if the vertex (index) lies on a processor boundary inside a ghost element. + bool isGhostVertex(GridIndexType vIdxGlobal) const { return isGhostVertex_[vIdxGlobal]; } + + //! Updates all finite volume geometries of the grid. Has to be called again after grid adaption. void update() { ParentType::update(); @@ -579,7 +517,7 @@ public: isGhostVertex_ = MpfaHelper::findGhostVertices(this->gridView(), this->vertexMapper()); // instantiate the dual grid index set (to be used for construction of interaction volumes) - CCMpfaDualGridIndexSet<TypeTag> dualIdSet(this->gridView()); + CCMpfaDualGridIndexSet<GridIndexType, LocalIndexType, dim> dualIdSet(this->gridView()); // Build the SCVs and SCV faces numScvf_ = 0; @@ -593,14 +531,14 @@ public: // the element-wise index sets for finite volume geometry const auto numLocalFaces = MpfaHelper::getNumLocalScvfs(elementGeometry.type()); - std::vector<IndexType> scvfsIndexSet; - std::vector< std::vector<IndexType> > neighborVolVarIndexSet; + std::vector<GridIndexType> scvfsIndexSet; + std::vector< std::vector<GridIndexType> > neighborVolVarIndexSet; scvfsIndexSet.reserve(numLocalFaces); neighborVolVarIndexSet.reserve(numLocalFaces); // for network grids there might be multiple intersections with the same geometryInInside // we indentify those by the indexInInside for now (assumes conforming grids at branching facets) - std::vector<std::vector<IndexType>> outsideIndices; + std::vector<std::vector<GridIndexType>> outsideIndices; if (dim < dimWorld) { outsideIndices.resize(element.subEntities(1)); @@ -661,15 +599,15 @@ public: if (!boundary) { return dim == dimWorld ? - std::vector<IndexType>({this->elementMapper().index(is.outside())}) : + std::vector<GridIndexType>({this->elementMapper().index(is.outside())}) : outsideIndices[indexInInside]; } else { // compute boundary scv idx and increment counter - const IndexType bIdx = numScvs_ + numBoundaryScvf_; + const GridIndexType bIdx = numScvs_ + numBoundaryScvf_; numBoundaryScvf_++; - return std::vector<IndexType>(1, bIdx); + return std::vector<GridIndexType>(1, bIdx); } } (); @@ -705,38 +643,28 @@ public: std::cout << "Initializing of the connectivity map took " << timer.elapsed() << " seconds." << std::endl; } - /*! - * \brief Returns the sub control volume face indices of an scv by global index. - */ - const std::vector<IndexType>& scvfIndicesOfScv(IndexType scvIdx) const + //! Returns the sub control volume face indices of an scv by global index. + const std::vector<GridIndexType>& scvfIndicesOfScv(GridIndexType scvIdx) const { return scvfIndicesOfScv_[scvIdx]; } - /*! - * \brief Returns the neighboring vol var indices for each scvf contained in an scv. - */ - const std::vector< std::vector<IndexType> >& neighborVolVarIndices(IndexType scvIdx) const + //! Returns the neighboring vol var indices for each scvf contained in an scv. + const std::vector< std::vector<GridIndexType> >& neighborVolVarIndices(GridIndexType scvIdx) const { return neighborVolVarIndices_[scvIdx]; } - /*! - * \brief Returns the connectivity map of which dofs have derivatives with respect - * to a given dof. - */ - const ConnectivityMap& connectivityMap() const - { return connectivityMap_; } + //! Returns the connectivity map of which dofs + //! have derivatives with respect to a given dof. + const ConnectivityMap& connectivityMap() const { return connectivityMap_; } - /*! - * \brief Returns the grit interaction volume seeds class. - */ - const GridIVIndexSets& gridInteractionVolumeIndexSets() const - { return ivIndexSets_; } + //! Returns the grid interaction volume seeds class. + const GridIVIndexSets& gridInteractionVolumeIndexSets() const { return ivIndexSets_; } private: // connectivity map for efficient assembly ConnectivityMap connectivityMap_; // containers storing the global data - std::vector<std::vector<IndexType>> scvfIndicesOfScv_; - std::vector< std::vector< std::vector<IndexType> > > neighborVolVarIndices_; + std::vector<std::vector<GridIndexType>> scvfIndicesOfScv_; + std::vector< std::vector< std::vector<GridIndexType> > > neighborVolVarIndices_; std::vector<bool> primaryInteractionVolumeVertices_; std::vector<bool> secondaryInteractionVolumeVertices_; std::vector<bool> isGhostVertex_; @@ -751,6 +679,6 @@ private: SecondaryIvIndicator secondaryIvIndicator_; }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/generalconnectivitymap.hh b/dumux/discretization/cellcentered/mpfa/generalconnectivitymap.hh index 26beb8a932812cf6d21b8d26458627330fc212e7..24166a0539f63d0e3d2b472858c29df8a5cd50f2 100644 --- a/dumux/discretization/cellcentered/mpfa/generalconnectivitymap.hh +++ b/dumux/discretization/cellcentered/mpfa/generalconnectivitymap.hh @@ -18,6 +18,7 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief Stores the face indices corresponding to the neighbors of an element * that contribute to the derivative calculation */ @@ -34,7 +35,7 @@ namespace Dumux { /*! - * \ingroup CellCentered + * \ingroup CCMpfaDiscretization * \brief General version of the assembly map for cellcentered schemes. To each * cell I we store a list of cells J that are needed to compute the fluxes * in these cells J that depend on cell I. Furthermore, we store for each cell J @@ -47,7 +48,7 @@ class CCMpfaGeneralConnectivityMap using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; + using GridIndexType = typename GridView::IndexSet::IndexType; using FluxStencil = Dumux::FluxStencil<TypeTag>; // To each cell "globalI" there will be a list of "globalJ", in which globalI is part @@ -55,9 +56,9 @@ class CCMpfaGeneralConnectivityMap // additional scvfs which are needed temporarily to set up the transmissibilities of the scvfsJ struct DataJ { - IndexType globalJ; - std::vector<IndexType> scvfsJ; - std::vector<IndexType> additionalScvfs; + GridIndexType globalJ; + std::vector<GridIndexType> scvfsJ; + std::vector<GridIndexType> additionalScvfs; }; using Map = std::vector<std::vector<DataJ>>; @@ -81,7 +82,7 @@ public: fvGeometry.bindElement(element); // obtain the data of J in elements I - std::vector<std::pair<IndexType, std::vector<DataJ>>> dataJForI; + std::vector<std::pair<GridIndexType, std::vector<DataJ>>> dataJForI; // loop over sub control faces for (auto&& scvf : scvfs(fvGeometry)) @@ -111,7 +112,7 @@ public: // land in the list of additional scvfs. Of that list we will delete those // that are already in the list of scvfsJ later... const auto scvfVectorAtVertex = MpfaHelper::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry); - std::vector<IndexType> scvfIndicesAtVertex(scvfVectorAtVertex.size()); + std::vector<GridIndexType> scvfIndicesAtVertex(scvfVectorAtVertex.size()); for (std::size_t i = 0; i < scvfVectorAtVertex.size(); ++i) scvfIndicesAtVertex[i] = scvfVectorAtVertex[i]->index(); globalJDataJ.additionalScvfs.insert(globalJDataJ.additionalScvfs.end(), @@ -131,7 +132,7 @@ public: // if entry for globalJ2 does not exist yet, add globalJ2 to the J-data of globalI // with an empty set of scvfs over which I and J are coupled (i.e. they aren't coupled) if (it2 == it->second.end()) - it->second.push_back(DataJ({globalJ2, std::vector<IndexType>()})); + it->second.push_back(DataJ({globalJ2, std::vector<GridIndexType>()})); } } else @@ -139,13 +140,13 @@ public: // No DataJ for globalI exists yet. Make it and insert data on the actual // global J as first entry in the vector of DataJs belonging to globalI dataJForI.emplace_back(std::make_pair(globalI, - std::vector<DataJ>({DataJ({globalJ, std::vector<IndexType>({scvf.index()})})}))); + std::vector<DataJ>({DataJ({globalJ, std::vector<GridIndexType>({scvf.index()})})}))); // Also, all scvfs connected to a vertex together with the actual scvf // land in the list of additional scvfs. Of that list we will delete those // that are already in the list of scvfsJ later... const auto scvfVectorAtVertex = MpfaHelper::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry); - std::vector<IndexType> scvfIndicesAtVertex(scvfVectorAtVertex.size()); + std::vector<GridIndexType> scvfIndicesAtVertex(scvfVectorAtVertex.size()); for (unsigned int i = 0; i < scvfVectorAtVertex.size(); ++i) scvfIndicesAtVertex[i] = scvfVectorAtVertex[i]->index(); dataJForI.back().second[0].additionalScvfs.insert(dataJForI.back().second[0].additionalScvfs.end(), @@ -155,7 +156,7 @@ public: // all the other dofs in the stencil will be "globalJ" to globalI as well for (auto globalJ2 : stencil) if (globalJ2 != globalJ && globalJ2 != globalI) - dataJForI.back().second.push_back(DataJ({globalJ2, std::vector<IndexType>()})); + dataJForI.back().second.push_back(DataJ({globalJ2, std::vector<GridIndexType>()})); } } } @@ -191,7 +192,8 @@ public: } } - const std::vector<DataJ>& operator[] (const IndexType globalI) const + //! Returns the assembly map of the element with given grid index + const std::vector<DataJ>& operator[] (const GridIndexType globalI) const { return map_[globalI]; } private: diff --git a/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh b/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh index e56c7288accdeca7c5427270de2d2bcbe01c1f4d..1ac49768a65ae2b545caac995bf8006ce52451a6 100644 --- a/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh +++ b/dumux/discretization/cellcentered/mpfa/gridfluxvariablescache.hh @@ -18,7 +18,8 @@ *****************************************************************************/ /*! * \file - * \brief The global object of flux var caches + * \ingroup CCMpfaDiscretization + * \brief Flux variable caches on a gridview */ #ifndef DUMUX_DISCRETIZATION_CCMPFA_GRID_FLUXVARSCACHE_HH #define DUMUX_DISCRETIZATION_CCMPFA_GRID_FLUXVARSCACHE_HH @@ -30,54 +31,56 @@ namespace Dumux { /*! - * \ingroup Mpfa - * \brief Base class for the flux variables cache vector, we store one cache per face + * \ingroup CCMpfaDiscretization + * \brief Flux variable caches on a gridview + * \note The class is specialized for a version with and without grid caching */ template<class TypeTag, bool EnableGridFluxVariablesCache> class CCMpfaGridFluxVariablesCache; - /*! - * \ingroup Mpfa - * \brief Spezialization when caching globally + * \ingroup CCMpfaDiscretization + * \brief Flux variable caches on a gridview with grid caching enabled + * \note The flux caches of the gridview are stored which is memory intensive but faster */ template<class TypeTag> class CCMpfaGridFluxVariablesCache<TypeTag, true> { - // the flux variables cache filler needs to be friend to fill - // the interaction volumes and data handles - friend CCMpfaFluxVariablesCacheFiller<TypeTag>; - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using Element = typename GridView::template Codim<0>::Entity; + using IndexType = typename GridView::IndexSet::IndexType; + using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - using IndexType = typename GridView::IndexSet::IndexType; using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache); using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); + using PrimaryIvDataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; using SecondaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); - using DataHandle = typename PrimaryInteractionVolume::Traits::DataHandle; + using SecondaryIvDataHandle = typename SecondaryInteractionVolume::Traits::DataHandle; using FluxVariablesCacheFiller = CCMpfaFluxVariablesCacheFiller<TypeTag>; public: + //! The constructor CCMpfaGridFluxVariablesCache(const Problem& problem) : problemPtr_(&problem) {} - // When global caching is enabled, precompute transmissibilities for all scv faces + //! When global caching is enabled, precompute transmissibilities for all scv faces void update(const FVGridGeometry& fvGridGeometry, const GridVolumeVariables& gridVolVars, const SolutionVector& sol, bool forceUpdate = false) { - // only do the update if fluxes are solution dependent or if update is forced + // Update only if the filler puts solution-dependent + // stuff into the caches or if update is enforced if (FluxVariablesCacheFiller::isSolDependent || forceUpdate) { - // clear data if forced update is desired + // clear previous data if forced update is desired if (forceUpdate) { clear_(); @@ -89,17 +92,20 @@ public: secondaryInteractionVolumes_.reserve(numSecondaryIVs); primaryIvDataHandles_.reserve(numPrimaryIvs); secondaryIvDataHandles_.reserve(numSecondaryIVs); - } - // reserve memory estimate for caches, interaction volumes and corresponding data - fluxVarsCache_.resize(fvGridGeometry.numScvf()); + // reserve memory estimate for caches, interaction volumes and corresponding data + fluxVarsCache_.resize(fvGridGeometry.numScvf()); + } // instantiate helper class to fill the caches FluxVariablesCacheFiller filler(problem()); + // set all the caches to "outdated" + for (auto& cache : fluxVarsCache_) + cache.setUpdateStatus(false); + for (const auto& element : elements(fvGridGeometry.gridView())) { - // Prepare the geometries within the elements of the stencil auto fvGeometry = localView(fvGridGeometry); fvGeometry.bind(element); @@ -118,7 +124,8 @@ public: const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) { - // update only if transmissibilities are solution-dependent + // Update only if the filler puts + // solution-dependent stuff into the caches if (FluxVariablesCacheFiller::isSolDependent) { const auto& fvGridGeometry = fvGeometry.fvGridGeometry(); @@ -150,7 +157,6 @@ public: auto& scvfCache = fluxVarsCache_[scvfIdx]; if (!scvfCache.isUpdated()) { - // update cache const auto& scvf = fvGeometry.scvf(scvfIdx); filler.fill(*this, scvfCache, elementJ, fvGeometry, elemVolVars, scvf); } @@ -167,18 +173,52 @@ public: friend inline ElementFluxVariablesCache localView(const CCMpfaGridFluxVariablesCache& global) { return ElementFluxVariablesCache(global); } - // access operators in the case of caching + //! access operators in the case of caching const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const { return fluxVarsCache_[scvf.index()]; } + //! access operators in the case of caching FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) { return fluxVarsCache_[scvf.index()]; } + //! access to the stored interaction volumes + const std::vector<PrimaryInteractionVolume>& primaryInteractionVolumes() const + { return primaryInteractionVolumes_; } + + //! access to the stored interaction volumes + std::vector<PrimaryInteractionVolume>& primaryInteractionVolumes() + { return primaryInteractionVolumes_; } + + //! access to the stored data handles + const std::vector<PrimaryIvDataHandle>& primaryDataHandles() const + { return primaryIvDataHandles_; } + + //! access to the stored data handles + std::vector<PrimaryIvDataHandle>& primaryDataHandles() + { return primaryIvDataHandles_; } + + //! access to the stored interaction volumes + const std::vector<SecondaryInteractionVolume>& secondaryInteractionVolumes() const + { return secondaryInteractionVolumes_; } + + //! access to the stored interaction volumes + std::vector<SecondaryInteractionVolume>& secondaryInteractionVolumes() + { return secondaryInteractionVolumes_; } + + //! access to the stored data handles + const std::vector<SecondaryIvDataHandle>& secondaryDataHandles() const + { return secondaryIvDataHandles_; } + + //! access to the stored data handles + std::vector<SecondaryIvDataHandle>& secondaryDataHandles() + { return secondaryIvDataHandles_; } + const Problem& problem() const { return *problemPtr_; } private: + //! clear all containers void clear_() { fluxVarsCache_.clear(); @@ -194,13 +234,13 @@ private: // store the interaction volumes and handles std::vector<PrimaryInteractionVolume> primaryInteractionVolumes_; std::vector<SecondaryInteractionVolume> secondaryInteractionVolumes_; - std::vector<DataHandle> primaryIvDataHandles_; - std::vector<DataHandle> secondaryIvDataHandles_; + std::vector<PrimaryIvDataHandle> primaryIvDataHandles_; + std::vector<SecondaryIvDataHandle> secondaryIvDataHandles_; }; /*! - * \ingroup ImplicitModel - * \brief Spezialization when not using global caching + * \ingroup CCMpfaDiscretization + * \brief Flux variable caches on a gridview with grid caching disabled */ template<class TypeTag> class CCMpfaGridFluxVariablesCache<TypeTag, false> @@ -216,14 +256,16 @@ class CCMpfaGridFluxVariablesCache<TypeTag, false> using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); public: + //! The constructor CCMpfaGridFluxVariablesCache(const Problem& problem) : problemPtr_(&problem) {} - // When global flux variables caching is disabled, we don't need to update the cache + //! When global flux variables caching is disabled, we don't need to update the cache void update(const FVGridGeometry& fvGridGeometry, const GridVolumeVariables& gridVolVars, const SolutionVector& sol, bool forceUpdate = false) {} + //! When global flux variables caching is disabled, we don't need to update the cache void updateElement(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars) {} @@ -243,6 +285,6 @@ private: const Problem* problemPtr_; }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh b/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh index 8c34070b8d44502372abe23afbafbe5ed749fd97..0cc347bf1b8dbaddd29f667868b7dcdaf6918b4a 100644 --- a/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh +++ b/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh @@ -18,6 +18,7 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief Class for the grid interaction volume index sets of mpfa schemes. */ #ifndef DUMUX_DISCRETIZATION_MPFA_O_GRIDINTERACTIONVOLUME_INDEXSETS_HH @@ -26,34 +27,39 @@ #include <memory> #include <dumux/common/properties.hh> +#include "dualgridindexset.hh" + namespace Dumux { -// forward declaration -template<class TypeTag> -class CCMpfaDualGridIndexSet; /*! - * \ingroup Mpfa - * \brief The grid interaction volume index sets class for the mpfa-o scheme. + * \ingroup CCMpfaDiscretization + * \brief Class that holds all interaction volume index sets on a grid view. */ template<class TypeTag> class CCMpfaGridInteractionVolumeIndexSets { using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using IndexType = typename GridView::IndexSet::IndexType; + using GridIndexType = typename GridView::IndexSet::IndexType; using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); + using PrimaryIV = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); using PrimaryIVIndexSet = typename PrimaryIV::Traits::IndexSet; using SecondaryIV = typename GET_PROP_TYPE(TypeTag, SecondaryInteractionVolume); using SecondaryIVIndexSet = typename SecondaryIV::Traits::IndexSet; - using Helper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); - using DualGridIndexSet = CCMpfaDualGridIndexSet<TypeTag>; - static const int dim = GridView::dimension; + static constexpr int dim = GridView::dimension; + using LocalIndexType = typename PrimaryIV::Traits::LocalIndexType; + using DualGridIndexSet = CCMpfaDualGridIndexSet< GridIndexType, LocalIndexType, dim>; public: - + /*! + * \brief Construct all interaction volume index sets on the grid view + * + * \param fvGridGeometry The finite volume geometry on the grid view + * \param dualGridIdSet The index sets of the dual grid on the grid view + */ void update(FVGridGeometry& fvGridGeometry, DualGridIndexSet&& dualGridIdSet) { dualGridIndexSet_ = std::make_unique<DualGridIndexSet>(std::move(dualGridIdSet)); @@ -91,32 +97,37 @@ public: } } + //! Return the iv index set in which a given scvf is embedded in const PrimaryIVIndexSet& primaryIndexSet(const SubControlVolumeFace& scvf) const { return primaryIndexSet(scvf.index()); } - const PrimaryIVIndexSet& primaryIndexSet(const IndexType scvfIdx) const + //! Return the iv index set in which a given scvf (index) is embedded in + const PrimaryIVIndexSet& primaryIndexSet(const GridIndexType scvfIdx) const { return primaryIVIndexSets_[scvfIndexMap_[scvfIdx]]; } + //! Return the iv index set in which a given scvf is embedded in const SecondaryIVIndexSet& secondaryIndexSet(const SubControlVolumeFace& scvf) const { return secondaryIndexSet(scvf.index()); } - const SecondaryIVIndexSet& secondaryIndexSet(const IndexType scvfIdx) const + //! Return the iv index set in which a given scvf (index) is embedded in + const SecondaryIVIndexSet& secondaryIndexSet(const GridIndexType scvfIdx) const { return secondaryIVIndexSets_[scvfIndexMap_[scvfIdx]]; } + //! Returns number of primary/secondary interaction volumes on the grid view std::size_t numPrimaryInteractionVolumes() const { return numPrimaryIV_; } std::size_t numSecondaryInteractionVolumes() const { return numSecondaryIV_; } private: std::vector<PrimaryIVIndexSet> primaryIVIndexSets_; std::vector<SecondaryIVIndexSet> secondaryIVIndexSets_; - std::vector<IndexType> scvfIndexMap_; + std::vector<GridIndexType> scvfIndexMap_; std::size_t numPrimaryIV_; std::size_t numSecondaryIV_; std::unique_ptr<DualGridIndexSet> dualGridIndexSet_; }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/helper.hh b/dumux/discretization/cellcentered/mpfa/helper.hh index 988abe331ed52f3e74aae3116f0ea7f37e388837..3de020e6b85e2c7aa8e566f639cbc6fa72435ac1 100644 --- a/dumux/discretization/cellcentered/mpfa/helper.hh +++ b/dumux/discretization/cellcentered/mpfa/helper.hh @@ -18,12 +18,14 @@ *****************************************************************************/ /*! * \file - * \brief Helper class to get information required for mpfa scheme. + * \ingroup CCMpfaDiscretization + * \brief Helper class to get data required for mpfa scheme. */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_HELPER_HH #define DUMUX_DISCRETIZATION_CC_MPFA_HELPER_HH #include <dune/common/version.hh> +#include <dune/common/exceptions.hh> #include <dune/common/fvector.hh> #include <dune/common/fmatrix.hh> #include <dune/common/parallel/mpihelper.hh> @@ -32,24 +34,20 @@ #include <dumux/common/properties.hh> #include <dumux/common/math.hh> -#include "methods.hh" namespace Dumux { /*! - * \brief Mpfa method-specific implementation of the helper class (dimension-dependent) - */ -template<class TypeTag, MpfaMethods Method, int dim, int dimWorld> -class MpfaMethodHelper; - -/*! - * \brief Dimension-specific implementation of the helper class (common for all methods) + * \ingroup CCMpfaDiscretization + * \brief Dimension-specific helper class to get data required for mpfa scheme. */ template<class TypeTag, int dim, int dimWorld> class MpfaDimensionHelper; /*! - * \brief Specialization for dim == 2 & dimWorld == 2 + * \ingroup CCMpfaDiscretization + * \brief Dimension-specific helper class to get data required for mpfa scheme. + * Specialization for dim == 2 & dimWorld == 2 */ template<class TypeTag> class MpfaDimensionHelper<TypeTag, /*dim*/2, /*dimWorld*/2> @@ -60,19 +58,20 @@ class MpfaDimensionHelper<TypeTag, /*dim*/2, /*dimWorld*/2> using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ScvfCornerVector = typename SubControlVolumeFace::Traits::CornerStorage; using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using ScvBasis = typename InteractionVolume::Traits::ScvBasis; + using LocalScvType = typename InteractionVolume::Traits::LocalScvType; + using ScvBasis = typename LocalScvType::LocalBasis; - //! We know that dim = 2 & dimworld = 2. However, the specialization for - //! dim = 2 & dimWorld = 3 reuses some methods of this class, thus, we - //! obtain the world dimension from the grid view here to get the - //! GlobalPosition vector right. Be picky about the dimension though. + // We know that dim = 2 & dimworld = 2. However, the specialization for + // dim = 2 & dimWorld = 3 reuses some methods of this class, thus, we + // obtain the world dimension from the grid view here to get the + // GlobalPosition vector right. Be picky about the dimension though. static_assert(GridView::dimension == 2, "The chosen mpfa helper expects a grid view with dim = 2"); static const int dim = 2; static const int dimWorld = GridView::dimensionworld; using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; - //! Container to store the positions of intersections required for scvf - //! corner computation. In 2d, these are the center plus the two corners + // Container to store the positions of intersections required for scvf + // corner computation. In 2d, these are the center plus the two corners using ScvfPositionsOnIntersection = std::array<GlobalPosition, 3>; public: @@ -104,7 +103,7 @@ public: * * \param scvBasis The basis of an scv */ - static Scalar calculateDetX(const ScvBasis& scvBasis) + static typename LocalScvType::ctype calculateDetX(const ScvBasis& scvBasis) { using std::abs; return abs(crossProduct<Scalar>(scvBasis[0], scvBasis[1])); @@ -227,15 +226,19 @@ public: }; /*! - * \brief Specialization for dim == 2 & dimWorld == 2. Reuses some - * functionality of the specialization for dim = dimWorld = 2 + * \ingroup CCMpfaDiscretization + * \brief Dimension-specific helper class to get data required for mpfa scheme. + * Specialization for dim == 2 & dimWorld == 2. Reuses some functionality + * of the specialization for dim = dimWorld = 2 */ template<class TypeTag> -class MpfaDimensionHelper<TypeTag, /*dim*/2, /*dimWorld*/3> : public MpfaDimensionHelper<TypeTag, 2, 2> +class MpfaDimensionHelper<TypeTag, /*dim*/2, /*dimWorld*/3> + : public MpfaDimensionHelper<TypeTag, 2, 2> { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using ScvBasis = typename InteractionVolume::Traits::ScvBasis; + using LocalScvType = typename InteractionVolume::Traits::LocalScvType; + using ScvBasis = typename LocalScvType::LocalBasis; public: @@ -269,7 +272,7 @@ public: * * \param scvBasis The basis of an scv */ - static Scalar calculateDetX(const ScvBasis& scvBasis) + static typename LocalScvType::ctype calculateDetX(const ScvBasis& scvBasis) { using std::abs; return abs(crossProduct<Scalar>(scvBasis[0], scvBasis[1]).two_norm()); @@ -285,9 +288,10 @@ public: static bool isRightHandSystem(const ScvBasis& scvBasis) { return true; } }; - /*! - * \brief Specialization for dim == 3 & dimWorld == 3. + * \ingroup CCMpfaDiscretization + * \brief Dimension-specific helper class to get data required for mpfa scheme. + * Specialization for dim == 3 & dimWorld == 3. */ template<class TypeTag> class MpfaDimensionHelper<TypeTag, /*dim*/3, /*dimWorld*/3> @@ -298,7 +302,8 @@ class MpfaDimensionHelper<TypeTag, /*dim*/3, /*dimWorld*/3> using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ScvfCornerVector = typename SubControlVolumeFace::Traits::CornerStorage; using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using ScvBasis = typename InteractionVolume::Traits::ScvBasis; + using LocalScvType = typename InteractionVolume::Traits::LocalScvType; + using ScvBasis = typename LocalScvType::LocalBasis; // Be picky about the dimensions static_assert(GridView::dimension == 3 && GridView::dimensionworld == 3, @@ -343,7 +348,7 @@ public: * * \param scvBasis The basis of an scv */ - static Scalar calculateDetX(const ScvBasis& scvBasis) + static typename LocalScvType::ctype calculateDetX(const ScvBasis& scvBasis) { using std::abs; return abs(tripleProduct<Scalar>(scvBasis[0], scvBasis[1], scvBasis[2])); @@ -470,9 +475,9 @@ public: { case 3: // triangle { - //! Only build the maps the first time we encounter a triangle - static const std::uint8_t vo = 1; //!< vertex offset in point vector p - static const std::uint8_t eo = 4; //!< edge offset in point vector p + // Only build the maps the first time we encounter a triangle + static const std::uint8_t vo = 1; // vertex offset in point vector p + static const std::uint8_t eo = 4; // edge offset in point vector p static const std::uint8_t map[3][4] = { {0, eo+1, eo+0, vo+0}, @@ -487,9 +492,9 @@ public: } case 4: // quadrilateral { - //! Only build the maps the first time we encounter a quadrilateral - static const std::uint8_t vo = 1; //!< vertex offset in point vector p - static const std::uint8_t eo = 5; //!< face offset in point vector p + // Only build the maps the first time we encounter a quadrilateral + static const std::uint8_t vo = 1; // vertex offset in point vector p + static const std::uint8_t eo = 5; // face offset in point vector p static const std::uint8_t map[4][4] = { {0, eo+0, eo+2, vo+0}, @@ -542,13 +547,12 @@ public: }; /*! - * \ingroup Mpfa + * \ingroup CCMpfaDiscretization * \brief Helper class to get the required information on an interaction volume. * Specializations depending on the method and dimension are provided. */ -template<class TypeTag, MpfaMethods Method, int dim, int dimWorld> -class CCMpfaHelperImplementation : public MpfaDimensionHelper<TypeTag, dim, dimWorld>, - public MpfaMethodHelper<TypeTag, Method, dim, dimWorld> +template<class TypeTag, int dim, int dimWorld> +class CCMpfaHelperImplementation : public MpfaDimensionHelper<TypeTag, dim, dimWorld> { using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); @@ -560,12 +564,11 @@ class CCMpfaHelperImplementation : public MpfaDimensionHelper<TypeTag, dim, dimW using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ScvfCornerVector = typename SubControlVolumeFace::Traits::CornerStorage; + using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); using LocalIndexType = typename InteractionVolume::Traits::LocalIndexType; - using ScvBasis = typename InteractionVolume::Traits::ScvBasis; + using GlobalPosition = typename InteractionVolume::Traits::GlobalPosition; - using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; - using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>; using CoordScalar = typename GridView::ctype; using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>; @@ -628,36 +631,18 @@ public: template<typename V1, typename V2> static bool vectorContainsValue(const std::vector<V1>& vector, const V2 value) { return std::find(vector.begin(), vector.end(), value) != vector.end(); } - - // calculates the product of a transposed vector n, a Matrix M and another vector v (n^T M v) - static Scalar nT_M_v(const GlobalPosition& n, const DimWorldMatrix& M, const GlobalPosition& v) - { - GlobalPosition tmp; - M.mv(v, tmp); - return n*tmp; - } - - // calculates the product of a transposed vector n, a Scalar M and another vector v (n^T M v) - static Scalar nT_M_v(const GlobalPosition& n, const Scalar M, const GlobalPosition& v) - { - return M*(n*v); - } }; /*! - * \ingroup Mpfa - * \brief Helper class for the mpfa methods for the construction of the interaction regions etc. + * \ingroup CCMpfaDiscretization + * \brief Helper class to obtain data required for mpfa methods. * It inherits from dimension-, dimensionworld- and method-specific implementations. */ template<class TypeTag> using CCMpfaHelper = CCMpfaHelperImplementation<TypeTag, - GET_PROP_VALUE(TypeTag, MpfaMethod), GET_PROP_TYPE(TypeTag, GridView)::dimension, GET_PROP_TYPE(TypeTag, GridView)::dimensionworld>; } // end namespace Dumux -// The implemented helper classes need to be included here -#include <dumux/discretization/cellcentered/mpfa/omethod/helper.hh> - #endif diff --git a/dumux/discretization/cellcentered/mpfa/interactionvolume.hh b/dumux/discretization/cellcentered/mpfa/interactionvolume.hh index b3bd11aab4a55b42ce566d504672bafab1970dde..0923b59f2d0f9b28b92be31683fff12f81d854b4 100644 --- a/dumux/discretization/cellcentered/mpfa/interactionvolume.hh +++ b/dumux/discretization/cellcentered/mpfa/interactionvolume.hh @@ -18,7 +18,8 @@ *****************************************************************************/ /*! * \file - * \brief Base classes for interaction volume of mpfa methods. + * \ingroup CCMpfaDiscretization + * \brief Class used for interaction volumes in mpfa schemes. */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_INTERACTIONVOLUME_HH #define DUMUX_DISCRETIZATION_CC_MPFA_INTERACTIONVOLUME_HH @@ -28,18 +29,20 @@ namespace Dumux { -// forward declaration of the base class + +// forward declaration of the method-specific implementation template<class TypeTag, MpfaMethods MpfaMethod> class CCMpfaInteractionVolumeImplementation; /*! - * \ingroup Mpfa - * \brief Base class for the interaction volumes of the mpfa method + * \ingroup CCMpfaDiscretization + * \brief Alias to select the correct implementation of the interactionvolume + * volume. The implementations for the schemes have to be included below. */ template<class TypeTag> using CCMpfaInteractionVolume = CCMpfaInteractionVolumeImplementation<TypeTag, GET_PROP_VALUE(TypeTag, MpfaMethod)>; -} // end namespace +} // end namespace Dumux // the specializations of this class for the available methods have to be included here #include <dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh> diff --git a/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh b/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh index acc01de45ce209fa815826e6b1efdbdd13f7f6d8..38bf007cca1bef3c2eac1cdeebee9f8234d5c5a1 100644 --- a/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh +++ b/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh @@ -18,200 +18,131 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief Base class for interaction volumes of mpfa methods. */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_INTERACTIONVOLUMEBASE_HH #define DUMUX_DISCRETIZATION_CC_MPFA_INTERACTIONVOLUMEBASE_HH -#include <dune/common/dynmatrix.hh> - -#include <dumux/discretization/cellcentered/mpfa/methods.hh> -#include <dumux/discretization/cellcentered/mpfa/interactionvolumedatahandle.hh> -#include <dumux/discretization/cellcentered/mpfa/dualgridindexset.hh> +#include <dumux/common/properties.hh> namespace Dumux { -/*! - * \ingroup Mpfa - * \brief Base class for the interaction volume traits. The types stated here - * have to be defined in interaction volume traits. It is recommended - * that different implementations inherit from this class and overwrite the - * desired types or publicly state the types of this base class. +/* + * \ingroup CCMpfaDiscretization + * \brief Type Traits to retrieve types associated with an implementation of a Dumux::CCMpfaInteractionVolumeBase. + * You have to specialize this class for every implementation of Dumux::CCMpfaInteractionVolumeBase. + * + * \code + * //! export the interaction volume type to be used on boundaries etc. + * using SecondaryInteractionVolume = ...; + * //! export the type used for local indices + * using LocalIndexType = ...; + * //! export the type used for indices on the grid + * using GridIndexType = ...; + * //! export the type for the interaction volume index set + * using IndexSet = ...; + * //! export the type used for global coordinates + * using GlobalPosition = ...; + * //! export the type of interaction-volume local scvs + * using LocalScvType = ...; + * //! export the type of interaction-volume local scvfs + * using LocalScvfType = ...; + * //! export the type of used for the iv-local face data + * using LocalFaceData = ...; + * //! export the type of face data container (use dynamic container here) + * using LocalFaceDataContainer = ...; + * //! export the type used for iv-local matrices + * using Matrix = ...; + * //! export the type used for iv-local vectors + * using Vector = ...; + * //! export the type used for the iv-stencils + * using Stencil = ...; + * //! export the data handle type for this iv + * using DataHandle = InteractionVolumeDataHandle< TypeTag, InteractionVolumeType >; + * \endcode */ -template<class TypeTag> -class CCMpfaInteractionVolumeTraitsBase -{ - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - - static const int dim = GridView::dimension; - static const int dimWorld = GridView::dimensionworld; - using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; - -public: - using LocalIndexType = std::uint8_t; - - //! The dynamic types are used e.g. by the mpfa-o method. - //! To be compatible with schemes using both dynamic and static - //! array types (e.g. L-method using mpfa-o interaction volumes - //! on the boudaries), other classes interacting with the interaction - //! volumes (e.g. flux vars cache) export the dynamic types. If your - //! scheme is fully static on the entire grid, overwrite these traits. - using DynamicLocalIndexContainer = std::vector<LocalIndexType>; - using DynamicGlobalIndexContainer = std::vector<typename GridView::IndexSet::IndexType>; - using DynamicMatrix = Dune::DynamicMatrix<Scalar>; - using DynamicVector = typename DynamicMatrix::row_type; - - //! The data handle type. Uses the dynamic types as well per default... - using DataHandle = InteractionVolumeDataHandle<TypeTag>; - - using ScvfVector = std::array<const SubControlVolumeFace*, dim>; - using ScvBasis = std::array<GlobalPosition, dim>; - - //! for network grids this means that we assume the tensors - //! to be given in world coordinates! If a transformation of - //! given data has to be performed, it has to be done in the - //! spatial parameters method where the tensor is returned or - //! in the volume variables where it is stored - using Tensor = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>; -}; +template< class InteractionVolume > +struct CCMpfaInteractionVolumeTraits {}; /*! - * \ingroup Mpfa + * \ingroup CCMpfaDiscretization * \brief Base class for the interaction volumes of mpfa methods. It defines * the interface and actual implementations should derive from this class. */ -template<class TypeTag, typename T> +template<class TypeTag, class Implementation> class CCMpfaInteractionVolumeBase { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + // Curiously recurring template pattern + Implementation & asImp() { return static_cast<Implementation&>(*this); } + const Implementation & asImp() const { return static_cast<const Implementation&>(*this); } + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Element = typename GridView::template Codim<0>::Entity; + +public: + // Types required in the assembly of the local eq system using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - using DualGridNodalIndexSet = typename CCMpfaDualGridIndexSet<TypeTag>::NodalIndexSet; - - using DataHandle = typename T::DataHandle; - using IndexSet = typename T::IndexSet; - using LocalIndexContainer = typename T::DynamicLocalIndexContainer; - using LocalIndexType = typename LocalIndexContainer::value_type; - using GlobalIndexContainer = typename T::DynamicGlobalIndexContainer; - using GlobalIndexType = typename GlobalIndexContainer::value_type; - static const int dim = GridView::dimension; - static const int dimWorld = GridView::dimensionworld; - using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; + //! state the traits type publicly + using Traits = CCMpfaInteractionVolumeTraits< Implementation >; -public: - // state the traits type publicly - using Traits = T; - - class LocalFaceData - { - LocalIndexType ivLocalScvfIndex_; //!< the iv-local scvf index this scvf maps to - LocalIndexType ivLocalInsideScvIndex_; //!< the iv-local index of the scvfs' inside scv - LocalIndexType ivLocalOutsideScvfIndex_; //!< the index of this scvf in the iv-local outside faces - LocalIndexType scvfLocalOutsideScvfIndex_; //!< the index of this scvf in the scvf-local outside faces - GlobalIndexType globalScvfIndex_; //!< the index of the corresponding global scvf - bool isOutside_; //!< indicates if this face maps to the iv-local index from "outside" - - public: - //! Constructor for "inside" faces - explicit LocalFaceData(LocalIndexType faceIndex, - LocalIndexType scvIndex, - GlobalIndexType globalScvfIndex) - : ivLocalScvfIndex_(faceIndex), - ivLocalInsideScvIndex_(scvIndex), - globalScvfIndex_(globalScvfIndex), - isOutside_(false) {} - - //! Constructor for "outside" faces - explicit LocalFaceData(LocalIndexType faceIndex, - LocalIndexType scvIndex, - LocalIndexType indexInIvOutsideFaces, - LocalIndexType indexInScvfOutsideFaces, - GlobalIndexType globalScvfIndex) - : ivLocalScvfIndex_(faceIndex), - ivLocalInsideScvIndex_(scvIndex), - ivLocalOutsideScvfIndex_(indexInIvOutsideFaces), - scvfLocalOutsideScvfIndex_(indexInScvfOutsideFaces), - globalScvfIndex_(globalScvfIndex), - isOutside_(true) {} - - //! The index of the scvf within the inside faces - LocalIndexType ivLocalScvfIndex() const { return ivLocalScvfIndex_; } - LocalIndexType ivLocalInsideScvIndex() const { return ivLocalInsideScvIndex_; } - LocalIndexType ivLocalOutsideScvfIndex() const { assert(isOutside_); return ivLocalOutsideScvfIndex_; } - LocalIndexType scvfLocalOutsideScvfIndex() const { assert(isOutside_); return scvfLocalOutsideScvfIndex_; } - GlobalIndexType globalScvfIndex() const { return globalScvfIndex_; } - bool isOutside() const { return isOutside_; } - }; - - struct DirichletData - { - GlobalIndexType volVarIndex_; - GlobalPosition ipGlobal_; - - public: - explicit DirichletData(const GlobalIndexType index, const GlobalPosition& ip) - : volVarIndex_(index) - , ipGlobal_(ip) - {} - - const GlobalPosition& ipGlobal() const { return ipGlobal_; } - GlobalIndexType volVarIndex() const { return volVarIndex_; } - }; - - using DirichletDataContainer = std::vector<DirichletData>; - using LocalFaceDataContainer = std::vector<LocalFaceData>; - - //! Sets up the local scope (geometries etc) for a given iv index set! - void setUpLocalScope(const IndexSet& indexSet, + //! Prepares everything for the assembly + void setUpLocalScope(const typename Traits::IndexSet& indexSet, const Problem& problem, const FVElementGeometry& fvGeometry) - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a setUpLocalScope() method."); } + { asImp().setUpLocalScope(); } + + //! returns the number of "primary" scvfs of this interaction volume + std::size_t numFaces() const { return asImp().numFaces(); } + + //! returns the number of intermediate unknowns within this interaction volume + std::size_t numUnknowns() const { return asImp().numUnknowns(); } + + //! returns the number of (in this context) known solution values within this interaction volume + std::size_t numKnowns() const { return asImp().numKnowns(); } + + //! returns the number of scvs embedded in this interaction volume + std::size_t numScvs() const { return asImp().numScvs(); } + + //! returns the number of scvfs embedded in this interaction volume + std::size_t numScvfs() const { return asImp().numScvfs(); } - //! sets the sizes of the corresponding matrices in the data handle - void prepareDataHandle(DataHandle& dataHandle) - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a prepareDataHandle() method."); } + //! returns a reference to the container with the local face data + const typename Traits::LocalFaceDataContainer& localFaceData() const { asImp().localFaceData(); } - //! solves for the transmissibilities subject to a given tensor - template<typename GetTensorFunction> - void solveLocalSystem(const GetTensorFunction& getTensor, - const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - DataHandle& dataHandle) - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a solveLocalSystem() method."); } + //! returns the cell-stencil of this interaction volume + const typename Traits::Stencil& stencil() const { return asImp().stencil(); } - //! obtain the local data object for a given global scvf - const LocalFaceData& getLocalFaceData(const SubControlVolumeFace& scvf) const - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a getLocalFaceData() method."); } + //! returns the local scvf entity corresponding to a given iv-local scvf idx + const typename Traits::LocalScvfType& localScvf(typename Traits::LocalIndexType ivLocalScvfIdx) const + { return asImp().localScvf(ivLocalScvfIdx); } - //!returns a reference to the container with the local face data - const LocalFaceDataContainer& localFaceData() const - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a localFaceData() method."); } + //! returns the local scv entity corresponding to a given iv-local scv idx + const typename Traits::LocalScvType& localScv(typename Traits::LocalIndexType ivLocalScvIdx) const + { return asImp().localScv(ivLocalScvIdx); } - //! returns the indices of the volvars in the stencil of the interaction volume - const GlobalIndexContainer& volVarsStencil() const - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a volVarsStencil() method."); } + //! returns the element in which the scv with the given local idx is embedded in + const Element& element(typename Traits::LocalIndexType ivLocalScvIdx) const + { return asImp().element(); } //! returns the number of interaction volumes living around a vertex - static std::size_t numInteractionVolumesAtVertex(const DualGridNodalIndexSet& nodalIndexSet) - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a numInteractionVolumesAtVertex() method."); } + template< class NodalIndexSet > + static std::size_t numInteractionVolumesAtVertex(const NodalIndexSet& nodalIndexSet) + { return Implementation::numInteractionVolumesAtVertex(nodalIndexSet); } //! adds the iv index sets living around a vertex to a given container //! and stores the the corresponding index in a map for each scvf - template<class IvIndexSetContainer, class ScvfIndexMap> + template<class IvIndexSetContainer, class ScvfIndexMap, class NodalIndexSet> static void addInteractionVolumeIndexSets(IvIndexSetContainer& ivIndexSetContainer, ScvfIndexMap& scvfIndexMap, - const DualGridNodalIndexSet& nodalIndexSet) - { DUNE_THROW(Dune::NotImplemented, "Interaction volume implementation does not provide a numInteractionVolumesAtVertex() method."); } + const NodalIndexSet& nodalIndexSet) + { Implementation::addInteractionVolumeIndexSets(ivIndexSetContainer, scvfIndexMap, nodalIndexSet); } }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/interactionvolumedatahandle.hh b/dumux/discretization/cellcentered/mpfa/interactionvolumedatahandle.hh index 520372856f35d807635adbe647eaf9db8588db1b..d1d032e088e845457b9b078d82db662d99c37ebe 100644 --- a/dumux/discretization/cellcentered/mpfa/interactionvolumedatahandle.hh +++ b/dumux/discretization/cellcentered/mpfa/interactionvolumedatahandle.hh @@ -24,383 +24,302 @@ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_INTERACTIONVOLUMEDATAHANDLE_HH #define DUMUX_DISCRETIZATION_CC_MPFA_INTERACTIONVOLUMEDATAHANDLE_HH -#include <dune/common/exceptions.hh> +#include <vector> + #include <dumux/common/properties.hh> +#include <dumux/common/parameters.hh> namespace Dumux { - //! Empty data handle class - template<class TypeTag> - class EmptyDataHandle - { - //! we use the dynamic types here to be compatible on the boundary - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using DirichletDataContainer = typename InteractionVolume::DirichletDataContainer; - using GlobalIndexContainer = typename InteractionVolume::Traits::DynamicGlobalIndexContainer; - using Matrix = typename InteractionVolume::Traits::DynamicMatrix; - using Vector = typename InteractionVolume::Traits::DynamicVector; - - public: - //! diffusion caches need to set phase and component index - void setDiffusionContext(unsigned int phaseIdx, unsigned int compIdx) {} - - //! functions to set the size of the matrices - void resizeT(unsigned int n, unsigned int m) {} - void resizeAB(unsigned int n, unsigned int m) {} - void resizeOutsideTij(unsigned int n, unsigned int m) {} - - //! functions to set the pointers to the stencil - void setVolVarsStencilPointer(const GlobalIndexContainer& stencil) {} - - //! return functions for the stored data - const GlobalIndexContainer& volVarsStencil() const { return throw_<const GlobalIndexContainer&>(); } - const DirichletDataContainer& dirichletData() const { return throw_<DirichletDataContainer&>(); } - - const Matrix& T() const { return throw_<const Matrix&>(); } - Matrix& T() { return throw_<Matrix&>(); } - - const Matrix& AB() const { return throw_<const Matrix&>(); } - Matrix& AB() { return throw_<Matrix&>(); } - - const Matrix& outsideTij() const { return throw_<const Matrix&>(); } - Matrix& outsideTij() { return throw_<Matrix&>(); } - - private: - template<class ReturnType> - ReturnType throw_() const { DUNE_THROW(Dune::InvalidStateException, "Trying to access data for a deactivated physical process"); } - }; - - //! Data handle for quantities related to advection - template<class TypeTag, bool EnableAdvection> - class AdvectionDataHandle - { - //! we use the dynamic types here to be compatible on the boundary - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using DirichletDataContainer = typename InteractionVolume::DirichletDataContainer; - using GlobalIndexContainer = typename InteractionVolume::Traits::DynamicGlobalIndexContainer; - using Matrix = typename InteractionVolume::Traits::DynamicMatrix; - using Vector = typename InteractionVolume::Traits::DynamicVector; - - public: - //! set the sizes of the matrices - void resizeT(unsigned int n, unsigned int m) { advectionT_.resize(n, m); } - void resizeAB(unsigned int n, unsigned int m) { advectionAB_.resize(n, m); } - void resizeOutsideTij(unsigned int n, unsigned int m) { advectionTout_.resize(n, m); } - - //! sets the pointer to the stencil - void setVolVarsStencilPointer(const GlobalIndexContainer& stencil) { advectionVolVarsStencil_ = &stencil; } - - //! return functions for the stored data - const GlobalIndexContainer& volVarsStencil() const { return *advectionVolVarsStencil_; } - - const Matrix& T() const { return advectionT_; } - Matrix& T() { return advectionT_; } - - const Matrix& AB() const { return advectionAB_; } - Matrix& AB() { return advectionAB_; } - - const Matrix& outsideTij() const { return advectionTout_; } - Matrix& outsideTij() { return advectionTout_; } - - private: - // advection-related variables - const GlobalIndexContainer* advectionVolVarsStencil_; //!< Pointer to the global volvar indices (stored in the interaction volume) - Matrix advectionT_; //!< The transmissibilities - Matrix advectionAB_; //!< Coefficients for gradient reconstruction - Matrix advectionTout_; //!< The transmissibilities associated with "outside" faces (only necessary on surface grids) - }; - - //! Data handle for quantities related to diffusion - template<class TypeTag, bool EnableDiffusion> - class DiffusionDataHandle - { - //! we use the dynamic types here to be compatible on the boundary - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using DirichletDataContainer = typename InteractionVolume::DirichletDataContainer; - using GlobalIndexContainer = typename InteractionVolume::Traits::DynamicGlobalIndexContainer; - using Matrix = typename InteractionVolume::Traits::DynamicMatrix; - using Vector = typename InteractionVolume::Traits::DynamicVector; - - static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); - static constexpr int numComponents = GET_PROP_VALUE(TypeTag, NumComponents); - - public: - //! diffusion caches need to set phase and component index - void setDiffusionContext(unsigned int phaseIdx, unsigned int compIdx) - { - contextPhaseIdx_ = phaseIdx; - contextCompIdx_ = compIdx; - } - - //! set the sizes of the matrices - void resizeT(unsigned int n, unsigned int m) - { - for (auto& array : diffusionT_) - for (auto& matrix : array) - matrix.resize(n, m); - } - - void resizeAB(unsigned int n, unsigned int m) - { - for (auto& array : diffusionAB_) - for (auto& matrix : array) - matrix.resize(n, m); - } - void resizeOutsideTij(unsigned int n, unsigned int m) - { - for (auto& array : diffusionTout_) - for (auto& matrix : array) - matrix.resize(n, m); - } - - //! sets the pointer to stencil - void setVolVarsStencilPointer(const GlobalIndexContainer& stencil) - { - diffusionVolVarsStencil_[contextPhaseIdx_][contextCompIdx_] = &stencil; - } - - //! return functions for the stored data - const GlobalIndexContainer& volVarsStencil() const - { return *diffusionVolVarsStencil_[contextPhaseIdx_][contextCompIdx_]; } +//! Empty data handle class +template<class InteractionVolume> +class EmptyDataHandle +{ +public: + void resize(const InteractionVolume& iv) {} +}; - const Matrix& T() const { return diffusionT_[contextPhaseIdx_][contextCompIdx_]; } - Matrix& T() { return diffusionT_[contextPhaseIdx_][contextCompIdx_]; } +//! Data handle for quantities related to advection +template<class TypeTag, class InteractionVolume, bool EnableAdvection> +class AdvectionDataHandle +{ + // export matrix & vector types from interaction volume + using Matrix = typename InteractionVolume::Traits::Matrix; + using Vector = typename InteractionVolume::Traits::Vector; + using Scalar = typename Vector::value_type; + using LocalIndexType = typename InteractionVolume::Traits::LocalIndexType; - const Matrix& AB() const { return diffusionAB_[contextPhaseIdx_][contextCompIdx_]; } - Matrix& AB() { return diffusionAB_[contextPhaseIdx_][contextCompIdx_]; } + using OutsideDataContainer = std::vector< std::vector<Vector> >; - const Matrix& outsideTij() const { return diffusionTout_[contextPhaseIdx_][contextCompIdx_]; } - Matrix& outsideTij() { return diffusionTout_[contextPhaseIdx_][contextCompIdx_]; } + static constexpr int dim = GET_PROP_TYPE(TypeTag, GridView)::dimension; + static constexpr int dimWorld = GET_PROP_TYPE(TypeTag, GridView)::dimensionworld; + static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); - private: - // diffusion-related variables (see comments in AdvectionDataHandle) - unsigned int contextPhaseIdx_; //!< The phase index set for the context - unsigned int contextCompIdx_; //!< The component index set for the context - std::array<std::array<const GlobalIndexContainer*, numComponents>, numPhases> diffusionVolVarsStencil_; - std::array<std::array<Matrix, numComponents>, numPhases> diffusionT_; - std::array<std::array<Matrix, numComponents>, numPhases> diffusionAB_; - std::array<std::array<Matrix, numComponents>, numPhases> diffusionTout_; - }; +public: - //! Data handle for quantities related to advection - template<class TypeTag, bool EnableHeatConduction> - class HeatConductionDataHandle - { - //! we use the dynamic types here to be compatible on the boundary - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using DirichletDataContainer = typename InteractionVolume::DirichletDataContainer; - using GlobalIndexContainer = typename InteractionVolume::Traits::DynamicGlobalIndexContainer; - using Matrix = typename InteractionVolume::Traits::DynamicMatrix; - using Vector = typename InteractionVolume::Traits::DynamicVector; - - public: - //! set the sizes of the matrices - void resizeT(unsigned int n, unsigned int m) { heatConductionT_.resize(n, m); } - void resizeAB(unsigned int n, unsigned int m) { heatConductionAB_.resize(n, m); } - void resizeOutsideTij(unsigned int n, unsigned int m) { heatConductionTout_.resize(n, m); } - - //! sets the pointer to the stencil - void setVolVarsStencilPointer(const GlobalIndexContainer& stencil) { heatConductionVolVarsStencil_ = &stencil; } - - //! return functions for the stored data - const GlobalIndexContainer& volVarsStencil() const { return *heatConductionVolVarsStencil_; } - - const Matrix& T() const { return heatConductionT_; } - Matrix& T() { return heatConductionT_; } - - const Matrix& AB() const { return heatConductionAB_; } - Matrix& AB() { return heatConductionAB_; } - - const Matrix& outsideTij() const { return heatConductionTout_; } - Matrix& outsideTij() { return heatConductionTout_; } - - private: - // heat conduction-related variables - const GlobalIndexContainer* heatConductionVolVarsStencil_; //!< Pointer to the global volvar indices (stored in the interaction volume) - Matrix heatConductionT_; //!< The transmissibilities - Matrix heatConductionAB_; //!< Coefficients for gradient reconstruction - Matrix heatConductionTout_; //!< The transmissibilities associated with "outside" faces (only necessary on surface grids) - }; - - //! Process-dependet data handle when related process is disabled - template<class TypeTag> class AdvectionDataHandle<TypeTag, false> : public EmptyDataHandle<TypeTag> {}; - template<class TypeTag> class DiffusionDataHandle<TypeTag, false> : public EmptyDataHandle<TypeTag> {}; - template<class TypeTag> class HeatConductionDataHandle<TypeTag, false> : public EmptyDataHandle<TypeTag> {}; - - //! Interaction volume data handle class - template<class TypeTag> - class InteractionVolumeDataHandle : public AdvectionDataHandle<TypeTag, GET_PROP_VALUE(TypeTag, EnableAdvection)>, - public DiffusionDataHandle<TypeTag, GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion)>, - public HeatConductionDataHandle<TypeTag, GET_PROP_VALUE(TypeTag, EnableEnergyBalance)> + //! prepare data handle for subsequent fill (normal grids) + template< int d = dim, int dw = dimWorld, std::enable_if_t<(d==dw), int> = 0> + void resize(const InteractionVolume& iv) { - using AdvectionHandle = AdvectionDataHandle<TypeTag, GET_PROP_VALUE(TypeTag, EnableAdvection)>; - using DiffusionHandle = DiffusionDataHandle<TypeTag, GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion)>; - using HeatConductionHandle = HeatConductionDataHandle<TypeTag, GET_PROP_VALUE(TypeTag, EnableEnergyBalance)>; - - //! we use the dynamic types here to be compatible on the boundary - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using DirichletDataContainer = typename InteractionVolume::DirichletDataContainer; - using GlobalIndexContainer = typename InteractionVolume::Traits::DynamicGlobalIndexContainer; - using Matrix = typename InteractionVolume::Traits::DynamicMatrix; - using Vector = typename InteractionVolume::Traits::DynamicVector; - - public: - enum class Contexts : unsigned int + // resize transmissibility matrix & pressure vectors + T_.resize(iv.numFaces(), iv.numKnowns()); + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + p_[pIdx].resize(iv.numKnowns()); + + // maybe resize gravity container + static const bool enableGravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); + if (enableGravity) { - undefined, - advection, - diffusion, - heatConduction - }; - - //! The constructor - InteractionVolumeDataHandle() : context_(Contexts::undefined) {} - - //! set the context of the cache - void setAdvectionContext() { context_ = Contexts::advection; } - void setHeatConductionContext() { context_ = Contexts::heatConduction; } - void setDiffusionContext(unsigned int phaseIdx, unsigned int compIdx) - { - context_ = Contexts::diffusion; - DiffusionHandle::setDiffusionContext(phaseIdx, compIdx); + CA_.resize(iv.numFaces(), iv.numUnknowns()); + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + g_[pIdx].resize(iv.numFaces()); } + } - //! returns the current context - Contexts getContext() const { return context_; } - - //! set the sizes of the matrices - void resizeT(unsigned int n, unsigned int m) - { - AdvectionHandle::resizeT(n, m); - DiffusionHandle::resizeT(n, m); - HeatConductionHandle::resizeT(n, m); - } - void resizeAB(unsigned int n, unsigned int m) - { - AdvectionHandle::resizeAB(n, m); - DiffusionHandle::resizeAB(n, m); - HeatConductionHandle::resizeAB(n, m); - } + //! prepare data handle for subsequent fill (surface grids) + template< int d = dim, int dw = dimWorld, std::enable_if_t<(d<dw), int> = 0> + void resize(const InteractionVolume& iv) + { + static const bool enableGravity = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Problem.EnableGravity"); - void resizeOutsideTij(unsigned int n, unsigned int m) + if (!enableGravity) { - AdvectionHandle::resizeOutsideTij(n, m); - DiffusionHandle::resizeOutsideTij(n, m); - HeatConductionHandle::resizeOutsideTij(n, m); + T_.resize(iv.numFaces(), iv.numKnowns()); + outsideT_.resize(iv.numFaces()); + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + p_[pIdx].resize(iv.numKnowns()); + + for (LocalIndexType i = 0; i < iv.numFaces(); ++i) + { + const auto numNeighbors = iv.localScvf(i).neighboringLocalScvIndices().size() - 1; + outsideT_[i].resize(numNeighbors); + for (LocalIndexType j = 0; j < numNeighbors; ++j) + outsideT_[i][j].resize(iv.numKnowns()); + } } - //! sets the pointer to the stencil - void setVolVarsStencilPointer(const GlobalIndexContainer& stencil) + else { - if (context_ == Contexts::advection) - AdvectionHandle::setVolVarsStencilPointer(stencil); - else if (context_ == Contexts::diffusion) - DiffusionHandle::setVolVarsStencilPointer(stencil); - else if (context_ == Contexts::heatConduction) - HeatConductionHandle::setVolVarsStencilPointer(stencil); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); - } + T_.resize(iv.numFaces(), iv.numKnowns()); + CA_.resize(iv.numFaces(), iv.numUnknowns()); + A_.resize(iv.numUnknowns(), iv.numUnknowns()); + outsideT_.resize(iv.numFaces()); + + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + p_[pIdx].resize(iv.numKnowns()); + g_[pIdx].resize(iv.numFaces()); + outsideG_[pIdx].resize(iv.numFaces()); + } + + for (LocalIndexType i = 0; i < iv.numFaces(); ++i) + { + const auto numNeighbors = iv.localScvf(i).neighboringLocalScvIndices().size() - 1; + outsideT_[i].resize(numNeighbors); + + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + outsideG_[pIdx][i].resize(numNeighbors); + + for (LocalIndexType j = 0; j < numNeighbors; ++j) + outsideT_[i][j].resize(iv.numKnowns()); + } - //! sets the dirichlet data container - void setDirichletData(DirichletDataContainer&& data) - { - dirichletData_ = std::move(data); } + } + + //! Access to the iv-wide pressure of one phase + const Vector& pressures(unsigned int pIdx) const { return p_[pIdx]; } + Vector& pressures(unsigned int pIdx) { return p_[pIdx]; } + + //! Access to the gravitational flux contributions for one phase + const Vector& gravity(unsigned int pIdx) const { return g_[pIdx]; } + Vector& gravity(unsigned int pIdx) { return g_[pIdx]; } + + //! Access to the gravitational flux contributions for all phases + const std::array< Vector, numPhases >& gravity() const { return g_; } + std::array< Vector, numPhases >& gravity() { return g_; } + + //! Projection matrix for gravitational acceleration + const Matrix& advectionCA() const { return CA_; } + Matrix& advectionCA() { return CA_; } + + //! Additional projection matrix needed on surface grids + const Matrix& advectionA() const { return A_; } + Matrix& advectionA() { return A_; } + + //! The transmissibilities associated with advective fluxes + const Matrix& advectionT() const { return T_; } + Matrix& advectionT() { return T_; } + + //! The transmissibilities for "outside" faces (used on surface grids) + const std::vector< std::vector<Vector> >& advectionTout() const { return outsideT_; } + std::vector< std::vector<Vector> >& advectionTout() { return outsideT_; } + + //! The gravitational acceleration for "outside" faces (used on surface grids) + const std::array< std::vector<Vector>, numPhases >& gravityOutside() const { return outsideG_; } + std::array< std::vector<Vector>, numPhases >& gravityOutside() { return outsideG_; } + + //! The gravitational acceleration for one phase on "outside" faces (used on surface grids) + const std::vector<Vector>& gravityOutside(unsigned int pIdx) const { return outsideG_[pIdx]; } + std::vector<Vector>& gravityOutside(unsigned int pIdx) { return outsideG_[pIdx]; } + +private: + //! advection-related variables + Matrix T_; //!< The transmissibilities such that f_i = T_ij*p_j + Matrix CA_; //!< Matrix to project gravitational acceleration to all scvfs + Matrix A_; //!< Matrix additionally needed for the projection on surface grids + std::array< Vector, numPhases > p_; //!< The interaction volume-wide phase pressures + std::array< Vector, numPhases > g_; //!< The gravitational acceleration at each scvf (only for enabled gravity) + std::vector< std::vector<Vector> > outsideT_; //!< The transmissibilities for "outside" faces (only on surface grids) + std::array< std::vector<Vector>, numPhases > outsideG_; //!< The gravitational acceleration on "outside" faces (only on surface grids) +}; + +//! Data handle for quantities related to diffusion +template<class TypeTag, class InteractionVolume, bool EnableDiffusion> +class DiffusionDataHandle +{ + // export matrix & vector types from interaction volume + using Matrix = typename InteractionVolume::Traits::Matrix; + using Vector = typename InteractionVolume::Traits::Vector; + using OutsideTContainer = std::vector< std::vector<Vector> >; - //! return functions for the stored data - const DirichletDataContainer& dirichletData() const { return dirichletData_; } + static constexpr int dim = GET_PROP_TYPE(TypeTag, GridView)::dimension; + static constexpr int dimWorld = GET_PROP_TYPE(TypeTag, GridView)::dimensionworld; - const GlobalIndexContainer& volVarsStencil() const - { - if (context_ == Contexts::advection) - return AdvectionHandle::volVarsStencil(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::volVarsStencil(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::volVarsStencil(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); - } + static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); + static constexpr int numComponents = GET_PROP_VALUE(TypeTag, NumComponents); - const Matrix& T() const - { - if (context_ == Contexts::advection) - return AdvectionHandle::T(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::T(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::T(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); - } +public: + //! diffusion caches need to set phase and component index + void setPhaseIndex(unsigned int phaseIdx) { phaseIdx_ = phaseIdx; } + void setComponentIndex(unsigned int compIdx) { compIdx_ = compIdx; } - Matrix& T() + //! prepare data handle for subsequent fill + void resize(const InteractionVolume& iv) + { + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) { - if (context_ == Contexts::advection) - return AdvectionHandle::T(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::T(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::T(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); + for (unsigned int cIdx = 0; cIdx < numComponents; ++cIdx) + { + if (pIdx == cIdx) + continue; + + // resize transmissibility matrix & mole fraction vector + T_[pIdx][cIdx].resize(iv.numFaces(), iv.numKnowns()); + xj_[pIdx][cIdx].resize(iv.numKnowns()); + + // resize outsideTij on surface grids + if (dim < dimWorld) + { + outsideT_[pIdx][cIdx].resize(iv.numFaces()); + + using LocalIndexType = typename InteractionVolume::Traits::LocalIndexType; + for (LocalIndexType i = 0; i < iv.numFaces(); ++i) + outsideT_[pIdx][cIdx][i].resize(iv.localScvf(i).neighboringLocalScvIndices().size()-1); + } + } } + } + + //! Access to the iv-wide mole fractions of a component in one phase + const Vector& moleFractions(unsigned int pIdx, unsigned int compIdx) const { return xj_[pIdx][compIdx]; } + Vector& moleFractions(unsigned int pIdx, unsigned int compIdx) { return xj_[pIdx][compIdx]; } + + //! The transmissibilities associated with diffusive fluxes + const Matrix& diffusionT() const { return T_[phaseIdx_][compIdx_]; } + Matrix& diffusionT() { return T_[phaseIdx_][compIdx_]; } + + //! The transmissibilities for "outside" faces (used on surface grids) + const OutsideTContainer& diffusionTout() const { return outsideT_[phaseIdx_][compIdx_]; } + OutsideTContainer& diffusionTout() { return outsideT_[phaseIdx_][compIdx_]; } + +private: + //! diffusion-related variables + unsigned int phaseIdx_; //!< The phase index set for the context + unsigned int compIdx_; //!< The component index set for the context + std::array< std::array<Matrix, numComponents>, numPhases > T_; //!< The transmissibilities such that f_i = T_ij*x_j + std::array< std::array<Vector, numComponents>, numPhases > xj_; //!< The interaction volume-wide mole fractions + std::array< std::array<OutsideTContainer, numComponents>, numPhases> outsideT_; +}; + +//! Data handle for quantities related to heat conduction +template<class TypeTag, class InteractionVolume, bool EnableHeatConduction> +class HeatConductionDataHandle +{ + //! export matrix & vector types from interaction volume + using Matrix = typename InteractionVolume::Traits::Matrix; + using Vector = typename InteractionVolume::Traits::Vector; - const Matrix& AB() const - { - if (context_ == Contexts::advection) - return AdvectionHandle::AB(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::AB(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::AB(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); - } + static constexpr int dim = GET_PROP_TYPE(TypeTag, GridView)::dimension; + static constexpr int dimWorld = GET_PROP_TYPE(TypeTag, GridView)::dimensionworld; - Matrix& AB() - { - if (context_ == Contexts::advection) - return AdvectionHandle::AB(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::AB(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::AB(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); - } +public: + //! prepare data handle for subsequent fill + void resize(const InteractionVolume& iv) + { + //! resize transmissibility matrix & temperature vector + T_.resize(iv.numFaces(), iv.numKnowns()); + Tj_.resize(iv.numKnowns()); - const Matrix& outsideTij() const + //! resize outsideTij on surface grids + if (dim < dimWorld) { - if (context_ == Contexts::advection) - return AdvectionHandle::outsideTij(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::outsideTij(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::outsideTij(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); - } + outsideT_.resize(iv.numFaces()); - Matrix& outsideTij() - { - if (context_ == Contexts::advection) - return AdvectionHandle::outsideTij(); - else if (context_ == Contexts::diffusion) - return DiffusionHandle::outsideTij(); - else if (context_ == Contexts::heatConduction) - return HeatConductionHandle::outsideTij(); - else - DUNE_THROW(Dune::InvalidStateException, "No valid context set!"); + using LocalIndexType = typename InteractionVolume::Traits::LocalIndexType; + for (LocalIndexType i = 0; i < iv.numFaces(); ++i) + outsideT_[i].resize(iv.localScvf(i).neighboringLocalScvIndices().size()-1); } + } + + //! Access to the iv-wide temperatures + const Vector& temperatures() const { return Tj_; } + Vector& temperatures() { return Tj_; } + + //! The transmissibilities associated with conductive fluxes + const Matrix& heatConductionT() const { return T_; } + Matrix& heatConductionT() { return T_; } + + //! The transmissibilities for "outside" faces (used on surface grids) + const std::vector< std::vector<Vector> >& heatConductionTout() const { return outsideT_; } + std::vector< std::vector<Vector> >& heatConductionTout() { return outsideT_; } + +private: + // heat conduction-related variables + Matrix T_; //!< The transmissibilities such that f_i = T_ij*T_j + Vector Tj_; //!< The interaction volume-wide temperatures + std::vector< std::vector<Vector> > outsideT_; //!< The transmissibilities for "outside" faces (only necessary on surface grids) +}; + +//! Process-dependent data handles when related process is disabled +template<class TypeTag, class InteractionVolume> +class AdvectionDataHandle<TypeTag, InteractionVolume, false> : public EmptyDataHandle<InteractionVolume> {}; +template<class TypeTag, class InteractionVolume> +class DiffusionDataHandle<TypeTag, InteractionVolume, false> : public EmptyDataHandle<InteractionVolume> {}; +template<class TypeTag, class InteractionVolume> +class HeatConductionDataHandle<TypeTag, InteractionVolume, false> : public EmptyDataHandle<InteractionVolume> {}; + +//! Interaction volume data handle class +template<class TypeTag, class InteractionVolume> +class InteractionVolumeDataHandle : public AdvectionDataHandle<TypeTag, InteractionVolume, GET_PROP_VALUE(TypeTag, EnableAdvection)>, + public DiffusionDataHandle<TypeTag, InteractionVolume, GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion)>, + public HeatConductionDataHandle<TypeTag, InteractionVolume, GET_PROP_VALUE(TypeTag, EnableEnergyBalance)> +{ + using AdvectionHandle = AdvectionDataHandle<TypeTag, InteractionVolume, GET_PROP_VALUE(TypeTag, EnableAdvection)>; + using DiffusionHandle = DiffusionDataHandle<TypeTag, InteractionVolume, GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion)>; + using HeatConductionHandle = HeatConductionDataHandle<TypeTag, InteractionVolume, GET_PROP_VALUE(TypeTag, EnableEnergyBalance)>; - private: - Contexts context_; //!< The context variable - DirichletDataContainer dirichletData_; //!< The dirichlet data container of this iv - }; +public: + //! prepare data handles for subsequent fills + void resize(const InteractionVolume& iv) + { + AdvectionHandle::resize(iv); + DiffusionHandle::resize(iv); + HeatConductionHandle::resize(iv); + } +}; } // end namespace Dumux diff --git a/dumux/discretization/cellcentered/mpfa/localassembler.hh b/dumux/discretization/cellcentered/mpfa/localassembler.hh new file mode 100644 index 0000000000000000000000000000000000000000..3f690d7a0dbab47c4e8282776bf65f0087140f1a --- /dev/null +++ b/dumux/discretization/cellcentered/mpfa/localassembler.hh @@ -0,0 +1,261 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * 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, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup CCMpfaDiscretization + * \brief Defines the general interface of classes used for the assembly + * of the local systems of equations involved in the transmissibility + * computaion in mpfa schemes. + */ +#ifndef DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_ASSEMBLER_HH +#define DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_ASSEMBLER_HH + +#include <dune/common/exceptions.hh> + +namespace Dumux +{ +//! Forward declaration of the implementation +template< class InteractionVolume > class InteractionVolumeAssemblerImpl; + +//! Alias to select the right implementation. +template< class InteractionVolume > +using InteractionVolumeAssembler = InteractionVolumeAssemblerImpl< InteractionVolume >; + +/*! + * \ingroup CCMpfaDiscretization + * \brief Defines the general interface of the local assembler + * classes for the assembly of the interaction volume-local + * transmissibility matrix. Specializations have to be provided + * for the available interaction volume implementations. these + * should derive from this base clases. + * + * \tparam Interaction Volume The interaction volume implementation + * used by the mpfa scheme + */ +template<class InteractionVolume> +class InteractionVolumeAssemblerBase +{ + using Problem = typename InteractionVolume::Problem; + using FVElementGeometry = typename InteractionVolume::FVElementGeometry; + using ElementVolumeVariables = typename InteractionVolume::ElementVolumeVariables; + + using Traits = typename InteractionVolume::Traits; + using Matrix = typename Traits::Matrix; + using Vector = typename Traits::Vector; + + public: + /*! + * \brief The constructor. + * Sets pointers to the objects required for a subsequent call to assemble(). + * + * \param problem The problem to be solved (boundary/initial conditions etc.) + * \param fvGeometry The local view on the finite volume grid geometry + * \param elemVolVars The local view on the primary/secondary variables + */ + InteractionVolumeAssemblerBase(const Problem& problem, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars) + { + problemPtr_ = &problem; + fvGeometryPtr_ = &fvGeometry; + elemVolVarsPtr_ = &elemVolVars; + } + + // return functions to the local views & problem + const Problem& problem() const { return *problemPtr_; } + const FVElementGeometry& fvGeometry() const { return *fvGeometryPtr_; } + const ElementVolumeVariables& elemVolVars() const { return *elemVolVarsPtr_; } + + /*! + * \brief General interface of a function assembling the + * interaction volume-local transmissibility matrix. + * + * \tparam GetTensorFunction Lambda to obtain the tensor w.r.t. + * which the local system is to be solved + * + * \param T The transmissibility matrix to be assembled + * \param iv The interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GetTensorFunction > + void assemble(Matrix& T, InteractionVolume& iv, const GetTensorFunction& getTensor) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assemble() function"); + } + + /*! + * \brief General interface of a function assembling the interaction + * volume-local transmissibilities matrix for surface grids. The + * transmissibility associated with "outside" faces are stored + * in a separate container. + * + * \param outsideTij tij on "outside" faces to be assembled + * \param T The transmissibility matrix tij to be assembled + * \param iv The mpfa-o interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class OutsideTijContainer, class GetTensorFunction > + void assemble(OutsideTijContainer& outsideTij, Matrix& T, InteractionVolume& iv, const GetTensorFunction& getTensor) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assemble() function to be used on surface grids"); + } + + /*! + * \brief General interface of a function assembling the interaction + * volume-local transmissibility matrix in the case that gravity + * is to be considered in the local system of equations. + * + * \tparam GravityContainer The type of container used to store the + * gravitational acceleration per scvf & phase + * \tparam GetTensorFunction Lambda to obtain the tensor w.r.t. + * which the local system is to be solved + * + * \param T The transmissibility matrix to be assembled + * \param g Container to assemble gravity per scvf & phase + * \param CA Matrix to store matrix product C*A^-1 + * \param iv The interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GravityContainer, class GetTensorFunction > + void assembleWithGravity(Matrix& T, + GravityContainer& g, + Matrix& CA, + InteractionVolume& iv, + const GetTensorFunction& getTensor) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assembleWithGravity() function"); + } + + /*! + * \brief General interface of a function assembling the interaction + * volume-local transmissibility matrix in the case that gravity + * is to be considered in the local system of equations. This + * specialization is to be used on surface grids, where the + * gravitational flux contributions on "outside" faces are stored + * in a separate container. + * + * \param outsideTij tij on "outside" faces to be assembled + * \param T The transmissibility matrix to be assembled + * \param outsideG Container to assemble gravity on "outside" faces + * \param g Container to assemble gravity per scvf & phase + * \param CA Matrix to store matrix product C*A^-1 + * \param A Matrix to store the inverse A^-1 + * \param iv The interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GravityContainer, + class OutsideGravityContainer, + class OutsideTijContainer, + class GetTensorFunction > + void assembleWithGravity(OutsideTijContainer& outsideTij, + Matrix& T, + OutsideGravityContainer& outsideG, + GravityContainer& g, + Matrix& CA, + Matrix& A, + InteractionVolume& iv, + const GetTensorFunction& getTensor) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assembleWithGravity() function to be used on surface grids"); + } + + /*! + * \brief General interface for the assembly of the vector of + * primary (cell) unknowns and (maybe) Dirichlet boundary + * conditions within an interaction volume. + * + * \tparam GetU Lambda to obtain the cell unknowns from grid indices + * + * \param u The vector to be filled with the cell unknowns + * \param iv The interaction volume + * \param getU Lambda to obtain the desired cell value from grid indices + */ + template< class GetU > + void assemble(Vector& u, const InteractionVolume& iv, const GetU& getU) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assemble() function for the cell unknowns"); + } + + /*! + * \brief General interface for the assembly of the gravitational + * flux contributions on the scvfs within an interaction volume. + * + * \note For each face, the gravity term in the form of \f$\rho \mathbf{n K g}\f$ is + * evaluated. Thus, make sure to only call this with a lambda that returns the + * hydraulic conductivity. + * + * \param g Container to assemble gravity per scvf & phase + * \param iv The interaction volume + * \param CA Projection matrix transforming the gravity terms in the local system of + * equations to the entire set of faces within the interaction volume + * \param getTensor Lambda to evaluate scv-wise hydraulic conductivities + */ + template< class GravityContainer, class GetTensorFunction > + void assembleGravity(GravityContainer& g, + const InteractionVolume& iv, + const Matrix& CA, + const GetTensorFunction& getTensor) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assembleGravity() function"); + } + + /*! + * \brief General interface for the assembly of the gravitational + * flux contributions on the scvfs within an interaction volume. + * This specialization is to be used on surface grids, where the gravitational + * flux contributions on "outside" faces are stored in a separate container. + * + * \note For each face, the gravity term in the form of \f$\rho \mathbf{n K g}\f$ is + * evaluated. Thus, make sure to only call this with a lambda that returns the + * hydraulic conductivity. + * + * \param g Container to store gravity per scvf & phase + * \param outsideG Container to store gravity per "outside" scvf & phase + * \param iv The mpfa-o interaction volume + * \param CA Projection matrix transforming the gravity terms in the local system of + * equations to the entire set of faces within the interaction volume + * \param A Matrix needed for the "reconstruction" of face unknowns as a function of gravity + * \param getTensor Lambda to evaluate scv-wise hydraulic conductivities + */ + template< class GravityContainer, + class OutsideGravityContainer, + class GetTensorFunction > + void assembleGravity(GravityContainer& g, + OutsideGravityContainer& outsideG, + const InteractionVolume& iv, + const Matrix& CA, + const Matrix& A, + const GetTensorFunction& getTensor) + { + DUNE_THROW(Dune::NotImplemented, "Implementation does not provide a assembleGravity() function to be used on surface grids"); + } + + private: + // pointers to the data required for assembly + const Problem* problemPtr_; + const FVElementGeometry* fvGeometryPtr_; + const ElementVolumeVariables* elemVolVarsPtr_; +}; + +} // end namespace Dumux + +//! include all specializations for different mpfa schemes +#include <dumux/discretization/cellcentered/mpfa/omethod/localassembler.hh> + +#endif diff --git a/dumux/discretization/cellcentered/mpfa/localfacedata.hh b/dumux/discretization/cellcentered/mpfa/localfacedata.hh new file mode 100644 index 0000000000000000000000000000000000000000..a7225683f919b742e23186b673871d9ddd161a9f --- /dev/null +++ b/dumux/discretization/cellcentered/mpfa/localfacedata.hh @@ -0,0 +1,80 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * 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, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + /*! + * \file + * \ingroup CCMpfaDiscretization + * \brief Data structure holding interaction volume-local information for + * a grid subb-control volume face embedded in it. + */ +#ifndef DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_FACE_DATA_HH +#define DUMUX_DISCRETIZATION_CC_MPFA_LOCAL_FACE_DATA_HH + +namespace Dumux +{ +/*! + * \ingroup CCMpfaDiscretization + * \brief General implementation of a data structure holding interaction + * volume-local information for a grid subb-control volume face embedded in it. + * + * \tparam GridIndexType The type used for indices on the grid + * \tparam LocalIndexType The type used for indices inside interaction volumes + */ +template< class GridIndexType, class LocalIndexType > +class InteractionVolumeLocalFaceData +{ + LocalIndexType ivLocalScvfIndex_; //!< the iv-local scvf index this scvf maps to + LocalIndexType ivLocalInsideScvIndex_; //!< the iv-local index of the scvfs' inside scv + LocalIndexType scvfLocalOutsideScvfIndex_; //!< the index of this scvf in the scvf-local outside faces + GridIndexType globalScvfIndex_; //!< the index of the corresponding global scvf + bool isOutside_; //!< indicates if this face maps to the iv-local index from "outside" + +public: + //! Constructor + InteractionVolumeLocalFaceData(LocalIndexType faceIndex, + LocalIndexType scvIndex, + GridIndexType globalScvfIndex) + : ivLocalScvfIndex_(faceIndex) + , ivLocalInsideScvIndex_(scvIndex) + , globalScvfIndex_(globalScvfIndex) + , isOutside_(false) + {} + + //! Constructor for "outside" faces + InteractionVolumeLocalFaceData(LocalIndexType faceIndex, + LocalIndexType scvIndex, + LocalIndexType indexInScvfOutsideFaces, + GridIndexType globalScvfIndex) + : ivLocalScvfIndex_(faceIndex) + , ivLocalInsideScvIndex_(scvIndex) + , scvfLocalOutsideScvfIndex_(indexInScvfOutsideFaces) + , globalScvfIndex_(globalScvfIndex) + , isOutside_(true) + {} + + // Functions to return stored data + LocalIndexType ivLocalScvfIndex() const { return ivLocalScvfIndex_; } + LocalIndexType ivLocalInsideScvIndex() const { return ivLocalInsideScvIndex_; } + LocalIndexType scvfLocalOutsideScvfIndex() const { assert(isOutside_); return scvfLocalOutsideScvfIndex_; } + GridIndexType globalScvfIndex() const { return globalScvfIndex_; } + bool isOutside() const { return isOutside_; } +}; + +} // end namespace + +#endif diff --git a/dumux/discretization/cellcentered/mpfa/methods.hh b/dumux/discretization/cellcentered/mpfa/methods.hh index 0c9c57d24a744c632476fd4b04967b7cdc563484..1f4e3244d0cd384f12badb2fa099f21c03f8a377 100644 --- a/dumux/discretization/cellcentered/mpfa/methods.hh +++ b/dumux/discretization/cellcentered/mpfa/methods.hh @@ -18,17 +18,23 @@ *****************************************************************************/ /*! * \file - * \brief Available implemented mpfa schemes + * \ingroup CCMpfaDiscretization + * \brief The available mpfa schemes in Dumux */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_METHODS_HH #define DUMUX_DISCRETIZATION_CC_MPFA_METHODS_HH namespace Dumux { + /*! + * \brief The available mpfa schemes in Dumux + * \ingroup CCMpfaDiscretization + */ enum class MpfaMethods : unsigned int { oMethod }; -} // end namespace + +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/omethod/CMakeLists.txt b/dumux/discretization/cellcentered/mpfa/omethod/CMakeLists.txt index 8a45cecd5c6bb656f2980953de3803e5caebbe9c..d2c61c2a7b45d6ba942dfb77a7933b45875f6e52 100644 --- a/dumux/discretization/cellcentered/mpfa/omethod/CMakeLists.txt +++ b/dumux/discretization/cellcentered/mpfa/omethod/CMakeLists.txt @@ -1,6 +1,6 @@ install(FILES -helper.hh interactionvolume.hh interactionvolumeindexset.hh +localassembler.hh localsubcontrolentities.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/discretization/cellcentered/mpfa/omethod) diff --git a/dumux/discretization/cellcentered/mpfa/omethod/helper.hh b/dumux/discretization/cellcentered/mpfa/omethod/helper.hh deleted file mode 100644 index 8c9cb79fe4615088ff75a32e47defce0be008184..0000000000000000000000000000000000000000 --- a/dumux/discretization/cellcentered/mpfa/omethod/helper.hh +++ /dev/null @@ -1,66 +0,0 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * 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, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ - -/*! - * \file - * \brief Helper class for interaction volumes using the mpfa-o scheme. - */ -#ifndef DUMUX_DISCRETIZATION_CC_MPFA_O_HELPER_HH -#define DUMUX_DISCRETIZATION_CC_MPFA_O_HELPER_HH - -#include <dumux/common/math.hh> -#include <dumux/discretization/cellcentered/mpfa/methods.hh> - -namespace Dumux -{ - -// forward declaration -template<class TypeTag, MpfaMethods m, int dim, int dimWorld> -class MpfaMethodHelper; - -/*! - * \ingroup Mpfa - * \brief Helper class to get the required information on an interaction volume. - * Specialization for the Mpfa-O method in two dimensions. This scheme does - * not require any additional functionality to be implemented. - */ -template<class TypeTag> -class MpfaMethodHelper<TypeTag, MpfaMethods::oMethod, /*dim*/2, /*dimWorld*/2> {}; - -/*! - * \ingroup Mpfa - * \brief Helper class to get the required information on an interaction volume. - * Specialization for the Mpfa-O method in two dimensions embedded in a 3d world. - * This scheme does not require any additional functionality to be implemented. - */ -template<class TypeTag> -class MpfaMethodHelper<TypeTag, MpfaMethods::oMethod, /*dim*/2, /*dimWorld*/3> {}; - -/*! - * \ingroup Mpfa - * \brief Helper class to get the required information on an interaction volume. - * Specialization for the Mpfa-O method in three dimensions. - * This scheme does not require any additional functionality to be implemented. - */ -template<class TypeTag> -class MpfaMethodHelper<TypeTag, MpfaMethods::oMethod, /*dim*/3, /*dimWorld*/3> {}; - -} // end namespace - -#endif diff --git a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh index 02cf2ec7ac09177641e3f43043e2782926727562..3d9b18b6d35097fb9e8017a8caf47985cc53abba 100644 --- a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh +++ b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh @@ -18,128 +18,150 @@ *****************************************************************************/ /*! * \file - * \brief Base classes for interaction volume of mpfa methods. + * \ingroup CCMpfaDiscretization + * \brief Class for the interaction volume of the mpfa-o scheme. */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_O_INTERACTIONVOLUME_HH #define DUMUX_DISCRETIZATION_CC_MPFA_O_INTERACTIONVOLUME_HH +#include <dune/common/dynmatrix.hh> +#include <dune/common/dynvector.hh> +#include <dune/common/fvector.hh> + #include <dumux/common/math.hh> +#include <dumux/common/properties.hh> +#include <dumux/discretization/cellcentered/mpfa/interactionvolumedatahandle.hh> #include <dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh> -#include <dumux/discretization/cellcentered/mpfa/methods.hh> #include <dumux/discretization/cellcentered/mpfa/dualgridindexset.hh> +#include <dumux/discretization/cellcentered/mpfa/localfacedata.hh> +#include <dumux/discretization/cellcentered/mpfa/methods.hh> #include "localsubcontrolentities.hh" #include "interactionvolumeindexset.hh" namespace Dumux { +//! Forward declaration of the interaction volume specialization for the mpfa-o scheme +template< class TypeTag > +class CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod>; + //! Specialization of the interaction volume traits class for the mpfa-o method -template<class TypeTag> -class CCMpfaOInteractionVolumeTraits : public CCMpfaInteractionVolumeTraitsBase<TypeTag> +template< class TypeTag > +struct CCMpfaInteractionVolumeTraits< CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod> > { - using BaseTraits = CCMpfaInteractionVolumeTraitsBase<TypeTag>; - using NodalIndexSet = typename CCMpfaDualGridIndexSet<TypeTag>::NodalIndexSet; - -public: - using SecondaryInteractionVolume = CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod>; +private: + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using typename BaseTraits::DynamicLocalIndexContainer; - using typename BaseTraits::DynamicGlobalIndexContainer; - using IndexSet = CCMpfaOInteractionVolumeIndexSet<NodalIndexSet, DynamicGlobalIndexContainer, DynamicLocalIndexContainer>; + static constexpr int dim = GridView::dimension; + static constexpr int dimWorld = GridView::dimensionworld; - // In the o-scheme, matrix & vector types are dynamic types - using typename BaseTraits::DynamicVector; - using typename BaseTraits::DynamicMatrix; - using Vector = DynamicVector; - using Matrix = DynamicMatrix; + using InteractionVolumeType = CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod>; - using LocalScvType = CCMpfaOInteractionVolumeLocalScv<TypeTag, IndexSet>; - using LocalScvfType = CCMpfaOInteractionVolumeLocalScvf<TypeTag>; +public: + //! Per default, we use the same interaction volume everywhere (also on boundaries etc...) + using SecondaryInteractionVolume = InteractionVolumeType; + + //! export the type used for local indices + using LocalIndexType = std::uint8_t; + //! export the type used for indices on the grid + using GridIndexType = typename GridView::IndexSet::IndexType; + //! export the type for the interaction volume index set + using IndexSet = CCMpfaOInteractionVolumeIndexSet< DualGridNodalIndexSet<GridIndexType, LocalIndexType, dim> >; + //! export the type used for global coordinates + using GlobalPosition = Dune::FieldVector< typename GridView::ctype, dimWorld >; + //! export the type of interaction-volume local scvs + using LocalScvType = CCMpfaOInteractionVolumeLocalScv< IndexSet, GlobalPosition, dim >; + //! export the type of interaction-volume local scvfs + using LocalScvfType = CCMpfaOInteractionVolumeLocalScvf< IndexSet >; + //! export the type of used for the iv-local face data + using LocalFaceData = InteractionVolumeLocalFaceData<GridIndexType, LocalIndexType>; + //! export the type of face data container (use dynamic container here) + using LocalFaceDataContainer = std::vector< LocalFaceData >; + //! export the type used for iv-local matrices + using Matrix = Dune::DynamicMatrix< Scalar >; + //! export the type used for iv-local vectors + using Vector = Dune::DynamicVector< Scalar >; + //! export the type used for the iv-stencils + using Stencil = std::vector< GridIndexType >; + //! export the data handle type for this iv + using DataHandle = InteractionVolumeDataHandle< TypeTag, InteractionVolumeType >; }; -//! Forward declaration of the mpfa-o interaction volume -template<class TypeTag, class Traits> -class CCMpfaOInteractionVolume; - /*! - * \ingroup Mpfa - * \brief Base class for the interaction volumes of the mpfa-o method. - * We introduce one more level of inheritance here because the o-method with - * full pressure support uses the mpfa-o interaction volume but uses a different - * traits class. + * \ingroup CCMpfaDiscretization + * \brief Class for the interaction volume of the mpfa-o method. */ template<class TypeTag> -class CCMpfaInteractionVolumeImplementation< TypeTag, MpfaMethods::oMethod> - : public CCMpfaOInteractionVolume< TypeTag, CCMpfaOInteractionVolumeTraits<TypeTag> > +class CCMpfaInteractionVolumeImplementation< TypeTag, MpfaMethods::oMethod > + : public CCMpfaInteractionVolumeBase< TypeTag, + CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod> > { - using TraitsType = CCMpfaOInteractionVolumeTraits<TypeTag>; -public: - // state the traits class type - using Traits = TraitsType; -}; + using ThisType = CCMpfaInteractionVolumeImplementation< TypeTag, MpfaMethods::oMethod >; + using ParentType = CCMpfaInteractionVolumeBase< TypeTag, ThisType >; -template<class TypeTag, class Traits> -class CCMpfaOInteractionVolume : public CCMpfaInteractionVolumeBase<TypeTag, Traits> -{ - using ParentType = CCMpfaInteractionVolumeBase<TypeTag, Traits>; - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Helper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - using DualGridNodalIndexSet = typename CCMpfaDualGridIndexSet<TypeTag>::NodalIndexSet; - - static const int dim = GridView::dimension; - static const int dimWorld = GridView::dimensionworld; using Element = typename GridView::template Codim<0>::Entity; + + static constexpr int dim = GridView::dimension; using DimVector = Dune::FieldVector<Scalar, dim>; - using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; - using Vector = typename Traits::DynamicVector; - using Matrix = typename Traits::DynamicMatrix; - using Tensor = typename Traits::Tensor; + using TraitsType = CCMpfaInteractionVolumeTraits< ThisType >; + using Matrix = typename TraitsType::Matrix; + using LocalScvType = typename TraitsType::LocalScvType; + using LocalScvfType = typename TraitsType::LocalScvfType; + using LocalFaceData = typename TraitsType::LocalFaceData; - using LocalScvType = typename Traits::LocalScvType; - using LocalScvfType = typename Traits::LocalScvfType; + using IndexSet = typename TraitsType::IndexSet; + using GridIndexType = typename TraitsType::GridIndexType; + using LocalIndexType = typename TraitsType::LocalIndexType; + using Stencil = typename TraitsType::Stencil; - using IndexSet = typename Traits::IndexSet; - using LocalIndexContainer = typename Traits::DynamicLocalIndexContainer; - using LocalIndexType = typename LocalIndexContainer::value_type; - using GlobalIndexContainer = typename Traits::DynamicGlobalIndexContainer; - using DataHandle = typename Traits::DataHandle; -public: + //! Data attached to scvf touching Dirichlet boundaries. + //! For the default o-scheme, we only store the corresponding vol vars index. + class DirichletData + { + GridIndexType volVarIndex_; + + public: + //! Constructor + DirichletData(const GridIndexType index) : volVarIndex_(index) {} + + //! Return corresponding vol var index + GridIndexType volVarIndex() const { return volVarIndex_; } + }; +public: //! publicly state the mpfa-scheme this interaction volume is associated with static constexpr MpfaMethods MpfaMethod = MpfaMethods::oMethod; - using typename ParentType::LocalFaceData; - using typename ParentType::DirichletDataContainer; - using typename ParentType::LocalFaceDataContainer; + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); + using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables); - //! Sets up the local scope for a given iv index set! + //! Sets up the local scope for a given iv index set void setUpLocalScope(const IndexSet& indexSet, const Problem& problem, const FVElementGeometry& fvGeometry) { - //! store a pointer to the index set - indexSetPtr_ = &indexSet; - - //! clear previous data - clear_(); + // for the o-scheme, the stencil is equal to the scv + // index set of the dual grid's nodal index set + stencil_ = &indexSet.nodalIndexSet().globalScvIndices(); - //! number of interaction-volume-local faces + // number of interaction-volume-local (= node-local for o-scheme) scvs/scvf numFaces_ = indexSet.numFaces(); - - //! number of interaction-volume-local (and node-local) scvs - const auto& scvIndices = indexSet.globalScvIndices(); const auto numLocalScvs = indexSet.numScvs(); - - //! number of global scvfs appearing in this interaction volume const auto numGlobalScvfs = indexSet.nodalIndexSet().numScvfs(); - //! reserve memory for local entities + // reserve memory for local entities + elements_.clear(); + scvs_.clear(); + scvfs_.clear(); + localFaceData_.clear(); + dirichletData_.clear(); elements_.reserve(numLocalScvs); scvs_.reserve(numLocalScvs); scvfs_.reserve(numFaces_); @@ -147,142 +169,104 @@ public: localFaceData_.reserve(numGlobalScvfs); // set up quantities related to sub-control volumes + const auto& scvIndices = indexSet.globalScvIndices(); for (LocalIndexType scvIdxLocal = 0; scvIdxLocal < numLocalScvs; scvIdxLocal++) { - const auto scvIdxGlobal = scvIndices[scvIdxLocal]; - scvs_.emplace_back(fvGeometry, fvGeometry.scv(scvIdxGlobal), scvIdxLocal, indexSet); - elements_.emplace_back(fvGeometry.fvGridGeometry().element(scvIdxGlobal)); + scvs_.emplace_back(Helper(), + fvGeometry, + fvGeometry.scv( scvIndices[scvIdxLocal] ), + scvIdxLocal, + indexSet); + elements_.emplace_back(fvGeometry.fvGridGeometry().element( scvIndices[scvIdxLocal] )); } // keep track of the number of unknowns etc numUnknowns_ = 0; - numOutsideFaces_ = 0; - numPotentials_ = numLocalScvs; + numKnowns_ = numLocalScvs; + + // resize omega storage container + wijk_.resize(numFaces_); // set up quantitites related to sub-control volume faces for (LocalIndexType faceIdxLocal = 0; faceIdxLocal < numFaces_; ++faceIdxLocal) { - const auto scvfIdxGlobal = indexSet.scvfIdxGlobal(faceIdxLocal); - const auto& neighborScvIndicesLocal = indexSet.neighboringLocalScvIndices(faceIdxLocal); - const auto insideLocalScvIdx = neighborScvIndicesLocal[0]; + // get corresponding grid scvf + const auto& scvf = fvGeometry.scvf(indexSet.scvfIdxGlobal(faceIdxLocal)); - // we have to use the "inside" scv face here - const auto& scvf = fvGeometry.scvf(scvfIdxGlobal); + // the neighboring scvs in local indices (order: 0 - inside scv, 1..n - outside scvs) + const auto& neighborScvIndicesLocal = indexSet.neighboringLocalScvIndices(faceIdxLocal); // create local face data object for this face - localFaceData_.emplace_back(faceIdxLocal, insideLocalScvIdx, scvf.index()); + localFaceData_.emplace_back(faceIdxLocal, neighborScvIndicesLocal[0], scvf.index()); // create iv-local scvf object if (scvf.boundary()) { - const auto insideElement = elements_[insideLocalScvIdx]; - const auto bcTypes = problem.boundaryTypes(insideElement, scvf); + const auto bcTypes = problem.boundaryTypes(elements_[neighborScvIndicesLocal[0]], scvf); if (bcTypes.hasOnlyDirichlet()) { - scvfs_.emplace_back(scvf, neighborScvIndicesLocal, /*isDirichlet*/true, numPotentials_++); - dirichletData_.emplace_back(scvf.outsideScvIdx(), scvf.ipGlobal()); + scvfs_.emplace_back(scvf, neighborScvIndicesLocal, numKnowns_++, /*isDirichlet*/true); + dirichletData_.emplace_back(scvf.outsideScvIdx()); } else - scvfs_.emplace_back(scvf, neighborScvIndicesLocal, /*isDirichlet*/false, numUnknowns_++); + scvfs_.emplace_back(scvf, neighborScvIndicesLocal, numUnknowns_++, /*isDirichlet*/false); + + // on boundary faces we will only need one inside omega + wijk_[faceIdxLocal].resize(1); } else { - scvfs_.emplace_back(scvf, neighborScvIndicesLocal, /*isDirichlet*/false, numUnknowns_++); + scvfs_.emplace_back(scvf, neighborScvIndicesLocal, numUnknowns_++, /*isDirichlet*/false); - // add local face data object for the outside faces - for (LocalIndexType i = 1; i < neighborScvIndicesLocal.size(); ++i) - { - const auto outsideLocalScvIdx = neighborScvIndicesLocal[i]; + // we will need as many omegas as scvs around the face + const auto numNeighborScvs = neighborScvIndicesLocal.size(); + wijk_[faceIdxLocal].resize(numNeighborScvs); + // add local face data objects for the outside faces + for (LocalIndexType i = 1; i < numNeighborScvs; ++i) + { // loop over scvfs in outside scv until we find the one coinciding with current scvf + const auto outsideLocalScvIdx = neighborScvIndicesLocal[i]; for (int coord = 0; coord < dim; ++coord) { if (indexSet.scvfIdxLocal(outsideLocalScvIdx, coord) == faceIdxLocal) { const auto globalScvfIdx = indexSet.nodalIndexSet().scvfIdxGlobal(outsideLocalScvIdx, coord); const auto& flipScvf = fvGeometry.scvf(globalScvfIdx); - localFaceData_.emplace_back(faceIdxLocal, //! iv-local scvf idx - outsideLocalScvIdx, //! iv-local scv index - numOutsideFaces_++, //! iv-local index in outside faces - i-1, //! scvf-local index in outside faces - flipScvf.index()); //!< global scvf index + localFaceData_.emplace_back(faceIdxLocal, // iv-local scvf idx + outsideLocalScvIdx, // iv-local scv index + i-1, // scvf-local index in outside faces + flipScvf.index()); // global scvf index } } } } } - // resize the local matrices + // Resize local matrices A_.resize(numUnknowns_, numUnknowns_); - B_.resize(numUnknowns_, numPotentials_); + B_.resize(numUnknowns_, numKnowns_); C_.resize(numFaces_, numUnknowns_); - D_.resize(numFaces_, numPotentials_); } - //! sets the sizes of the corresponding matrices in the data handle - void prepareDataHandle(DataHandle& dataHandle) - { - // resize the transmissibility matrix in the data handle - dataHandle.resizeT(numFaces_, numPotentials_); + //! returns the number of primary scvfs of this interaction volume + std::size_t numFaces() const { return numFaces_; } - // move the dirichlet data into the handle - dataHandle.setDirichletData(std::move(dirichletData_)); + //! returns the number of intermediate unknowns within this interaction volume + std::size_t numUnknowns() const { return numUnknowns_; } - // resize possible additional containers in the data handle - if (requireABMatrix_()) - dataHandle.resizeAB(numUnknowns_, numPotentials_); - if (dim < dimWorld) - dataHandle.resizeOutsideTij(numOutsideFaces_, numPotentials_); - } + //! returns the number of (in this context) known solution values within this interaction volume + std::size_t numKnowns() const { return numKnowns_; } - //! solves for the transmissibilities subject to a given tensor - template<typename GetTensorFunction> - void solveLocalSystem(const GetTensorFunction& getTensor, - const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - DataHandle& dataHandle) - { - // if only dirichlet faces are present, assemble T_ directly - if (numUnknowns_ == 0) - assemblePureDirichletT_(getTensor, problem, fvGeometry, elemVolVars, dataHandle.T()); - else - { - // assemble - assembleLocalMatrices_(getTensor, problem, fvGeometry, elemVolVars); - - // solve - A_.invert(); + //! returns the number of scvs embedded in this interaction volume + std::size_t numScvs() const { return scvs_.size(); } - // T = C*A^-1*B + D - dataHandle.T() = multiplyMatrices(C_.rightmultiply(A_), B_); - dataHandle.T() += D_; - - // store A-1B only when gradient reconstruction is necessary - if (requireABMatrix_()) - dataHandle.AB() = B_.leftmultiply(A_); - } + //! returns the number of scvfs embedded in this interaction volume + std::size_t numScvfs() const { return scvfs_.size(); } - // set vol vars stencil pointer in handle - dataHandle.setVolVarsStencilPointer(indexSet().globalScvIndices()); - - // on surface grids, additionally prepare the outside transmissibilities - if (dim < dimWorld) - computeOutsideTransmissibilities_(dataHandle); - } - - //! obtain the local data object for a given global scvf - const LocalFaceData& getLocalFaceData(const SubControlVolumeFace& scvf) const - { - //! find corresponding entry in the local face data container - const auto scvfIdxGlobal = scvf.index(); - auto it = std::find_if(localFaceData_.begin(), - localFaceData_.end(), - [scvfIdxGlobal] (const LocalFaceData& d) { return d.globalScvfIndex() == scvfIdxGlobal; }); - assert(it != localFaceData_.end() && "Could not find the local face data corresponding to the given scvf"); - return localFaceData_[std::distance(localFaceData_.begin(), it)]; - } + //! returns the cell-stencil of this interaction volume + const Stencil& stencil() const { return *stencil_; } //! returns the grid element corresponding to a given iv-local scv idx const Element& element(const LocalIndexType ivLocalScvIdx) const { return elements_[ivLocalScvIdx]; } @@ -296,19 +280,36 @@ public: //! returns a reference to the container with the local face data const std::vector<LocalFaceData>& localFaceData() const { return localFaceData_; } - //! returns a reference to the index set of this iv - const IndexSet& indexSet() const { return *indexSetPtr_; } + //! returns a reference to the information container on Dirichlet BCs within this iv + const std::vector<DirichletData>& dirichletData() const { return dirichletData_; } + + //! returns the matrix associated with face unknowns in local equation system + const Matrix& A() const { return A_; } + Matrix& A() { return A_; } + + //! returns the matrix associated with cell unknowns in local equation system + const Matrix& B() const { return B_; } + Matrix& B() { return B_; } + + //! returns the matrix associated with face unknowns in flux expressions + const Matrix& C() const { return C_; } + Matrix& C() { return C_; } + + //! returns container storing the transmissibilities for each face & coordinate + const std::vector< std::vector< DimVector > >& omegas() const { return wijk_; } + std::vector< std::vector< DimVector > >& omegas() { return wijk_; } //! returns the number of interaction volumes living around a vertex //! the mpfa-o scheme always constructs one iv per vertex - static std::size_t numInteractionVolumesAtVertex(const DualGridNodalIndexSet& nodalIndexSet) { return 1; } + template< class NodalIndexSet > + static std::size_t numInteractionVolumesAtVertex(const NodalIndexSet& nodalIndexSet) { return 1; } //! adds the iv index sets living around a vertex to a given container //! and stores the the corresponding index in a map for each scvf - template<class IvIndexSetContainer, class ScvfIndexMap> + template<class IvIndexSetContainer, class ScvfIndexMap, class NodalIndexSet> static void addInteractionVolumeIndexSets(IvIndexSetContainer& ivIndexSetContainer, ScvfIndexMap& scvfIndexMap, - const DualGridNodalIndexSet& nodalIndexSet) + const NodalIndexSet& nodalIndexSet) { // the global index of the iv index set that is about to be created const auto curGlobalIndex = ivIndexSetContainer.size(); @@ -322,301 +323,28 @@ public: } private: - //! returns a boolean whether or not the AB matrix has to be passed to the handles - static bool requireABMatrix_() - { - static const bool requireAB = getParamFromGroup<bool>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Vtk.AddVelocity") || dim < dimWorld; - return requireAB; - } - - //! clears all the containers - void clear_() - { - elements_.clear(); - scvs_.clear(); - scvfs_.clear(); - localFaceData_.clear(); - dirichletData_.clear(); - } - - //! Assembles the local matrices that define the local system of equations and flux expressions - template<typename GetTensorFunction> - void assembleLocalMatrices_(const GetTensorFunction& getTensor, - const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars) - { - // reset matrices - A_ = 0.0; - B_ = 0.0; - C_ = 0.0; - D_ = 0.0; - - // reserve space for the omegas - wijk_.resize(scvfs_.size()); - - // loop over the local faces - for (LocalIndexType faceIdx = 0; faceIdx < numFaces_; ++faceIdx) - { - const auto& curLocalScvf = localScvf(faceIdx); - const auto& curGlobalScvf = fvGeometry.scvf(curLocalScvf.globalScvfIndex()); - const auto curIsDirichlet = curLocalScvf.isDirichlet(); - const auto curLocalDofIdx = curLocalScvf.localDofIndex(); - - // get diffusion tensor in "positive" sub volume - const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices(); - const auto posLocalScvIdx = neighborScvIndices[0]; - const auto& posLocalScv = localScv(posLocalScvIdx); - const auto& posGlobalScv = fvGeometry.scv(posLocalScv.globalScvIndex()); - const auto& posVolVars = elemVolVars[posGlobalScv]; - const auto& posElement = element(posLocalScvIdx); - const auto tensor = getTensor(problem, posElement, posVolVars, fvGeometry, posGlobalScv); - - // the omega factors of the "positive" sub volume - auto posWijk = calculateOmegas_(posLocalScv, curGlobalScvf.unitOuterNormal(), curGlobalScvf.area(), tensor); - posWijk *= posVolVars.extrusionFactor(); - - // go over the coordinate directions in the positive sub volume - for (unsigned int localDir = 0; localDir < dim; localDir++) - { - const auto otherLocalScvfIdx = posLocalScv.scvfIdxLocal(localDir); - const auto& otherLocalScvf = localScvf(otherLocalScvfIdx); - const auto otherLocalDofIdx = otherLocalScvf.localDofIndex(); - - // if we are not on a Dirichlet face, add entries associated with unknown face pressures - // i.e. in matrix C and maybe A (if current face is not a Dirichlet face) - if (!otherLocalScvf.isDirichlet()) - { - C_[faceIdx][otherLocalDofIdx] -= posWijk[localDir]; - if (!curIsDirichlet) - A_[curLocalDofIdx][otherLocalDofIdx] -= posWijk[localDir]; - } - // the current face is a Dirichlet face and creates entries in D & maybe B - else - { - D_[faceIdx][otherLocalDofIdx] -= posWijk[localDir]; - if (!curIsDirichlet) - B_[curLocalDofIdx][otherLocalDofIdx] += posWijk[localDir]; - } - - // add entries related to pressures at the scv centers (dofs) - const auto posScvLocalDofIdx = posLocalScv.localDofIndex(); - D_[faceIdx][posScvLocalDofIdx] += posWijk[localDir]; - - if (!curIsDirichlet) - B_[curLocalDofIdx][posScvLocalDofIdx] -= posWijk[localDir]; - } - - // store the omegas - wijk_[faceIdx].emplace_back(std::move(posWijk)); - - // If we are on an interior face, add values from negative sub volume - if (!curGlobalScvf.boundary()) - { - // loop over all the outside neighbors of this face and add entries - for (unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside) - { - const auto negLocalScvIdx = neighborScvIndices[idxInOutside+1]; - const auto& negLocalScv = localScv(negLocalScvIdx); - const auto& negGlobalScv = fvGeometry.scv(negLocalScv.globalScvIndex()); - const auto& negVolVars = elemVolVars[negGlobalScv]; - const auto& negElement = element(negLocalScvIdx); - const auto negTensor = getTensor(problem, negElement, negVolVars, fvGeometry, negGlobalScv); - - // the omega factors of the "negative" sub volume - DimVector negWijk; - - // if dim < dimWorld, use outside normal vector - if (dim < dimWorld) - { - const auto& flipScvf = fvGeometry.flipScvf(curGlobalScvf.index(), idxInOutside); - auto negNormal = flipScvf.unitOuterNormal(); - negNormal *= -1.0; - negWijk = calculateOmegas_(negLocalScv, negNormal, curGlobalScvf.area(), negTensor); - } - else - negWijk = calculateOmegas_(negLocalScv, curGlobalScvf.unitOuterNormal(), curGlobalScvf.area(), negTensor); - - // scale by extrusion factpr - negWijk *= negVolVars.extrusionFactor(); - - // go over the coordinate directions in the positive sub volume - for (int localDir = 0; localDir < dim; localDir++) - { - const auto otherLocalScvfIdx = negLocalScv.scvfIdxLocal(localDir); - const auto& otherLocalScvf = localScvf(otherLocalScvfIdx); - const auto otherLocalDofIdx = otherLocalScvf.localDofIndex(); - - if (!otherLocalScvf.isDirichlet()) - A_[curLocalDofIdx][otherLocalDofIdx] += negWijk[localDir]; - else - B_[curLocalDofIdx][otherLocalDofIdx] -= negWijk[localDir]; - - // add entries to matrix B - B_[curLocalDofIdx][negLocalScv.localDofIndex()] += negWijk[localDir]; - } - - // store the omegas - wijk_[faceIdx].emplace_back(std::move(negWijk)); - } - } - } - } - - //! for interaction volumes that have only dirichlet scvfs, - //! the transmissibility matrix can be assembled directly - template<typename GetTensorFunction> - void assemblePureDirichletT_(const GetTensorFunction& getTensor, - const Problem& problem, - const FVElementGeometry& fvGeometry, - const ElementVolumeVariables& elemVolVars, - Matrix& T) - { - // reset the transmissibility matrix beforehand - T = 0.0; - - // Loop over all the faces, in this case these are all dirichlet boundaries - for (unsigned int faceIdx = 0; faceIdx < numFaces_; ++faceIdx) - { - const auto& curLocalScvf = localScvf(faceIdx); - const auto& curGlobalScvf = fvGeometry.scvf(curLocalScvf.globalScvfIndex()); - - // get diffusion tensor in "positive" sub volume - const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices(); - const auto posLocalScvIdx = neighborScvIndices[0]; - const auto& posLocalScv = localScv(posLocalScvIdx); - const auto& posGlobalScv = fvGeometry.scv(posLocalScv.globalScvIndex()); - const auto& posVolVars = elemVolVars[posGlobalScv]; - const auto& posElement = element(posLocalScvIdx); - const auto tensor = getTensor(problem, posElement, posVolVars, fvGeometry, posGlobalScv); - - // the omega factors of the "positive" sub volume - auto posWijk = calculateOmegas_(posLocalScv, curGlobalScvf.unitOuterNormal(), curGlobalScvf.area(), tensor); - posWijk *= posVolVars.extrusionFactor(); - - const auto posScvLocalDofIdx = posLocalScv.localDofIndex(); - for (LocalIndexType localDir = 0; localDir < dim; localDir++) - { - const auto otherLocalScvfIdx = posLocalScv.scvfIdxLocal(localDir); - const auto& otherLocalScvf = localScvf(otherLocalScvfIdx); - const auto otherLocalDofIdx = otherLocalScvf.localDofIndex(); - T[faceIdx][otherLocalDofIdx] -= posWijk[localDir]; - T[faceIdx][posScvLocalDofIdx] += posWijk[localDir]; - } - } - } - - //! computes the transmissibilities associated with "outside" faces on surface grids - void computeOutsideTransmissibilities_(DataHandle& dataHandle) const - { - assert(dim < dimWorld && "only for dim < dimWorld the outside transmissiblity container has the right size"); - - for (const auto& localFaceData : localFaceData_) - { - //! continue only for "outside" faces - if (!localFaceData.isOutside()) continue; - - const auto localScvIdx = localFaceData.ivLocalInsideScvIndex(); - const auto localScvfIdx = localFaceData.ivLocalScvfIndex(); - const auto& posLocalScv = localScv(localScvIdx); - const auto& wijk = wijk_[localScvfIdx][localFaceData.scvfLocalOutsideScvfIndex() + 1]; - - //! store the calculated transmissibilities in the data handle - auto& tij = dataHandle.outsideTij()[localFaceData.ivLocalOutsideScvfIndex()]; - - //! reset transmissibility vector - tij = 0.0; - - //! add contributions from all local directions - for (LocalIndexType localDir = 0; localDir < dim; localDir++) - { - //! the scvf corresponding to this local direction in the scv - const auto& curLocalScvf = localScvf(posLocalScv.scvfIdxLocal(localDir)); - - //! on interior faces the coefficients of the AB matrix come into play - if (!curLocalScvf.isDirichlet()) - { - auto tmp = dataHandle.AB()[curLocalScvf.localDofIndex()]; - tmp *= wijk[localDir]; - tij -= tmp; - } - else - tij[curLocalScvf.localDofIndex()] -= wijk[localDir]; - - // add entry from the scv unknown - tij[localScvIdx] += wijk[localDir]; - } - } - } - - // calculates n_i^T*K_j*nu_k - DimVector calculateOmegas_(const LocalScvType& localScv, - const GlobalPosition& normal, - const Scalar area, - const Tensor& T) const - { - // make sure we have positive definite diffsion tensors - assert(this->tensorIsPositiveDefinite(T) && "only positive definite tensors can be handled by mpfa methods"); - - DimVector wijk; - GlobalPosition tmp; - for (LocalIndexType dir = 0; dir < dim; ++dir) - { - T.mv(localScv.innerNormal(dir), tmp); - wijk[dir] = tmp*normal; - } - wijk *= area; - wijk /= localScv.detX(); - - return wijk; - } - - // calculates n_i^T*K_j*nu_k - DimVector calculateOmegas_(const LocalScvType& localScv, - const GlobalPosition& normal, - const Scalar area, - const Scalar t) const - { - // make sure we have positive diffusion coefficients - assert(t > 0.0 && "non-positive diffusion coefficients cannot be handled by mpfa methods"); - - DimVector wijk; - GlobalPosition tmp(normal); - tmp *= t; - - for (LocalIndexType dir = 0; dir < dim; ++dir) - wijk[dir] = tmp*localScv.innerNormal(dir); - wijk *= area; - wijk /= localScv.detX(); - - return wijk; - } - - const IndexSet* indexSetPtr_; + // pointer to cell stencil (in iv index set) + const Stencil* stencil_; // Variables defining the local scope std::vector<Element> elements_; std::vector<LocalScvType> scvs_; std::vector<LocalScvfType> scvfs_; std::vector<LocalFaceData> localFaceData_; - DirichletDataContainer dirichletData_; + std::vector<DirichletData> dirichletData_; - // sizes involved in the local matrices - unsigned int numFaces_; - unsigned int numUnknowns_; - unsigned int numPotentials_; - unsigned int numOutsideFaces_; - - // The omega factors and the matrix Aâ»1*B are stored - // in order to recover the transmissibilities of outside faces on network grids - std::vector< std::vector< DimVector > > wijk_; - Matrix CAinv_; - - // Matrices involved in transmissibility calculations + // Matrices needed for computation of transmissibilities Matrix A_; Matrix B_; Matrix C_; - Matrix D_; + + // The omega factors are stored during assemble of local system + std::vector< std::vector< DimVector > > wijk_; + + // sizes involved in the local system equations + std::size_t numFaces_; + std::size_t numUnknowns_; + std::size_t numKnowns_; }; } // end namespace diff --git a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh index 2645b214ad35139af3c0ec4cbf17a164edfb311a..84a26f7a4e4a253f905b1ca6405f6b1e2a2bdd65 100644 --- a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh +++ b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh @@ -18,6 +18,7 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief Class for the index set within an interaction volume of the mpfa-o scheme. */ #ifndef DUMUX_DISCRETIZATION_MPFA_O_INTERACTIONVOLUME_INDEXSET_HH @@ -28,20 +29,42 @@ namespace Dumux { /*! - * \ingroup Mpfa + * \ingroup CCMpfaDiscretization * \brief The interaction volume index set class for the mpfa-o scheme. + * + * \tparam DualGridNodalIndexSet The type used for the nodal index set in the dual grid. */ -template<class DualGridNodalIndexSet, class GlobalIndexContainer, class LocalIndexContainer> +template< class DualGridNodalIndexSet > class CCMpfaOInteractionVolumeIndexSet { - using LocalIndexType = typename LocalIndexContainer::value_type; - using GlobalIndexType = typename GlobalIndexContainer::value_type; - public: - explicit CCMpfaOInteractionVolumeIndexSet(const DualGridNodalIndexSet& nodalIndexSet) : nodalIndexSet_(nodalIndexSet) + using LocalIndexType = typename DualGridNodalIndexSet::LocalIndexType; + using GridIndexType = typename DualGridNodalIndexSet::GridIndexType; + + using LocalIndexContainer = typename DualGridNodalIndexSet::LocalIndexContainer; + using GridIndexContainer = typename DualGridNodalIndexSet::GridIndexContainer; + + /*! + * \brief The constructor + * \note The actual type used for the nodal index sets might be different, as maybe + * a different type for the local indexes is used. We therefore template this + * constructor. However, a static assertion enforces you to use the same LocalIndexType + * in the traits for both the secondary and the primary interaction volume traits. + * + * \tparam NodalIndexSet Possibly differing type for the DualGridNodalIndexSet + */ + template< class NodalIndexSet > + CCMpfaOInteractionVolumeIndexSet(const NodalIndexSet& nodalIndexSet) + : nodalIndexSet_( static_cast<const DualGridNodalIndexSet&>(nodalIndexSet) ) { - //! determine the number of iv-local faces for memory reservation - //! note that this might be a vast overestimation on surface grids! + // make sure the index types used are the same in order to avoid any losses due to type conversion + static_assert(std::is_same<GridIndexType, typename NodalIndexSet::GridIndexType>::value, + "Provided nodal index set does not use the same type for grid indices as the given template argument"); + static_assert(std::is_same<LocalIndexType, typename NodalIndexSet::LocalIndexType>::value, + "Provided nodal index set does not use the same type for local indices as the given template argument"); + + // determine the number of iv-local faces for memory reservation + // note that this might be a vast overestimation on surface grids! const auto numNodalScvfs = nodalIndexSet.numScvfs(); const auto numBoundaryScvfs = nodalIndexSet.numBoundaryScvfs(); const std::size_t numFaceEstimate = numBoundaryScvfs + (numNodalScvfs-numBoundaryScvfs)/2; @@ -49,26 +72,26 @@ public: // make sure we found a reasonable number of faces assert((numNodalScvfs-numBoundaryScvfs)%2 == 0); - //! index transformation from interaction-volume-local to node-local + // index transformation from interaction-volume-local to node-local ivToNodeScvf_.reserve(numFaceEstimate); nodeToIvScvf_.resize(numNodalScvfs); - //! the local neighboring scv indices of the faces + // the local neighboring scv indices of the faces scvfNeighborScvLocalIndices_.reserve(numFaceEstimate); - //! keeps track of which nodal scvfs have been handled already + // keeps track of which nodal scvfs have been handled already std::vector<bool> isHandled(numNodalScvfs, false); - //! go over faces in nodal index set, check if iv-local face has been - //! inserted already for this scvf and if not, insert index mapping + // go over faces in nodal index set, check if iv-local face has been + // inserted already for this scvf and if not, insert index mapping numFaces_ = 0; for (LocalIndexType i = 0; i < numNodalScvfs; ++i) { - //! check if the nodal scvf still has to be handled + // check if the nodal scvf still has to be handled if (isHandled[i]) continue; - //! for scvfs touching the boundary there are no "outside" scvfs + // for scvfs touching the boundary there are no "outside" scvfs if (nodalIndexSet.scvfIsOnBoundary(i)) { nodeToIvScvf_[i] = ivToNodeScvf_.size(); @@ -78,8 +101,8 @@ public: continue; } - //! We insert a new iv-local face and find all "outside" scvfs that map - //! to this face as well by comparing the set of neighboring scv indices. + // We insert a new iv-local face and find all "outside" scvfs that map + // to this face as well by comparing the set of neighboring scv indices. const auto scvIndices = [&nodalIndexSet, i] () { auto tmp = nodalIndexSet.neighboringScvIndices(i); @@ -91,7 +114,7 @@ public: std::vector<LocalIndexType> outsideScvfs; for (LocalIndexType j = i+1; j < numNodalScvfs; ++j) { - //! a face that has been handled already cannot be an "outside" face here + // a face that has been handled already cannot be an "outside" face here if (!isHandled[j]) { const auto scvIndices2 = [&nodalIndexSet, j] () @@ -125,8 +148,8 @@ public: } // compute local neighboring scv indices for the iv-local scvfs - scvfNeighborScvLocalIndices_.resize(numFaces()); - for (unsigned int i = 0; i < numFaces(); ++i) + scvfNeighborScvLocalIndices_.resize(numFaces_); + for (unsigned int i = 0; i < numFaces_; ++i) { const auto& neighborsGlobal = nodalIndexSet_.neighboringScvIndices(ivToNodeScvf_[i]); const auto numNeighbors = nodalIndexSet_.scvfIsOnBoundary(ivToNodeScvf_[i]) ? 1 : neighborsGlobal.size(); @@ -141,16 +164,12 @@ public: const DualGridNodalIndexSet& nodalIndexSet() const { return nodalIndexSet_; } //! returns a global scvf idx for a given iv_local scvf index - GlobalIndexType scvfIdxGlobal(LocalIndexType ivLocalScvfIdx) const - { return nodalIndexSet_.scvfIdxGlobal(ivToNodeScvf_[ivLocalScvfIdx]); } + GridIndexType scvfIdxGlobal(LocalIndexType ivLocalScvfIdx) const + { return nodalIndexSet_.scvfIdxGlobal( ivToNodeScvf_[ivLocalScvfIdx] ); } //! returns the iv-local scvf idx of the i-th scvfs embedded in a local scv LocalIndexType scvfIdxLocal(LocalIndexType scvIdxLocal, unsigned int i) const - { return nodeToIvScvf_[nodalIndexSet_.scvfIdxLocal(scvIdxLocal, i)]; } - - //! returns whether or not an scvf touches the boundary - bool scvfTouchesBoundary(LocalIndexType ivLocalScvfIdx) const - { return nodalIndexSet_.scvfTouchesBoundary(ivToNodeScvf_[ivLocalScvfIdx]); } + { return nodeToIvScvf_[ nodalIndexSet_.scvfIdxLocal(scvIdxLocal, i) ]; } //! returns the local indices of the neighboring scvs of an scvf const LocalIndexContainer& neighboringLocalScvIndices(LocalIndexType ivLocalScvfIdx) const @@ -163,14 +182,14 @@ public: std::size_t numScvs() const { return nodalIndexSet_.numScvs(); } //! returns the global scv indices connected to this dual grid node - const GlobalIndexContainer& globalScvIndices() const { return nodalIndexSet_.globalScvIndices(); } + const GridIndexContainer& globalScvIndices() const { return nodalIndexSet_.globalScvIndices(); } //! returns the global scvf indices connected to this dual grid node - const GlobalIndexContainer& globalScvfIndices() const { return nodalIndexSet_.globalScvfIndices(); } + const GridIndexContainer& globalScvfIndices() const { return nodalIndexSet_.globalScvfIndices(); } private: //! returns the local scv index to a given global scv index - unsigned int findLocalScvIdx_(GlobalIndexType globalScvIdx) const + unsigned int findLocalScvIdx_(GridIndexType globalScvIdx) const { auto it = std::find( nodalIndexSet_.globalScvIndices().begin(), nodalIndexSet_.globalScvIndices().end(), globalScvIdx ); assert(it != nodalIndexSet_.globalScvIndices().end() && "Global scv index not found in local container!"); @@ -180,13 +199,13 @@ private: const DualGridNodalIndexSet& nodalIndexSet_; std::size_t numFaces_; - LocalIndexContainer ivToNodeScvf_; - LocalIndexContainer nodeToIvScvf_; - //! maps to each scvf a list of neighbouring scv indices - //! ordering: 0 - inside scv idx; 1..n - outside scv indices - std::vector<LocalIndexContainer> scvfNeighborScvLocalIndices_; + std::vector<LocalIndexType> ivToNodeScvf_; + std::vector<LocalIndexType> nodeToIvScvf_; + // maps to each scvf a list of neighbouring scv indices + // ordering: 0 - inside scv idx; 1..n - outside scv indices + std::vector< LocalIndexContainer > scvfNeighborScvLocalIndices_; }; -} // end namespace +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/omethod/localassembler.hh b/dumux/discretization/cellcentered/mpfa/omethod/localassembler.hh new file mode 100644 index 0000000000000000000000000000000000000000..26f922da3448e3d0a3064d736e4478c5499fbc3f --- /dev/null +++ b/dumux/discretization/cellcentered/mpfa/omethod/localassembler.hh @@ -0,0 +1,739 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * 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, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup CCMpfaDiscretization + * \brief Class for the assembly of the local systems of equations + * involved in the transmissibility computaion in the mpfa-o scheme. + */ +#ifndef DUMUX_DISCRETIZATION_CC_MPFA_O_LOCAL_ASSEMBLER_HH +#define DUMUX_DISCRETIZATION_CC_MPFA_O_LOCAL_ASSEMBLER_HH + +#include <dumux/common/math.hh> +#include <dumux/common/properties.hh> + +#include <dumux/discretization/cellcentered/mpfa/methods.hh> +#include <dumux/discretization/cellcentered/mpfa/localassembler.hh> +#include <dumux/discretization/cellcentered/mpfa/computetransmissibility.hh> +#include <dumux/discretization/cellcentered/mpfa/interactionvolume.hh> + +namespace Dumux +{ + +/*! + * \ingroup CCMpfaDiscretization + * \brief Specialization of the interaction volume-local + * assembler class for the mpfa-o scheme. + */ +template< class TypeTag > +class InteractionVolumeAssemblerImpl< CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod> > + : public InteractionVolumeAssemblerBase< CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod> > +{ + using InteractionVolume = CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::oMethod>; + using ParentType = InteractionVolumeAssemblerBase< InteractionVolume >; + + using Traits = typename InteractionVolume::Traits; + using LocalIndexType = typename Traits::LocalIndexType; + using Matrix = typename Traits::Matrix; + using Vector = typename Traits::Vector; + + static constexpr int dim = Traits::LocalScvType::myDimension; + static constexpr int dimWorld = Traits::LocalScvType::worldDimension; + + // obtain the number of phases via the property system + static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases); + +public: + //! Use the constructor of the base class + using ParentType::ParentType; + + /*! + * \brief Assembles the transmissibility matrix + * within an interaction volume for the mpfa-o scheme. + * + * \param T The transmissibility matrix to be assembled + * \param iv The mpfa-o interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GetTensorFunction > + void assemble(Matrix& T, InteractionVolume& iv, const GetTensorFunction& getTensor) + { + // assemble D into T directly + assembleLocalMatrices_(iv.A(), iv.B(), iv.C(), T, iv, getTensor); + + // maybe solve the local system + if (iv.numUnknowns() > 0) + { + // T = C*A^-1*B + D + iv.A().invert(); + iv.C().rightmultiply(iv.A()); + T += multiplyMatrices(iv.C(), iv.B()); + } + } + + /*! + * \brief Assembles the interaction volume-local transmissibility + * matrix for surface grids. The transmissibilities associated + * with "outside" faces are stored in a separate container. + * + * \param outsideTij tij on "outside" faces to be assembled + * \param T The transmissibility matrix tij to be assembled + * \param iv The mpfa-o interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class OutsideTijContainer, class GetTensorFunction > + void assemble(OutsideTijContainer& outsideTij, Matrix& T, InteractionVolume& iv, const GetTensorFunction& getTensor) + { + // assemble D into T directly + assembleLocalMatrices_(iv.A(), iv.B(), iv.C(), T, iv, getTensor); + + // maybe solve the local system + if (iv.numUnknowns() > 0) + { + // T = C*A^-1*B + D + iv.A().invert(); + iv.B().leftmultiply(iv.A()); + T += multiplyMatrices(iv.C(), iv.B()); + + // compute outside transmissibilities + for (const auto& localFaceData : iv.localFaceData()) + { + // continue only for "outside" faces + if (!localFaceData.isOutside()) + continue; + + const auto localScvIdx = localFaceData.ivLocalInsideScvIndex(); + const auto localScvfIdx = localFaceData.ivLocalScvfIndex(); + const auto idxInOutside = localFaceData.scvfLocalOutsideScvfIndex(); + const auto& posLocalScv = iv.localScv(localScvIdx); + const auto& wijk = iv.omegas()[localScvfIdx][idxInOutside+1]; + + // store the calculated transmissibilities in the data handle + auto& tij = outsideTij[localScvfIdx][idxInOutside]; + tij = 0.0; + + // add contributions from all local directions + for (LocalIndexType localDir = 0; localDir < dim; localDir++) + { + // the scvf corresponding to this local direction in the scv + const auto& curLocalScvf = iv.localScvf(posLocalScv.scvfIdxLocal(localDir)); + + // on interior faces the coefficients of the AB matrix come into play + if (!curLocalScvf.isDirichlet()) + { + auto tmp = iv.B()[curLocalScvf.localDofIndex()]; + tmp *= wijk[localDir]; + tij -= tmp; + } + else + tij[curLocalScvf.localDofIndex()] -= wijk[localDir]; + + // add entry from the scv unknown + tij[localScvIdx] += wijk[localDir]; + } + } + } + } + + /*! + * \brief Assemble the transmissibility matrix within an interaction + * volume for the mpfa-o scheme to be used for advective flux + * computation in the case that gravity is to be considered in + * the local system of equations. + * + * \param T The transmissibility matrix to be assembled + * \param g Container to assemble gravity per scvf & phase + * \param CA Matrix to store matrix product C*A^-1 + * \param iv The mpfa-o interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GravityContainer, class GetTensorFunction > + void assembleWithGravity(Matrix& T, + GravityContainer& g, + Matrix& CA, + InteractionVolume& iv, + const GetTensorFunction& getTensor) + { + // assemble D into T & C into CA directly + assembleLocalMatrices_(iv.A(), iv.B(), CA, T, iv, getTensor); + + // maybe solve the local system + if (iv.numUnknowns() > 0) + { + // T = C*A^-1*B + D + iv.A().invert(); + CA.rightmultiply(iv.A()); + T += multiplyMatrices(CA, iv.B()); + } + + // assemble gravitational acceleration container (enforce usage of mpfa-o type version) + assembleGravity(g, iv, CA, getTensor); + } + + /*! + * \brief Assembles the interaction volume-local transmissibility + * matrix in the case that gravity is to be considered in the + * local system of equations. This specialization is to be used + * on surface grids, where the gravitational flux contributions + * on "outside" faces are stored in a separate container. + * + * \param outsideTij tij on "outside" faces to be assembled + * \param T The transmissibility matrix to be assembled + * \param outsideG Container to assemble gravity on "outside" faces + * \param g Container to assemble gravity per scvf & phase + * \param CA Matrix to store matrix product C*A^-1 + * \param A Matrix to store the inverse A^-1 + * \param iv The mpfa-o interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GravityContainer, + class OutsideGravityContainer, + class OutsideTijContainer, + class GetTensorFunction > + void assembleWithGravity(OutsideTijContainer& outsideTij, + Matrix& T, + OutsideGravityContainer& outsideG, + GravityContainer& g, + Matrix& CA, + Matrix& A, + InteractionVolume& iv, + const GetTensorFunction& getTensor) + { + // assemble D into T directly + assembleLocalMatrices_(iv.A(), iv.B(), iv.C(), T, iv, getTensor); + + // maybe solve the local system + if (iv.numUnknowns() > 0) + { + // T = C*A^-1*B + D + iv.A().invert(); + iv.B().leftmultiply(iv.A()); + T += multiplyMatrices(iv.C(), iv.B()); + A = iv.A(); + CA = iv.C().rightmultiply(A); + + // compute outside transmissibilities + for (const auto& localFaceData : iv.localFaceData()) + { + // continue only for "outside" faces + if (!localFaceData.isOutside()) + continue; + + const auto localScvIdx = localFaceData.ivLocalInsideScvIndex(); + const auto localScvfIdx = localFaceData.ivLocalScvfIndex(); + const auto idxInOutside = localFaceData.scvfLocalOutsideScvfIndex(); + const auto& posLocalScv = iv.localScv(localScvIdx); + const auto& wijk = iv.omegas()[localScvfIdx][idxInOutside+1]; + + // store the calculated transmissibilities in the data handle + auto& tij = outsideTij[localScvfIdx][idxInOutside]; + tij = 0.0; + + // add contributions from all local directions + for (LocalIndexType localDir = 0; localDir < dim; localDir++) + { + // the scvf corresponding to this local direction in the scv + const auto& curLocalScvf = iv.localScvf(posLocalScv.scvfIdxLocal(localDir)); + + // on interior faces the coefficients of the AB matrix come into play + if (!curLocalScvf.isDirichlet()) + { + auto tmp = iv.B()[curLocalScvf.localDofIndex()]; + tmp *= wijk[localDir]; + tij -= tmp; + } + else + tij[curLocalScvf.localDofIndex()] -= wijk[localDir]; + + // add entry from the scv unknown + tij[localScvIdx] += wijk[localDir]; + } + } + } + + assembleGravity(g, outsideG, iv, CA, A, getTensor); + } + + /*! + * \brief Assembles the vector of primary (cell) unknowns and (maybe) + * Dirichlet boundary conditions within an interaction volume. + * + * \param u The vector to be filled with the cell unknowns + * \param iv The mpfa-o interaction volume + * \param getU Lambda to obtain the desired cell/Dirichlet value from grid index + */ + template< class GetU > + void assemble(Vector& u, const InteractionVolume& iv, const GetU& getU) + { + // resize given container + u.resize(iv.numKnowns()); + + // put the cell pressures first + + for (LocalIndexType i = 0; i < iv.numScvs(); ++i) + u[i] = getU( iv.localScv(i).globalScvIndex() ); + + // Dirichlet BCs come afterwards + unsigned int i = iv.numScvs(); + for (const auto& data : iv.dirichletData()) + u[i++] = getU( data.volVarIndex() ); + } + + /*! + * \brief Assemble the gravitational flux contributions on the scvfs within + * an mpfa-o interaction volume. + * + * \note For each face, the gravity term in the form of \f$\rho \mathbf{n K g}\f$ is + * evaluated. Thus, make sure to only call this with a lambda that returns the + * hydraulic conductivity. + * + * \param g Container to assemble gravity per scvf & phase + * \param iv The mpfa-o interaction volume + * \param CA Projection matrix transforming the gravity terms in the local system of + * equations to the entire set of faces within the interaction volume + * \param getTensor Lambda to evaluate scv-wise hydraulic conductivities + */ + template< class GravityContainer, class GetTensorFunction > + void assembleGravity(GravityContainer& g, + const InteractionVolume& iv, + const Matrix& CA, + const GetTensorFunction& getTensor) + { + // we require the CA matrix and the g vector to have the correct size already + assert(g.size() == numPhases && "Provided gravity container does not have NumPhases entries"); + assert(g[0].size() == iv.numFaces() && "Gravitation vector g does not have the correct size"); + assert(CA.rows() == iv.numFaces() && CA.cols() == iv.numUnknowns() && "Matrix CA does not have the correct size"); + + //! For each face, we... + //! - arithmetically average the phase densities + //! - compute the term \f$ \alpha := A \rho \ \mathbf{n}^T \mathbf{K} \mathbf{g} \f$ in each neighboring cell + //! - compute \f$ \alpha^* = \alpha_{outside} - \alpha_{inside} \f$ + using Scalar = typename Vector::value_type; + + std::array< Vector, numPhases > sum_alphas; + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + g[pIdx] = 0.0; + sum_alphas[pIdx].resize(iv.numUnknowns(), 0.0); + } + + for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx) + { + // gravitational acceleration on this face + const auto& curLocalScvf = iv.localScvf(faceIdx); + const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.globalScvfIndex()); + const auto gravity = this->problem().gravityAtPos(curGlobalScvf.ipGlobal()); + + // get permeability tensor in "positive" sub volume + const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices(); + const auto& posLocalScv = iv.localScv(neighborScvIndices[0]); + const auto& posGlobalScv = this->fvGeometry().scv(posLocalScv.globalScvIndex()); + const auto& posVolVars = this->elemVolVars()[posGlobalScv]; + const auto& posElement = iv.element(neighborScvIndices[0]); + const auto tensor = getTensor(this->problem(), posElement, posVolVars, this->fvGeometry(), posGlobalScv); + + // This function should never be called for surface grids, + // for which there is the specialization of this function below + assert(neighborScvIndices.size() <= 2 && "Scvf seems to have more than one outside scv!"); + + std::array< Scalar, numPhases > rho; + const auto alpha_inside = posVolVars.extrusionFactor()*vtmv(curGlobalScvf.unitOuterNormal(), tensor, gravity); + if (!curLocalScvf.isDirichlet()) + { + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + rho[pIdx] = posVolVars.density(pIdx); + + if (!curGlobalScvf.boundary()) + { + // obtain outside tensor + const auto& negLocalScv = iv.localScv( neighborScvIndices[1] ); + const auto& negGlobalScv = this->fvGeometry().scv(negLocalScv.globalScvIndex()); + const auto& negVolVars = this->elemVolVars()[negGlobalScv]; + const auto& negElement = iv.element( neighborScvIndices[1] ); + const auto negTensor = getTensor(this->problem(), negElement, negVolVars, this->fvGeometry(), negGlobalScv); + + const auto sum_alpha = negVolVars.extrusionFactor() + * vtmv(curGlobalScvf.unitOuterNormal(), negTensor, gravity) + - alpha_inside; + + const auto localDofIdx = curLocalScvf.localDofIndex(); + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + rho[pIdx] = 0.5*( rho[pIdx] + negVolVars.density(pIdx) ); + sum_alphas[pIdx][localDofIdx] = sum_alpha*rho[pIdx]*curGlobalScvf.area(); + } + } + else + { + const auto localDofIdx = curLocalScvf.localDofIndex(); + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + sum_alphas[pIdx][localDofIdx] -= alpha_inside*rho[pIdx]*curGlobalScvf.area(); + } + } + // use Dirichlet BC densities + else + { + const auto& dirichletVolVars = this->elemVolVars()[curGlobalScvf.outsideScvIdx()]; + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + rho[pIdx] = dirichletVolVars.density(pIdx); + } + + // add "inside" alpha to gravity container + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + g[pIdx][faceIdx] += alpha_inside*rho[pIdx]*curGlobalScvf.area(); + } + + // g += CA*sum_alphas + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + CA.umv(sum_alphas[pIdx], g[pIdx]); + } + + /*! + * \brief Assembles the gravitational flux contributions on the scvfs within an mpfa-o + * interaction volume. This specialization is to be used on surface grids, where the + * gravitational flux contributions on "outside" faces are stored in a separate container. + * + * \note For each face, the gravity term in the form of \f$\rho \mathbf{n K g}\f$ is + * evaluated. Thus, make sure to only call this with a lambda that returns the + * hydraulic conductivity. + * + * \param g Container to store gravity per scvf & phase + * \param outsideG Container to store gravity per "outside" scvf & phase + * \param iv The mpfa-o interaction volume + * \param CA Projection matrix transforming the gravity terms in the local system of + * equations to the entire set of faces within the interaction volume + * \param A Matrix needed for the "reconstruction" of face unknowns as a function of gravity + * \param getTensor Lambda to evaluate scv-wise hydraulic conductivities + */ + template< class GravityContainer, + class OutsideGravityContainer, + class GetTensorFunction > + void assembleGravity(GravityContainer& g, + OutsideGravityContainer& outsideG, + const InteractionVolume& iv, + const Matrix& CA, + const Matrix& A, + const GetTensorFunction& getTensor) + { + // we require the CA matrix and the gravity containers to have the correct size already + assert(CA.rows() == iv.numFaces() && CA.cols() == iv.numUnknowns() && "Matrix CA does not have the correct size"); + assert(g.size() == numPhases && "Provided gravity container does not have NumPhases entries"); + assert(outsideG.size() == numPhases && "Provided outside gravity container does not have NumPhases entries"); + assert(std::all_of(g.cbegin(), g.cend(), [&iv](const auto& d) { return d.size() == iv.numFaces(); }) + && "Gravitation vector g does not have the correct size"); + assert(std::all_of(outsideG.cbegin(), outsideG.cend(), [&iv](const auto& d) { return d.size() == iv.numFaces(); }) + && "Outside gravity container does not have the correct size"); + + //! For each face, we... + //! - arithmetically average the phase densities + //! - compute the term \f$ \alpha := \mathbf{A} \rho \ \mathbf{n}^T \mathbf{K} \mathbf{g} \f$ in each neighboring cell + //! - compute \f$ \alpha^* = \sum{\alpha_{outside, i}} - \alpha_{inside} \f$ + using Scalar = typename Vector::value_type; + + // reset everything to zero + std::array< Vector, numPhases > sum_alphas; + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + g[pIdx] = 0.0; + std::for_each(outsideG[pIdx].begin(), outsideG[pIdx].end(), [] (auto& v) { v = 0.0; }); + sum_alphas[pIdx].resize(iv.numUnknowns(), 0.0); + } + + for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx) + { + // gravitational acceleration on this face + const auto& curLocalScvf = iv.localScvf(faceIdx); + const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.globalScvfIndex()); + const auto gravity = this->problem().gravityAtPos(curGlobalScvf.ipGlobal()); + + // get permeability tensor in "positive" sub volume + const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices(); + const auto& posLocalScv = iv.localScv(neighborScvIndices[0]); + const auto& posGlobalScv = this->fvGeometry().scv(posLocalScv.globalScvIndex()); + const auto& posVolVars = this->elemVolVars()[posGlobalScv]; + const auto& posElement = iv.element(neighborScvIndices[0]); + const auto tensor = getTensor(this->problem(), posElement, posVolVars, this->fvGeometry(), posGlobalScv); + + const auto alpha_inside = posVolVars.extrusionFactor()*vtmv(curGlobalScvf.unitOuterNormal(), tensor, gravity); + const auto numOutsideFaces = curGlobalScvf.boundary() ? 0 : curGlobalScvf.numOutsideScvs(); + std::vector< Scalar > alpha_outside(numOutsideFaces); + std::array< Scalar, numPhases > rho; + + if (!curLocalScvf.isDirichlet()) + { + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + rho[pIdx] = posVolVars.density(pIdx); + + // arithmetically average density on inside faces + const auto localDofIdx = curLocalScvf.localDofIndex(); + if (!curGlobalScvf.boundary()) + { + for (unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside) + { + // obtain outside tensor + const auto& negLocalScv = iv.localScv( neighborScvIndices[idxInOutside] ); + const auto& negGlobalScv = this->fvGeometry().scv(negLocalScv.globalScvIndex()); + const auto& negVolVars = this->elemVolVars()[negGlobalScv]; + const auto& negElement = iv.element( neighborScvIndices[idxInOutside] ); + const auto negTensor = getTensor(this->problem(), negElement, negVolVars, this->fvGeometry(), negGlobalScv); + + const auto& flipScvf = this->fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside); + alpha_outside[idxInOutside] = negVolVars.extrusionFactor() + * vtmv(flipScvf.unitOuterNormal(), negTensor, gravity); + + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + rho[pIdx] += negVolVars.density(pIdx); + sum_alphas[pIdx][localDofIdx] -= alpha_outside[idxInOutside]; + } + } + } + + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + rho[pIdx] /= numOutsideFaces + 1; + sum_alphas[pIdx][localDofIdx] -= alpha_inside; + sum_alphas[pIdx][localDofIdx] *= rho[pIdx]*curGlobalScvf.area(); + } + } + // use Dirichlet BC densities + else + { + const auto& dirichletVolVars = this->elemVolVars()[curGlobalScvf.outsideScvIdx()]; + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + rho[pIdx] = dirichletVolVars.density(pIdx); + } + + // add "inside" & "outside" alphas to gravity containers + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + g[pIdx][faceIdx] += alpha_inside*rho[pIdx]*curGlobalScvf.area(); + unsigned int i = 0; + for (const auto& alpha : alpha_outside) + outsideG[pIdx][faceIdx][i++] -= alpha*rho[pIdx]*curGlobalScvf.area(); + } + } + + // g += CA*sum_alphas + // outsideG = wikj*A^-1*sum_alphas + outsideG + for (unsigned int pIdx = 0; pIdx < numPhases; ++pIdx) + { + CA.umv(sum_alphas[pIdx], g[pIdx]); + + Vector AG(iv.numUnknowns()); + A.mv(sum_alphas[pIdx], AG); + + // compute gravitational accelerations + for (const auto& localFaceData : iv.localFaceData()) + { + // continue only for "outside" faces + if (!localFaceData.isOutside()) + continue; + + const auto localScvIdx = localFaceData.ivLocalInsideScvIndex(); + const auto localScvfIdx = localFaceData.ivLocalScvfIndex(); + const auto idxInOutside = localFaceData.scvfLocalOutsideScvfIndex(); + const auto& posLocalScv = iv.localScv(localScvIdx); + const auto& wijk = iv.omegas()[localScvfIdx][idxInOutside+1]; + + // add contributions from all local directions + for (LocalIndexType localDir = 0; localDir < dim; localDir++) + { + // the scvf corresponding to this local direction in the scv + const auto& curLocalScvf = iv.localScvf(posLocalScv.scvfIdxLocal(localDir)); + + // on interior faces the coefficients of the AB matrix come into play + if (!curLocalScvf.isDirichlet()) + outsideG[pIdx][localScvfIdx][idxInOutside] -= wijk[localDir]*AG[curLocalScvf.localDofIndex()]; + } + } + } + } + +private: + /*! + * \brief Assemble the matrices involved in the flux expressions + * across the scvfs inside an interaction volume as well as those involved + * in the interaction volume-local system of equations resulting from flux + * and solution continuity across the scvfs. + * + * Flux expressions: \f$\mathbf{f} = \mathbf{C} \bar{\mathbf{u}} + \mathbf{D} \mathbf{u}\f$. + * + * Continuity equations: \f$\mathbf{A} \, \bar{\mathbf{u}} = \mathbf{B} \, \mathbf{u}\f$. + * + * \note The matrices are expected to have been resized beforehand. + * + * \param A The A matrix of the iv-local equation system + * \param B The B matrix of the iv-local equation system + * \param C The C matrix of the iv-local flux expressions + * \param D The D matrix of the iv-local flux expressions + * \param iv The mpfa-o interaction volume + * \param getTensor Lambda to evaluate the scv-wise tensors + */ + template< class GetTensorFunction > + void assembleLocalMatrices_(Matrix& A, Matrix& B, Matrix& C, Matrix& D, + InteractionVolume& iv, + const GetTensorFunction& getTensor) + { + // Matrix D is assumed to have the right size already + assert(D.rows() == iv.numFaces() && D.cols() == iv.numKnowns() && "Matrix D does not have the correct size"); + + // if only Dirichlet faces are present in the iv, + // the matrices A, B & C are undefined and D = T + if (iv.numUnknowns() == 0) + { + // reset matrix beforehand + D = 0.0; + + // Loop over all the faces, in this case these are all dirichlet boundaries + for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx) + { + const auto& curLocalScvf = iv.localScvf(faceIdx); + const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.globalScvfIndex()); + const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices(); + + // get tensor in "positive" sub volume + const auto& posLocalScv = iv.localScv(neighborScvIndices[0]); + const auto& posGlobalScv = this->fvGeometry().scv(posLocalScv.globalScvIndex()); + const auto& posVolVars = this->elemVolVars()[posGlobalScv]; + const auto& posElement = iv.element(neighborScvIndices[0]); + const auto tensor = getTensor(this->problem(), posElement, posVolVars, this->fvGeometry(), posGlobalScv); + + // the omega factors of the "positive" sub volume + const auto wijk = computeMpfaTransmissibility(posLocalScv, curGlobalScvf, tensor, posVolVars.extrusionFactor()); + + const auto posScvLocalDofIdx = posLocalScv.localDofIndex(); + for (LocalIndexType localDir = 0; localDir < dim; localDir++) + { + const auto& otherLocalScvf = iv.localScvf( posLocalScv.scvfIdxLocal(localDir) ); + const auto otherLocalDofIdx = otherLocalScvf.localDofIndex(); + D[faceIdx][otherLocalDofIdx] -= wijk[localDir]; + D[faceIdx][posScvLocalDofIdx] += wijk[localDir]; + } + } + } + else + { + // we require the matrices A,B,C to have the correct size already + assert(A.rows() == iv.numUnknowns() && A.cols() == iv.numUnknowns() && "Matrix A does not have the correct size"); + assert(B.rows() == iv.numUnknowns() && B.cols() == iv.numKnowns() && "Matrix B does not have the correct size"); + assert(C.rows() == iv.numFaces() && C.cols() == iv.numKnowns() && "Matrix C does not have the correct size"); + + // reset matrices + A = 0.0; + B = 0.0; + C = 0.0; + D = 0.0; + + auto& wijk = iv.omegas(); + for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx) + { + const auto& curLocalScvf = iv.localScvf(faceIdx); + const auto& curGlobalScvf = this->fvGeometry().scvf(curLocalScvf.globalScvfIndex()); + const auto curIsDirichlet = curLocalScvf.isDirichlet(); + const auto curLocalDofIdx = curLocalScvf.localDofIndex(); + + // get tensor in "positive" sub volume + const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices(); + const auto& posLocalScv = iv.localScv(neighborScvIndices[0]); + const auto& posGlobalScv = this->fvGeometry().scv(posLocalScv.globalScvIndex()); + const auto& posVolVars = this->elemVolVars()[posGlobalScv]; + const auto& posElement = iv.element(neighborScvIndices[0]); + const auto tensor = getTensor(this->problem(), posElement, posVolVars, this->fvGeometry(), posGlobalScv); + + // the omega factors of the "positive" sub volume + wijk[faceIdx][0] = computeMpfaTransmissibility(posLocalScv, curGlobalScvf, tensor, posVolVars.extrusionFactor()); + + // go over the coordinate directions in the positive sub volume + for (unsigned int localDir = 0; localDir < dim; localDir++) + { + const auto& otherLocalScvf = iv.localScvf( posLocalScv.scvfIdxLocal(localDir) ); + const auto otherLocalDofIdx = otherLocalScvf.localDofIndex(); + + // if we are not on a Dirichlet face, add entries associated with unknown face pressures + // i.e. in matrix C and maybe A (if current face is not a Dirichlet face) + if (!otherLocalScvf.isDirichlet()) + { + C[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir]; + if (!curIsDirichlet) + A[curLocalDofIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir]; + } + // the current face is a Dirichlet face and creates entries in D & maybe B + else + { + D[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir]; + if (!curIsDirichlet) + B[curLocalDofIdx][otherLocalDofIdx] += wijk[faceIdx][0][localDir]; + } + + // add entries related to pressures at the scv centers (dofs) + const auto posScvLocalDofIdx = posLocalScv.localDofIndex(); + D[faceIdx][posScvLocalDofIdx] += wijk[faceIdx][0][localDir]; + + if (!curIsDirichlet) + B[curLocalDofIdx][posScvLocalDofIdx] -= wijk[faceIdx][0][localDir]; + } + + // If we are on an interior face, add values from negative sub volume + if (!curGlobalScvf.boundary()) + { + // loop over all the outside neighbors of this face and add entries + for (unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside) + { + const auto idxOnScvf = idxInOutside+1; + const auto& negLocalScv = iv.localScv( neighborScvIndices[idxOnScvf] ); + const auto& negGlobalScv = this->fvGeometry().scv(negLocalScv.globalScvIndex()); + const auto& negVolVars = this->elemVolVars()[negGlobalScv]; + const auto& negElement = iv.element( neighborScvIndices[idxOnScvf] ); + const auto negTensor = getTensor(this->problem(), negElement, negVolVars, this->fvGeometry(), negGlobalScv); + + // On surface grids, use outside face for "negative" transmissibility calculation + const auto& scvf = dim < dimWorld ? this->fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside) + : curGlobalScvf; + wijk[faceIdx][idxOnScvf] = computeMpfaTransmissibility(negLocalScv, scvf, negTensor, negVolVars.extrusionFactor()); + + // flip sign on surface grids (since we used the "outside" normal) + if (dim < dimWorld) + wijk[faceIdx][idxOnScvf] *= -1.0; + + // go over the coordinate directions in the positive sub volume + for (int localDir = 0; localDir < dim; localDir++) + { + const auto otherLocalScvfIdx = negLocalScv.scvfIdxLocal(localDir); + const auto& otherLocalScvf = iv.localScvf(otherLocalScvfIdx); + const auto otherLocalDofIdx = otherLocalScvf.localDofIndex(); + + if (!otherLocalScvf.isDirichlet()) + A[curLocalDofIdx][otherLocalDofIdx] += wijk[faceIdx][idxOnScvf][localDir]; + else + B[curLocalDofIdx][otherLocalDofIdx] -= wijk[faceIdx][idxOnScvf][localDir]; + + // add entries to matrix B + B[curLocalDofIdx][negLocalScv.localDofIndex()] += wijk[faceIdx][idxOnScvf][localDir]; + } + } + } + } + } + } +}; + +} // end namespace + +#endif diff --git a/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh b/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh index 4336c1017b798cf9da41f26f7a378a841305ca88..a0553b3ef78ef7afca0b5bd1b52a081cf7510c15 100644 --- a/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh +++ b/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh @@ -18,50 +18,67 @@ *****************************************************************************/ /*! * \file - * \brief Base class for sub control entities of the mpfa-o method. + * \ingroup CCMpfaDiscretization + * \brief Classes for sub control entities of the mpfa-o method. */ -#ifndef DUMUX_DISCRETIZATION_CC_MPFA_O_LOCALSUBCONTROLENTITIES_HH -#define DUMUX_DISCRETIZATION_CC_MPFA_O_LOCALSUBCONTROLENTITIES_HH +#ifndef DUMUX_DISCRETIZATION_CC_MPFA_O_LOCAL_SUBCONTROLENTITIES_HH +#define DUMUX_DISCRETIZATION_CC_MPFA_O_LOCAL_SUBCONTROLENTITIES_HH #include <dune/common/fvector.hh> #include <dumux/common/properties.hh> namespace Dumux { -template<class TypeTag, class IvIndexSet> + +/*! + * \ingroup CCMpfaDiscretization + * \brief Class for the interaction volume-local sub-control volume used + * in the mpfa-o scheme. + * + * \tparam IvIndexSet The type used for index sets within interaction volumes + * \tparam GC The type used for global coordinates + * \tparam dim The dimensionality of the grid + */ +template< class IvIndexSet, class GC, int dim > class CCMpfaOInteractionVolumeLocalScv { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using GlobalIndexType = typename GridView::IndexSet::IndexType; - using Helper = typename GET_PROP_TYPE(TypeTag, MpfaHelper); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry); - using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume); - - //! The mpfa-o method always uses the dynamic types - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using LocalIndexType = typename InteractionVolume::Traits::LocalIndexType; - using LocalBasis = typename InteractionVolume::Traits::ScvBasis; - - static const int dim = GridView::dimension; - static const int dimWorld = GridView::dimensionworld; - using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>; public: - explicit CCMpfaOInteractionVolumeLocalScv(const FVElementGeometry& fvGeometry, - const SubControlVolume& scv, - const LocalIndexType localIndex, - const IvIndexSet& indexSet) - : indexSet_(indexSet) - , globalScvIndex_(scv.dofIndex()) - , localDofIndex_(localIndex) + // export some types + using GridIndexType = typename IvIndexSet::GridIndexType; + using LocalIndexType = typename IvIndexSet::LocalIndexType; + using GlobalCoordinate = GC; + using ctype = typename GlobalCoordinate::value_type; + using LocalBasis = std::array< GlobalCoordinate, dim >; + + static constexpr int myDimension = dim; + static constexpr int worldDimension = GlobalCoordinate::dimension; + + /*! + * \brief The constructor + * + * \param helper Helper class for mpfa schemes + * \param fvGeometry The element finite volume geometry + * \param scv The grid sub-control volume + * \param localIndex The iv-local index of this scvIdx + * \param indexSet The interaction volume index set + */ + template<class MpfaHelper, class FVElementGeometry, class SubControlVolume> + CCMpfaOInteractionVolumeLocalScv(const MpfaHelper& helper, + const FVElementGeometry& fvGeometry, + const SubControlVolume& scv, + const LocalIndexType localIndex, + const IvIndexSet& indexSet) + : indexSet_(indexSet) + , globalScvIndex_(scv.dofIndex()) + , localDofIndex_(localIndex) { // center of the global scv - const auto center = scv.center(); + const auto& center = scv.center(); // set up local basis LocalBasis localBasis; - for (unsigned int coordIdx = 0; coordIdx < dim; ++coordIdx) + for (unsigned int coordIdx = 0; coordIdx < myDimension; ++coordIdx) { const auto scvfIdx = indexSet.nodalIndexSet().scvfIdxGlobal(localDofIndex_, coordIdx); const auto& scvf = fvGeometry.scvf(scvfIdx); @@ -69,67 +86,83 @@ public: localBasis[coordIdx] -= center; } - innerNormals_ = Helper::calculateInnerNormals(localBasis); - detX_ = Helper::calculateDetX(localBasis); + nus_ = helper.calculateInnerNormals(localBasis); + detX_ = helper.calculateDetX(localBasis); } //! detX is needed for setting up the omegas in the interaction volumes - Scalar detX() const { return detX_; } - - //! the inner normals are needed for setting up the omegas in the interaction volumes - const GlobalPosition& innerNormal(const LocalIndexType coordDir) const - { - assert(coordDir < dim); - return innerNormals_[coordDir]; - } + ctype detX() const { return detX_; } //! grid view-global index related to this scv - GlobalIndexType globalScvIndex() const { return globalScvIndex_; } + GridIndexType globalScvIndex() const { return globalScvIndex_; } //! returns the index in the set of cell unknowns of the iv LocalIndexType localDofIndex() const { return localDofIndex_; } //! iv-local index of the coordir's scvf in this scv - LocalIndexType scvfIdxLocal(const unsigned int coordDir) const + LocalIndexType scvfIdxLocal(unsigned int coordDir) const { - assert(coordDir < dim); + assert(coordDir < myDimension); return indexSet_.scvfIdxLocal(localDofIndex_, coordDir); } + //! the nu vectors are needed for setting up the omegas of the iv + const GlobalCoordinate& nu(unsigned int coordDir) const + { + assert(coordDir < myDimension); + return nus_[coordDir]; + } + private: const IvIndexSet& indexSet_; - GlobalIndexType globalScvIndex_; + GridIndexType globalScvIndex_; LocalIndexType localDofIndex_; - LocalBasis innerNormals_; - Scalar detX_; + LocalBasis nus_; + ctype detX_; }; - -template<class TypeTag> +/*! + * \ingroup CCMpfaDiscretization + * \brief Class for the interaction volume-local sub-control volume face + * used in the mpfa-o scheme. + * + * \tparam IvIndexSet The type used for index sets within interaction volumes + */ +template< class IvIndexSet > struct CCMpfaOInteractionVolumeLocalScvf { - using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace); - - //! The mpfa-o method always uses the dynamic types - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using GlobalIndexType = typename GridView::IndexSet::IndexType; - using InteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume); - using LocalIndexContainer = typename InteractionVolume::Traits::DynamicLocalIndexContainer; - using LocalIndexType = typename LocalIndexContainer::value_type; + using LocalIndexContainer = typename IvIndexSet::LocalIndexContainer; public: + // export index types + using GridIndexType = typename IvIndexSet::GridIndexType; + using LocalIndexType = typename IvIndexSet::LocalIndexType; + + /*! + * \brief The constructor + * + * \param scvf The grid sub-control volume face + * \param localScvIndices The iv-local neighboring scv indices + * \param localDofIdx This scvf's interaction volume-local dof index + * \param isDirichlet Specifies if this scv is on a Dirichlet boundary + */ + template< class SubControlVolumeFace > CCMpfaOInteractionVolumeLocalScvf(const SubControlVolumeFace& scvf, const LocalIndexContainer& localScvIndices, - const bool isDirichlet, - const LocalIndexType localDofIdx) - : scvfIdxGlobal_(scvf.index()) - , neighborScvIndicesLocal_(localScvIndices) - , isDirichlet_(isDirichlet) + const LocalIndexType localDofIdx, + const bool isDirichlet) + : isDirichlet_(isDirichlet) + , scvfIdxGlobal_(scvf.index()) , localDofIndex_(localDofIdx) + , neighborScvIndicesLocal_(localScvIndices) {} + //! This is either the iv-local index of the intermediate unknown (interior/Neumann face) + //! or the index of the Dirichlet boundary within the vol vars (Dirichlet faces) + LocalIndexType localDofIndex() const { return localDofIndex_; } + //! returns the grid view-global index of this scvf - GlobalIndexType globalScvfIndex() const { return scvfIdxGlobal_; } + GridIndexType globalScvfIndex() const { return scvfIdxGlobal_; } //! Returns the local indices of the scvs neighboring this scvf const LocalIndexContainer& neighboringLocalScvIndices() const { return neighborScvIndicesLocal_; } @@ -137,17 +170,13 @@ public: //! states if this is scvf is on a Dirichlet boundary bool isDirichlet() const { return isDirichlet_; } - //! This is either the iv-local index of the intermediate unknown (interior/Neumann face) - //! or the index of the Dirichlet boundary within the vol vars (Dirichlet faces) - LocalIndexType localDofIndex() const { return localDofIndex_; } - private: - GlobalIndexType scvfIdxGlobal_; - const LocalIndexContainer& neighborScvIndicesLocal_; - bool isDirichlet_; + GridIndexType scvfIdxGlobal_; LocalIndexType localDofIndex_; + const LocalIndexContainer& neighborScvIndicesLocal_; }; -} // end namespace + +} // end namespace Dumux #endif diff --git a/dumux/discretization/cellcentered/mpfa/properties.hh b/dumux/discretization/cellcentered/mpfa/properties.hh index 78f21d0b7a378efa509191c803e67b2715649801..f306b74653c3fce598c07726c7bf08cd074f55e6 100644 --- a/dumux/discretization/cellcentered/mpfa/properties.hh +++ b/dumux/discretization/cellcentered/mpfa/properties.hh @@ -17,13 +17,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * *****************************************************************************/ /*! - * \ingroup Properties * \file - * - * \brief Defines a type tag and some properties for models using - * a cell-centered scheme with multi-point flux approximation. + * \ingroup CCMpfaDiscretization + * \brief Properties for all models using cell-centered finite volume scheme with mpfa + * \note Inherit from these properties to use a cell-centered finite volume scheme with mpfa */ - #ifndef DUMUX_CC_MPFA_PROPERTIES_HH #define DUMUX_CC_MPFA_PROPERTIES_HH diff --git a/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh b/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh index 9830e8991de30d28f037fd15c10658f834d15cf2..7698ff82cd72ffccca1613eaa5398840ebb3981b 100644 --- a/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh +++ b/dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh @@ -18,7 +18,8 @@ *****************************************************************************/ /*! * \file - * \brief Class for the sub-control volume face in mpfa schemes + * \ingroup CCMpfaDiscretization + * \brief The sub control volume face */ #ifndef DUMUX_DISCRETIZATION_CC_MPFA_SUBCONTROLVOLUMEFACE_HH #define DUMUX_DISCRETIZATION_CC_MPFA_SUBCONTROLVOLUMEFACE_HH @@ -26,13 +27,14 @@ #include <vector> #include <dune/common/version.hh> #include <dune/geometry/type.hh> + #include "methods.hh" namespace Dumux { /*! - * \ingroup Mpfa + * \ingroup CCMpfaDiscretization * \brief Default implementation of the class for a sub-control volume face in mpfa methods. */ template<class ScvfGeometryTraits> @@ -51,7 +53,7 @@ public: /*! * \brief Constructor * - * \param geomHelper The mpfa geometry helper + * \param helper The helper class for mpfa schemes * \param corners The corners of the scv face * \param unitOuterNormal The unit outer normal vector of the scvf * \param vIdxGlobal The global vertex index the scvf is connected to @@ -63,35 +65,35 @@ public: * \param boundary Boolean to specify whether or not the scvf is on a boundary */ template<class MpfaHelper> - explicit CCMpfaDefaultSubControlVolumeFace(const MpfaHelper& helper, - CornerStorage&& corners, - GlobalPosition&& unitOuterNormal, - GridIndexType vIdxGlobal, - unsigned int vIdxLocal, - GridIndexType scvfIndex, - GridIndexType insideScvIdx, - const std::vector<GridIndexType>& outsideScvIndices, - Scalar q, - bool boundary) - : boundary_(boundary), - vertexIndex_(vIdxGlobal), - scvfIndex_(scvfIndex), - insideScvIdx_(insideScvIdx), - outsideScvIndices_(outsideScvIndices), - vIdxInElement_(vIdxLocal), - corners_(std::move(corners)), - center_(0.0), - unitOuterNormal_(std::move(unitOuterNormal)) - { - // compute the center of the scvf - for (const auto& corner : corners_) - center_ += corner; - center_ /= corners_.size(); - - // use helper class to obtain area & integration point - ipGlobal_ = helper.getScvfIntegrationPoint(corners_, q); - area_ = helper.getScvfArea(corners_); - } + CCMpfaDefaultSubControlVolumeFace(const MpfaHelper& helper, + CornerStorage&& corners, + GlobalPosition&& unitOuterNormal, + GridIndexType vIdxGlobal, + unsigned int vIdxLocal, + GridIndexType scvfIndex, + GridIndexType insideScvIdx, + const std::vector<GridIndexType>& outsideScvIndices, + Scalar q, + bool boundary) + : boundary_(boundary) + , vertexIndex_(vIdxGlobal) + , scvfIndex_(scvfIndex) + , insideScvIdx_(insideScvIdx) + , outsideScvIndices_(outsideScvIndices) + , vIdxInElement_(vIdxLocal) + , corners_(std::move(corners)) + , center_(0.0) + , unitOuterNormal_(std::move(unitOuterNormal)) + { + // compute the center of the scvf + for (const auto& corner : corners_) + center_ += corner; + center_ /= corners_.size(); + + // use helper class to obtain area & integration point + ipGlobal_ = helper.getScvfIntegrationPoint(corners_, q); + area_ = helper.getScvfArea(corners_); + } //! The area of the sub control volume face Scalar area() const { return area_; } @@ -169,7 +171,7 @@ private: }; /*! - * \ingroup Mpfa + * \ingroup CCMpfaDiscretization * \brief Class for a sub control volume face in mpfa methods, i.e a part of the boundary * of a control volume we compute fluxes on. Per default, we use the default * implementation of the mpfa scvf class. If a scheme requires a different implementation, diff --git a/dumux/discretization/cellcentered/mpfa/tensorlambdafactory.hh b/dumux/discretization/cellcentered/mpfa/tensorlambdafactory.hh index 30a39cbf6d1881cdf3e32652e6b76b55c020a278..ddbef9b1e5ce5c0478d9da78a6fe98fa3a00f9e9 100644 --- a/dumux/discretization/cellcentered/mpfa/tensorlambdafactory.hh +++ b/dumux/discretization/cellcentered/mpfa/tensorlambdafactory.hh @@ -18,6 +18,7 @@ *****************************************************************************/ /*! * \file + * \ingroup CCMpfaDiscretization * \brief Helper class to be used to obtain lambda functions for the tensors * involved in the laws that describe the different kind of fluxes that * occur in DuMuX models (i.e. advective, diffusive and heat conduction fluxes). @@ -30,6 +31,7 @@ #define DUMUX_DISCRETIZATION_MPFA_TENSOR_LAMBDA_FACTORY_HH #include <dumux/common/properties.hh> + #include <dumux/discretization/methods.hh> #include <dumux/discretization/cellcentered/mpfa/tensorlambdafactory.hh> @@ -37,7 +39,7 @@ namespace Dumux { /*! - * \ingroup MpfaModel + * \ingroup CCMpfaDiscretization * \brief Helper class to be used to obtain lambda functions for the tensors * involved in the laws that describe the different kind of fluxes that * occur in DuMuX models (i.e. advective, diffusive and heat conduction fluxes). @@ -55,8 +57,9 @@ public: //! We return zero scalars here in the functions below. //! We have to return something as the local systems expect a type - //! to perform actions on. We return 0.0 as this call should never happen - //! for a tensor which is not treated by an mpfa method anyway. + //! to perform actions on, thus a compiler error will occur. + //! We return 0.0 as this call should never happen for a tensor + //! which is not treated by an mpfa method anyway. //! lambda for the law describing the advective term static auto getAdvectionLambda() diff --git a/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh b/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh index 54a1e9433b13f56bb687b982eab475fcc6449569..03c99d3a6bacdfc531e8fcf93ad6d78664be603e 100644 --- a/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh +++ b/dumux/porousmediumflow/1p/incompressiblelocalresidual.hh @@ -124,7 +124,7 @@ public: "1p/incompressiblelocalresidual.hh: Only fluids with constant viscosities are allowed!"); const auto& fluxVarsCache = elemFluxVarsCache[scvf]; - const auto& volVarIndices = fluxVarsCache.advectionVolVarsStencil(); + const auto& volVarIndices = fluxVarsCache.advectionStencil(); const auto& tij = fluxVarsCache.advectionTij(); // we know the "upwind factor" is constant, get inner one here and compute derivatives @@ -211,7 +211,7 @@ public: const SubControlVolumeFace& scvf) const { const auto& fluxVarsCache = elemFluxVarsCache[scvf]; - const auto& volVarIndices = fluxVarsCache.advectionVolVarsStencil(); + const auto& volVarIndices = fluxVarsCache.advectionStencil(); const auto& tij = fluxVarsCache.advectionTij(); // we know the "upwind factor" is constant, get inner one here and compute derivatives diff --git a/test/porousmediumflow/2p/implicit/fracture/CMakeLists.txt b/test/porousmediumflow/2p/implicit/fracture/CMakeLists.txt index b10e576cc912d62dccd589081672d8f1eb8b762e..96b59da1c1d89156d3b31343eee4a7d7cd16f802 100644 --- a/test/porousmediumflow/2p/implicit/fracture/CMakeLists.txt +++ b/test/porousmediumflow/2p/implicit/fracture/CMakeLists.txt @@ -48,9 +48,19 @@ dune_add_test(NAME test_2p_fracture_gravity_tpfa COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py CMD_ARGS --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/fracturecc2p_gravity-reference.vtu - ${CMAKE_CURRENT_BINARY_DIR}/fracturetpfa_gravity-00043.vtu + ${CMAKE_CURRENT_BINARY_DIR}/fracturetpfa_gravity-00042.vtu --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p_fracture_tpfa test_fracture.input -Problem.Name fracturetpfa_gravity -Problem.EnableGravity true") +dune_add_test(NAME test_2p_fracture_gravity_mpfa + SOURCES test_2p_fracture_fv.cc + CMAKE_GUARD dune-foamgrid_FOUND + COMPILE_DEFINITIONS TYPETAG=FractureCCMpfaTypeTag + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/fractureccmpfa2p_gravity-reference.vtu + ${CMAKE_CURRENT_BINARY_DIR}/fracturempfa_gravity-00042.vtu + --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p_fracture_mpfa test_fracture.input -Problem.Name fracturempfa_gravity -Problem.EnableGravity true") + set(CMAKE_BUILD_TYPE Release) #install sources diff --git a/test/references/fractureccmpfa2p_gravity-reference.vtu b/test/references/fractureccmpfa2p_gravity-reference.vtu new file mode 100644 index 0000000000000000000000000000000000000000..d4f3b873637076d32b542156bf45e7465dfa1c01 --- /dev/null +++ b/test/references/fractureccmpfa2p_gravity-reference.vtu @@ -0,0 +1,2509 @@ +<?xml version="1.0"?> +<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian"> + <UnstructuredGrid> + <Piece NumberOfCells="1670" NumberOfPoints="911"> + <CellData Scalars="Sw"> + <DataArray type="Float32" Name="Sw" NumberOfComponents="1" format="ascii"> + 1 0.0672208 0.0638164 0.122357 1 0.0765743 0.854272 1 0.997466 1 0.988668 1 + 0.998907 1 0.959554 1 1 0.980262 0.990862 1 1 0.94712 1 1 + 0.993477 1 0.661789 1 1 0.72274 1 1 0.064893 0.754 1 0.068929 + 1 0.893124 1 1 0.997629 0.998855 0.998294 0.998928 1 0.998887 0.963757 1 + 0.837646 1 0.0830117 1 1 0.0639912 1 0.177691 0.765775 1 0.0665333 1 + 0.999145 1 1 0.0687718 0.729163 0.0790799 1 0.225244 1 1 1 0.124935 + 0.882395 0.99984 1 0.995172 0.995744 1 1 0.174087 0.998859 0.930591 1 1 + 0.962358 0.995532 1 1 0.689055 1 1 0.0636639 1 0.676169 1 1 + 0.0669959 0.999613 0.102051 0.809216 1 0.0758747 1 1 1 0.926585 0.603942 1 + 0.0801846 0.347749 0.998829 0.0635939 0.0769958 0.874236 1 0.794812 1 0.0676663 1 1 + 1 0.078656 0.801497 0.0670232 0.0712062 0.399739 1 0.863665 1 0.0833881 0.998361 0.135874 + 1 0.993639 0.993844 0.98968 0.992521 1 1 1 1 1 0.159153 1 + 0.123357 0.887161 0.869118 1 1 1 1 0.0913216 1 1 0.0710833 0.841124 + 1 0.0663357 0.771308 0.0702213 1 0.681224 0.458612 0.111149 0.962808 0.966569 0.851976 1 + 0.96 0.954411 1 0.279761 1 0.998142 1 0.999063 0.849689 1 0.0715921 0.0980733 + 1 0.996754 0.148909 0.919095 0.998881 1 1 0.347016 1 1 1 1 + 1 0.99914 1 0.998797 1 0.392442 0.999454 0.994374 0.995686 0.988934 0.945732 0.945325 + 0.649731 0.109925 0.0710846 1 0.0760194 1 0.528589 0.178373 0.923121 0.997541 0.999973 1 + 1 1 0.0659423 0.0702147 1 1 0.757051 0.688665 0.868293 1 0.0629099 1 + 0.598709 0.722674 1 0.0640038 1 1 0.455096 1 0.999154 0.998742 1 0.0786612 + 1 0.803224 0.281651 0.999997 0.999836 0.999986 1 1 1 1 1 1 + 0.113432 1 1 1 1 1 1 1 0.299657 0.396906 1 0.853256 + 0.835492 1 1 1 1 1 1 1 1 0.663802 1 1 + 1 1 1 0.513371 1 1 1 1 1 1 1 1 + 0.0959253 1 1 1 1 1 1 1 1 1 0.817895 1 + 0.877728 1 0.153552 1 1 1 1 1 1 0.987304 1 1 + 1 1 1 1 1 1 1 1 1 1 1 0.562844 + 1 1 1 1 1 1 1 0.758315 1 1 1 1 + 1 1 0.733568 1 1 1 1 1 1 1 1 1 + 1 1 1 0.653696 0.999625 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 0.529632 1 1 1 1 1 1 1 1 1 + 1 1 1 0.843711 0.104642 1 1 0.159938 1 1 1 1 + 1 1 1 1 0.998269 1 1 1 1 1 1 0.99883 + 1 0.999209 1 1 1 1 0.998447 1 1 1 1 1 + 0.999638 1 0.313272 1 1 1 1 1 1 1 1 1 + 0.898042 1 1 1 1 1 1 1 0.999869 1 1 0.700727 + 1 1 1 1 1 1 1 0.213927 1 1 0.999134 1 + 1 1 1 1 1 1 1 1 1 1 0.856422 1 + 1 1 1 1 1 1 0.99926 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 0.698868 + 0.998334 1 1 0.999276 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 0.314252 0.999483 1 + 1 1 0.994225 1 1 1 0.755165 0.874668 1 0.64316 1 1 + 0.988009 1 1 1 1 1 0.932431 0.54237 1 1 1 1 + 1 0.999617 1 1 1 1 1 1 0.351012 1 1 0.999703 + 0.877684 1 1 0.161462 1 1 1 1 1 1 1 1 + 1 1 1 0.727756 1 1 1 0.94046 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 0.918029 0.994808 + 1 0.731928 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 0.869824 1 1 1 1 1 + 0.924278 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 0.708323 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 0.843294 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 0.963568 0.99955 1 0.763766 1 1 1 1 1 1 0.268643 0.76975 + 0.821971 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 0.387654 1 1 1 + 1 1 1 1 1 0.993558 1 1 1 1 1 1 + 0.987563 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 0.998951 1 0.98756 1 1 1 1 + 0.976013 1 0.838929 1 1 0.127159 1 1 1 1 1 1 + 1 1 1 0.848603 1 1 1 1 1 1 1 1 + 1 1 1 0.977226 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 0.0925661 1 1 + 1 0.417534 0.14388 1 1 1 1 0.998814 1 1 1 1 + 1 1 1 1 1 1 1 1 1 0.564628 1 1 + 1 1 1 0.694764 1 1 1 1 1 1 1 1 + 0.705063 1 1 1 0.935998 1 1 1 1 1 1 0.207973 + 1 1 1 1 1 1 1 1 0.751493 1 0.998894 1 + 1 0.165601 1 1 1 1 1 1 1 0.244635 1 1 + 1 1 1 1 0.631634 1 0.480641 1 1 1 1 1 + 1 1 1 1 0.501756 1 1 1 1 1 1 1 + 1 0.693714 1 1 1 1 1 1 1 1 1 1 + 1 1 0.601261 0.996232 1 0.247665 1 1 0.974563 1 1 1 + 1 1 1 1 0.996662 1 1 1 1 1 1 1 + 0.915477 1 0.830286 1 1 1 1 0.993411 0.665256 0.751471 0.982532 1 + 0.856313 1 0.980538 1 1 1 1 1 0.967118 1 1 1 + 1 1 0.0961835 1 1 0.142693 1 1 1 1 1 1 + 1 1 0.8035 1 1 0.999193 0.995903 1 0.949807 1 0.351955 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 0.132233 0.825137 0.936947 1 1 1 1 + 1 0.47059 1 0.864604 0.936807 1 1 1 1 1 1 1 + 1 1 1 1 1 0.932534 1 1 1 1 0.938532 0.84897 + 1 1 0.9243 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 0.91384 0.599845 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 0.704099 1 1 1 1 1 + 1 1 1 1 1 0.773462 1 1 1 1 1 1 + 1 1 1 0.921237 1 1 1 1 1 1 0.99594 1 + 1 0.411018 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 0.998351 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 0.780205 0.779609 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 0.998136 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 0.814144 1 1 1 1 1 1 1 1 1 1 + 1 0.99987 1 1 1 1 1 1 1 0.988955 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 0.638798 1 0.628824 0.99888 0.995877 1 0.582259 0.99746 1 1 1 + 1 1 1 1 1 1 1 1 1 0.299324 0.662126 0.998857 + 0.836557 1 0.990577 1 1 1 1 1 0.998222 1 1 1 + 1 1 1 1 1 0.84676 1 1 1 1 1 1 + 1 1 1 1 1 0.99898 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 0.873685 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 0.933719 1 1 1 1 0.72563 0.99736 + 1 0.513852 1 0.355747 1 1 1 1 1 1 1 1 + 0.969165 1 1 1 1 1 1 1 1 0.537518 0.900376 1 + 1 0.954865 0.461344 1 0.882943 1 1 1 1 1 1 0.808935 + 1 1 1 1 1 0.99805 0.72527 0.999506 1 1 1 0.929041 + 0.208678 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 0.16053 + 0.0960418 1 1 0.236566 1 0.581672 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 0.141047 1 1 1 0.240044 1 1 1 1 1 1 + 1 1 1 1 1 1 1 0.870902 1 1 1 1 + 1 0.109737 1 0.17461 1 1 1 1 1 1 1 0.293317 + 1 0.998425 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 0.129142 1 1 1 1 1 1 1 0.178213 1 0.360428 1 + 1 1 1 1 1 1 0.99894 1 1 1 0.953009 1 + 1 0.0940025 1 0.171302 1 1 1 1 1 0.978376 0.841421 1 + 1 0.158044 1 0.433101 1 0.999106 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 0.99887 1 1 1 + 1 1 1 1 0.79158 1 1 1 0.931673 0.186903 1 1 + 1 0.296002 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 0.818487 1 0.993392 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 + 1 0.987163 0.789565 1 1 0.994211 1 1 1 1 1 1 + 0.876594 1 0.222081 1 1 1 0.104207 1 0.127278 1 1 1 + 1 1 1 1 1 1 1 1 0.995225 1 1 1 + 1 1 + </DataArray> + <DataArray type="Float32" Name="Sn" NumberOfComponents="1" format="ascii"> + 1.60741e-07 0.932779 0.936184 0.877643 0 0.923426 0.145728 0 0.00253412 2.82389e-11 0.0113316 0 + 0.00109323 0 0.040446 0 0 0.0197377 0.00913841 0 0 0.0528803 0 4.80583e-38 + 0.0065235 0 0.338211 0 2.0661e-10 0.27726 0 0 0.935107 0.246 0 0.931071 + 0 0.106876 5.02327e-16 0 0.00237078 0.00114534 0.001706 0.00107204 4.10318e-17 0.00111309 0.0362433 9.87043e-08 + 0.162354 0 0.916988 0 0 0.936009 0 0.822308 0.234225 0 0.933467 0 + 0.000854694 0 0 0.931228 0.270837 0.92092 0 0.774756 0 0 0 0.875065 + 0.117605 0.000159832 0 0.00482804 0.00425639 3.35818e-28 0 0.825913 0.00114145 0.0694093 0 2.02091e-32 + 0.0376421 0.0044682 0 0 0.310945 0 0 0.936336 0 0.323831 0 0 + 0.933004 0.000387421 0.897949 0.190784 0 0.924125 0 0 0 0.073415 0.396058 0 + 0.919815 0.652251 0.00117068 0.936406 0.923004 0.125764 0 0.205188 0 0.932334 0 0 + 0 0.921344 0.198503 0.932977 0.928794 0.600261 0 0.136335 0 0.916612 0.00163864 0.864126 + 0 0.00636117 0.00615593 0.0103195 0.00747905 0 -8.28494e-25 0 0 0 0.840847 0 + 0.876643 0.112839 0.130882 0 0 0 0 0.908678 0 0 0.928917 0.158876 + 0 0.933664 0.228692 0.929779 0 0.318776 0.541388 0.888851 0.0371921 0.0334306 0.148024 0 + 0.0399997 0.0455888 0 0.720239 0 0.0018577 0 0.000937295 0.150311 0 0.928408 0.901927 + 0 0.00324625 0.851091 0.0809052 0.00111922 0 0 0.652984 0 0 0 0 + -2.55203e-24 0.000859753 7.6925e-28 0.00120276 0 0.607558 0.000546176 0.0056264 0.00431392 0.0110663 0.0542682 0.0546753 + 0.350269 0.890075 0.928915 0 0.923981 0 0.471411 0.821627 0.0768786 0.0024588 2.73474e-05 0 + 0 0 0.934058 0.929785 0 0 0.242949 0.311335 0.131707 0 0.93709 0 + 0.401291 0.277326 0 0.935996 0 0 0.544904 0 0.000845691 0.00125779 0 0.921339 + 0 0.196776 0.718349 3.38052e-06 0.000164216 1.42688e-05 0 0 0 0 0 0 + 0.886568 0 0 0 0 0 0 0 0.700343 0.603094 0 0.146744 + 0.164508 0 0 0 0 0 0 0 0 0.336198 0 0 + 0 0 0 0.486629 0 0 0 0 0 0 0 0 + 0.904075 0 0 0 0 0 0 0 0 0 0.182105 0 + 0.122272 0 0.846448 0 0 0 0 0 0 0.0126961 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0.437156 + 0 0 0 0 0 0 0 0.241685 0 0 0 0 + 0 0 0.266432 0 0 0 0 0 0 0 0 0 + 0 0 0 0.346304 0.000374582 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0.470368 0 0 0 0 0 0 0 0 0 + 0 0 0 0.156289 0.895358 0 0 0.840062 0 0 0 0 + 0 0 0 0 0.00173103 0 0 0 0 0 0 0.00116994 + 0 0.000790899 0 0 0 0 0.00155295 0 0 0 0 0 + 0.000361537 0 0.686728 0 0 0 0 0 0 0 0 0 + 0.101958 0 0 0 0 0 0 0 0.000131486 0 0 0.299273 + 0 0 0 0 0 0 0 0.786073 0 0 0.000865839 0 + 0 0 0 0 0 0 0 0 0 0 0.143578 0 + 0 0 0 0 0 0 0.000740086 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0.301132 + 0.00166596 0 0 0.000723869 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0.685748 0.000516607 0 + 0 0 0.00577547 0 0 0 0.244835 0.125332 0 0.35684 0 0 + 0.0119907 0 0 0 0 0 0.0675691 0.45763 0 0 0 0 + 0 0.000383234 0 0 0 0 0 0 0.648988 0 0 0.000296549 + 0.122316 0 0 0.838538 0 0 0 0 0 0 0 0 + 0 0 0 0.272244 0 0 0 0.0595397 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0.0819705 0.00519175 + 0 0.268072 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0.130176 0 0 0 0 0 + 0.0757218 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0.291677 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0.156706 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0364317 0.000449953 0 0.236234 0 0 0 0 0 0 0.731357 0.23025 + 0.178029 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0.612346 0 0 0 + 0 0 0 0 0 0.00644153 0 0 0 0 0 0 + 0.0124369 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0.00104948 0 0.0124395 0 0 0 0 + 0.0239866 0 0.161071 0 0 0.872841 0 0 0 0 0 0 + 0 0 0 0.151397 0 0 0 0 0 0 0 0 + 0 0 0 0.0227742 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0.907434 0 0 + 0 0.582466 0.85612 0 0 0 0 0.00118642 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0.435372 0 0 + 0 0 0 0.305236 0 0 0 0 0 0 0 0 + 0.294937 0 0 0 0.0640025 0 0 0 0 0 0 0.792027 + 0 0 0 0 0 0 0 0 0.248507 0 0.0011064 0 + 0 0.834399 0 0 0 0 0 0 0 0.755365 0 0 + 0 0 0 0 0.368366 0 0.519359 0 0 0 0 0 + 0 0 0 0 0.498244 0 0 0 0 0 0 0 + 0 0.306286 0 0 0 0 0 0 0 0 0 0 + 0 0 0.398739 0.00376768 0 0.752335 0 0 0.0254373 0 0 0 + 0 0 0 0 0.0033376 0 0 0 0 0 0 0 + 0.0845229 0 0.169714 0 0 0 0 0.00658947 0.334744 0.248529 0.0174676 0 + 0.143687 0 0.0194618 0 0 0 0 0 0.0328819 0 0 0 + 0 0 0.903817 0 0 0.857307 0 0 0 0 0 0 + 0 0 0.1965 0 0 0.000807198 0.00409712 0 0.0501927 0 0.648045 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0.867767 0.174863 0.0630534 0 0 0 0 + 0 0.52941 0 0.135396 0.0631931 0 0 0 0 0 0 0 + 0 0 0 0 0 0.0674658 0 0 0 0 0.061468 0.15103 + 0 0 0.0757001 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.0861597 0.400155 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0.295901 0 0 0 0 0 + 0 0 0 0 0 0.226538 0 0 0 0 0 0 + 0 0 0 0.0787631 0 0 0 0 0 0 0.00405998 0 + 0 0.588982 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0.00164882 0 0 -4.77843e-43 0 + 0 0 0 0 0 0 0 0 0 0 0.219795 0.220391 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0.00186441 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.185856 0 0 0 0 0 0 0 0 0 0 + 0 0.000130128 0 0 0 0 0 0 0 0.0110452 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.361202 0 0.371176 0.00111972 0.00412333 0 0.417741 0.00254021 0 0 0 + 0 0 0 0 0 0 0 0 0 0.700676 0.337874 0.00114282 + 0.163443 0 0.00942316 0 0 0 0 0 0.00177769 0 0 0 + 0 0 0 0 0 0.15324 0 0 0 0 0 0 + 0 0 0 0 0 0.00102043 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.126315 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0.0662806 0 0 0 0 0.27437 0.00263994 + 0 0.486148 0 0.644253 0 0 0 0 0 0 0 0 + 0.0308347 0 0 0 0 0 0 0 0 0.462482 0.0996235 0 + 0 0.045135 0.538656 0 0.117057 0 0 0 0 0 0 0.191065 + 0 0 0 0 0 0.00194972 0.27473 0.00049371 0 0 0 0.0709587 + 0.791322 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0.83947 + 0.903958 0 0 0.763434 0 0.418328 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.858953 0 0 0 0.759956 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0.129098 0 0 0 0 + 0 0.890263 0 0.82539 0 0 0 0 0 0 0 0.706683 + 0 0.0015754 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0.870858 0 0 0 0 0 0 0 0.821787 0 0.639572 0 + 0 0 0 0 0 0 0.00106009 0 0 0 0.046991 0 + 0 0.905997 0 0.828698 0 -0 0 0 0 0.0216241 0.158579 0 + 0 0.841956 0 0.566899 0 0.000893864 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0.00113015 0 0 0 + 0 0 0 0 0.20842 0 0 0 0.068327 0.813097 0 0 + 0 0.703998 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0.181513 0 0.00660822 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.0128368 0.210435 0 0 0.00578931 0 0 0 0 0 0 + 0.123406 0 0.777919 0 0 0 0.895793 0 0.872722 0 0 0 + 0 0 0 0 0 0 0 0 0.00477463 0 0 0 + 0 0 + </DataArray> + <DataArray type="Float32" Name="pw" NumberOfComponents="1" format="ascii"> + 96414.9 100224 100640 99743.7 91012.9 100092 91300.9 91344.6 90974 96337.8 96367.3 95024.3 + 97466.4 93611.9 96217.2 95204.4 93173.8 97912.9 96589.3 92631.8 97070.2 94006.4 93093.9 97289.8 + 93781.7 94028.6 98429.3 92653.5 95662.7 95112.6 91009.8 95085.6 100317 94648.2 94623.1 99984.7 + 91244.8 96185.2 95585.5 93812.1 97966.6 93113.8 96417.3 94622.9 96742.5 94310.8 95772.9 95238.7 + 94522.9 94490.6 99361.1 91740.6 90984.3 100564 97911.3 97964.6 93135.3 93157 100206 90973.3 + 95937 91283.3 95629.2 100024 95668.1 99082.9 93594.1 98936.8 92146.1 92245.3 95576.1 98823.6 + 95664.1 94545 93826.4 94927.1 94455.8 96595.3 92189.6 98149.6 98117.4 92948.2 93609.3 97048.9 + 95191.9 94021.6 94419 94684 96104.5 90926.5 96074.8 100511 94955.1 98308.8 92782.6 91248.9 + 100249 98306.2 98368.2 92742.9 92766.2 99878.3 91234.5 92122.6 97503 93572.6 97531.2 92982.8 + 98993.1 98866.1 92206.8 100694 99006.8 98822.1 90935.7 92216.2 92254.5 100216 90909.1 91815.5 + 95806.8 99312.4 95870.6 100285 99415.6 99162.8 91265.6 91889 91924.9 99830.9 91235.6 98359.1 + 92781.1 98299.5 92771.1 97245.8 97417.7 93647 96113.4 92309.8 95167.6 92102.4 98787.5 94722.4 + 98992.7 95240.2 94765.8 91197.6 91689.7 93843.8 91706.3 99387.8 93656.2 91209.8 99964.1 93852.4 + 97429.6 100257 93651 99617.8 97244.8 97279.7 97473.9 98724.1 97140 96661 97161.2 93175.1 + 97503.1 97889.7 95883.6 98323.2 94126.5 96937.3 94092.6 96963.3 97415.4 91805.5 99498 98464.6 + 92664.6 98412.9 99283 92646.6 91791.8 92512.4 92719.6 98324 96042.8 96506.9 94546.8 94064.9 + 97322.5 93752.1 97510.9 93566.9 93176.2 97993 97905.1 93170.9 95391.5 95868.4 95003.3 94529 + 97964.7 98636.3 99515.3 91818 99103.8 92146.5 98940.1 99269.8 92119.5 91793 94997.7 94563.9 + 91145.6 91639.7 100272 99659.9 96558.3 96695 96727.3 96594.5 96622.4 90875.9 100642 96976.2 + 97019.3 94104.6 94109.3 100392 90885.4 94509.3 98514.1 92575.4 95450.9 95232.3 91952.8 99206.6 + 96389.5 96439.8 98179.9 95908.8 95012.6 95407.8 96221.2 96244.1 93399 93640.9 95795.5 98283.4 + 100069 96059 98114.3 97160.5 95800.1 97603.8 95690.7 92024.5 99682.9 99759 94573.7 96221.2 + 96166.2 94991.4 95129.8 96183.4 92781.6 92560.2 95178.4 94984 95639.4 98758.4 95334.7 93353.5 + 93637.8 95508.8 93206 99400.3 95838.6 93337.2 95349.4 95255.1 93623.3 94617.5 91261 96853.8 + 100094 93513.2 98725 96238.5 96252.7 94246.4 92549.1 95839.4 96370.4 96152.7 95156 93893.5 + 94319.4 96257.2 99768.4 98563.6 95627.7 95278.6 95529.7 97905.9 95200.5 98874.7 97683.4 97369.9 + 92840.4 95872.4 91626.2 92572.8 94421.9 92369 95842.6 95741 95066.4 93073.3 97183.8 99519.4 + 95138.8 91447.9 95850.8 95644.4 94508.2 94158.1 93943.7 98201.2 95905.9 96760.7 93288.4 94041.7 + 96903.6 94715.2 98700.2 98504.1 96344.6 98379 95300.7 95670.8 94121.1 91089 97296.7 95026.1 + 94265.3 95435.4 96129.9 99005.3 97658.2 97291.6 95261.5 93549.5 95513.8 93648.8 95465.2 95350.2 + 95520.3 96008.8 94494.9 91913 96191 98567.9 91958.5 94506.9 95937.9 95570.5 93455.4 97012.3 + 95143.8 95181.2 99448.2 96641.2 96812.8 96665.4 91555.9 91907.2 92981.2 94668.4 98369.7 98234.7 + 92278.8 93845.5 94624.4 96912.5 100099 96697.5 97781.4 99811.9 95386.7 97632 93356.5 98342.8 + 94833.8 96652.8 97393 93857.2 98502.8 96921.9 96028.4 97819.6 95836.3 93131.2 97174.4 98170.6 + 94811.6 92695.2 97615.9 92215.1 97207.9 94272.5 95330.3 95207.4 96153.1 95377.5 93895.7 92424 + 96703 94891.4 99684.8 97416.3 92250.9 93170 94153.6 96064.5 95284.5 92229.3 95342.5 96335.8 + 99183.4 92925 98471.9 95528.9 97421.9 92751.6 95480 93946.2 92240.6 98001.3 95195.4 98220.4 + 94960.4 94025 96113.7 94213.3 95312.1 92635 93701.1 99939.1 93948.3 96496.9 98769 94376.3 + 95710.3 96576.4 93684.6 93205.7 97454.8 95459.5 96015 94844.5 95130.2 91342.5 99180.3 91286.8 + 91843.7 95993.4 95025 91267.5 91831.6 96699.2 98127.2 96967.2 94705.8 92936.5 97920.4 93112.1 + 95299.4 94048.3 95133.2 93984.6 96912.6 90978.3 91303.9 91839.3 92727.7 95382 92869.3 97593.6 + 94519 93653.1 95368.4 93844.6 96602.3 93091.7 94524.2 94920.9 97092.6 93363.9 94229 94539.7 + 94322.1 93379.7 93181.8 93506.6 96663.9 92193.3 94499.6 96660.6 94516.6 99730.2 97655 94554.5 + 94446.1 92047.4 99008.1 92890.7 95122.8 94960.5 97662.7 99258 95404.2 99310.9 94977.4 94658.4 + 98835.8 95556.9 94477 94583.9 94913.7 92751.5 98867.6 99195.8 95017.1 92614.3 96321.7 97712.7 + 94302.7 97185 94888.9 96043.8 94909.5 94038.6 94125.4 95337.8 99731.3 94547 96295.5 97177.2 + 93293.9 97166.7 94105.8 100063 95184.8 94122.9 91527.4 91961.5 94646.1 91202.8 97565.1 91066.5 + 94839.2 93783.9 96420.1 99227.1 94783.4 94418.7 97319.4 92353.1 97999.5 95374.2 96353.9 96968.2 + 93604.7 94989.2 95568.1 98460.5 98209.4 91356.4 91519 94872 98968.2 91191.2 91306.9 98940.4 + 93221.1 99297 95650.9 96058.6 95681.2 95158.1 96653.6 91718.7 96539.4 98088.1 93949.2 94898.5 + 95486.2 92092.3 92152.4 92195 98314.8 97807.6 92498.4 97898 90873.4 97490 96836.9 94194.4 + 99025.8 95275.9 92658 92729.8 94841.1 98020.5 97477.1 94848.2 95496.6 95437.2 95788.2 93638.5 + 92662.3 95275.7 95286.3 98097.9 97720 97181.4 94522 96705.9 96395.1 94494.9 92827.7 95999.7 + 96731.2 95355.2 95313.8 96544 95335 95229.7 95329.8 95286.3 97942.4 97810.3 95416.7 96473.2 + 94942.3 95343 94647.9 95294.7 94821.2 98707.7 93558.7 90982.2 94042.3 91341.6 93126 94530 + 92184.1 95996.2 94732.6 91299.6 97880.1 95967 93909.1 94938.5 95669.8 95176.5 95086.3 94843.4 + 95528.1 96171.6 96309.6 95616.9 94835.3 98272.8 91787.6 95521.6 96570.8 95668.8 95429.5 98161.4 + 95308.1 95379.3 95119.9 92645.5 95162.6 94908.7 95892.4 94958 96356.4 95964.8 95784.9 97306.9 + 99076.2 98690.7 95206.6 98113.2 95186.2 95033.9 96036.4 96140.1 96807.1 95094.9 99879 98644.4 + 96230.8 95789.5 95092.2 94723.5 96536.9 97692.4 97825.2 97249.9 97167.9 97757.2 98318.2 98671.1 + 94118.4 95316.6 94915.1 92205.3 95355.8 93948.9 92403.1 96117.5 99712.7 94480.1 97603.3 97393 + 94261.5 97331 92597.2 93089.6 96512 94008 96006.4 97916.6 94174.2 94091.4 94883 95217 + 95409.5 95918.6 94356.8 95237.4 95481.4 93805 94583.3 95462.6 93483 97192.2 93055.8 93144.2 + 95610.9 95768.9 96580.5 93904 94385.4 96714.4 95478.9 94724 91814.8 92156.7 94427 97066.4 + 93364.2 95204 96930.5 95501.2 93778.9 100052 95042.9 92445 95543 93630 94594.9 94329 + 96638.4 97106 97714.9 99287.2 97355.1 92221 96596.5 96750.1 91073.2 95791.2 96586.7 96140 + 92817.6 94488.2 97956.6 92401.8 94756.1 94544.3 94147.9 96747.7 95802.9 95261.6 95258.7 96104 + 95579.6 97514.3 95211.8 94997.9 93978.5 91972.2 93749.9 92106.8 96124.6 100127 98086.6 95543.5 + 97092.2 99530.2 99801.3 96235.7 96343.1 98574.5 98040.8 98840.4 96965.1 94217.6 96155 93963.7 + 92803.4 93219.2 94790.3 96109.2 93687.2 96608.1 94104.7 95839.6 91423.3 99218.7 91513.7 93302.6 + 95905.9 93747.9 95010.5 99261.2 96185.8 93039.2 92916.4 93619.4 92288.9 96854.8 94509.4 96219.6 + 98205 96826.4 91179.9 93483.8 98869.3 93868.7 95876.1 94143 97363.2 93530.5 97629.1 99827.7 + 94457.8 91892.2 95581 98610.7 96863.2 97256.7 93066.5 95917.9 99396.7 95766.9 97164.3 92232.2 + 92731.8 99869.3 94380.9 94956 98082.7 92191.7 94474.9 95372.2 95865.6 99844.9 94418.6 91857.7 + 96204.5 95960 97316.1 92614 99239.7 95244.1 99538.5 94573.5 97120.4 94799.2 98513.1 98339.4 + 93302.3 94261.3 92676.9 96859.8 99446.3 92475.4 92287.6 92249.7 96685.4 96541.4 91080.9 96878.1 + 94324.4 97591.2 98388.8 96186.2 95610 95265.7 91394 96527.8 97698.1 94465.9 94013.6 92747 + 93553.3 95256.1 99373.9 98140.8 93491.5 99771.2 91759 91716 99052 93729.6 93740 92783 + 91550.6 94770 92602.7 93576.3 98183.7 96970.8 91870.8 95346.2 98346.2 93560.5 92670.5 98769.4 + 91571.2 94968.5 99145.1 96436.4 93795.8 95318.3 91381.8 98981.1 99088.7 97644.3 98630.6 97743.1 + 92704.3 93075.2 98578.6 95529.1 94319.9 94085.5 90937.5 97919.4 98944.8 94854.7 92182.4 94512.6 + 92063.8 93810.8 100163 93381.9 96670.5 100084 95485.2 91192.3 94068.4 94399.2 97416 93310.5 + 97110 91183.8 94912.9 95747.1 93396 98725.4 98807.5 92775.5 99096.5 92614 99545 98288.8 + 91707.2 92969.9 91247.8 93140.6 97851.6 93158.9 94318 96579.6 96759 93261.9 91826.9 96534.5 + 96336.5 96697 95330.5 98255.5 97685.4 99909 95321.4 94735.1 94169.9 97620.2 97231.4 91973.8 + 92894.4 99481.4 96716.4 93852.7 93911.9 96626.4 93031.5 93140.4 97319 97247.7 94609 94570.1 + 97477 97244.6 95166.5 92721.5 90965.6 94381.1 92893.6 93778.4 95170 93344.6 94787 98835.8 + 91352.8 91300 96022 94548.8 94615.2 95647.1 95473.1 94572.3 98079.9 98326.2 95524.3 95696.6 + 95284.6 92216.1 95580.4 97486 97210.8 94727.5 97795.4 91590.3 94427 97426.1 95258 95332.8 + 97131.2 95976.4 99731.9 94068.7 90951.6 97469.6 92273.9 94477.9 94528.1 96541.8 98297.7 94815.7 + 94569.4 94773.2 95540.9 97091.6 96295.3 94613.7 91270.5 92437 95310.1 95665 95105.6 93110 + 95201.7 92084.2 93210.8 93516.4 98159.4 94981.9 99302.1 98367 96438 98587.4 94985.8 94587.7 + 95206.4 97176.2 93048.8 91510.5 95425.8 99536.9 94839.5 95012 96106.4 96499.8 96845.7 92701.3 + 94819.7 94188.8 97467.9 96643.9 93917.9 95933.9 92257.6 92452.8 94572.4 92586.1 95191.8 95328 + 96758.3 99929.6 93554.2 95323.9 96632.2 95257.4 94847 91949.5 93209 93547.3 95240.8 97262.8 + 95089.7 97069.9 95190.3 95140.9 95074 95973.7 94388.4 99057 94534.7 92412.8 99046.4 95919.9 + 94443 94866.2 97498.6 93887.9 95399 95368.8 91580.5 94324.9 94093.8 94149.7 99382.4 98957.9 + 98006.2 95962.2 92573.1 92691.7 98727.4 97079.9 95603 93983.7 90942.8 94071.9 93198.7 91220.3 + 95197.8 93249 97444.6 92675.1 96027.3 94116.2 93520.2 97094.4 92429.1 94041 94667.8 93126.8 + 94818.5 97176.9 93095.5 92741.8 96179.8 97666.4 92663.3 98760.4 93795.8 96535.8 95294.2 95790.6 + 94805.3 95193.2 97014.5 98504.8 94105.8 96093.9 91348.3 93593.9 98733.7 97802.2 96777.4 94940.2 + 95230.1 98592.6 95059.4 94553.6 91822.6 97863.7 92543.4 94845.6 93548.3 98242.2 95333.2 97045.6 + 98016.8 92226.3 95276.9 92711.1 96008.6 96809 94211.7 96137.6 95187.3 98150.2 97296.8 91113.8 + 96474 93852.9 92239 96276.5 95052.9 96594.3 93685.4 97742.9 93546.7 95306.3 94770.3 95964.8 + 95696 99640.7 91837.9 99723.6 99151.1 94435.7 95519.8 99697.4 99142.7 94134.4 92782.6 93895 + 95996.1 97875.4 93076.3 97853.1 95244.8 96644 95353.4 96735 93889.2 100045 99702.9 99157.1 + 98070.8 95590.8 97916 93344.5 96043.3 97053.7 95533.1 96616.9 93760.3 97838.7 96208.5 96038.7 + 93857.8 97571.7 96484.8 96145.5 96518.1 97363.6 97732.7 97398 94195.8 98803.9 96473.4 94213.4 + 96106.2 91296.5 93206.7 96261.4 96533.9 98878.2 91992.5 97999.5 95722.8 96041.5 93213 91750.2 + 95581.7 91698.6 95914.6 96242.6 92133.9 95424.1 95855.1 96174.1 95528.4 98230.5 92158.8 91812.8 + 95860.6 98205.8 94415.2 93272.5 95957.7 93647.8 95870 94902 95646.2 96929.3 96834.4 95617.2 + 91320.7 96408.7 94698.8 93644.5 97192.5 93172.5 96895.8 90996.9 95352 96820 99399.6 98950.7 + 96280.7 99816.9 93343.8 99942.4 96099.1 96439.8 93800.2 91804.3 95592.4 96574.6 93664.3 98034.8 + 92264.3 95414.4 94635.1 94041.9 97367.9 95795.7 94892.6 92524.6 92765.4 99603.1 99490.3 95599.1 + 98957.5 91242.4 99836.3 92053.7 97517.6 91730.4 95241.1 94839 95048.1 95582.3 94346.6 99206.8 + 94465.5 92905.7 96817.8 95686.4 94941.7 98813.8 98702.2 98718.8 92672.4 93156.6 97885 92395.8 + 100164 93473.4 94140 96547.4 91996.1 95239.2 98309 98228.2 95738.8 92910.6 93514.4 96068.2 + 95362.6 95438.6 95204.7 97135.4 98243.2 95260.1 95215.6 92842.5 93212.9 93811.8 96424 94085.7 + 94365.2 96504.2 98085.9 94983.3 94256.9 95111 95143.4 94435.7 93021.3 97997.9 91296.9 99739.1 + 100076 90966.6 91009.4 100028 91342.9 99674.5 92948.6 98074.1 94046.2 96977.5 96042.7 94976.2 + 95830.4 95187.5 94472.4 96550.6 97053.8 98395.8 92624.8 97269.4 97932 93087.2 94011.8 97002.9 + 90988.9 100041 95923.8 95083.1 91221.9 99805.8 94619.1 96388.8 93792.8 97223.6 94979.5 96040 + 96358.6 94660.6 93343.4 94384.1 96634.7 97678.4 91714.5 99311.5 94483.4 96527.2 93103.9 97908.6 + 90946.6 100079 90971.6 100059 93155 97852.5 95199.4 95820.2 95378.2 91263.6 95624.5 99761.6 + 93465.3 98915.8 93584.4 97428.7 95384 95564.4 92257.9 98765.9 95936.3 95082.7 98432.6 93669.3 + 93817.3 97351.1 97202.2 92167.6 98103.7 92177.2 98841.6 93206.3 93585.4 97815.1 97433.6 90906.8 + 100122 94929.5 96072.7 96079.1 94936 92714.8 98301.1 91209 99817.6 91238 99783.2 92762.9 + 98247.5 97490.4 92104 98913.4 92107.3 92896.6 98852.6 92973.2 98041.3 97971.2 98821.3 92205.4 + 90893.4 100143 90927.5 100105 92253 98757.5 95142.2 91803.4 95798.1 99220.9 99153.3 91877.5 + 91221.6 99812.7 91259 99764.7 91921.7 99092.2 92718.5 98288.6 92768.6 98248.4 94471 94942.8 + 96568.2 96093.9 95858.6 96300.7 95155 94711.7 92090.9 92327.4 98934.3 98696.6 93577 93725.2 + 97173.5 91673.1 93837.2 91180.2 99348.7 97355.3 93652.8 91673.7 99349.6 99843.3 97425 97236.2 + 91182.8 99843.5 94231.5 93526.5 93544.2 97505.8 97477 92587 94027.3 95166.4 97023.8 95869.1 + 94408.7 95281 95716.5 95739.1 95303.4 93058.1 92615.7 91764.7 98401.6 99259.7 91794.9 99224 + 92658.1 98355.5 94940.4 96492.1 96027 92742.2 92510.9 98280 98511.1 96538.4 94479.3 96989.3 + 94028.2 93126.1 97890.7 93161.1 97856.4 93918.2 94128.8 96891.5 97102.7 93992.9 93721.8 92101.3 + 91774.6 98926.5 99255.6 91810.1 92140.2 99209.1 98875.5 94443 94271.7 96554.4 96687.1 91621.7 + 99403.1 91127.5 99898 94030.8 96974.4 90861.5 100168 90859.2 100170 94107.8 96897.7 96522.1 + 94492.2 94988.5 96031.2 94553 96466.8 94522 96379.3 91941.1 99082.7 93560.1 92532.7 98488.1 + 95720.6 95298.9 + </DataArray> + <DataArray type="Float32" Name="pn" NumberOfComponents="1" format="ascii"> + 96414.9 101022 101487 100281 91012.9 100801 91499.6 91344.6 91022.3 96337.8 96478.5 95024.3 + 97489.3 93611.9 96364 95204.4 93173.8 98038.3 96695.4 92631.8 97070.2 94162.3 93093.9 97289.8 + 93874.8 94028.6 98683.4 92653.5 95662.7 95350.6 91009.8 95085.6 101147 94877.7 94623.1 100762 + 91244.8 96369.1 95585.5 93812.1 98012.3 93137.8 96451.7 94645.4 96742.5 94334.1 95916.1 95238.7 + 94727.3 94490.6 100029 91740.6 90984.3 101408 97911.3 98421.5 93361.5 93157 101013 90973.3 + 95955.2 91283.3 95629.2 100803 95904.4 99774.6 93594.1 99352.4 92146.1 92245.3 95576.1 99355.9 + 95852.4 94548.5 93826.4 95005.3 94527.7 96595.3 92189.6 98610.3 98141.3 93114.2 93609.3 97048.9 + 95336.4 94095.9 94419 94684 96351.5 90926.5 96074.8 101361 94955.1 98559.1 92782.6 91248.9 + 101050 98314.7 98957.5 92956.3 92766.2 100592 91234.5 92122.6 97503 93740.8 97800.5 92982.8 + 99677.7 99216 92231.2 101545 99712.7 99013.5 90935.7 92434 92254.5 101008 90909.1 91815.5 + 95806.8 100007 96086.4 101086 100170 99492.9 91265.6 92084.4 91924.9 100497 91268.7 98871.3 + 92781.1 98391.4 92861.4 97354.8 97516.9 93647 96113.4 92309.8 95167.6 92102.4 99265.8 94722.4 + 99528.2 95426.5 94959.2 91197.6 91689.7 93843.8 91706.3 100016 93656.2 91209.8 100719 94055.6 + 97429.6 101066 93875.6 100382 97244.8 97528.8 97784.4 99287.6 97284.1 96801.7 97360.7 93175.1 + 97649.5 98040.6 95883.6 98704.9 94126.5 96974.4 94092.6 96983.1 97615.7 91805.5 100248 99067 + 92664.6 98471.7 99775 92818.6 91815.2 92512.4 92719.6 98674.2 96042.8 96506.9 94546.8 94064.9 + 97322.5 93770.4 97510.9 93592 93176.2 98325.7 97917 93256.8 95464 95979 95160.2 94686.2 + 98222 99203 100270 91818 99816.8 92146.5 99229.9 99726 92289.5 91840.1 94998.3 94563.9 + 91145.6 91639.7 101086 100424 96558.3 96695 96955.9 96841.6 96816.1 90875.9 101505 96976.2 + 97290 94342.6 94109.3 101236 90885.4 94509.3 98825.7 92575.4 95468.9 95258.4 91952.8 99901.1 + 96389.5 96655 98560.6 95908.8 95016.3 95408.1 96221.2 96244.1 93399 93640.9 95795.5 98283.4 + 100627 96059 98114.3 97160.5 95800.1 97603.8 95690.7 92024.5 100054 100090 94573.7 96420.3 + 96371.3 94991.4 95129.8 96183.4 92781.6 92560.2 95178.4 94984 95639.4 99012 95334.7 93353.5 + 93637.8 95508.8 93206 99694.4 95838.6 93337.2 95349.4 95255.1 93623.3 94617.5 91261 96853.8 + 100704 93513.2 98725 96238.5 96252.7 94246.4 92549.1 95839.4 96370.4 96152.7 95366.7 93893.5 + 94509.5 96257.2 100254 98563.6 95627.7 95278.6 95529.7 97905.9 95200.5 98988.6 97683.4 97369.9 + 92840.4 95872.4 91626.2 92572.8 94421.9 92369 95842.6 95741 95066.4 93073.3 97183.8 99799.8 + 95138.8 91447.9 95850.8 95644.4 94508.2 94158.1 93943.7 98429.5 95905.9 96760.7 93288.4 94041.7 + 96903.6 94715.2 98935.3 98504.1 96344.6 98379 95300.7 95670.8 94121.1 91089 97296.7 95026.1 + 94265.3 95435.4 96129.9 99261.5 97666.5 97291.6 95261.5 93549.5 95513.8 93648.8 95465.2 95350.2 + 95520.3 96008.8 94494.9 91913 96191 98567.9 91958.5 94506.9 95937.9 95570.5 93455.4 97012.3 + 95143.8 95181.2 99737.7 96641.2 96812.8 96665.4 91555.9 91907.2 92981.2 94668.4 98369.7 98234.7 + 92278.8 93845.5 94624.4 97114.8 100680 96697.5 97781.4 100289 95386.7 97632 93356.5 98342.8 + 94833.8 96652.8 97393 93857.2 98537.6 96921.9 96028.4 97819.6 95836.3 93131.2 97174.4 98195 + 94811.6 92712.1 97615.9 92215.1 97207.9 94272.5 95361.9 95207.4 96153.1 95377.5 93895.7 92424 + 96710.9 94891.4 100050 97416.3 92250.9 93170 94153.6 96064.5 95284.5 92229.3 95342.5 96335.8 + 99365.2 92925 98471.9 95528.9 97421.9 92751.6 95480 93946.2 92243.6 98001.3 95195.4 98464.2 + 94960.4 94025 96113.7 94213.3 95312.1 92635 93701.1 100363 93948.3 96496.9 98787.5 94376.3 + 95710.3 96576.4 93684.6 93205.7 97454.8 95459.5 96015 94844.5 95130.2 91342.5 99378.3 91286.8 + 91843.7 95993.4 95025 91267.5 91831.6 96699.2 98143.1 96967.2 94705.8 92936.5 97920.4 93112.1 + 95299.4 94048.3 95133.2 93984.6 96912.6 90978.3 91303.9 91839.3 92727.7 95382 92869.3 97838 + 94552.6 93653.1 95368.4 93860.2 96602.3 93091.7 94524.2 94920.9 97092.6 93363.9 94229 94539.7 + 94322.1 93379.7 93181.8 93506.6 96663.9 92193.3 94499.6 96660.6 94516.6 100095 97666.2 94554.5 + 94446.1 92047.4 99095.3 92890.7 95122.8 94960.5 97891.8 99449.3 95404.2 99570 94977.4 94658.4 + 98948.3 95556.9 94477 94583.9 94913.7 92751.5 99032.6 99481.8 95017.1 92614.3 96321.7 97712.7 + 94302.7 97193.4 94888.9 96043.8 94909.5 94038.6 94125.4 95337.8 100080 94547 96295.5 97183.8 + 93484 97166.7 94105.8 100539 95184.8 94122.9 91527.4 91961.5 94646.1 91202.8 97565.1 91066.5 + 94839.2 93783.9 96420.1 99463.7 94783.4 94418.7 97319.4 92513.3 97999.5 95374.2 96353.9 96968.2 + 93604.7 94989.2 95568.1 98460.5 98209.4 91356.4 91519 94872 98968.2 91191.2 91479.5 99022.3 + 93221.1 99532.5 95650.9 96058.6 95681.2 95158.1 96653.6 91718.7 96539.4 98088.1 93949.2 94898.5 + 95486.2 92092.3 92152.4 92195 98314.8 97807.6 92691.5 97898 90873.4 97490 96836.9 94194.4 + 99195.2 95275.9 92658 92729.8 94841.1 98020.5 97477.1 94848.2 95496.6 95437.2 95788.2 93638.5 + 92662.3 95275.7 95286.3 98097.9 97720 97181.4 94522 96705.9 96395.1 94494.9 92827.7 95999.7 + 96731.2 95355.2 95313.8 96544 95335 95229.7 95329.8 95286.3 97942.4 97810.3 95416.7 96473.2 + 94942.3 95343 94647.9 95294.7 94821.2 98949.6 93558.7 90982.2 94042.3 91341.6 93126 94530 + 92184.1 95996.2 94732.6 91299.6 97880.1 95967 93909.1 94938.5 95669.8 95176.5 95086.3 94843.4 + 95528.1 96171.6 96512 95616.9 94835.3 98272.8 91787.6 95521.6 96570.8 95668.8 95429.5 98161.4 + 95308.1 95379.3 95119.9 92645.5 95162.6 94908.7 95892.4 94958 96356.4 95964.8 95784.9 97306.9 + 99219.6 98700.5 95206.6 98339.9 95186.2 95033.9 96036.4 96140.1 96807.1 95094.9 100267 98869.4 + 96440.2 95789.5 95092.2 94723.5 96536.9 97692.4 97825.2 97249.9 97167.9 97757.2 98318.2 98671.1 + 94118.4 95316.6 94915.1 92205.3 95355.8 93948.9 92403.1 96117.5 100047 94480.1 97603.3 97393 + 94261.5 97331 92597.2 93089.6 96512 94100.5 96006.4 97916.6 94174.2 94091.4 94883 95217 + 95523 95918.6 94356.8 95237.4 95481.4 93805 94583.3 95462.6 93483 97192.2 93055.8 93144.2 + 95610.9 95768.9 96580.5 93904 94385.4 96736.5 95478.9 94837.4 91814.8 92156.7 94427 97066.4 + 93495 95204 97134.4 95501.2 93778.9 100580 95042.9 92445 95543 93630 94594.9 94329 + 96638.4 97106 97714.9 99487.9 97355.1 92221 96596.5 96750.1 91073.2 95791.2 96586.7 96140 + 92817.6 94488.2 97956.6 92531.2 94756.1 94544.3 94147.9 96747.7 95802.9 95261.6 95258.7 96104 + 95579.6 97514.3 95211.8 94997.9 93978.5 91972.2 93749.9 92106.8 96124.6 100750 98086.6 95543.5 + 97092.2 99854.1 100301 96235.7 96343.1 98574.5 98040.8 98865.2 96965.1 94217.6 96155 93963.7 + 92803.4 93219.2 94790.3 96109.2 93687.2 96608.1 94104.7 95839.6 91423.3 99498.6 91513.7 93302.6 + 95905.9 93747.9 95010.5 99506.7 96185.8 93039.2 92916.4 93619.4 92288.9 96854.8 94509.4 96219.6 + 98447.8 96826.4 91179.9 93483.8 99032.2 93868.7 95876.1 94143 97363.2 93530.5 97629.1 100257 + 94457.8 91892.2 95581 98610.7 96863.2 97256.7 93066.5 95917.9 99626.8 95766.9 97187.5 92232.2 + 92731.8 100340 94380.9 94956 98082.7 92191.7 94474.9 95372.2 95865.6 100247 94418.6 91857.7 + 96204.5 95960 97316.1 92614 99501.8 95244.1 99842.3 94573.5 97120.4 94799.2 98513.1 98339.4 + 93302.3 94261.3 92676.9 96859.8 99743.8 92475.4 92287.6 92249.7 96685.4 96541.4 91080.9 96878.1 + 94324.4 97837 98388.8 96186.2 95610 95265.7 91394 96527.8 97698.1 94465.9 94013.6 92747 + 93553.3 95256.1 99644 98206.7 93491.5 100172 91759 91716 99184.5 93729.6 93740 92783 + 91550.6 94770 92602.7 93576.3 98243.8 96970.8 91870.8 95346.2 98346.2 93560.5 92670.5 98769.4 + 91745 94968.5 99351.8 96436.4 93795.8 95318.3 91381.8 99074.7 99341.9 97874.5 98752.7 97743.1 + 92902.3 93075.2 98703.5 95529.1 94319.9 94085.5 90937.5 97919.4 99085 94854.7 92182.4 94512.6 + 92063.8 93810.8 100772 93381.9 96670.5 100585 95485.2 91192.3 94068.4 94399.2 97416 93310.5 + 97110 91183.8 95128.1 95747.1 93396 98742.6 98877.5 92775.5 99250.7 92614 99893.1 98288.8 + 91707.2 92969.9 91247.8 93140.6 97851.6 93158.9 94318 96579.6 96759 93261.9 91826.9 96534.5 + 96336.5 96697 95330.5 98255.5 97685.4 100428 95529.9 94897.4 94169.9 97620.2 97231.4 91973.8 + 92894.4 99788.2 96716.4 94047.7 94074.4 96626.4 93031.5 93140.4 97319 97247.7 94609 94570.1 + 97477 97244.6 95166.5 92721.5 90965.6 94546 92893.6 93778.4 95170 93344.6 94948.4 99036.4 + 91352.8 91300 96191.3 94548.8 94615.2 95647.1 95473.1 94572.3 98079.9 98326.2 95524.3 95696.6 + 95284.6 92216.1 95580.4 97486 97210.8 94727.5 97795.4 91590.3 94427 97426.1 95258 95332.8 + 97131.2 96151 100002 94068.7 90951.6 97469.6 92273.9 94477.9 94528.1 96541.8 98297.7 94815.7 + 94569.4 94773.2 95540.9 97091.6 96295.3 94613.7 91270.5 92437 95310.1 95665 95105.6 93110 + 95201.7 92084.2 93210.8 93516.4 98159.4 94981.9 99545.1 98367 96438 98587.4 94985.8 94587.7 + 95206.4 97176.2 93048.8 91510.5 95425.8 99760.9 94839.5 95012 96106.4 96499.8 96845.7 92701.3 + 94819.7 94188.8 97467.9 96814.8 93917.9 95933.9 92257.6 92452.8 94572.4 92586.1 95261.3 95328 + 96758.3 100256 93554.2 95323.9 96632.2 95257.4 94847 91949.5 93209 93547.3 95240.8 97262.8 + 95089.7 97069.9 95190.3 95140.9 95074 95973.7 94388.4 99090.4 94534.7 92412.8 99046.4 95919.9 + 94443 94866.2 97498.6 93887.9 95399 95368.8 91580.5 94324.9 94093.8 94149.7 99604.5 99180.1 + 98006.2 95962.2 92573.1 92691.7 98727.4 97079.9 95603 93983.7 90942.8 94071.9 93198.7 91220.3 + 95197.8 93249 97444.6 92675.1 96027.3 94116.2 93520.2 97094.4 92429.1 94041 94667.8 93126.8 + 94818.5 97176.9 93095.5 92741.8 96179.8 97666.4 92700.5 98760.4 93795.8 96535.8 95294.2 95790.6 + 94805.3 95193.2 97014.5 98504.8 94105.8 96093.9 91348.3 93593.9 98733.7 97802.2 96777.4 94940.2 + 95230.1 98804.5 95059.4 94553.6 91822.6 97863.7 92543.4 94845.6 93548.3 98242.2 95333.2 97045.6 + 98016.8 92229.2 95276.9 92711.1 96008.6 96809 94211.7 96137.6 95187.3 98260.8 97296.8 91113.8 + 96474 93852.9 92239 96276.5 95052.9 96594.3 93685.4 97742.9 93546.7 95306.3 94770.3 95964.8 + 95696 99900.9 91837.9 99986.4 99174.5 94506 95519.8 99972.5 99191.1 94134.4 92782.6 93895 + 95996.1 97875.4 93076.3 97853.1 95244.8 96644 95353.4 96735 93889.2 100417 99957 99181 + 98275.5 95590.8 98022.8 93344.5 96043.3 97053.7 95533.1 96616.9 93795.9 97838.7 96208.5 96038.7 + 93857.8 97571.7 96484.8 96145.5 96518.1 97564.9 97732.7 97398 94195.8 98803.9 96473.4 94213.4 + 96106.2 91296.5 93206.7 96261.4 96533.9 98899.7 91992.5 97999.5 95722.8 96041.5 93213 91750.2 + 95581.7 91698.6 95914.6 96242.6 92133.9 95424.1 95855.1 96174.1 95528.4 98230.5 92158.8 91812.8 + 95860.6 98397.4 94415.2 93272.5 95957.7 93647.8 95870 94902 95646.2 96929.3 96834.4 95617.2 + 91320.7 96408.7 94698.8 93644.5 97192.5 93336.7 96895.8 90996.9 95352 96820 99636.9 99000.7 + 96280.7 100111 93343.8 100289 96099.1 96439.8 93800.2 91804.3 95592.4 96574.6 93664.3 98034.8 + 92402.5 95414.4 94635.1 94041.9 97367.9 95795.7 94892.6 92524.6 92765.4 99890.4 99671.1 95599.1 + 98957.5 91392.8 100146 92053.7 97705.7 91730.4 95241.1 94839 95048.1 95582.3 94346.6 99420.3 + 94465.5 92905.7 96817.8 95686.4 94941.7 98852.4 98939.5 98729.6 92672.4 93156.6 97885 92562.6 + 100592 93473.4 94140 96547.4 91996.1 95239.2 98309 98228.2 95738.8 92910.6 93514.4 96068.2 + 95362.6 95438.6 95204.7 97135.4 98243.2 95260.1 95215.6 92842.5 93212.9 93811.8 96424 94085.7 + 94365.2 96504.2 98085.9 94983.3 94256.9 95111 95143.4 94435.7 93021.3 97997.9 91296.9 100216 + 100685 90966.6 91009.4 100436 91342.9 99949.8 92948.6 98074.1 94046.2 96977.5 96042.7 94976.2 + 95830.4 95187.5 94472.4 96550.6 97053.8 98395.8 92624.8 97269.4 97932 93087.2 94011.8 97002.9 + 90988.9 100545 95923.8 95083.1 91221.9 100211 94619.1 96388.8 93792.8 97223.6 94979.5 96040 + 96358.6 94660.6 93343.4 94384.1 96634.7 97678.4 91714.5 99504.2 94483.4 96527.2 93103.9 97908.6 + 90946.6 100646 90971.6 100519 93155 97852.5 95199.4 95820.2 95378.2 91263.6 95624.5 100136 + 93465.3 98947.8 93584.4 97428.7 95384 95564.4 92257.9 98765.9 95936.3 95082.7 98432.6 93669.3 + 93817.3 97351.1 97202.2 92167.6 98103.7 92177.2 98841.6 93206.3 93585.4 97815.1 97433.6 90906.8 + 100646 94929.5 96072.7 96079.1 94936 92714.8 98301.1 91209 100274 91238 100128 92762.9 + 98247.5 97490.4 92104 98913.4 92107.3 92896.6 98874.9 92973.2 98041.3 97971.2 98973.1 92205.4 + 90893.4 100760 90927.5 100569 92253 98757.5 95142.2 91803.4 95798.1 99348.8 99356.4 91877.5 + 91221.6 100292 91259 100083 91921.7 99111.3 92718.5 98288.6 92768.6 98248.4 94471 94942.8 + 96568.2 96093.9 95858.6 96300.7 95155 94711.7 92090.9 92327.4 98957.9 98696.6 93577 93725.2 + 97173.5 91673.1 93837.2 91180.2 99567.4 97355.3 93652.8 91673.7 99515 100291 97425 97236.2 + 91182.8 100217 94231.5 93526.5 93544.2 97505.8 97477 92587 94027.3 95166.4 97023.8 95869.1 + 94408.7 95281 95716.5 95739.1 95303.4 93058.1 92615.7 91764.7 98401.6 99470.2 91794.9 99317.8 + 92658.1 98355.5 94940.4 96492.1 96027 92742.2 92510.9 98280 98511.1 96538.4 94479.3 96989.3 + 94028.2 93126.1 97890.7 93161.1 97856.4 93918.2 94128.8 96891.5 97102.7 93992.9 93721.8 92101.3 + 91774.6 99040.6 99474.9 91810.1 92140.2 99296.4 98875.5 94443 94271.7 96554.4 96687.1 91621.7 + 99593.6 91127.5 100316 94030.8 96974.4 90861.5 100751 90859.2 100697 94107.8 96897.7 96522.1 + 94492.2 94988.5 96031.2 94553 96466.8 94522 96379.3 91941.1 99160.4 93560.1 92532.7 98488.1 + 95720.6 95298.9 + </DataArray> + <DataArray type="Float32" Name="pc" NumberOfComponents="1" format="ascii"> + 0.00362121 797.906 847.12 537.587 0 708.942 198.704 0 48.2741 6.36181e-07 111.153 0 + 22.9418 0 146.826 0 0 125.356 106.044 0 0 155.962 0 0 + 93.1032 0 254.147 0 4.65462e-06 238.006 0 0 830.03 229.457 0 777.638 + 0 183.897 1.45519e-11 0 45.6694 23.9531 34.3734 22.5286 0 23.3282 143.278 0.00222365 + 204.361 0 668.087 0 0 844.232 0 456.917 226.155 0 806.793 0 + 18.2192 0 0 779.405 236.271 691.694 0 415.642 0 0 0 532.32 + 188.263 3.56407 0 78.2045 71.8571 0 0 460.763 23.8778 166 0 0 + 144.491 74.291 0 0 246.979 0 0 849.676 0 250.373 0 0 + 800.764 8.51331 589.318 213.403 0 714.126 0 0 0 168.179 269.353 0 + 684.673 349.899 24.4421 850.861 705.9 191.427 0 217.749 0 792.383 0 0 + 0 694.477 215.748 800.414 753.952 330.069 0 195.354 0 666.015 33.1654 512.217 + 0 91.917 90.347 108.934 99.1313 0 0 0 0 0 478.249 0 + 535.517 186.354 193.351 0 0 0 0 628.123 0 0 755.147 203.203 + 0 809.435 224.584 763.782 0 249.043 310.524 563.511 144.104 140.732 199.505 0 + 146.462 150.82 0 381.739 0 37.0508 0 19.8721 200.296 0 750.257 602.432 + 0 58.8679 491.997 172.049 23.447 0 0 350.201 0 0 0 0 + 0 18.321 0 25.0586 0 332.682 11.8791 85.9254 72.5279 110.587 156.883 157.15 + 257.308 566.695 755.135 0 713.039 0 289.846 456.204 170 47.0813 0.615018 0 + 0 0 814.815 763.85 0 0 228.606 247.082 193.657 0 862.87 0 + 270.741 238.023 0 844.026 0 0 311.625 0 18.0379 26.1101 0 694.443 + 0 215.227 380.726 0.0761418 3.66081 0.321162 0 0 0 0 0 0 + 557.776 0 0 0 0 0 0 0 371.507 331.078 0 199.059 + 205.071 0 0 0 0 0 0 0 0 253.62 0 0 + 0 0 0 294.17 0 0 0 0 0 0 0 0 + 610.09 0 0 0 0 0 0 0 0 0 210.714 0 + 190.088 0 485.562 0 0 0 0 0 0 113.915 0 0 + 0 0 0 0 0 0 0 0 0 0 0 280.374 + 0 0 0 0 0 0 0 228.253 0 0 0 0 + 0 0 235.075 0 0 0 0 0 0 0 0 0 + 0 0 0 256.268 8.23802 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 289.553 0 0 0 0 0 0 0 0 0 + 0 0 0 202.334 581.43 0 0 477.26 0 0 0 0 + 0 0 0 0 34.8193 0 0 0 0 0 0 24.4278 + 0 16.9298 0 0 0 0 31.6113 0 0 0 0 0 + 7.95783 0 364.987 0 0 0 0 0 0 0 0 0 + 181.806 0 0 0 0 0 0 0 2.93734 0 0 243.889 + 0 0 0 0 0 0 0 424.174 0 0 18.4433 0 + 0 0 0 0 0 0 0 0 0 0 197.948 0 + 0 0 0 0 0 0 15.8947 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 244.383 + 33.6568 0 0 15.5629 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 364.531 11.2575 0 + 0 0 87.2251 0 0 0 229.132 191.262 0 259.03 0 0 + 112.517 0 0 0 0 0 164.97 285.996 0 0 0 0 + 0 8.42358 0 0 0 0 0 0 348.561 0 0 6.5548 + 190.105 0 0 475.364 0 0 0 0 0 0 0 0 + 0 0 0 236.652 0 0 0 160.237 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 172.58 81.8833 + 0 235.521 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 193.088 0 0 0 0 0 + 169.398 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 241.869 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 202.474 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 143.443 9.84751 0 226.722 0 0 0 0 0 0 387.877 225.028 + 209.431 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 334.424 0 0 0 + 0 0 0 0 0 92.5103 0 0 0 0 0 0 + 113.409 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 22.0872 0 113.414 0 0 0 0 + 130.81 0 203.935 0 0 527.953 0 0 0 0 0 0 + 0 0 0 200.669 0 0 0 0 0 0 0 0 + 0 0 0 129.333 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 623.01 0 0 + 0 323.891 499.391 0 0 0 0 24.745 0 0 0 0 + 0 0 0 0 0 0 0 0 0 279.889 0 0 + 0 0 0 245.47 0 0 0 0 0 0 0 0 + 242.737 0 0 0 162.918 0 0 0 0 0 0 428.939 + 0 0 0 0 0 0 0 0 230.153 0 23.1982 0 + 0 470.368 0 0 0 0 0 0 0 402.385 0 0 + 0 0 0 0 262.053 0 303.774 0 0 0 0 0 + 0 0 0 0 297.527 0 0 0 0 0 0 0 + 0 245.748 0 0 0 0 0 0 0 0 0 0 + 0 0 270.063 65.8628 0 400.448 0 0 132.504 0 0 0 + 0 0 0 0 60.139 0 0 0 0 0 0 0 + 173.834 0 206.77 0 0 0 0 93.5715 253.238 230.159 122.067 0 + 197.986 0 124.972 0 0 0 0 0 140.217 0 0 0 + 0 0 609.146 0 0 501.207 0 0 0 0 0 0 + 0 0 215.143 0 0 17.2603 69.9622 0 154.129 0 348.178 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 518.543 208.425 162.359 0 0 0 0 + 0 306.822 0 195.012 162.442 0 0 0 0 0 0 0 + 0 0 0 0 0 164.912 0 0 0 0 161.412 200.543 + 0 0 169.387 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 174.625 270.439 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 242.994 0 0 0 0 0 + 0 0 0 0 0 223.969 0 0 0 0 0 0 + 0 0 0 170.968 0 0 0 0 0 0 69.5121 0 + 0 326.123 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 33.3486 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 222.03 222.202 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 37.1679 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 211.883 0 0 0 0 0 0 0 0 0 0 + 0 2.90724 0 0 0 0 0 0 0 110.541 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 260.173 0 262.791 23.4568 70.2779 0 275.131 48.3699 0 0 0 + 0 0 0 0 0 0 0 0 0 371.671 254.059 23.9042 + 204.721 0 106.82 0 0 0 0 0 35.6461 0 0 0 + 0 0 0 0 0 201.299 0 0 0 0 0 0 + 0 0 0 0 0 21.517 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 191.636 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 164.238 0 0 0 0 237.226 49.9262 + 0 294.032 0 346.646 0 0 0 0 0 0 0 0 + 138.238 0 0 0 0 0 0 0 0 287.345 180.791 0 + 0 150.481 309.673 0 188.046 0 0 0 0 0 0 213.489 + 0 0 0 0 0 38.6461 237.323 10.7746 0 0 0 166.853 + 428.364 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 476.52 + 609.664 0 0 407.712 0 275.288 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 503.772 0 0 0 405.385 0 0 0 0 0 0 + 0 0 0 0 0 0 0 192.685 0 0 0 0 + 0 567.191 0 460.197 0 0 0 0 0 0 0 374.67 + 0 32.0203 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 524.188 0 0 0 0 0 0 0 456.371 0 344.78 0 + 0 0 0 0 0 0 22.295 0 0 0 151.852 0 + 0 617.334 0 463.827 0 0 0 0 0 127.877 203.104 0 + 0 479.66 0 318.691 0 19.0054 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 23.659 0 0 0 + 0 0 0 0 218.706 0 0 0 165.397 447.645 0 0 + 0 373.32 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 210.529 0 93.7032 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 114.186 219.3 0 0 87.3436 0 0 0 0 0 0 + 190.525 0 417.961 0 0 0 582.721 0 527.724 0 0 0 + 0 0 0 0 0 0 0 0 77.641 0 0 0 + 0 0 + </DataArray> + <DataArray type="Float32" Name="rhoW" NumberOfComponents="1" format="ascii"> + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 + </DataArray> + <DataArray type="Float32" Name="rhoN" NumberOfComponents="1" format="ascii"> + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 1460 + 1460 1460 + </DataArray> + <DataArray type="Float32" Name="mobW" NumberOfComponents="1" format="ascii"> + 1000 0.00314162 0.00160753 0.248715 1000 0.0117608 488.633 1000 999.376 1000 988.194 1000 + 999.883 1000 877.642 1000 1000 966.11 992.214 1000 1000 811.324 1000 1000 + 995.967 1000 190.396 1000 1000 261.615 1000 1000 0.00201971 305.398 1000 0.00418907 + 1000 582.719 1000 1000 999.454 999.872 999.716 999.887 1000 999.879 898.498 1000 + 452.912 1000 0.0227611 1000 1000 0.0016702 1000 1.41129 323.334 1000 0.00277543 1000 + 999.928 1000 1000 0.00408412 270.177 0.0154717 1000 3.728 1000 1000 1000 0.276759 + 555.1 999.997 1000 997.768 998.259 1000 1000 1.2928 999.872 721.839 1000 1000 + 891.679 998.084 1000 1000 220.115 1000 1000 0.00155418 1000 205.66 1000 1000 + 0.00301846 999.985 0.0911013 397.183 1000 0.0108436 1000 1000 1000 701.522 137.405 1000 + 0.0173311 19.1985 999.866 0.00153009 0.0123379 534.972 1000 371.279 1000 0.00339546 1000 1000 + 1000 0.0147955 383.118 0.00303322 0.00591869 31.7442 1000 509.941 1000 0.0235602 999.738 0.419511 + 1000 996.161 996.4 990.145 994.73 1000 1000 1000 1000 1000 0.873173 1000 + 0.259353 567.204 522.711 1000 1000 1000 1000 0.0450926 1000 1000 0.00581492 460.183 + 1000 0.00267575 332.052 0.00512134 1000 211.241 51.8126 0.148857 893.887 911.79 483.551 1000 + 879.907 850.843 1000 8.59146 1000 999.663 1000 999.914 478.539 1000 0.00625249 0.0715021 + 1000 998.981 0.646008 666.386 999.877 1000 1000 19.0516 1000 1000 1000 1000 + 1000 999.927 1000 999.858 1000 29.7142 999.971 996.983 998.212 988.721 803.697 801.457 + 178.27 0.13996 0.00581595 1000 0.0110293 1000 85.6901 1.4345 684.751 999.413 1000 1000 + 1000 1000 0.00248451 0.00511624 1000 1000 309.965 219.666 520.76 1000 0.00130772 1000 + 133.223 261.528 1000 0.00167478 1000 1000 50.4158 1000 999.93 999.845 1000 0.0148035 + 1000 386.226 8.81189 1000 999.997 1000 1000 1000 1000 1000 1000 1000 + 0.166462 1000 1000 1000 1000 1000 1000 1000 11.1088 30.9451 1000 486.378 + 448.462 1000 1000 1000 1000 1000 1000 1000 1000 192.479 1000 1000 + 1000 1000 1000 77.2741 1000 1000 1000 1000 1000 1000 1000 1000 + 0.0622072 1000 1000 1000 1000 1000 1000 1000 1000 1000 413.523 1000 + 543.499 1000 0.743272 1000 1000 1000 1000 1000 1000 985.309 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 107.018 + 1000 1000 1000 1000 1000 1000 1000 311.873 1000 1000 1000 1000 + 1000 1000 276.175 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 182.191 999.986 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 86.2897 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 465.658 0.105637 1000 1000 0.892526 1000 1000 1000 1000 + 1000 1000 1000 1000 999.708 1000 1000 1000 1000 1000 1000 999.866 + 1000 999.939 1000 1000 1000 1000 999.764 1000 1000 1000 1000 1000 + 999.987 1000 13.0963 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 595.842 1000 1000 1000 1000 1000 1000 1000 999.998 1000 1000 233.87 + 1000 1000 1000 1000 1000 1000 1000 3.03644 1000 1000 999.926 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 493.435 1000 + 1000 1000 1000 1000 1000 1000 999.946 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 231.636 + 999.729 1000 1000 999.949 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 13.2482 999.974 1000 + 1000 1000 996.824 1000 1000 1000 307.135 536.021 1000 171.911 1000 1000 + 986.836 1000 1000 1000 1000 1000 731.445 93.8607 1000 1000 1000 1000 + 1000 999.986 1000 1000 1000 1000 1000 1000 19.8617 1000 1000 999.991 + 543.39 1000 1000 0.930916 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 268.282 1000 1000 1000 774.714 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 661.759 997.424 + 1000 273.93 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 524.386 1000 1000 1000 1000 1000 + 690.26 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 243.171 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 464.771 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 897.587 999.98 1000 320.214 1000 1000 1000 1000 1000 1000 7.37098 329.578 + 421.396 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 28.4325 1000 1000 1000 + 1000 1000 1000 1000 1000 996.065 1000 1000 1000 1000 1000 1000 + 985.879 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 999.892 1000 985.873 1000 1000 1000 1000 + 951.388 1000 455.582 1000 1000 0.302597 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 476.175 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 955.807 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 0.0493576 1000 1000 + 1000 37.0969 0.550796 1000 1000 1000 1000 999.862 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 108.224 1000 1000 + 1000 1000 1000 226.763 1000 1000 1000 1000 1000 1000 1000 1000 + 239.145 1000 1000 1000 750.443 1000 1000 1000 1000 1000 1000 2.71031 + 1000 1000 1000 1000 1000 1000 1000 1000 301.684 1000 999.88 1000 + 1000 1.04078 1000 1000 1000 1000 1000 1000 1000 5.14921 1000 1000 + 1000 1000 1000 1000 161.17 1000 61.1951 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 71.261 1000 1000 1000 1000 1000 1000 1000 + 1000 225.529 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 135.25 998.632 1000 5.4002 1000 1000 945.883 1000 1000 1000 + 1000 1000 1000 1000 998.923 1000 1000 1000 1000 1000 1000 1000 + 651.106 1000 437.864 1000 1000 1000 1000 995.886 193.995 301.651 973.049 1000 + 493.192 1000 966.989 1000 1000 1000 1000 1000 914.312 1000 1000 1000 + 1000 1000 0.0632786 1000 1000 0.529794 1000 1000 1000 1000 1000 1000 + 1000 1000 386.726 1000 1000 999.936 998.385 1000 826.027 1000 20.0561 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 0.367528 427.601 755.567 1000 1000 1000 1000 + 1000 56.7774 1000 512.12 754.811 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 731.988 1000 1000 1000 1000 764.176 476.972 + 1000 1000 690.365 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 644.619 134.122 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 237.964 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 335.498 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 675.992 1000 1000 1000 1000 1000 1000 998.414 1000 + 1000 35.0691 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 999.735 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 346.476 345.494 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 999.661 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 406.392 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 999.998 1000 1000 1000 1000 1000 1000 1000 988.763 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 167.785 1000 158.629 999.877 998.365 1000 120.683 999.373 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 11.063 190.743 999.872 + 450.657 1000 991.736 1000 1000 1000 1000 1000 999.692 1000 1000 1000 + 1000 1000 1000 1000 1000 472.188 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 999.898 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 533.64 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 738.256 1000 1000 1000 1000 265.44 999.324 + 1000 77.5303 1000 20.8517 1000 1000 1000 1000 1000 1000 1000 1000 + 923.503 1000 1000 1000 1000 1000 1000 1000 1000 90.923 602.18 1000 + 1000 853.253 52.9168 1000 556.478 1000 1000 1000 1000 1000 1000 396.663 + 1000 1000 1000 1000 1000 999.629 264.961 999.976 1000 1000 1000 713.877 + 2.74762 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 0.90732 + 0.0626889 1000 1000 4.51982 1000 120.252 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 0.501574 1000 1000 1000 4.78428 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 526.954 1000 1000 1000 1000 + 1000 0.138625 1000 1.30956 1000 1000 1000 1000 1000 1000 1000 10.2584 + 1000 999.758 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 0.326956 1000 1000 1000 1000 1000 1000 1000 1.42902 1000 21.8634 1000 + 1000 1000 1000 1000 1000 1000 999.89 1000 1000 1000 843.35 1000 + 1000 0.0546082 1000 1.206 1000 1000 1000 1000 1000 959.841 460.809 1000 + 1000 0.846333 1000 42.2706 1000 999.922 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 999.875 1000 1000 1000 + 1000 1000 1000 1000 365.667 1000 1000 1000 727.47 1.74705 1000 1000 + 1000 10.6128 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 414.658 1000 995.863 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 + 1000 984.995 362.204 1000 1000 996.809 1000 1000 1000 1000 1000 1000 + 540.714 1000 3.52498 1000 1000 1000 0.103096 1000 0.304017 1000 1000 1000 + 1000 1000 1000 1000 1000 1000 1000 1000 997.816 1000 1000 1000 + 1000 1000 + </DataArray> + <DataArray type="Float32" Name="mobN" NumberOfComponents="1" format="ascii"> + 3.08207e-10 1743.46 1747.23 1615.37 0 1729.59 69.105 0 0.0314033 2.11115e-17 0.545848 0 + 0.0063175 0 6.14347 0 0 1.57049 0.362293 0 0 10.2157 0 0 + 0.19056 0 327.111 0 9.40672e-16 227.789 0 0 1746.12 182.854 0 1741.3 + 0 38.612 1.83696e-26 0 0.0276558 0.0069044 0.014764 0.00608602 0 0.00653831 4.98803 1.2156e-10 + 84.5711 0 1717.44 0 0 1747.05 0 1470.94 167.044 0 1744.28 0 + 0.00395026 0 0 1741.5 218.212 1725.1 0 1347.91 0 0 0 1607.99 + 46.223 0.000161262 0 0.107357 0.0844252 0 0 1480.11 0.00685972 17.0982 0 0 + 5.36003 0.0926167 0 0 280.834 0 0 1747.38 0 302.342 0 0 + 1743.73 0.000873168 1672.17 114.231 0 1730.8 0 0 0 19.012 434.531 0 + 1723.02 1027.56 0.00719869 1747.45 1728.86 52.4287 0 130.761 0 1742.91 0 0 + 0 1725.88 122.966 1743.7 1738.15 895.518 0 60.998 0 1716.67 0.0136721 1577.2 + 0 0.181623 0.170615 0.456727 0.247284 0 0 0 0 0 1517.8 0 + 1612.51 42.7639 56.5031 0 0 0 0 1699.15 0 0 1738.33 81.2189 + 0 1744.51 159.831 1739.55 0 293.827 751.776 1647.27 5.23897 4.27835 71.1565 0 + 6.01541 7.7103 0 1204.78 0 0.0173688 0 0.00471037 73.2268 0 1737.59 1682.54 + 0 0.0503617 1543.29 22.8431 0.00660709 0 0 1029.45 0 0 0 0 + 0 0.00399499 0 0.00757961 0 913.799 0.00168124 0.143729 0.0866146 0.521758 10.7299 10.8829 + 348.492 1650.7 1738.32 0 1730.55 0 591.422 1469.2 20.7429 0.0296472 5.55576e-06 0 + 0 0 1744.96 1739.56 0 0 178.699 281.476 57.1729 0 1748.11 0 + 444.833 227.888 0 1747.04 0 0 760.153 0 0.00387127 0.00825488 0 1725.87 + 0 120.987 1199.82 1.02942e-07 0.000169806 1.60597e-06 0 0 0 0 0 0 + 1640.84 0 0 0 0 0 0 0 1152.59 902.604 0 70.0096 + 86.6773 0 0 0 0 0 0 0 0 323.596 0 0 + 0 0 0 625.19 0 0 0 0 0 0 0 0 + 1687.97 0 0 0 0 0 0 0 0 0 104.755 0 + 49.7284 0 1531.78 0 0 0 0 0 0 0.677869 0 0 + 0 0 0 0 0 0 0 0 0 0 0 517.887 + 0 0 0 0 0 0 0 176.989 0 0 0 0 + 0 0 211.746 0 0 0 0 0 0 0 0 0 + 0 0 0 341.4 0.000818798 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 589.132 0 0 0 0 0 0 0 0 0 + 0 0 0 78.7656 1665.23 0 0 1515.83 0 0 0 0 + 0 0 0 0 0.0151799 0 0 0 0 0 0 0.00719002 + 0 0.0034069 0 0 0 0 0.0123407 0 0 0 0 0 + 0.00076526 0 1117 0 0 0 0 0 0 0 0 0 + 35.335 0 0 0 0 0 0 0 0.000111119 0 0 261.926 + 0 0 0 0 0 0 0 1377.45 0 0 0.00404911 0 + 0 0 0 0 0 0 0 0 0 0 67.2089 0 + 0 0 0 0 0 0 0.00300155 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 264.9 + 0.0141102 0 0 0.00287733 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 1114.44 0.00151188 0 + 0 0 0.151076 0 0 0 181.262 52.0909 0 360.372 0 0 + 0.607929 0 0 0 0 0 16.2508 561.417 0 0 0 0 + 0 0.000855255 0 0 0 0 0 0 1019.16 0 0 0.000524369 + 49.7624 0 0 1512.01 0 0 0 0 0 0 0 0 + 0 0 0 220.295 0 0 0 12.79 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 23.4144 0.123302 + 0 214.143 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 55.9329 0 0 0 0 0 + 20.157 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 249.919 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 79.1589 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 5.03741 0.00116163 0 169.697 0 0 0 0 0 0 1234 161.847 + 100.431 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 925.841 0 0 0 + 0 0 0 0 0 0.186022 0 0 0 0 0 0 + 0.651751 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0.005844 0 0.652011 0 0 0 0 + 2.2759 0 83.3274 0 0 1601.65 0 0 0 0 0 0 + 0 0 0 74.2195 0 0 0 0 0 0 0 0 + 0 0 0 2.06206 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 1696.19 0 0 + 0 851.338 1555.81 0 0 0 0 0.00738445 0 0 0 0 + 0 0 0 0 0 0 0 0 0 514.154 0 0 + 0 0 0 271.517 0 0 0 0 0 0 0 0 + 255.042 0 0 0 14.6658 0 0 0 0 0 0 1392.94 + 0 0 0 0 0 0 0 0 186.301 0 0.00646357 0 + 0 1501.59 0 0 0 0 0 0 0 1297.09 0 0 + 0 0 0 0 381.596 0 699.943 0 0 0 0 0 + 0 0 0 0 651.396 0 0 0 0 0 0 0 + 0 273.22 0 0 0 0 0 0 0 0 0 0 + 0 0 439.798 0.0669064 0 1289.14 0 0 2.54487 0 0 0 + 0 0 0 0 0.0530989 0 0 0 0 0 0 0 + 24.81 0 91.8651 0 0 0 0 0.194251 321.067 186.331 1.24459 0 + 67.3038 0 1.52898 0 0 0 0 0 4.14592 0 0 0 + 0 0 1687.32 0 0 1558.89 0 0 0 0 0 0 + 0 0 120.672 0 0 0.00354209 0.0785037 0 9.25381 0 1016.74 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 1587.31 97.1294 14.2569 0 0 0 0 + 0 723.447 0 60.2123 14.3167 0 0 0 0 0 0 0 + 0 0 0 0 0 16.2038 0 0 0 0 13.5858 73.8834 + 0 0 20.1461 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 25.7247 442.59 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 256.567 0 0 0 0 0 + 0 0 0 0 0 157.061 0 0 0 0 0 0 + 0 0 0 21.7141 0 0 0 0 0 0 0.077152 0 + 0 867.448 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0.0138345 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 148.525 149.271 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0.0174887 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 108.805 0 0 0 0 0 0 0 0 0 0 + 0 0.000108938 0 0 0 0 0 0 0 0.519862 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 368.348 0 386.843 0.00661276 0.0794641 0 477.82 0.0315474 0 0 0 + 0 0 0 0 0 0 0 0 0 1153.46 326.522 0.00687538 + 85.6332 0 0.38411 0 0 0 0 0 0.0159699 0 0 0 + 0 0 0 0 0 75.9179 0 0 0 0 0 0 + 0 0 0 0 0 0.00553936 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 52.8604 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 15.6694 0 0 0 0 223.458 0.0339518 + 0 624.115 0 1007 0 0 0 0 0 0 0 0 + 3.66914 0 0 0 0 0 0 0 0 571.917 33.8264 0 + 0 7.56532 745.285 0 45.8189 0 0 0 0 0 0 114.544 + 0 0 0 0 0 0.0190468 223.996 0.00138662 0 0 0 17.8272 + 1391.1 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 1514.34 + 1687.68 0 0 1318.26 0 479.014 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 1563.23 0 0 0 1309.14 0 0 0 0 0 0 + 0 0 0 0 0 0 0 55.0672 0 0 0 0 + 0 1651.22 0 1478.78 0 0 0 0 0 0 0 1169.2 + 0 0.0126832 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 1596.02 0 0 0 0 0 0 0 1469.61 0 995.004 0 + 0 0 0 0 0 0 0.00595724 0 0 0 8.1664 0 + 0 1692.72 0 1487.18 0 0 0 0 0 1.86844 80.9356 0 + 0 1520.57 0 813.191 0 0.00430278 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0.00673075 0 0 0 + 0 0 0 0 134.605 0 0 0 16.5974 1447.37 0 0 + 0 1162.17 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 104.122 0 0.195306 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0.692244 137.027 0 0 0.151767 0 0 0 0 0 0 + 50.5987 0 1356.18 0 0 0 1666.4 0 1601.31 0 0 0 + 0 0 0 0 0 0 0 0 0.105104 0 0 0 + 0 0 + </DataArray> + <DataArray type="Float32" Name="porosity" NumberOfComponents="1" format="ascii"> + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 + </DataArray> + <DataArray type="Float32" Name="process rank" NumberOfComponents="1" format="ascii"> + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 + </DataArray> + </CellData> + <Points> + <DataArray type="Float32" Name="Coordinates" NumberOfComponents="3" format="ascii"> + 0.504759 0 0.409458 0.56866 0 0.351514 0.572699 0 0.47199 0 0 0 + 0.0998781 0 0.0998781 0 0 0.1 0.1 0 0 1 0 0 + 1 0 0.1 0.900122 0 0.0998781 1 0 1 0.9 0 1 + 0.900122 0 0.900122 0.9 0 0 0 0 1 0 0 0.9 + 0.0998781 0 0.900122 1 0 0.9 0.1 0 1 0.644013 0 0.432702 + 0.311966 0 0.428016 0.349623 0 0.357058 0.401159 0 0.463634 0.666173 0 0.558699 + 0.71279 0 0.495371 0.747312 0 0.605379 0.49458 0 0.304084 0.606624 0 0.254899 + 0.432494 0 0.650473 0.506328 0 0.697406 0.39352 0 0.745349 0.224142 0 0.493066 + 0.244617 0 0.373899 0.78488 0 0.503 0.497 0 0.78488 0.503 0 0.21512 + 0.433014 0 0.359843 0.64071 0 0.848866 0.604121 0 0.745283 0.727794 0 0.801265 + 0.848866 0 0.35929 0.745283 0 0.395879 0.801265 0 0.272206 0.152055 0 0.638341 + 0.257134 0 0.606013 0.198735 0 0.727794 0.707143 0 0.707143 0.707143 0 0.292857 + 0.292857 0 0.707143 0.848175 0 0.640795 0.793413 0 0.720731 0.640795 0 0.151825 + 0.720938 0 0.206955 0.359205 0 0.848175 0.279086 0 0.793086 0 0 0.5 + 0.109843 0 0.53354 0 0 0.6 0.5 0 1 0.4 0 1 + 0.460465 0 0.890324 1 0 0.5 1 0 0.6 0.890324 0 0.539535 + 0.5 0 0 0.6 0 0 0.539535 0 0.109676 0.0719314 0 0.642143 + 0.927812 0 0.644127 0.644127 0 0.0721883 0.355873 0 0.927812 0.162597 0 0.437943 + 0.365315 0 0.574098 0.439098 0 0.558631 0.645583 0 0.347403 0.352788 0 0.654331 + 0.30986 0 0.50993 0.574766 0 0.563124 0.8 0 1 0.7 0 1 + 0.739074 0 0.902335 0.2 0 0 0.3 0 0 0.258767 0 0.0987232 + 1 0 0.2 1 0 0.3 0.902335 0 0.260926 0 0 0.2 + 0.0976651 0 0.260926 0 0 0.3 0 0 0.7 0.0977591 0 0.738832 + 0 0 0.8 1 0 0.7 1 0 0.8 0.900559 0 0.740305 + 0.7 0 0 0.8 0 0 0.740305 0 0.0994409 0.3 0 1 + 0.2 0 1 0.259695 0 0.900559 0.497045 0 0.506971 0.56908 0 0.916779 + 0.916779 0 0.43092 0.428783 0 0.0816948 0.0832487 0 0.429921 0.346467 0 0.141978 + 0.267312 0 0.197239 0.554275 0 0.837227 0.837227 0 0.445725 0.425312 0 0.171615 + 0.499476 0 0.597977 0.566986 0 0.640157 0.651952 0 0.642499 0.829497 0 0.829497 + 0.170503 0 0.170503 0.20417 0 0.273039 0.829497 0 0.170503 0.170503 0 0.829497 + 0 0 0.4 0.6 0 1 1 0 0.4 0.4 0 0 + 0.817673 0 0.572177 0.572488 0 0.18288 0.427548 0 0.817182 0.820102 0 0.920029 + 0.179898 0 0.0799714 0.920029 0 0.179898 0.0799714 0 0.179898 0.0799714 0 0.820102 + 0.920029 0 0.820102 0.820102 0 0.0799714 0.179898 0 0.920029 0.151134 0 0.35929 + 0.401022 0 0.262573 0.185794 0 0.56774 0.649773 0 0.933596 0.933596 0 0.350227 + 0.347717 0 0.0653656 0.0664096 0 0.350028 0.33825 0 0.215847 0.296336 0 0.281373 + 1.5399 0.539897 0.33409 1.56476 0.564762 0.447407 1.5076 0.507598 0.391035 1.5885 0.588504 0.358064 + 1.4627 0.462702 0.793313 1.3947 0.394698 0.775278 1.45549 0.45549 0.698107 1.38773 0.387725 0.694209 + 1.25182 0.25182 0.473634 1.20456 0.204561 0.517531 1.20138 0.201378 0.418553 1.10725 0.107248 0.156086 + 1.1636 0.163604 0.201139 1.12933 0.129328 0.270685 1.13333 0.133333 0 1.2 0.2 0 + 1.12458 0.124579 0.077958 1.93333 0.933333 1 1.86667 0.866667 1 1.92776 0.927761 0.898125 + 1.06548 0.065484 0.258879 1.3194 0.319398 0.284147 1.39967 0.399671 0.285266 1.34042 0.340417 0.359313 + 1.15941 0.15941 0.473764 1.34313 0.343134 0.21133 1.86157 0.861568 0.911325 1.53333 0.533333 1 + 1.48074 0.48074 0.908278 1.56881 0.568815 0.912918 1.18324 0.18324 0.116201 1.33333 0.333333 0 + 1.4 0.4 0 1.36296 0.362961 0.1097 1.8 0.8 1 1.8061 0.806099 0.868827 + 1.8 0.8 0 1.86962 0.869619 0.0840346 1.8082 0.808202 0.115217 1.86667 0.866667 0 + 1.68787 0.687867 0.637379 1.70823 0.708233 0.539942 1.7473 0.747298 0.65289 1.77257 0.772575 0.573068 + 1.68124 0.681242 0.339883 1.62453 0.624525 0.409985 1.62813 0.628126 0.30893 1.52684 0.526845 0.822669 + 1.41634 0.416342 0.865994 1.63019 0.630185 0.497529 1.63291 0.632915 0.599835 1.31667 0.316667 0.45 + 1.36802 0.368018 0.46644 1.31064 0.310644 0.53682 1.6 0.6 0 1.66667 0.666667 0 + 1.63501 0.635012 0.0879763 1.36484 0.36484 0.554326 1.52972 0.529717 0.719629 2 1 0.5 + 2 1 0.6 1.9231 0.923097 0.537051 1.07793 0.0779285 0.728088 1.43246 0.432458 0.0702888 + 1.94957 0.949572 0.643523 1.63092 0.630918 0.883914 1.59837 0.59837 0.824866 1.66395 0.663948 0.820172 + 1.73976 0.739764 0.443236 1.78708 0.787082 0.493732 1.62224 0.622237 0.759433 1.33333 0.333333 1 + 1.26667 0.266667 1 1.30171 0.301709 0.892833 1.40602 0.406019 0.376934 1.06667 0.0666667 0 + 1.06226 0.0622627 0.0885724 1.15028 0.150279 0.66528 1.14777 0.147772 0.74723 1.25173 0.251728 0.143408 + 1.21964 0.219639 0.212101 1.74369 0.743694 0.152525 1.80106 0.801058 0.209881 1.72722 0.72722 0.255796 + 1.56172 0.561722 0.624065 1.59656 0.596557 0.691682 1.79573 0.795729 0.304944 1.27312 0.273121 0.398495 + 1.93333 0.933333 0 1.09998 0.0999799 0.625156 1.93182 0.931821 0.0981555 1.44259 0.442585 0.450938 + 1.45435 0.454348 0.356652 1.24701 0.247006 0.567873 1.87719 0.877192 0.174855 1.84619 0.846195 0.5 + 1.87605 0.876047 0.427525 1.43666 0.436659 0.149698 1.54328 0.543283 0.155153 1.56432 0.564318 0.253136 + 1.49209 0.492089 0.200084 1.48767 0.487672 0.290007 1.05916 0.0591641 0.815678 1.49904 0.499036 0.499069 + 1.46667 0.466667 1 1.33686 0.336861 0.79717 1.2804 0.2804 0.790359 1.4129 0.412896 0.606802 + 1.49106 0.491057 0.595976 1.23193 0.231927 0.850838 1.89268 0.892683 0.642453 1.94141 0.941408 0.428843 + 2 1 0.2 2 1 0.3 1.93102 0.931016 0.260306 2 1 0.7 + 2 1 0.8 1.93208 0.93208 0.73811 1.29794 0.297935 0.0824869 1.85674 0.856736 0.270444 + 1.2342 0.234199 0.929921 1.74129 0.741286 0.357728 1.6798 0.679805 0.431798 1.73223 0.732233 0.832923 + 1.78216 0.78216 0.791154 1.75204 0.75204 0.923492 1.57464 0.574635 0.758537 1.70335 0.703353 0.0800119 + 1.27657 0.276574 0.322434 1.68853 0.688533 0.915713 1.63494 0.634938 0.22651 1.69479 0.694788 0.73592 + 1.56727 0.567271 0.0774632 1.39498 0.394984 0.200044 1.87896 0.878965 0.824806 1.0564 0.0564012 0.432881 + 1.08065 0.0806509 0.522858 1.2 0.2 1 1.13333 0.133333 1 1.17069 0.170691 0.905933 + 1.60043 0.600434 0.166452 1.34053 0.34053 0.635347 1.14607 0.146072 0.412561 1.53333 0.533333 0 + 1.496 0.496005 0.0920461 1.67405 0.674049 0.177327 1.82801 0.828008 0.788915 1.8088 0.808798 0.40541 + 1.79559 0.795588 0.715852 1.82574 0.825742 0.62677 1.85753 0.857526 0.727843 1.30645 0.30645 0.156548 + 1.06878 0.0687788 0.901703 1.89556 0.895557 0.352427 1.20934 0.209339 0.704215 1.27758 0.277583 0.70112 + 1.23345 0.233454 0.770739 1.46667 0.466667 0 1.22261 0.222609 0.315471 1.37491 0.37491 0.924709 + 1.6 0.6 1 1.1175 0.117495 0.831884 1.74924 0.749236 0.744476 1.33603 0.336031 0.727768 + 2 1 0.4 1.75772 0.757716 0.0695508 1.27649 0.276491 0.235817 1.04882 0.0488211 0.163386 + 1.45148 0.451479 0.542033 1.6707 0.670696 0.264285 1.44348 0.443481 0.223762 1.23847 0.238466 0.640362 + 1.94513 0.945126 0.17656 1.94411 0.944113 0.819957 1.04609 0.04609 0.578689 2 1 0.1 + 2 1 0.9 1.1818 0.181797 0.805327 1.10314 0.103145 0.362243 1.04501 0.045006 0.350801 + 1.51315 0.513148 0.658494 1.36773 0.367734 0.850385 1.14265 0.142649 0.554092 1.23803 0.238034 0.0681273 + 1.28433 0.284329 0.620777 1.63333 0.633333 0.951476 1.86903 0.869034 0.572052 1.54176 0.541759 0.541355 + 1.04526 0.045256 0.6463 1.73333 0.733333 0 1.18954 0.189538 0.609802 1.95316 0.953159 0.348797 + 1.26667 0.266667 0 1.59091 0.590912 0.542616 1.06667 0.0666667 1 1.11971 0.11971 0.92842 + 1.4 0.4 1 1.65241 0.652409 0.68812 1.18232 0.182322 0.265185 1.84317 0.843174 0.34533 + 1.73333 0.733333 1 1.66667 0.666667 1 1.40526 0.405265 0.524353 1.1087 0.108704 0.462185 + 1.96629 0.966288 0.0495389 1.96667 0.966667 0.95 1.43034 0.430343 0.939041 1.03386 0.0338614 0.950426 + 1.16414 0.164142 0.340783 2 1 1 2 1 0 1.82013 0.820126 0.553124 + 0.0617485 -0.938251 0.571755 0.129823 -0.870177 0.572092 0.0848857 -0.915114 0.454066 0.167108 -0.832892 0.491586 + 0.217856 -0.782144 0.440472 0.247412 -0.752588 0.495642 0.213425 -0.786575 0.5668 0.731244 -0.268756 0.190176 + 0.672842 -0.327158 0.201576 0.688867 -0.311133 0.301389 0.763236 -0.236764 0.254286 0.846231 -0.153769 0.514059 + 0.926161 -0.0738395 0.567101 0.922906 -0.0770937 0.45412 0.95012 -0.0498799 0.35 0.865571 -0.134429 0.605118 + 0.165375 -0.834625 0.639339 0.226441 -0.773559 0.684015 0.253009 -0.746991 0.799884 0.294804 -0.705196 0.72085 + 0.203637 -0.796363 0.758499 0.333333 -0.666667 0 0.366667 -0.633333 0.111264 0.4 -0.6 0 + 0.6126 -0.3874 0.686044 0.631656 -0.368344 0.778409 0.689972 -0.310028 0.707868 0.94337 -0.0566303 0.917806 + 0.933333 -0.0666667 1 0.223175 -0.776825 0.870423 0.293695 -0.706305 0.90503 0.8 -0.2 1 + 0.83562 -0.16438 0.9102 0.761371 -0.238629 0.925648 0.694655 -0.305345 0.821056 0.637141 -0.362859 0.57181 + 0.566517 -0.433483 0.587705 0.628575 -0.371425 0.87458 0.693482 -0.306518 0.918489 0.350953 -0.649047 0.648865 + 0.285026 -0.714974 0.595616 0.927704 -0.0722961 0.266711 0.576457 -0.423543 0.485025 0.540077 -0.459923 0.386778 + 0.493981 -0.506019 0.43933 0.312025 -0.687975 0.808998 0.357837 -0.642163 0.554069 0.21504 -0.78496 0.372761 + 0.288772 -0.711228 0.395092 0.240259 -0.759741 0.307213 0.304312 -0.695688 0.499069 0.432328 -0.567672 0.505792 + 0.424821 -0.575179 0.61071 0.257492 -0.742508 0.15472 0.197263 -0.802737 0.117019 0.199541 -0.800459 0.225411 + 0.2 -0.8 0 0.140237 -0.859763 0.0813243 0.507303 -0.492697 0.519688 0.813058 -0.186942 0.166272 + 0.791339 -0.208661 0.86218 0.124405 -0.875595 0.177019 0.891879 -0.108121 0.367311 0.418745 -0.581255 0.412808 + 0.353505 -0.646495 0.460696 0.651141 -0.348859 0.46706 0.833333 -0.166667 0.233333 0.15223 -0.84777 0.728735 + 0.157997 -0.842003 0.40437 0.108113 -0.891887 0.346426 0.834637 -0.165363 0.415008 0.70861 -0.29139 0.602846 + 0.707141 -0.292859 0.512865 0.310279 -0.689721 0.279917 0.768077 -0.231923 0.486428 0.852373 -0.147627 0.303159 + 0.885222 -0.114777 0.129242 0.828806 -0.171194 0.0816261 0.878807 -0.121193 0.204127 0 -1 0.5 + 0.300021 -0.699979 0.0867057 0.170314 -0.829686 0.316659 0.125742 -0.874258 0.264803 0.364796 -0.635204 0.38142 + 0.349623 -0.650377 0.320603 0.378178 -0.621822 0.233396 0.312647 -0.687353 0.185775 0.666667 -0.333333 0 + 0.694961 -0.305039 0.100312 0.733333 -0.266667 0 0.430412 -0.569588 0.0838403 0.133333 -0.866667 0 + 0.115201 -0.884799 0.818127 0.0933912 -0.906609 0.886079 0.15889 -0.84111 0.909717 0 -1 0.4 + 0.263815 -0.736185 0.235762 0.615315 -0.384685 0.255557 0.624963 -0.375037 0.341629 0.800141 -0.199859 0.292967 + 0.939632 -0.0603678 0.162602 0.765242 -0.234758 0.129682 0.2 -0.8 1 0.233333 -0.766667 0.941338 + 0.765913 -0.234087 0.566244 0.809308 -0.190692 0.61692 0.89062 -0.10938 0.840524 0.823404 -0.176596 0.805278 + 0.662081 -0.337919 0.642142 0.528046 -0.471954 0.835588 0.475069 -0.524931 0.887516 0.512403 -0.487597 0.935262 + 0.771591 -0.228409 0.404645 0.766667 -0.233333 0.0580474 0.133333 -0.866667 1 0.421185 -0.578815 0.168082 + 0.551394 -0.448606 0.676084 0.757083 -0.242917 0.777065 0.053705 -0.946295 0.848105 0.091912 -0.908088 0.111041 + 0.0541916 -0.945808 0.159024 0.0705318 -0.929468 0.747455 0.756108 -0.243892 0.664344 0.500468 -0.499532 0.623768 + 0.108558 -0.891442 0.65097 0.898381 -0.101619 0.661991 0.865025 -0.134975 0.738609 0.931573 -0.0684265 0.747165 + 0 -1 0.8 0 -1 0.7 0 -1 0.3 0.069149 -0.930851 0.254405 + 0 -1 0.2 0 -1 0.6 0.361693 -0.638307 0.74518 0.244289 -0.755711 0.0716889 + 0.633333 -0.366667 0.948653 0.0513137 -0.948686 0.3507 0.0454979 -0.954502 0.93535 0.0463942 -0.953606 0.0654887 + 0.18284 -0.81716 0.825033 0.35142 -0.64858 0.849054 0.8 -0.2 0 0.866667 -0.133333 0 + 0.46623 -0.53377 0.564989 0.740007 -0.259993 0.860276 0.395549 -0.604451 0.810008 0.571747 -0.428252 0.328148 + 0.547679 -0.452321 0.25987 0.50832 -0.49168 0.305485 0.47838 -0.52162 0.156502 0.452288 -0.547712 0.255406 + 0.571327 -0.428673 0.91673 0.866667 -0.133333 1 0.712437 -0.287563 0.408507 0.464937 -0.535063 0.364563 + 0.478544 -0.521456 0.80485 0.45827 -0.54173 0.680102 0 -1 0.9 0 -1 0.1 + 0.402471 -0.597529 0.687049 0.40609 -0.59391 0.31319 0.604475 -0.395525 0.40113 0.805663 -0.194337 0.72053 + 0.466667 -0.533333 1 0.847776 -0.152224 0.665518 0.42579 -0.574211 0.927246 0.933333 -0.0666667 0 + 0.944003 -0.0559971 0.0790298 0.628711 -0.371289 0.163344 0.627337 -0.372663 0.0762417 0.582155 -0.417845 0.199788 + 0.048524 -0.951476 0.65 0.266667 -0.733333 1 0.333333 -0.666667 1 0.507827 -0.492173 0.733138 + 0.533333 -0.466667 1 0.6 -0.4 1 0.466667 -0.533333 0 0.569556 -0.430443 0.749766 + 0.953122 -0.0468775 0.652679 0.660245 -0.339755 0.392967 0.4 -0.6 1 0.355834 -0.644166 0.926727 + 0.799135 -0.200865 0.354744 0.266667 -0.733333 0 0.666667 -0.333333 1 0.733333 -0.266667 1 + 0.433333 -0.566667 0.752222 0.754794 -0.245206 0.336495 0.503661 -0.496339 0.233957 0.1 -0.9 0.950307 + 0.947069 -0.052931 0.829968 0.895626 -0.104374 0.0592182 0.6 -0.4 0 0.533333 -0.466667 0 + 0.482751 -0.517249 0.069577 0.531277 -0.468723 0.102862 0.58334 -0.41666 0.135414 0.535729 -0.464271 0.184752 + 0.395202 -0.604798 0.871255 0.585832 -0.414168 0.831015 0.575057 -0.424943 0.0629034 0.891322 -0.108678 0.940261 + 0 -1 1 0 -1 0 0.0666667 -0.933333 1 0.0666667 -0.933333 0 + 0.437967 -0.562033 0.842815 0.1 -0.9 0.0485882 2.5399 -0.539897 0.66591 2.56476 -0.564762 0.552593 + 2.5076 -0.507598 0.608965 2.5885 -0.588504 0.641936 2.4627 -0.462702 0.206687 2.3947 -0.394698 0.224722 + 2.45549 -0.45549 0.301893 2.38773 -0.387725 0.305791 2.25182 -0.25182 0.526366 2.20456 -0.204561 0.482469 + 2.20138 -0.201378 0.581447 2.10725 -0.107248 0.843914 2.1636 -0.163604 0.798861 2.12933 -0.129328 0.729315 + 2.13333 -0.133333 1 2.2 -0.2 1 2.12458 -0.124579 0.922042 2.93333 -0.933333 0 + 2.86667 -0.866667 0 2.92776 -0.927761 0.101875 2.06548 -0.065484 0.741121 2.3194 -0.319398 0.715853 + 2.39967 -0.399671 0.714734 2.34042 -0.340417 0.640687 2.15941 -0.15941 0.526236 2.34313 -0.343134 0.78867 + 2.86157 -0.861568 0.088675 2.53333 -0.533333 0 2.48074 -0.48074 0.091722 2.56881 -0.568815 0.0870817 + 2.18324 -0.18324 0.883799 2.33333 -0.333333 1 2.4 -0.4 1 2.36296 -0.362961 0.8903 + 2.8 -0.8 0 2.8061 -0.806099 0.131173 2.8 -0.8 1 2.86962 -0.869619 0.915965 + 2.8082 -0.808202 0.884783 2.86667 -0.866667 1 2.68787 -0.687867 0.362621 2.70823 -0.708233 0.460058 + 2.7473 -0.747298 0.34711 2.77257 -0.772575 0.426932 2.68124 -0.681242 0.660117 2.62453 -0.624525 0.590015 + 2.62813 -0.628126 0.69107 2.52684 -0.526845 0.177331 2.41634 -0.416342 0.134006 2.63019 -0.630185 0.502471 + 2.63291 -0.632915 0.400165 2.31667 -0.316667 0.55 2.36802 -0.368018 0.53356 2.31064 -0.310644 0.46318 + 2.6 -0.6 1 2.66667 -0.666667 1 2.63501 -0.635012 0.912024 2.36484 -0.36484 0.445674 + 2.52972 -0.529717 0.280371 3 -1 0.5 3 -1 0.4 2.9231 -0.923097 0.462949 + 2 0 0.3 2.07793 -0.0779285 0.271912 2 0 0.2 2.43246 -0.432458 0.929711 + 2.94957 -0.949572 0.356477 2.63092 -0.630918 0.116086 2.59837 -0.59837 0.175134 2.66395 -0.663948 0.179828 + 2.73976 -0.739764 0.556764 2.78708 -0.787082 0.506268 2.62224 -0.622237 0.240567 2.33333 -0.333333 0 + 2.26667 -0.266667 0 2.30171 -0.301709 0.107167 2.40602 -0.406019 0.623066 2 0 1 + 2.06667 -0.0666667 1 2.06226 -0.0622627 0.911428 2.15028 -0.150279 0.33472 2.14777 -0.147772 0.25277 + 2.25173 -0.251728 0.856592 2.21964 -0.219639 0.787899 2.74369 -0.743694 0.847475 2.80106 -0.801058 0.790119 + 2.72722 -0.72722 0.744204 2.56172 -0.561722 0.375935 2.59656 -0.596557 0.308318 2.79573 -0.795729 0.695056 + 2.27312 -0.273121 0.601505 2.93333 -0.933333 1 2.09998 -0.0999799 0.374844 2.93182 -0.931821 0.901845 + 2.44259 -0.442585 0.549062 2.45435 -0.454348 0.643348 2 0 0.9 2.24701 -0.247006 0.432127 + 2.87719 -0.877192 0.825145 2 0 0.8 2 0 0.7 2.84619 -0.846195 0.5 + 2.87605 -0.876047 0.572475 2.43666 -0.436659 0.850302 2.54328 -0.543283 0.844847 2.56432 -0.564318 0.746864 + 2.49209 -0.492089 0.799916 2.48767 -0.487672 0.709993 2.05916 -0.0591641 0.184322 2.49904 -0.499036 0.500931 + 2.46667 -0.466667 0 2.33686 -0.336861 0.20283 2.2804 -0.2804 0.209641 2.4129 -0.412896 0.393198 + 2.49106 -0.491057 0.404024 2.23193 -0.231927 0.149162 2.89268 -0.892683 0.357547 2.94141 -0.941408 0.571157 + 3 -1 0.8 3 -1 0.7 2.93102 -0.931016 0.739694 3 -1 0.3 + 3 -1 0.2 2.93208 -0.93208 0.26189 2.29794 -0.297935 0.917513 2.85674 -0.856736 0.729557 + 2.2342 -0.234199 0.0700793 2.74129 -0.741286 0.642272 2.6798 -0.679805 0.568202 2.73223 -0.732233 0.167077 + 2.78216 -0.78216 0.208846 2.75204 -0.75204 0.0765075 2.57464 -0.574635 0.241463 2.70335 -0.703353 0.919988 + 2.27657 -0.276574 0.677566 2.68853 -0.688533 0.0842873 2.63494 -0.634938 0.77349 2.69479 -0.694788 0.26408 + 2.56727 -0.567271 0.922537 2.39498 -0.394984 0.799956 2.87896 -0.878965 0.175194 2 0 0.5 + 2.0564 -0.0564012 0.567119 2.08065 -0.0806509 0.477142 2.2 -0.2 0 2.13333 -0.133333 0 + 2.17069 -0.170691 0.0940672 2.60043 -0.600434 0.833548 2.34053 -0.34053 0.364653 2.14607 -0.146072 0.587439 + 2.53333 -0.533333 1 2.496 -0.496005 0.907954 2.67405 -0.674049 0.822673 2.82801 -0.828008 0.211085 + 2.8088 -0.808798 0.59459 2.79559 -0.795588 0.284148 2.82574 -0.825742 0.37323 2.85753 -0.857526 0.272157 + 2.30645 -0.30645 0.843452 2 0 0.1 2.06878 -0.0687788 0.0982974 2.89556 -0.895557 0.647573 + 2.20934 -0.209339 0.295785 2.27758 -0.277583 0.29888 2.23345 -0.233454 0.229261 2.46667 -0.466667 1 + 2.22261 -0.222609 0.684529 2.37491 -0.37491 0.0752912 2.6 -0.6 0 2.1175 -0.117495 0.168116 + 2.74924 -0.749236 0.255524 2.33603 -0.336031 0.272232 3 -1 0.6 2.75772 -0.757716 0.930449 + 2.27649 -0.276491 0.764183 2.04882 -0.0488211 0.836614 2.45148 -0.451479 0.457967 2.6707 -0.670696 0.735715 + 2.44348 -0.443481 0.776238 2.23847 -0.238466 0.359638 2.94513 -0.945126 0.82344 2.94411 -0.944113 0.180043 + 2.04609 -0.04609 0.421311 3 -1 0.9 3 -1 0.1 2.1818 -0.181797 0.194673 + 2.10314 -0.103145 0.637757 2.04501 -0.045006 0.649199 2.51315 -0.513148 0.341505 2.36773 -0.367734 0.149615 + 2.14265 -0.142649 0.445908 2.23803 -0.238034 0.931873 2.28433 -0.284329 0.379223 2 0 0.6 + 2.63333 -0.633333 0.0485243 2.86903 -0.869034 0.427948 2.54176 -0.541759 0.458645 2.04526 -0.045256 0.3537 + 2.73333 -0.733333 1 2.18954 -0.189538 0.390198 2.95316 -0.953159 0.651203 2.26667 -0.266667 1 + 2.59091 -0.590912 0.457384 2.06667 -0.0666667 0 2.11971 -0.11971 0.0715799 2.4 -0.4 0 + 2.65241 -0.652409 0.31188 2.18232 -0.182322 0.734815 2.84317 -0.843174 0.65467 2.73333 -0.733333 0 + 2.66667 -0.666667 0 2.40526 -0.405265 0.475647 2 0 0.4 2.1087 -0.108704 0.537815 + 2.96629 -0.966288 0.950461 2.96667 -0.966667 0.05 2.43034 -0.430343 0.0609593 2.03386 -0.0338614 0.0495743 + 2.16414 -0.164142 0.659217 3 -1 1 3 -1 0 2 0 0 + 2.82013 -0.820126 0.446876 1.57073 0 0.812853 1.64227 0 0.753823 1.57201 0 0.698737 + 1.42916 0 0.187207 1.35551 0 0.247327 1.42799 0 0.301263 1.90012 0 0.900122 + 1.09988 0 0.0998781 1.1 0 0 1.9 0 1 1.1 0 1 + 1.09988 0 0.900122 1.9 0 0 1.90012 0 0.0998781 1.50219 0 0.776767 + 1.49781 0 0.223233 1.64494 0 0.651547 1.53699 0 0.599532 1.35522 0 0.347563 + 1.46301 0 0.400468 1.65047 0 0.432494 1.6962 0 0.505542 1.74535 0 0.39352 + 1.34953 0 0.567506 1.30313 0 0.49402 1.25465 0 0.60648 1.78488 0 0.497 + 1.21512 0 0.503 1.64016 0 0.566986 1.35984 0 0.433014 1.15113 0 0.35929 + 1.25472 0 0.395879 1.19873 0 0.272206 1.64071 0 0.151134 1.60814 0 0.258045 + 1.72779 0 0.198735 1.35929 0 0.848866 1.39186 0 0.741955 1.27221 0 0.801265 + 1.29286 0 0.292857 1.70714 0 0.292857 1.29286 0 0.707143 1.15182 0 0.640795 + 1.20691 0 0.720914 1.84818 0 0.359205 1.79309 0 0.279086 1.5 0 1 + 1.6 0 1 1.53656 0 0.889904 1.5 0 0 1.4 0 0 + 1.46344 0 0.110096 1.89032 0 0.460465 1.10968 0 0.539535 1.64327 0 0.928221 + 1.35649 0 0.0721241 1.07219 0 0.644127 1.92781 0 0.355873 1.59168 0 0.495378 + 1.40832 0 0.504623 1.5741 0 0.365315 1.55585 0 0.438731 1.4259 0 0.634685 + 1.44415 0 0.561269 1.48918 0 0.691767 1.34545 0 0.647119 1.65455 0 0.352881 + 1.51082 0 0.308233 1.64071 0 0.848866 1.35929 0 0.151134 1.90128 0 0.741233 + 1.09767 0 0.260926 1.7 0 1 1.8 0 1 1.73907 0 0.902335 + 1.3 0 0 1.2 0 0 1.2597 0 0.0993906 1.2 0 1 + 1.3 0 1 1.26093 0 0.902335 1.8 0 0 1.7 0 0 + 1.73907 0 0.0976651 1.09944 0 0.740305 1.90056 0 0.259695 1.5 0 0.5 + 1.91831 0 0.571217 1.43042 0 0.916709 1.08322 0 0.43092 1.56958 0 0.0832908 + 1.85802 0 0.653533 1.80276 0 0.732688 1.275 0 0.204694 1.82838 0 0.574688 + 1.16277 0 0.445725 1.44406 0 0.83484 1.55594 0 0.16516 1.8295 0 0.829497 + 1.72696 0 0.79583 1.1705 0 0.170503 1.1705 0 0.829497 1.8295 0 0.170503 + 1.4 0 1 1.6 0 0 1.81718 0 0.427548 1.18282 0 0.572452 + 1.92003 0 0.820102 1.07997 0 0.179898 1.8201 0 0.920029 1.1799 0 0.0799714 + 1.1799 0 0.920029 1.8201 0 0.0799714 1.07997 0 0.820102 1.92003 0 0.179898 + 1.73743 0 0.598978 1.93463 0 0.652283 1.35013 0 0.933582 1.64987 0 0.066418 + 1.0664 0 0.350227 1.78415 0 0.66175 1.71863 0 0.703664 + </DataArray> + </Points> + <Cells> + <DataArray type="Int32" Name="connectivity" NumberOfComponents="1" format="ascii"> + 0 1 2 3 4 5 3 6 4 7 8 9 + 10 11 12 7 9 13 14 15 16 10 12 17 + 14 16 18 1 19 2 20 21 22 23 24 25 + 1 26 27 28 29 30 31 32 20 24 33 25 + 29 34 30 26 35 27 21 36 22 37 38 39 + 40 41 42 43 44 45 46 39 38 47 42 41 + 48 45 44 49 50 25 51 52 27 53 54 30 + 19 23 2 55 56 57 58 59 60 61 62 63 + 64 65 66 57 56 67 62 68 63 65 69 66 + 59 70 60 31 71 32 19 24 23 46 25 50 + 47 27 52 48 30 54 36 0 22 72 73 28 + 19 1 74 72 28 75 31 20 76 23 77 2 + 43 67 56 49 63 68 51 66 69 53 60 70 + 78 79 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 100 101 + 102 22 0 58 60 103 61 63 104 64 66 105 + 55 106 56 107 108 83 49 95 50 51 98 52 + 53 101 54 34 109 60 33 110 63 35 111 66 + 31 56 71 28 73 112 113 114 38 72 44 76 + 72 75 44 19 74 41 115 80 39 116 117 88 + 118 86 42 119 91 45 46 38 114 47 41 74 + 31 76 44 48 44 75 113 77 114 23 114 77 + 55 120 106 121 58 103 122 61 104 123 64 105 + 33 124 25 35 125 27 34 126 30 78 80 127 + 81 83 128 84 86 129 87 130 88 92 91 131 + 94 132 95 97 133 98 100 134 101 37 39 80 + 40 42 86 43 45 91 135 88 117 115 50 95 + 116 83 108 118 52 98 119 54 101 6 81 128 + 5 130 87 8 84 129 11 78 127 92 131 15 + 94 17 132 97 13 133 100 18 134 60 109 103 + 63 110 104 66 111 105 56 106 71 6 128 4 + 5 4 130 8 129 9 11 127 12 15 131 16 + 17 12 132 13 9 133 18 16 134 116 108 117 + 115 39 50 118 42 52 119 45 54 36 21 136 + 36 136 26 113 38 29 19 41 24 34 60 126 + 33 63 124 53 126 60 35 66 125 49 124 63 + 51 125 66 31 137 56 43 56 137 79 138 80 + 37 80 138 49 68 95 53 70 101 51 69 98 + 93 95 68 99 101 70 96 98 69 43 91 67 + 85 139 86 82 140 83 90 67 91 107 83 140 + 40 86 139 135 141 88 89 88 141 142 107 111 + 143 21 32 20 32 21 135 117 32 34 29 38 + 143 136 21 35 26 136 33 24 41 136 142 111 + 113 29 112 36 26 0 28 112 29 1 0 26 + 143 32 117 115 127 80 116 128 83 116 88 130 + 115 95 132 118 129 86 118 98 133 119 131 91 + 119 101 134 37 109 38 34 38 109 35 136 111 + 33 41 110 40 110 41 23 25 114 46 114 25 + 1 27 74 28 30 75 47 74 27 48 75 30 + 46 50 39 143 117 108 47 52 42 48 54 45 + 72 76 22 20 22 76 31 44 137 43 137 44 + 143 142 136 107 142 108 116 4 128 115 12 127 + 116 130 4 115 132 12 118 9 129 118 133 9 + 119 16 131 119 134 16 102 77 112 113 112 77 + 121 103 138 37 138 103 123 105 140 107 140 105 + 122 104 139 40 139 104 135 106 141 120 141 106 + 135 32 71 79 121 138 82 123 140 85 122 139 + 89 141 120 57 67 90 62 93 68 65 96 69 + 59 99 70 49 25 124 51 27 125 53 30 126 + 102 73 22 72 22 73 37 103 109 107 105 111 + 40 104 110 135 71 106 143 108 142 102 0 2 + 102 112 73 102 2 77 144 145 146 147 145 144 + 148 149 150 149 151 150 152 153 154 155 156 157 + 158 159 160 161 162 163 155 157 164 165 166 167 + 154 153 168 169 166 165 162 170 163 171 172 173 + 160 159 174 175 176 177 178 179 170 180 181 182 + 180 183 181 184 185 186 187 186 185 188 189 190 + 191 172 148 192 148 172 193 185 194 184 194 185 + 195 196 197 198 199 200 197 196 201 191 148 202 + 150 202 148 203 204 205 93 206 94 176 207 177 + 204 208 205 209 210 211 212 213 185 187 185 213 + 214 211 210 162 178 170 215 216 217 218 167 166 + 7 219 220 221 222 206 223 224 174 225 226 227 + 147 190 189 228 229 202 191 173 172 230 227 226 + 195 231 167 195 167 196 183 232 181 233 221 206 + 232 234 181 146 235 236 7 220 8 174 224 156 + 195 197 152 237 152 197 238 226 182 84 164 85 + 239 240 205 241 177 207 242 243 244 245 244 243 + 94 206 246 247 235 146 171 248 172 249 217 250 + 150 251 252 253 250 217 247 146 145 254 205 208 + 203 205 255 256 257 258 259 260 261 175 177 262 + 238 263 226 216 264 217 188 265 266 212 266 265 + 267 268 179 267 179 269 202 229 270 199 271 200 + 188 266 189 272 167 231 209 211 273 178 269 179 + 274 190 243 184 186 275 198 200 276 241 277 177 + 218 196 167 169 177 277 278 170 179 61 279 280 + 150 151 251 281 282 283 274 243 284 205 240 255 + 285 251 151 193 266 185 168 286 154 287 276 288 + 200 289 284 284 289 274 278 179 290 191 202 270 + 212 265 291 267 273 211 212 185 266 292 293 294 + 230 291 265 278 294 261 238 258 263 253 217 264 + 225 182 226 169 295 177 17 246 296 297 263 258 + 254 261 294 254 294 293 298 299 300 245 236 166 + 292 186 293 187 293 186 301 287 288 154 302 231 + 218 166 236 147 243 190 215 217 303 304 171 173 + 305 206 222 275 186 306 241 288 244 242 244 288 + 94 246 17 285 307 299 308 203 255 180 182 309 + 219 158 160 225 227 289 310 302 224 219 160 220 + 230 226 263 242 284 243 191 270 210 84 311 164 + 252 251 312 227 313 289 245 166 314 298 315 299 + 242 288 276 272 231 302 188 227 265 169 277 166 + 230 265 227 256 258 316 260 317 261 200 284 276 + 233 318 280 319 316 234 320 163 317 253 283 321 + 322 323 164 228 202 324 238 182 181 61 280 318 + 154 231 152 212 291 213 285 151 307 249 325 217 + 225 309 182 233 280 326 159 327 174 85 164 323 + 305 321 283 298 321 222 285 299 328 122 279 61 + 239 213 291 304 173 329 239 205 330 218 236 235 + 223 174 327 209 173 210 155 164 311 254 330 205 + 272 302 310 305 246 206 247 145 331 233 206 332 + 319 256 316 260 320 317 239 291 240 199 333 271 + 334 326 153 150 324 202 254 208 261 297 258 335 + 292 294 290 209 329 173 93 332 206 336 175 262 + 238 316 258 278 261 317 155 174 156 267 275 306 + 193 145 189 259 261 208 257 335 258 299 250 300 + 322 164 157 193 337 145 147 189 145 228 252 331 + 247 331 252 281 283 264 155 160 174 338 296 339 + 305 283 339 278 163 170 292 290 268 340 215 303 + 253 264 283 147 144 243 242 276 284 245 243 144 + 184 341 194 191 210 173 342 157 156 298 300 321 + 230 343 291 267 211 275 291 343 240 214 275 211 + 274 289 313 282 338 339 282 339 283 305 339 296 + 344 345 273 168 153 326 209 273 329 333 180 309 + 238 181 234 267 269 273 346 201 196 238 234 316 + 278 317 163 249 250 307 194 341 229 237 334 153 + 272 165 167 299 307 250 214 341 275 184 275 341 + 150 252 324 178 344 269 249 307 149 151 149 307 + 245 144 146 305 296 246 334 221 326 245 146 236 + 267 306 268 336 262 327 200 271 289 228 324 252 + 221 233 326 217 325 303 177 295 262 192 149 148 + 247 252 312 61 318 62 333 309 271 223 327 262 + 280 347 326 301 288 207 346 251 201 285 201 251 + 241 207 288 168 326 347 297 335 255 228 194 229 + 297 240 343 305 222 321 8 311 84 287 198 276 + 346 312 251 345 329 273 188 313 227 342 224 302 + 308 255 335 225 271 309 228 337 194 195 152 231 + 179 268 290 298 221 334 298 334 315 237 153 152 + 176 301 207 237 315 334 322 347 279 225 289 271 + 232 348 234 161 163 349 62 332 93 159 336 327 + 230 263 343 299 315 328 340 303 350 192 350 303 + 285 328 197 338 351 296 245 314 244 216 281 264 + 237 197 328 257 308 335 204 259 208 8 220 311 + 297 255 240 233 332 318 342 302 352 319 234 348 + 320 349 163 145 337 331 322 286 347 85 323 122 + 298 222 221 228 331 337 278 290 294 223 295 310 + 169 310 295 248 340 350 17 296 351 297 343 263 + 353 349 320 10 17 351 354 319 348 223 262 295 + 344 273 269 155 220 160 346 196 235 218 235 196 + 193 189 266 193 194 337 322 279 323 248 350 172 + 122 323 279 342 156 224 214 270 229 292 306 186 + 254 293 330 192 172 350 345 304 329 192 303 325 + 223 310 224 169 165 310 354 348 232 353 161 349 + 10 351 338 272 310 165 154 352 302 214 229 341 + 155 311 220 187 355 293 253 321 300 253 300 250 + 292 268 306 241 244 314 342 352 157 285 197 201 + 247 312 235 346 235 312 280 279 347 214 210 270 + 192 325 149 187 213 355 239 355 213 241 314 277 + 166 277 314 322 157 352 237 328 315 274 313 190 + 188 190 313 62 318 332 249 149 325 168 347 286 + 322 352 286 293 355 330 239 330 355 154 286 352 + 356 357 358 358 357 359 360 359 361 361 359 362 + 363 364 365 366 363 365 367 368 369 122 370 369 + 367 371 368 357 372 362 373 374 375 359 357 362 + 373 376 374 377 378 379 380 381 382 10 383 384 + 385 386 374 387 388 389 390 382 381 380 391 392 + 390 393 394 122 369 61 395 396 375 10 17 383 + 84 397 85 398 399 400 401 374 386 395 402 396 + 403 404 405 406 396 402 407 402 408 373 375 396 + 360 404 403 409 410 411 412 413 410 398 400 414 + 395 408 402 366 415 363 416 389 388 417 411 410 + 418 369 370 407 419 420 398 391 421 422 415 366 + 373 372 423 407 420 402 359 424 358 390 381 393 + 373 423 376 425 358 424 367 369 426 427 428 391 + 418 426 369 405 404 429 367 426 430 418 397 431 + 432 433 415 432 415 434 435 356 358 377 436 378 + 437 411 438 411 417 438 439 440 404 429 404 440 + 441 442 429 373 396 362 443 444 445 379 378 446 + 447 413 412 448 449 450 398 392 391 435 358 451 + 429 442 452 364 453 365 397 434 431 454 365 453 + 418 370 397 422 366 455 84 456 397 457 363 415 + 458 459 450 367 430 460 367 460 461 462 463 388 + 391 428 421 380 382 464 465 466 467 430 426 468 + 445 444 469 470 458 450 441 471 378 85 397 370 + 380 392 472 441 378 442 416 463 473 390 473 382 + 448 474 449 417 475 476 448 423 477 422 431 434 + 427 464 382 427 382 478 479 392 414 373 362 372 + 417 410 413 480 477 423 380 464 391 398 414 392 + 360 361 404 385 459 386 427 391 464 61 369 368 + 481 482 483 484 477 485 486 487 488 93 483 94 + 489 356 435 407 400 419 448 477 474 417 476 487 + 395 375 490 409 491 410 406 404 361 417 413 475 + 393 492 394 416 388 463 451 358 493 449 474 494 + 475 495 476 376 423 496 412 410 491 496 423 448 + 401 497 490 498 433 499 407 408 500 416 473 501 + 407 414 400 490 497 502 425 493 358 385 450 459 + 409 452 442 503 504 505 506 471 507 457 469 444 + 441 507 471 465 467 508 441 429 440 399 503 505 + 387 509 388 510 428 430 511 399 505 405 429 452 + 465 512 466 479 408 513 494 474 514 495 515 476 + 479 500 408 395 516 408 401 490 375 511 507 517 + 439 404 420 406 361 396 359 360 424 398 518 399 + 406 420 404 378 436 442 362 396 361 61 368 62 + 519 461 478 520 467 466 481 521 482 520 466 522 + 510 430 468 7 523 524 364 525 453 405 411 437 + 409 442 436 443 526 444 7 524 8 511 400 399 + 511 517 419 364 363 444 453 525 527 457 444 363 + 441 517 507 425 487 493 480 528 477 519 521 461 + 529 530 386 465 531 512 367 461 371 511 419 400 + 486 493 487 485 477 528 479 531 472 510 421 428 + 532 533 508 379 446 534 533 492 508 465 535 531 + 398 421 518 481 483 536 425 424 437 8 524 456 + 421 537 518 519 473 463 462 483 482 93 536 483 + 538 522 539 540 426 431 427 478 460 439 419 517 + 541 436 377 418 431 426 542 543 394 380 535 381 + 8 456 84 544 531 513 439 420 419 479 513 531 + 366 365 545 544 512 531 506 507 546 498 469 433 + 461 460 478 393 508 492 480 423 372 364 444 525 + 511 505 507 484 474 477 488 487 476 405 452 411 + 457 433 469 449 547 450 409 436 491 94 548 17 + 94 483 548 499 433 549 417 487 438 479 414 500 + 514 474 484 488 476 515 481 368 371 406 402 420 + 480 356 528 550 526 443 425 438 487 17 548 383 + 409 411 452 489 528 356 504 503 453 462 548 483 + 551 552 553 407 500 414 534 552 551 496 385 374 + 454 453 503 376 496 374 554 553 555 506 555 553 + 529 386 459 401 375 374 556 539 522 454 537 365 + 432 549 433 465 508 557 393 557 508 530 538 539 + 510 365 537 454 518 537 543 387 389 510 545 365 + 395 490 516 412 491 541 554 527 525 510 537 421 + 480 357 356 437 424 403 542 394 492 540 468 426 + 504 453 527 479 472 392 544 516 490 462 482 463 + 382 473 478 470 450 547 551 553 558 378 471 446 + 519 478 473 551 558 550 462 388 559 462 559 383 + 457 415 433 531 535 472 544 490 502 530 539 386 + 520 532 467 385 496 450 390 501 473 519 482 521 + 506 446 471 85 370 122 538 520 522 448 450 496 + 422 434 415 401 386 497 393 381 557 560 494 514 + 561 515 495 427 460 428 432 456 524 485 528 489 + 451 493 486 430 428 460 543 389 394 444 526 525 + 534 446 552 541 491 436 506 553 552 560 562 494 + 561 495 563 381 535 557 506 552 446 480 372 357 + 481 536 368 62 536 93 509 384 559 506 546 555 + 554 558 553 425 437 438 390 394 501 62 368 536 + 462 383 548 380 472 535 499 549 523 458 529 459 + 441 440 517 445 469 498 405 437 403 384 383 559 + 544 513 516 408 516 513 366 545 455 544 564 512 + 540 455 545 533 542 492 563 565 447 562 470 547 + 544 502 564 432 434 456 554 525 526 556 522 564 + 554 526 558 466 564 522 550 558 526 397 456 434 + 532 508 467 465 557 535 509 559 388 519 463 482 + 504 527 555 386 539 497 461 521 371 510 468 545 + 540 545 468 556 502 497 394 389 501 399 518 503 + 439 517 440 454 503 518 360 403 424 554 555 527 + 504 555 546 523 549 524 447 565 413 475 413 565 + 481 371 521 422 455 431 540 431 455 416 501 389 + 466 512 564 432 524 549 562 547 494 563 495 565 + 475 565 495 449 494 547 556 497 539 556 564 502 + 504 546 505 507 505 546 566 567 568 569 567 566 + 570 571 572 571 573 572 574 575 576 577 578 579 + 580 581 582 583 584 585 577 579 586 587 588 589 + 576 575 590 591 588 587 584 592 585 593 594 595 + 582 581 596 597 598 599 600 601 592 602 603 604 + 602 605 603 606 607 608 609 608 607 610 611 612 + 613 594 570 614 570 594 615 607 616 606 616 607 + 617 618 619 620 621 622 619 618 623 613 570 624 + 572 624 570 625 626 627 628 629 630 598 631 599 + 626 632 627 633 634 635 636 637 607 609 607 637 + 638 635 634 584 600 592 639 640 641 642 589 588 + 643 644 645 646 647 629 648 649 596 650 651 652 + 569 612 611 653 654 624 613 595 594 655 652 651 + 617 656 589 617 589 618 605 657 603 658 646 629 + 657 659 603 568 660 661 643 645 662 596 649 578 + 617 619 574 663 574 619 664 651 604 665 586 666 + 667 668 627 669 599 631 670 671 672 673 672 671 + 630 629 674 675 660 568 593 676 594 677 641 678 + 572 679 680 681 678 641 675 568 567 682 627 632 + 625 627 683 684 685 686 687 688 689 597 599 690 + 664 691 651 640 692 641 610 693 694 636 694 693 + 695 696 601 695 601 697 624 654 698 621 699 622 + 610 694 611 700 589 656 633 635 701 600 697 601 + 702 612 671 606 608 703 620 622 704 669 705 599 + 642 618 589 591 599 705 706 592 601 707 708 709 + 572 573 679 710 711 712 702 671 713 627 668 683 + 714 679 573 615 694 607 590 715 576 716 704 717 + 622 718 713 713 718 702 706 601 719 613 624 698 + 636 693 720 695 701 635 636 607 694 721 722 723 + 655 720 693 664 686 691 706 723 689 681 641 692 + 650 604 651 591 724 599 725 674 726 727 691 686 + 682 689 723 682 723 722 728 729 730 673 661 588 + 721 608 722 609 722 608 731 716 717 576 732 656 + 642 588 661 569 671 612 639 641 733 734 593 595 + 735 629 647 703 608 736 669 717 672 670 672 717 + 630 674 725 714 737 729 738 625 683 602 604 739 + 644 580 582 650 652 718 740 732 649 644 582 645 + 655 651 691 670 713 671 613 698 634 665 741 586 + 680 679 742 652 743 718 673 588 744 728 745 729 + 670 717 704 700 656 732 610 652 693 591 705 588 + 655 693 652 684 686 746 688 747 689 622 713 704 + 658 748 709 749 746 659 750 585 747 681 712 751 + 752 753 586 653 624 754 664 604 603 707 709 748 + 576 656 574 636 720 637 714 573 737 677 755 641 + 650 739 604 658 709 756 581 757 596 666 586 753 + 735 751 712 728 751 647 714 729 758 759 708 707 + 667 637 720 734 595 760 667 627 761 642 661 660 + 648 596 757 633 595 634 577 586 741 682 761 627 + 700 732 740 735 674 629 675 567 762 658 629 763 + 749 684 746 688 750 747 667 720 668 621 764 699 + 765 756 575 572 754 624 682 632 689 727 686 766 + 721 723 719 633 760 595 628 763 629 767 597 690 + 664 746 686 706 689 747 577 596 578 695 703 736 + 615 567 611 685 766 686 687 689 632 729 678 730 + 752 586 579 615 768 567 569 611 567 653 680 762 + 675 762 680 710 712 692 577 582 596 769 726 770 + 735 712 770 706 585 592 721 719 696 771 639 733 + 681 692 712 569 566 671 670 704 713 673 671 566 + 606 772 616 613 634 595 773 579 578 728 730 751 + 655 774 720 695 635 703 720 774 668 638 703 635 + 702 718 743 711 769 770 711 770 712 735 770 726 + 775 776 701 590 575 756 633 701 760 764 602 739 + 664 603 659 695 697 701 777 623 618 664 659 746 + 706 747 585 677 678 737 616 772 654 663 765 575 + 700 587 589 729 737 678 638 772 703 606 703 772 + 572 680 754 600 775 697 677 737 571 573 571 737 + 673 566 568 735 726 674 765 646 756 673 568 661 + 695 736 696 767 690 757 622 699 718 653 754 680 + 646 658 756 641 755 733 599 724 690 614 571 570 + 675 680 742 707 748 778 764 739 699 648 757 690 + 709 779 756 731 717 631 777 679 623 714 623 679 + 669 631 717 590 756 779 727 766 683 653 616 654 + 727 668 774 735 647 751 662 741 665 716 620 704 + 777 742 679 776 760 701 610 743 652 773 649 732 + 738 683 766 650 699 739 653 768 616 617 574 656 + 601 696 719 728 646 765 728 765 745 663 575 574 + 598 731 631 663 745 765 752 779 708 650 718 699 + 657 780 659 583 585 781 778 763 628 581 767 757 + 655 691 774 729 745 758 771 733 782 614 782 733 + 714 758 619 769 783 726 673 744 672 640 710 692 + 663 619 758 685 738 766 626 687 632 662 645 741 + 727 683 668 658 763 748 773 732 784 749 659 780 + 750 781 585 567 768 762 752 715 779 666 753 759 + 728 647 646 653 762 768 706 719 723 648 724 740 + 591 740 724 676 771 782 725 726 783 727 774 691 + 785 749 780 786 781 750 787 725 783 648 690 724 + 775 701 697 577 645 582 777 618 660 642 660 618 + 615 611 694 615 616 768 752 708 753 676 782 594 + 759 753 708 773 578 649 638 698 654 721 736 608 + 682 722 761 614 594 782 776 734 760 614 733 755 + 648 740 649 591 587 740 785 780 657 786 583 781 + 787 783 769 700 740 587 576 784 732 638 654 772 + 577 741 645 609 788 722 681 751 730 681 730 678 + 721 696 736 669 672 744 773 784 579 714 619 623 + 675 742 660 777 660 742 709 708 779 638 634 698 + 614 755 571 609 637 788 667 788 637 669 744 705 + 588 705 744 752 579 784 663 758 745 702 743 612 + 610 612 743 778 748 763 677 571 755 590 779 715 + 752 784 715 722 788 761 667 761 788 576 715 784 + 789 790 791 792 793 794 643 662 795 7 8 796 + 7 796 797 643 795 798 10 799 800 787 801 802 + 10 800 17 787 802 725 803 789 791 804 792 794 + 791 805 806 794 807 808 809 810 811 812 813 814 + 810 815 811 813 816 814 805 817 806 807 818 808 + 819 820 821 822 823 824 825 826 827 828 821 820 + 829 824 823 830 827 826 831 832 814 833 834 811 + 835 836 837 838 839 840 707 778 841 61 62 842 + 836 843 837 839 844 840 62 845 842 778 846 841 + 830 814 832 829 811 834 817 847 806 818 848 808 + 849 850 809 851 852 812 803 791 853 851 812 854 + 849 809 855 804 794 856 857 837 843 858 840 844 + 831 842 845 833 841 846 665 666 859 84 85 860 + 861 862 863 864 865 866 867 868 869 870 871 872 + 93 94 873 628 630 874 875 806 847 875 808 848 + 707 841 876 835 837 877 61 842 878 838 840 879 + 880 881 859 858 866 882 831 873 832 833 874 834 + 815 883 841 816 884 842 803 885 837 804 886 840 + 809 850 847 812 852 848 858 882 793 851 826 853 + 851 854 826 849 823 856 849 855 823 887 888 863 + 889 860 821 890 869 827 891 872 824 803 853 826 + 830 826 854 804 856 823 829 823 855 892 835 877 + 893 838 879 759 707 876 122 61 878 815 894 811 + 816 895 814 665 859 896 84 860 897 862 898 863 + 865 899 866 867 869 900 870 872 901 94 902 873 + 630 903 874 819 821 860 857 863 888 822 824 872 + 825 827 869 887 859 881 889 882 866 890 832 873 + 891 834 874 828 793 882 8 84 897 662 665 896 + 862 798 898 865 797 899 799 867 900 801 870 901 + 94 17 902 630 725 903 841 883 876 837 885 877 + 842 884 878 840 886 879 8 897 796 662 896 795 + 798 795 898 797 796 899 799 900 800 801 901 802 + 17 800 902 725 802 903 887 881 888 889 821 882 + 890 827 832 891 824 834 817 805 904 817 904 810 + 818 807 820 818 820 813 815 841 894 833 894 841 + 816 842 895 831 895 842 857 789 837 803 837 789 + 858 792 840 804 840 792 666 905 859 880 859 905 + 833 846 874 857 843 863 831 845 873 861 863 843 + 858 844 866 628 874 846 93 873 845 825 869 906 + 822 872 907 864 866 844 85 908 860 819 860 908 + 868 906 869 871 907 872 909 880 883 910 805 790 + 791 790 805 828 807 793 794 793 807 857 888 790 + 910 904 805 815 810 904 828 820 807 816 813 820 + 904 909 883 817 810 847 809 847 810 818 813 848 + 812 848 813 910 790 888 887 896 859 887 863 898 + 889 897 860 889 866 899 890 900 869 891 901 872 + 890 873 902 891 874 903 815 904 883 819 884 820 + 816 820 884 803 826 885 825 885 826 804 823 886 + 822 886 823 809 811 855 812 814 854 829 855 811 + 830 854 814 910 888 881 828 882 821 830 832 827 + 829 834 824 791 806 853 851 853 806 849 856 808 + 794 808 856 910 909 904 880 909 881 887 795 896 + 887 898 795 889 796 897 889 899 796 890 800 900 + 890 902 800 891 802 901 891 903 802 759 876 905 + 880 905 876 122 878 908 819 908 878 825 906 877 + 822 907 879 892 877 906 893 879 907 666 759 905 + 85 122 908 836 861 843 839 864 844 868 892 906 + 871 893 907 62 93 845 778 628 846 833 811 894 + 831 814 895 875 852 806 875 850 808 851 806 852 + 849 808 850 880 876 883 819 878 884 825 877 885 + 822 879 886 910 881 909 857 790 789 858 793 792 + 875 847 850 875 848 852 + </DataArray> + <DataArray type="Int32" Name="offsets" NumberOfComponents="1" format="ascii"> + 3 6 9 12 15 18 21 24 27 30 33 36 + 39 42 45 48 51 54 57 60 63 66 69 72 + 75 78 81 84 87 90 93 96 99 102 105 108 + 111 114 117 120 123 126 129 132 135 138 141 144 + 147 150 153 156 159 162 165 168 171 174 177 180 + 183 186 189 192 195 198 201 204 207 210 213 216 + 219 222 225 228 231 234 237 240 243 246 249 252 + 255 258 261 264 267 270 273 276 279 282 285 288 + 291 294 297 300 303 306 309 312 315 318 321 324 + 327 330 333 336 339 342 345 348 351 354 357 360 + 363 366 369 372 375 378 381 384 387 390 393 396 + 399 402 405 408 411 414 417 420 423 426 429 432 + 435 438 441 444 447 450 453 456 459 462 465 468 + 471 474 477 480 483 486 489 492 495 498 501 504 + 507 510 513 516 519 522 525 528 531 534 537 540 + 543 546 549 552 555 558 561 564 567 570 573 576 + 579 582 585 588 591 594 597 600 603 606 609 612 + 615 618 621 624 627 630 633 636 639 642 645 648 + 651 654 657 660 663 666 669 672 675 678 681 684 + 687 690 693 696 699 702 705 708 711 714 717 720 + 723 726 729 732 735 738 741 744 747 750 753 756 + 759 762 765 768 771 774 777 780 783 786 789 792 + 795 798 801 804 807 810 813 816 819 822 825 828 + 831 834 837 840 843 846 849 852 855 858 861 864 + 867 870 873 876 879 882 885 888 891 894 897 900 + 903 906 909 912 915 918 921 924 927 930 933 936 + 939 942 945 948 951 954 957 960 963 966 969 972 + 975 978 981 984 987 990 993 996 999 1002 1005 1008 + 1011 1014 1017 1020 1023 1026 1029 1032 1035 1038 1041 1044 + 1047 1050 1053 1056 1059 1062 1065 1068 1071 1074 1077 1080 + 1083 1086 1089 1092 1095 1098 1101 1104 1107 1110 1113 1116 + 1119 1122 1125 1128 1131 1134 1137 1140 1143 1146 1149 1152 + 1155 1158 1161 1164 1167 1170 1173 1176 1179 1182 1185 1188 + 1191 1194 1197 1200 1203 1206 1209 1212 1215 1218 1221 1224 + 1227 1230 1233 1236 1239 1242 1245 1248 1251 1254 1257 1260 + 1263 1266 1269 1272 1275 1278 1281 1284 1287 1290 1293 1296 + 1299 1302 1305 1308 1311 1314 1317 1320 1323 1326 1329 1332 + 1335 1338 1341 1344 1347 1350 1353 1356 1359 1362 1365 1368 + 1371 1374 1377 1380 1383 1386 1389 1392 1395 1398 1401 1404 + 1407 1410 1413 1416 1419 1422 1425 1428 1431 1434 1437 1440 + 1443 1446 1449 1452 1455 1458 1461 1464 1467 1470 1473 1476 + 1479 1482 1485 1488 1491 1494 1497 1500 1503 1506 1509 1512 + 1515 1518 1521 1524 1527 1530 1533 1536 1539 1542 1545 1548 + 1551 1554 1557 1560 1563 1566 1569 1572 1575 1578 1581 1584 + 1587 1590 1593 1596 1599 1602 1605 1608 1611 1614 1617 1620 + 1623 1626 1629 1632 1635 1638 1641 1644 1647 1650 1653 1656 + 1659 1662 1665 1668 1671 1674 1677 1680 1683 1686 1689 1692 + 1695 1698 1701 1704 1707 1710 1713 1716 1719 1722 1725 1728 + 1731 1734 1737 1740 1743 1746 1749 1752 1755 1758 1761 1764 + 1767 1770 1773 1776 1779 1782 1785 1788 1791 1794 1797 1800 + 1803 1806 1809 1812 1815 1818 1821 1824 1827 1830 1833 1836 + 1839 1842 1845 1848 1851 1854 1857 1860 1863 1866 1869 1872 + 1875 1878 1881 1884 1887 1890 1893 1896 1899 1902 1905 1908 + 1911 1914 1917 1920 1923 1926 1929 1932 1935 1938 1941 1944 + 1947 1950 1953 1956 1959 1962 1965 1968 1971 1974 1977 1980 + 1983 1986 1989 1992 1995 1998 2001 2004 2007 2010 2013 2016 + 2019 2022 2025 2028 2031 2034 2037 2040 2043 2046 2049 2052 + 2055 2058 2061 2064 2067 2070 2073 2076 2079 2082 2085 2088 + 2091 2094 2097 2100 2103 2106 2109 2112 2115 2118 2121 2124 + 2127 2130 2133 2136 2139 2142 2145 2148 2151 2154 2157 2160 + 2163 2166 2169 2172 2175 2178 2181 2184 2187 2190 2193 2196 + 2199 2202 2205 2208 2211 2214 2217 2220 2223 2226 2229 2232 + 2235 2238 2241 2244 2247 2250 2253 2256 2259 2262 2265 2268 + 2271 2274 2277 2280 2283 2286 2289 2292 2295 2298 2301 2304 + 2307 2310 2313 2316 2319 2322 2325 2328 2331 2334 2337 2340 + 2343 2346 2349 2352 2355 2358 2361 2364 2367 2370 2373 2376 + 2379 2382 2385 2388 2391 2394 2397 2400 2403 2406 2409 2412 + 2415 2418 2421 2424 2427 2430 2433 2436 2439 2442 2445 2448 + 2451 2454 2457 2460 2463 2466 2469 2472 2475 2478 2481 2484 + 2487 2490 2493 2496 2499 2502 2505 2508 2511 2514 2517 2520 + 2523 2526 2529 2532 2535 2538 2541 2544 2547 2550 2553 2556 + 2559 2562 2565 2568 2571 2574 2577 2580 2583 2586 2589 2592 + 2595 2598 2601 2604 2607 2610 2613 2616 2619 2622 2625 2628 + 2631 2634 2637 2640 2643 2646 2649 2652 2655 2658 2661 2664 + 2667 2670 2673 2676 2679 2682 2685 2688 2691 2694 2697 2700 + 2703 2706 2709 2712 2715 2718 2721 2724 2727 2730 2733 2736 + 2739 2742 2745 2748 2751 2754 2757 2760 2763 2766 2769 2772 + 2775 2778 2781 2784 2787 2790 2793 2796 2799 2802 2805 2808 + 2811 2814 2817 2820 2823 2826 2829 2832 2835 2838 2841 2844 + 2847 2850 2853 2856 2859 2862 2865 2868 2871 2874 2877 2880 + 2883 2886 2889 2892 2895 2898 2901 2904 2907 2910 2913 2916 + 2919 2922 2925 2928 2931 2934 2937 2940 2943 2946 2949 2952 + 2955 2958 2961 2964 2967 2970 2973 2976 2979 2982 2985 2988 + 2991 2994 2997 3000 3003 3006 3009 3012 3015 3018 3021 3024 + 3027 3030 3033 3036 3039 3042 3045 3048 3051 3054 3057 3060 + 3063 3066 3069 3072 3075 3078 3081 3084 3087 3090 3093 3096 + 3099 3102 3105 3108 3111 3114 3117 3120 3123 3126 3129 3132 + 3135 3138 3141 3144 3147 3150 3153 3156 3159 3162 3165 3168 + 3171 3174 3177 3180 3183 3186 3189 3192 3195 3198 3201 3204 + 3207 3210 3213 3216 3219 3222 3225 3228 3231 3234 3237 3240 + 3243 3246 3249 3252 3255 3258 3261 3264 3267 3270 3273 3276 + 3279 3282 3285 3288 3291 3294 3297 3300 3303 3306 3309 3312 + 3315 3318 3321 3324 3327 3330 3333 3336 3339 3342 3345 3348 + 3351 3354 3357 3360 3363 3366 3369 3372 3375 3378 3381 3384 + 3387 3390 3393 3396 3399 3402 3405 3408 3411 3414 3417 3420 + 3423 3426 3429 3432 3435 3438 3441 3444 3447 3450 3453 3456 + 3459 3462 3465 3468 3471 3474 3477 3480 3483 3486 3489 3492 + 3495 3498 3501 3504 3507 3510 3513 3516 3519 3522 3525 3528 + 3531 3534 3537 3540 3543 3546 3549 3552 3555 3558 3561 3564 + 3567 3570 3573 3576 3579 3582 3585 3588 3591 3594 3597 3600 + 3603 3606 3609 3612 3615 3618 3621 3624 3627 3630 3633 3636 + 3639 3642 3645 3648 3651 3654 3657 3660 3663 3666 3669 3672 + 3675 3678 3681 3684 3687 3690 3693 3696 3699 3702 3705 3708 + 3711 3714 3717 3720 3723 3726 3729 3732 3735 3738 3741 3744 + 3747 3750 3753 3756 3759 3762 3765 3768 3771 3774 3777 3780 + 3783 3786 3789 3792 3795 3798 3801 3804 3807 3810 3813 3816 + 3819 3822 3825 3828 3831 3834 3837 3840 3843 3846 3849 3852 + 3855 3858 3861 3864 3867 3870 3873 3876 3879 3882 3885 3888 + 3891 3894 3897 3900 3903 3906 3909 3912 3915 3918 3921 3924 + 3927 3930 3933 3936 3939 3942 3945 3948 3951 3954 3957 3960 + 3963 3966 3969 3972 3975 3978 3981 3984 3987 3990 3993 3996 + 3999 4002 4005 4008 4011 4014 4017 4020 4023 4026 4029 4032 + 4035 4038 4041 4044 4047 4050 4053 4056 4059 4062 4065 4068 + 4071 4074 4077 4080 4083 4086 4089 4092 4095 4098 4101 4104 + 4107 4110 4113 4116 4119 4122 4125 4128 4131 4134 4137 4140 + 4143 4146 4149 4152 4155 4158 4161 4164 4167 4170 4173 4176 + 4179 4182 4185 4188 4191 4194 4197 4200 4203 4206 4209 4212 + 4215 4218 4221 4224 4227 4230 4233 4236 4239 4242 4245 4248 + 4251 4254 4257 4260 4263 4266 4269 4272 4275 4278 4281 4284 + 4287 4290 4293 4296 4299 4302 4305 4308 4311 4314 4317 4320 + 4323 4326 4329 4332 4335 4338 4341 4344 4347 4350 4353 4356 + 4359 4362 4365 4368 4371 4374 4377 4380 4383 4386 4389 4392 + 4395 4398 4401 4404 4407 4410 4413 4416 4419 4422 4425 4428 + 4431 4434 4437 4440 4443 4446 4449 4452 4455 4458 4461 4464 + 4467 4470 4473 4476 4479 4482 4485 4488 4491 4494 4497 4500 + 4503 4506 4509 4512 4515 4518 4521 4524 4527 4530 4533 4536 + 4539 4542 4545 4548 4551 4554 4557 4560 4563 4566 4569 4572 + 4575 4578 4581 4584 4587 4590 4593 4596 4599 4602 4605 4608 + 4611 4614 4617 4620 4623 4626 4629 4632 4635 4638 4641 4644 + 4647 4650 4653 4656 4659 4662 4665 4668 4671 4674 4677 4680 + 4683 4686 4689 4692 4695 4698 4701 4704 4707 4710 4713 4716 + 4719 4722 4725 4728 4731 4734 4737 4740 4743 4746 4749 4752 + 4755 4758 4761 4764 4767 4770 4773 4776 4779 4782 4785 4788 + 4791 4794 4797 4800 4803 4806 4809 4812 4815 4818 4821 4824 + 4827 4830 4833 4836 4839 4842 4845 4848 4851 4854 4857 4860 + 4863 4866 4869 4872 4875 4878 4881 4884 4887 4890 4893 4896 + 4899 4902 4905 4908 4911 4914 4917 4920 4923 4926 4929 4932 + 4935 4938 4941 4944 4947 4950 4953 4956 4959 4962 4965 4968 + 4971 4974 4977 4980 4983 4986 4989 4992 4995 4998 5001 5004 + 5007 5010 + </DataArray> + <DataArray type="UInt8" Name="types" NumberOfComponents="1" format="ascii"> + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 + </DataArray> + </Cells> + </Piece> + </UnstructuredGrid> +</VTKFile>