cachedmapping.hh
00001 #ifndef DUNE_GENERICGEOMETRY_MAPPINGS_HH
00002 #define DUNE_GENERICGEOMETRY_MAPPINGS_HH
00003
00004 #include <dune/common/smallobject.hh>
00005
00006 #include <dune/grid/genericgeometry/misc.hh>
00007 #include <dune/grid/genericgeometry/topologytypes.hh>
00008 #include <dune/grid/genericgeometry/referenceelements.hh>
00009 #include <dune/grid/genericgeometry/matrix.hh>
00010 #include <dune/grid/genericgeometry/mapping.hh>
00011 #include <dune/grid/genericgeometry/hybridmapping.hh>
00012 #include <dune/grid/genericgeometry/traceprovider.hh>
00013
00014 namespace Dune
00015 {
00016
00017 namespace GenericGeometry
00018 {
00019
00020
00021
00022
00023 template< class Topology, class GeometryTraits >
00024 class CachedMapping
00025 : public SmallObject
00026 {
00027 typedef CachedMapping< Topology, GeometryTraits > This;
00028
00029 typedef typename GeometryTraits :: template Mapping< Topology > :: type
00030 MappingImpl;
00031
00032 public:
00033 typedef MappingTraits
00034 < typename GeometryTraits :: CoordTraits,
00035 Topology :: dimension, GeometryTraits :: dimWorld >
00036 Traits;
00037
00038 typedef GenericGeometry :: Mapping
00039 < typename GeometryTraits :: CoordTraits,
00040 Topology, GeometryTraits :: dimWorld, MappingImpl >
00041 Mapping;
00042
00043 static const unsigned int dimension = Traits :: dimension;
00044 static const unsigned int dimWorld = Traits :: dimWorld;
00045
00046 typedef typename Traits :: FieldType FieldType;
00047 typedef typename Traits :: LocalCoordType LocalCoordType;
00048 typedef typename Traits :: GlobalCoordType GlobalCoordType;
00049 typedef typename Traits :: JacobianType JacobianType;
00050 typedef typename Traits :: JacobianTransposedType JacobianTransposedType;
00051
00052 typedef GenericGeometry :: ReferenceElement< Topology, FieldType > ReferenceElement;
00053
00054 static const bool alwaysAffine = Mapping :: alwaysAffine;
00055
00056 template< unsigned int codim >
00057 struct Codim
00058 {
00059 typedef typename TraceProvider< Topology, GeometryTraits, codim, false > :: Trace
00060 Trace;
00061 };
00062
00063 private:
00064 typedef typename GeometryTraits :: Caching Caching;
00065 typedef typename Traits :: MatrixHelper MatrixHelper;
00066
00067 public:
00068 unsigned int referenceCount;
00069
00070 private:
00071 static const unsigned int numNormals = ReferenceElement :: numNormals;
00072
00073 Mapping mapping_;
00074
00075 mutable JacobianTransposedType jacobianTransposed_;
00076 mutable JacobianType jacobianInverseTransposed_;
00077 mutable FieldType integrationElement_;
00078 mutable array< GlobalCoordType, numNormals > normal_;
00079
00080 mutable bool affine_;
00081
00082 mutable bool jacobianTransposedComputed_;
00083 mutable bool jacobianInverseTransposedComputed_;
00084 mutable bool integrationElementComputed_;
00085 mutable array< bool, numNormals > normalComputed_;
00086
00087 public:
00088 template< class CoordVector >
00089 explicit CachedMapping ( const CoordVector &coords )
00090 : mapping_( coords ),
00091 jacobianTransposedComputed_( false ),
00092 jacobianInverseTransposedComputed_( false ),
00093 integrationElementComputed_( false )
00094 {
00095 for( unsigned int i = 0; i < numNormals; ++i )
00096 normalComputed_[ i ] = false;
00097
00098 if( alwaysAffine )
00099 affine_ = true;
00100 else
00101 computeJacobianTransposed( baryCenter() );
00102
00103 if( affine() )
00104 {
00105 if( (Caching :: evaluateJacobianTransposed == PreCompute) && !jacobianTransposedComputed_ )
00106 computeJacobianTransposed( baryCenter() );
00107
00108 if( Caching :: evaluateJacobianInverseTransposed == PreCompute )
00109 computeJacobianInverseTransposed( baryCenter() );
00110 else if( Caching :: evaluateIntegrationElement == PreCompute )
00111 computeIntegrationElement( baryCenter() );
00112 }
00113 }
00114
00115 unsigned int topologyId () const
00116 {
00117 return ReferenceElement :: topologyId;
00118 }
00119
00120 const GlobalCoordType &corner ( int i ) const
00121 {
00122 return mapping_.corner( i );
00123 }
00124
00125 int numCorners () const
00126 {
00127 return ReferenceElement :: numCorners;
00128 }
00129
00130 static bool checkInside ( const LocalCoordType &x )
00131 {
00132 return ReferenceElement :: checkInside( x );
00133 }
00134
00135 bool affine () const
00136 {
00137 return (alwaysAffine || affine_);
00138 }
00139
00140 GlobalCoordType global ( const LocalCoordType &x ) const
00141 {
00142 GlobalCoordType y;
00143 if( jacobianTransposedComputed_ )
00144 {
00145 MatrixHelper :: template ATx< dimension, dimWorld >( jacobianTransposed_, x, y );
00146 y += corner( 0 );
00147 }
00148 else
00149 mapping_.global( x, y );
00150 return y;
00151 }
00152
00153 LocalCoordType local ( const GlobalCoordType &y ) const
00154 {
00155 LocalCoordType x;
00156 if( jacobianInverseTransposedComputed_ )
00157 {
00158 GlobalCoordType z = y - corner( 0 );
00159 MatrixHelper :: template ATx< dimWorld, dimension >( jacobianInverseTransposed_, z, x );
00160 }
00161 else if( affine() )
00162 {
00163 const JacobianTransposedType &JT = jacobianTransposed( baryCenter() );
00164 GlobalCoordType z = y - corner( 0 );
00165 MatrixHelper :: template xTRightInvA< dimension, dimWorld >( JT, z, x );
00166 }
00167 else
00168 mapping_.local( y, x );
00169 return x;
00170 }
00171
00172 const JacobianTransposedType &jacobianTransposed ( const LocalCoordType &x ) const
00173 {
00174 const EvaluationType evaluate = Caching :: evaluateJacobianTransposed;
00175 if( (evaluate == PreCompute) && alwaysAffine )
00176 return jacobianTransposed_;
00177
00178 if( !jacobianTransposedComputed_ )
00179 computeJacobianTransposed( x );
00180 return jacobianTransposed_;
00181 }
00182
00183 FieldType integrationElement ( const LocalCoordType &x ) const
00184 {
00185 const EvaluationType evaluateI = Caching :: evaluateIntegrationElement;
00186 const EvaluationType evaluateJ = Caching :: evaluateJacobianInverseTransposed;
00187 if( ((evaluateI == PreCompute) || (evaluateJ == PreCompute)) && alwaysAffine )
00188 return integrationElement_;
00189
00190 if( !integrationElementComputed_ )
00191 computeIntegrationElement( x );
00192 return integrationElement_;
00193 }
00194
00195 const JacobianType &jacobianInverseTransposed ( const LocalCoordType &x ) const
00196 {
00197 const EvaluationType evaluate = Caching :: evaluateJacobianInverseTransposed;
00198 if( (evaluate == PreCompute) && alwaysAffine )
00199 return jacobianInverseTransposed_;
00200
00201 if( !jacobianInverseTransposedComputed_ )
00202 computeJacobianInverseTransposed( x );
00203 return jacobianInverseTransposed_;
00204 }
00205
00206 FieldType volume () const
00207 {
00208 const FieldType refVolume = ReferenceElement :: volume();
00209 return refVolume * integrationElement( baryCenter() );
00210 }
00211
00212 const GlobalCoordType &normal ( int face, const LocalCoordType &x ) const
00213 {
00214 assert( (unsigned int)face < numNormals );
00215 if( !normalComputed_[ face ] )
00216 {
00217 const JacobianType &JT = jacobianInverseTransposed( x );
00218 const LocalCoordType &refNormal = ReferenceElement :: integrationOuterNormal( face );
00219 MatrixHelper :: template Ax< dimWorld, dimension >( JT, refNormal, normal_[ face ] );
00220 normal_[ face ] *= integrationElement_;
00221 normalComputed_[ face ] = affine();
00222 }
00223 return normal_[ face ];
00224 }
00225
00226 template< unsigned int codim, bool hybrid >
00227 typename TraceProvider< Topology, GeometryTraits, codim, hybrid > :: Trace *
00228 trace ( unsigned int i ) const
00229 {
00230 typedef TraceProvider< Topology, GeometryTraits, codim, hybrid > Provider;
00231 return Provider :: trace( mapping_, i );
00232 }
00233
00234 template< unsigned int codim >
00235 typename Codim< codim > :: Trace *trace ( unsigned int i ) const
00236 {
00237 return trace< codim, false >( i );
00238 }
00239
00240 private:
00241 static const LocalCoordType &baryCenter ()
00242 {
00243 return ReferenceElement :: template baryCenter< 0 >( 0 );
00244 }
00245
00246 void computeJacobianTransposed ( const LocalCoordType &x ) const
00247 {
00248 affine_ = mapping_.jacobianTransposed( x, jacobianTransposed_ );
00249 jacobianTransposedComputed_ = affine_;
00250 }
00251
00252 void computeJacobianInverseTransposed ( const LocalCoordType &x ) const
00253 {
00254 integrationElement_ = mapping_.jacobianInverseTransposed( x, jacobianInverseTransposed_ );
00255 integrationElementComputed_ = jacobianInverseTransposedComputed_ = affine();
00256 }
00257
00258 void computeIntegrationElement ( const LocalCoordType &x ) const
00259 {
00260 integrationElement_ = mapping_.integrationElement( x );
00261 integrationElementComputed_ = affine();
00262 }
00263 };
00264
00265 }
00266
00267 }
00268
00269 #endif