dune-grid  2.1.1
cachedmapping.hh
Go to the documentation of this file.
00001 #ifndef DUNE_GENERICGEOMETRY_CACHED_MAPPING_HH
00002 #define DUNE_GENERICGEOMETRY_CACHED_MAPPING_HH
00003 
00004 #include <dune/grid/genericgeometry/topologytypes.hh>
00005 #include <dune/grid/genericgeometry/referenceelements.hh>
00006 #include <dune/grid/genericgeometry/matrixhelper.hh>
00007 #include <dune/grid/genericgeometry/mapping.hh>
00008 #include <dune/grid/genericgeometry/traceprovider.hh>
00009 
00010 namespace Dune
00011 {
00012 
00013   namespace GenericGeometry
00014   {
00015 
00016     // Internal Forward Declarations
00017     // -----------------------------
00018 
00019     template< unsigned int, class >
00020     class CachedJacobianTransposed;
00021 
00022     template< unsigned int, class >
00023     class CachedJacobianInverseTransposed;
00024 
00025 
00026 
00027     // CachedStorage
00028     // -------------
00029 
00030     template< unsigned int dim, class GeometryTraits >
00031     class CachedStorage
00032     {
00033       friend class CachedJacobianTransposed< dim, GeometryTraits >;
00034 
00035     public:
00036       static const unsigned int dimension = dim;
00037       static const unsigned int dimWorld = GeometryTraits::dimWorld;
00038 
00039       typedef MappingTraits< typename GeometryTraits::CoordTraits, dimension, dimWorld > Traits;
00040 
00041       typedef typename GeometryTraits::Caching Caching;
00042 
00043       typename Traits::JacobianTransposedType jacobianTransposed;
00044       typename Traits::JacobianType jacobianInverseTransposed;
00045       typename Traits::FieldType integrationElement;
00046 
00047       CachedStorage ()
00048       : affine( false ),
00049         jacobianTransposedComputed( false ),
00050         jacobianInverseTransposedComputed( false ),
00051         integrationElementComputed( false )
00052       {}
00053 
00054       bool affine;
00055 
00056       bool jacobianTransposedComputed;        // = affine, if jacobian transposed was computed
00057       bool jacobianInverseTransposedComputed; // = affine, if jacobian inverse transposed was computed
00058       bool integrationElementComputed;        // = affine, if integration element was computed
00059     };
00060 
00061 
00062 
00063     // CachedJacobianTranposed
00064     // -----------------------
00065 
00066     template< unsigned int dim, class GeometryTraits >
00067     class CachedJacobianTransposed
00068     {
00069       friend class CachedJacobianInverseTransposed< dim, GeometryTraits >;
00070 
00071       typedef CachedStorage< dim, GeometryTraits > Storage;
00072       typedef typename Storage::Traits Traits;
00073 
00074       typedef typename Traits::MatrixHelper MatrixHelper;
00075 
00076     public:
00077       typedef typename Traits::FieldType ctype;
00078 
00079       static const int rows = Traits::dimension;
00080       static const int cols = Traits::dimWorld;
00081 
00082       typedef typename Traits::JacobianTransposedType FieldMatrix;
00083 
00084       operator bool () const
00085       {
00086         return storage().jacobianTransposedComputed;
00087       }
00088 
00089       operator const FieldMatrix & () const
00090       {
00091         return storage().jacobianTransposed;
00092       }
00093 
00094       template< class X, class Y >
00095       void mv ( const X &x, Y &y ) const
00096       {
00097         static_cast< const FieldMatrix & >( *this ).mv( x, y );
00098       }
00099 
00100       template< class X, class Y >
00101       void mtv ( const X &x, Y &y ) const
00102       {
00103         static_cast< const FieldMatrix & >( *this ).mtv( x, y );
00104       }
00105 
00106       template< class X, class Y >
00107       void umv ( const X &x, Y &y ) const
00108       {
00109         static_cast< const FieldMatrix & >( *this ).umv( x, y );
00110       }
00111 
00112       template< class X, class Y >
00113       void umtv ( const X &x, Y &y ) const
00114       {
00115         static_cast< const FieldMatrix & >( *this ).umtv( x, y );
00116       }
00117 
00118       template< class X, class Y >
00119       void mmv ( const X &x, Y &y ) const
00120       {
00121         static_cast< const FieldMatrix & >( *this ).mmv( x, y );
00122       }
00123 
00124       template< class X, class Y >
00125       void mmtv ( const X &x, Y &y ) const
00126       {
00127         static_cast< const FieldMatrix & >( *this ).mmtv( x, y );
00128       }
00129 
00130       ctype det () const
00131       {
00132         if( !storage().integrationElementComputed )
00133         {
00134           storage().integrationElement = MatrixHelper::template sqrtDetAAT< rows, cols >( storage().jacobianTransposed );
00135           storage().integrationElementComputed = storage().affine;
00136         }
00137         return storage().integrationElement;
00138       }
00139 
00140     private:
00141       Storage &storage () const { return storage_; }
00142 
00143       mutable Storage storage_;
00144     };
00145 
00146 
00147 
00148     // CachedJacobianInverseTransposed
00149     // -------------------------------
00150 
00151     template< unsigned int dim, class GeometryTraits >
00152     class CachedJacobianInverseTransposed
00153     {
00154       template< class, class > friend class CachedMapping;
00155 
00156       typedef CachedJacobianTransposed< dim, GeometryTraits > JacobianTransposed;
00157       typedef typename JacobianTransposed::Storage Storage;
00158       typedef typename JacobianTransposed::Traits Traits;
00159 
00160       typedef typename Traits::MatrixHelper MatrixHelper;
00161 
00162     public:
00163       typedef typename Traits::FieldType ctype;
00164 
00165       static const int rows = Traits::dimWorld;
00166       static const int cols = Traits::dimension;
00167 
00168       typedef typename Traits::JacobianType FieldMatrix;
00169 
00170       operator bool () const
00171       {
00172         return storage().jacobianInverseTransposedComputed;
00173       }
00174 
00175       operator const FieldMatrix & () const
00176       {
00177         return storage().jacobianInverseTransposed;
00178       }
00179 
00180       template< class X, class Y >
00181       void mv ( const X &x, Y &y ) const
00182       {
00183         static_cast< const FieldMatrix & >( *this ).mv( x, y );
00184       }
00185 
00186       template< class X, class Y >
00187       void mtv ( const X &x, Y &y ) const
00188       {
00189         static_cast< const FieldMatrix & >( *this ).mtv( x, y );
00190       }
00191 
00192       template< class X, class Y >
00193       void umv ( const X &x, Y &y ) const
00194       {
00195         static_cast< const FieldMatrix & >( *this ).umv( x, y );
00196       }
00197 
00198       template< class X, class Y >
00199       void umtv ( const X &x, Y &y ) const
00200       {
00201         static_cast< const FieldMatrix & >( *this ).umtv( x, y );
00202       }
00203 
00204       template< class X, class Y >
00205       void mmv ( const X &x, Y &y ) const
00206       {
00207         static_cast< const FieldMatrix & >( *this ).mmv( x, y );
00208       }
00209 
00210       template< class X, class Y >
00211       void mmtv ( const X &x, Y &y ) const
00212       {
00213         static_cast< const FieldMatrix & >( *this ).mmtv( x, y );
00214       }
00215 
00216       ctype det () const
00217       {
00218         // integrationElement is always computed with jacobianInverseTransposed
00219         return ctype( 1 ) / storage().integrationElement;
00220       }
00221 
00222     private:
00223       JacobianTransposed &jacobianTransposed () { return jacobianTransposed_; }
00224       const JacobianTransposed &jacobianTransposed () const { return jacobianTransposed_; }
00225 
00226       Storage &storage () const { return jacobianTransposed().storage(); }
00227 
00228       JacobianTransposed jacobianTransposed_;
00229     };
00230 
00231 
00232 
00233     // CachedMapping
00234     // -------------
00235 
00248     template< class Topology, class GeometryTraits >
00249     class CachedMapping
00250     {
00251       typedef CachedMapping< Topology, GeometryTraits > This;
00252 
00253       typedef typename GeometryTraits::template Mapping< Topology >::type
00254         MappingImpl;
00255 
00256     public:
00257       typedef MappingTraits
00258         < typename GeometryTraits::CoordTraits, Topology::dimension, GeometryTraits::dimWorld >
00259         Traits;
00260 
00261       typedef GenericGeometry::Mapping
00262         < typename GeometryTraits::CoordTraits, Topology, GeometryTraits::dimWorld, MappingImpl >
00263         Mapping;
00264 
00265       static const unsigned int dimension = Traits::dimension;
00266       static const unsigned int dimWorld = Traits::dimWorld;
00267 
00268       typedef typename Traits::FieldType FieldType;           
00269       typedef typename Traits::LocalCoordinate LocalCoordinate;
00270       typedef typename Traits::GlobalCoordinate GlobalCoordinate;
00271 
00272       typedef CachedStorage< dimension, GeometryTraits > Storage;
00273       typedef CachedJacobianTransposed< dimension, GeometryTraits > JacobianTransposed;
00274       typedef CachedJacobianInverseTransposed< dimension, GeometryTraits > JacobianInverseTransposed;
00275 
00276       typedef GenericGeometry::ReferenceElement< Topology, FieldType > ReferenceElement;
00277 
00279       static const bool alwaysAffine = Mapping::alwaysAffine;
00280 
00281       template< unsigned int codim >
00282       struct Codim
00283       {
00284         typedef typename TraceProvider< Topology, GeometryTraits, codim, false >::Trace Trace;
00285       };
00286 
00287       typedef typename GeometryTraits::Caching Caching;
00288   
00289     private:
00290       typedef typename Traits::MatrixHelper MatrixHelper;
00291 
00292     public:
00293       template< class CoordVector >
00294       explicit CachedMapping ( const CoordVector &coords )
00295       : mapping_( coords )
00296       {
00297         if( alwaysAffine )
00298           storage().affine = true;
00299         else
00300           computeJacobianTransposed( baryCenter() );
00301         preCompute();
00302       }
00303 
00304       template< class CoordVector >
00305       explicit CachedMapping ( const std::pair< const CoordVector &, bool > &coords )
00306       : mapping_( coords.first )
00307       {
00308         storage().affine = coords.second;
00309         preCompute();
00310       }
00311 
00313       unsigned int topologyId () const
00314       {
00315         return ReferenceElement::topologyId;
00316       }
00317 
00318       // do we still require this mehtod?
00319       const GlobalCoordinate &corner ( int i ) const
00320       {
00321         return mapping_.corner( i );
00322       }
00323 
00325       int numCorners () const
00326       {
00327         return ReferenceElement::numCorners;
00328       }
00329 
00335       GlobalCoordinate center () const
00336       {
00337         return global( ReferenceElement::template baryCenter< 0 >( 0 ) );
00338       }
00339 
00347       static bool checkInside ( const LocalCoordinate &x )
00348       {
00349         return ReferenceElement::checkInside( x );
00350       }
00351 
00353       bool affine () const
00354       {
00355         return (alwaysAffine || storage().affine);
00356       }
00357 
00364       GlobalCoordinate global ( const LocalCoordinate &x ) const
00365       {
00366         GlobalCoordinate y;
00367         if( jacobianTransposed() )
00368         {
00369           y = corner( 0 );
00370           jacobianTransposed().umtv( x, y );
00371           //MatrixHelper::template ATx< dimension, dimWorld >( jacobianTransposed_, x, y );
00372           //y += corner( 0 );
00373         }
00374         else
00375           mapping_.global( x, y );
00376         return y;
00377       }
00378 
00390       LocalCoordinate local ( const GlobalCoordinate &y ) const
00391       {
00392         LocalCoordinate x;
00393         if( jacobianInverseTransposed() )
00394         {
00395           GlobalCoordinate z = y - corner( 0 );
00396           jacobianInverseTransposed().mtv( z, x );
00397           // MatrixHelper::template ATx< dimWorld, dimension >( jacobianInverseTransposed(), z, x );
00398         }
00399         else if( affine() )
00400         {
00401           const JacobianTransposed &JT = jacobianTransposed( baryCenter() );
00402           GlobalCoordinate z = y - corner( 0 );
00403           MatrixHelper::template xTRightInvA< dimension, dimWorld >( JT, z, x );
00404         }
00405         else
00406           mapping_.local( y, x );
00407         return x;
00408       }
00409 
00419       const JacobianTransposed &jacobianTransposed ( const LocalCoordinate &x ) const
00420       {
00421         const EvaluationType evaluate = Caching::evaluateJacobianTransposed;
00422         if( (evaluate == PreCompute) && alwaysAffine )
00423           return jacobianTransposed();
00424 
00425         if( !jacobianTransposed() )
00426           computeJacobianTransposed( x );
00427         return jacobianTransposed();
00428       }
00429 
00444       FieldType integrationElement ( const LocalCoordinate &x ) const
00445       {
00446         const EvaluationType evaluateI = Caching::evaluateIntegrationElement;
00447         const EvaluationType evaluateJ = Caching::evaluateJacobianInverseTransposed;
00448         if( ((evaluateI == PreCompute) || (evaluateJ == PreCompute)) && alwaysAffine )
00449           return storage().integrationElement;
00450         else
00451           return jacobianTransposed( x ).det();
00452       }
00453 
00460       const JacobianInverseTransposed &
00461       jacobianInverseTransposed ( const LocalCoordinate &x ) const
00462       {
00463         const EvaluationType evaluate = Caching::evaluateJacobianInverseTransposed;
00464         if( (evaluate == PreCompute) && alwaysAffine )
00465           return jacobianInverseTransposed();
00466 
00467         if( !jacobianInverseTransposed() )
00468           computeJacobianInverseTransposed( x );
00469         return jacobianInverseTransposed();
00470       }
00471 
00480       FieldType volume () const
00481       {
00482         // do we need a quadrature of higher order, here?
00483         const FieldType refVolume = ReferenceElement::volume();
00484         return refVolume * integrationElement( baryCenter() );
00485       }
00486 
00487       This *clone () const
00488       {
00489         return new This( *this );
00490       }
00491 
00492       This* clone ( char *mappingStorage ) const
00493       {
00494         return new( mappingStorage ) This( *this );
00495       }
00496 
00497       template< unsigned int codim, bool hybrid >
00498       typename TraceProvider< Topology, GeometryTraits, codim, hybrid >::Trace*
00499       trace ( unsigned int i, char *mappingStorage ) const
00500       {
00501         return TraceProvider< Topology, GeometryTraits, codim, hybrid >::construct( mapping_, i, mappingStorage );
00502       }
00503 
00504     private:
00505       static const LocalCoordinate &baryCenter ()
00506       {
00507         return ReferenceElement::template baryCenter< 0 >( 0 );
00508       }
00509 
00510       Storage &storage () const
00511       {
00512         return jacobianInverseTransposed().storage();
00513       }
00514 
00515       const JacobianTransposed &jacobianTransposed () const
00516       {
00517         return jacobianInverseTransposed().jacobianTransposed();
00518       }
00519 
00520       const JacobianInverseTransposed &jacobianInverseTransposed () const
00521       {
00522         return jacobianInverseTransposed_;
00523       }
00524 
00525       void preCompute ()
00526       {
00527         assert( affine() == mapping_.jacobianTransposed( baryCenter(), storage().jacobianTransposed ) );
00528         if( !affine() )
00529           return;
00530 
00531         if( (Caching::evaluateJacobianTransposed == PreCompute) && !jacobianTransposed() )
00532           computeJacobianTransposed( baryCenter() );
00533 
00534         if( Caching::evaluateJacobianInverseTransposed == PreCompute )
00535           computeJacobianInverseTransposed( baryCenter() );
00536         else if( Caching::evaluateIntegrationElement == PreCompute )
00537           jacobianTransposed().det();
00538       }
00539 
00540       void computeJacobianTransposed ( const LocalCoordinate &x ) const
00541       {
00542         storage().affine = mapping_.jacobianTransposed( x, storage().jacobianTransposed );
00543         storage().jacobianTransposedComputed = affine();
00544       }
00545 
00546       void computeJacobianInverseTransposed ( const LocalCoordinate &x ) const
00547       {
00548         storage().integrationElement
00549           = MatrixHelper::template rightInvA< dimension, dimWorld >( jacobianTransposed( x ), storage().jacobianInverseTransposed );
00550         storage().integrationElementComputed = affine();
00551         storage().jacobianInverseTransposedComputed = affine();
00552       }
00553 
00554     private:
00555       Mapping mapping_;
00556       JacobianInverseTransposed jacobianInverseTransposed_;
00557     };
00558 
00559   }
00560 
00561 }
00562 
00563 #endif // #ifndef DUNE_GENERICGEOMETRY_CACHED_MAPPING_HH