dune-grid
2.1.1
|
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