00001 #ifndef DUNE_GENERICGEOMETRY_CORNERMAPPING_HH
00002 #define DUNE_GENERICGEOMETRY_CORNERMAPPING_HH
00003
00004 #include <dune/grid/genericgeometry/misc.hh>
00005 #include <dune/grid/genericgeometry/topologytypes.hh>
00006 #include <dune/grid/genericgeometry/referenceelements.hh>
00007 #include <dune/grid/genericgeometry/matrix.hh>
00008
00009 namespace Dune
00010 {
00011
00012 namespace GenericGeometry
00013 {
00014
00015
00016
00017
00018 template< class CT, unsigned int dim, unsigned int dimW >
00019 struct MappingTraits;
00020
00021
00022
00023
00024
00025
00026
00027 template< class Topology, class Traits, bool affine, unsigned int offset = 0 >
00028 class GenericCornerMapping;
00029
00030 template< class Traits, bool affine, unsigned int offset >
00031 class GenericCornerMapping < Point, Traits, affine, offset >
00032 {
00033 typedef Point Topology;
00034
00035 public:
00036 static const unsigned int dim = Topology :: dimension;
00037 static const unsigned int dimW = Traits :: dimWorld;
00038
00039 typedef typename Traits :: FieldType FieldType;
00040 typedef typename Traits :: LocalCoordType LocalCoordType;
00041 typedef typename Traits :: GlobalCoordType GlobalCoordType;
00042 typedef typename Traits :: JacobianTransposedType JacobianTransposedType;
00043
00044 static const bool alwaysAffine = true;
00045
00046 template< class CoordStorage >
00047 static const GlobalCoordType &origin ( const CoordStorage &coords )
00048 {
00049 dune_static_assert( CoordStorage :: size, "Invalid offset." );
00050 return coords[ offset ];
00051 }
00052
00053 template< class CoordStorage >
00054 static void phi_set ( const CoordStorage &coords,
00055 const LocalCoordType &x,
00056 const FieldType &factor,
00057 GlobalCoordType &p )
00058 {
00059 const GlobalCoordType &y = origin( coords );
00060 for( unsigned int i = 0; i < dimW; ++i )
00061 p[ i ] = factor * y[ i ];
00062 }
00063
00064 template< class CoordStorage >
00065 static void phi_add ( const CoordStorage &coords,
00066 const LocalCoordType &x,
00067 const FieldType &factor,
00068 GlobalCoordType &p )
00069 {
00070 const GlobalCoordType &y = origin( coords );
00071 for( unsigned int i = 0; i < dimW; ++i )
00072 p[ i ] += factor * y[ i ];
00073 }
00074
00075 template< class CoordStorage >
00076 static bool Dphi_set ( const CoordStorage &coords,
00077 const LocalCoordType &x,
00078 const FieldType &factor,
00079 JacobianTransposedType &J )
00080 {
00081 return true;
00082 }
00083
00084 template< class CoordStorage >
00085 static bool Dphi_add ( const CoordStorage &coords,
00086 const LocalCoordType &x,
00087 const FieldType &factor,
00088 JacobianTransposedType &J )
00089 {
00090 return true;
00091 }
00092 };
00093
00094
00095 template< class BaseTopology, class Traits, bool affine, unsigned int offset >
00096 class GenericCornerMapping< Prism< BaseTopology >, Traits, affine, offset >
00097 {
00098 typedef Prism< BaseTopology > Topology;
00099
00100 typedef GenericCornerMapping< BaseTopology, Traits, affine, offset >
00101 BottomMapping;
00102 typedef GenericCornerMapping
00103 < BaseTopology, Traits, affine, offset + BaseTopology :: numCorners >
00104 TopMapping;
00105
00106 public:
00107 static const unsigned int dim = Topology :: dimension;
00108 static const unsigned int dimW = Traits :: dimWorld;
00109
00110 typedef typename Traits :: FieldType FieldType;
00111 typedef typename Traits :: LocalCoordType LocalCoordType;
00112 typedef typename Traits :: GlobalCoordType GlobalCoordType;
00113 typedef typename Traits :: JacobianTransposedType JacobianTransposedType;
00114
00115 static const bool alwaysAffine = ((dim < 2) || affine);
00116
00117 template< class CoordStorage >
00118 static const GlobalCoordType &origin ( const CoordStorage &coords )
00119 {
00120 return BottomMapping :: origin( coords );
00121 }
00122
00123 template< class CoordStorage >
00124 static void phi_set ( const CoordStorage &coords,
00125 const LocalCoordType &x,
00126 const FieldType &factor,
00127 GlobalCoordType &p )
00128 {
00129 const FieldType xn = x[ dim-1 ];
00130 const FieldType cxn = FieldType( 1 ) - xn;
00131 BottomMapping :: phi_set( coords, x, factor * cxn, p );
00132 TopMapping :: phi_add( coords, x, factor * xn, p );
00133 }
00134
00135 template< class CoordStorage >
00136 static void phi_add ( const CoordStorage &coords,
00137 const LocalCoordType &x,
00138 const FieldType &factor,
00139 GlobalCoordType &p )
00140 {
00141 const FieldType xn = x[ dim-1 ];
00142 const FieldType cxn = FieldType( 1 ) - xn;
00143 BottomMapping :: phi_add( coords, x, factor * cxn, p );
00144 TopMapping :: phi_add( coords, x, factor * xn, p );
00145 }
00146
00147 template< class CoordStorage >
00148 static bool Dphi_set ( const CoordStorage &coords,
00149 const LocalCoordType &x,
00150 const FieldType &factor,
00151 JacobianTransposedType &J )
00152 {
00153 const FieldType xn = x[ dim-1 ];
00154 bool affine = true;
00155 if( alwaysAffine )
00156 {
00157 const FieldType cxn = FieldType( 1 ) - xn;
00158 BottomMapping :: Dphi_set( coords, x, factor * cxn, J );
00159 TopMapping :: Dphi_add( coords, x, factor * xn, J );
00160 }
00161 else
00162 {
00163 JacobianTransposedType Jtop;
00164 affine &= BottomMapping :: Dphi_set( coords, x, factor, J );
00165 affine &= TopMapping :: Dphi_set( coords, x, factor, Jtop );
00166
00167 FieldType norm = FieldType( 0 );
00168 for( unsigned int i = 0; i < dim-1; ++i )
00169 {
00170 Jtop[ i ] -= J[ i ];
00171 norm += Jtop[ i ].two_norm2();
00172 J[ i ].axpy( xn, Jtop[ i ] );
00173 }
00174 affine &= (norm < 1e-12);
00175 }
00176 BottomMapping :: phi_set( coords, x, -factor, J[ dim-1 ] );
00177 TopMapping :: phi_add( coords, x, factor, J[ dim-1 ] );
00178 return affine;
00179 }
00180
00181 template< class CoordStorage >
00182 static bool Dphi_add ( const CoordStorage &coords,
00183 const LocalCoordType &x,
00184 const FieldType &factor,
00185 JacobianTransposedType &J )
00186 {
00187 const FieldType xn = x[ dim-1 ];
00188 bool affine = true;
00189 if( alwaysAffine )
00190 {
00191 const FieldType cxn = FieldType( 1 ) - xn;
00192 BottomMapping :: Dphi_add( coords, x, factor * cxn, J );
00193 TopMapping :: Dphi_add( coords, x, factor * xn, J );
00194 }
00195 else
00196 {
00197 JacobianTransposedType Jbottom, Jtop;
00198 affine &= BottomMapping :: Dphi_set( coords, x, FieldType( 1 ), Jbottom );
00199 affine &= TopMapping :: Dphi_set( coords, x, FieldType( 1 ), Jtop );
00200
00201 FieldType norm = FieldType( 0 );
00202 for( unsigned int i = 0; i < dim-1; ++i )
00203 {
00204 Jtop[ i ] -= Jbottom[ i ];
00205 norm += Jtop[ i ].two_norm2();
00206 J[ i ].axpy( factor, Jbottom[ i ] );
00207 J[ i ].axpy( factor*xn, Jtop[ i ] );
00208 }
00209 affine &= (norm < 1e-12);
00210 }
00211 BottomMapping :: phi_add( coords, x, -factor, J[ dim-1 ] );
00212 TopMapping :: phi_add( coords, x, factor, J[ dim-1 ] );
00213 return affine;
00214 }
00215 };
00216
00217
00218 template< class BaseTopology, class Traits, bool affine, unsigned int offset >
00219 class GenericCornerMapping < Pyramid< BaseTopology >, Traits, affine, offset >
00220 {
00221 typedef Pyramid< BaseTopology > Topology;
00222
00223 typedef GenericCornerMapping< BaseTopology, Traits, affine, offset >
00224 BottomMapping;
00225 typedef GenericCornerMapping
00226 < Point, Traits, affine, offset + BaseTopology :: numCorners >
00227 TopMapping;
00228
00229 public:
00230 static const unsigned int dim = Topology :: dimension;
00231 static const unsigned int dimW = Traits :: dimWorld;
00232
00233 typedef typename Traits :: FieldType FieldType;
00234 typedef typename Traits :: LocalCoordType LocalCoordType;
00235 typedef typename Traits :: GlobalCoordType GlobalCoordType;
00236 typedef typename Traits :: JacobianTransposedType JacobianTransposedType;
00237
00238 static const bool alwaysAffine = (BottomMapping :: alwaysAffine || affine);
00239
00240 template< class CoordStorage >
00241 static const GlobalCoordType &origin ( const CoordStorage &coords )
00242 {
00243 return BottomMapping :: origin( coords );
00244 }
00245
00246 template< class CoordStorage >
00247 static void phi_set ( const CoordStorage &coords,
00248 const LocalCoordType &x,
00249 const FieldType &factor,
00250 GlobalCoordType &p )
00251 {
00252 const FieldType xn = x[ dim-1 ];
00253 if( alwaysAffine )
00254 {
00255 const GlobalCoordType &top = TopMapping :: origin( coords );
00256 const GlobalCoordType &bottom = BottomMapping :: origin( coords );
00257
00258 BottomMapping :: phi_set( coords, x, factor, p );
00259 for( unsigned int i = 0; i < dimW; ++i )
00260 p[ i ] += (factor * xn) * (top[ i ] - bottom[ i ]);
00261 }
00262 else
00263 {
00264 TopMapping :: phi_set( coords, x, factor * xn, p );
00265 const FieldType cxn = FieldType( 1 ) - xn;
00266 if( cxn > 1e-12 )
00267 {
00268 const FieldType icxn = FieldType( 1 ) / cxn;
00269 LocalCoordType xb;
00270 for( unsigned int i = 0; i < dim-1; ++i )
00271 xb[ i ] = icxn * x[ i ];
00272
00273 BottomMapping :: phi_add( coords, xb, factor * cxn, p );
00274 }
00275 }
00276 }
00277
00278 template< class CoordStorage >
00279 static void phi_add ( const CoordStorage &coords,
00280 const LocalCoordType &x,
00281 const FieldType &factor,
00282 GlobalCoordType &p )
00283 {
00284 const FieldType xn = x[ dim-1 ];
00285 if( alwaysAffine )
00286 {
00287 const GlobalCoordType &top = TopMapping :: origin( coords );
00288 const GlobalCoordType &bottom = BottomMapping :: origin( coords );
00289
00290 BottomMapping :: phi_add( coords, x, factor, p );
00291 for( unsigned int i = 0; i < dimW; ++i )
00292 p[ i ] += (factor * xn) * (top[ i ] - bottom[ i ]);
00293 }
00294 else
00295 {
00296 TopMapping :: phi_add( coords, x, factor * xn, p );
00297 const FieldType cxn = FieldType( 1 ) - xn;
00298 if( cxn > 1e-12 )
00299 {
00300 const FieldType icxn = FieldType( 1 ) / cxn;
00301 LocalCoordType xb;
00302 for( unsigned int i = 0; i < dim-1; ++i )
00303 xb[ i ] = icxn * x[ i ];
00304
00305 BottomMapping :: phi_add( coords, xb, factor * cxn, p );
00306 }
00307 }
00308 }
00309
00310 template< class CoordStorage >
00311 static bool Dphi_set ( const CoordStorage &coords,
00312 const LocalCoordType &x,
00313 const FieldType &factor,
00314 JacobianTransposedType &J )
00315 {
00316 GlobalCoordType &q = J[ dim-1 ];
00317 bool affine;
00318 if( alwaysAffine )
00319 {
00320 const GlobalCoordType &top = TopMapping :: origin( coords );
00321 const GlobalCoordType &bottom = BottomMapping :: origin( coords );
00322
00323 affine = BottomMapping :: Dphi_set( coords, x, factor, J );
00324 for( unsigned int i = 0; i < dimW; ++i )
00325 q[ i ] = factor * (top[ i ] - bottom[ i ]);
00326 }
00327 else
00328 {
00329 const FieldType xn = x[ dim-1 ];
00330 const FieldType cxn = FieldType( 1 ) - xn;
00331 const FieldType icxn = FieldType( 1 ) / cxn;
00332 LocalCoordType xb;
00333 for( unsigned int i = 0; i < dim-1; ++i )
00334 xb[ i ] = icxn * x[ i ];
00335 affine = BottomMapping :: Dphi_set( coords, xb, factor, J );
00336
00337 TopMapping :: phi_set( coords, x, factor, q );
00338 BottomMapping :: phi_add( coords, xb, -factor, q );
00339 xb *= factor;
00340 for( unsigned int j = 0; j < dim-1; ++j )
00341 {
00342 for( unsigned int i = 0; i < dimW; ++i )
00343 q[ i ] += J[ j ][ i ] * xb[ j ];
00344 }
00345 }
00346 return affine;
00347 }
00348
00349 template< class CoordStorage >
00350 static bool Dphi_add ( const CoordStorage &coords,
00351 const LocalCoordType &x,
00352 const FieldType &factor,
00353 JacobianTransposedType &J )
00354 {
00355 GlobalCoordType &q = J[ dim-1 ];
00356 bool affine;
00357 if( alwaysAffine )
00358 {
00359 const GlobalCoordType &top = TopMapping :: origin( coords );
00360 const GlobalCoordType &bottom = BottomMapping :: origin( coords );
00361
00362 affine = BottomMapping :: Dphi_add( coords, x, factor, J );
00363 for( unsigned int i = 0; i < dimW; ++i )
00364 q[ i ] = factor * (top[ i ] - bottom[ i ]);
00365 }
00366 else
00367 {
00368 const FieldType xn = x[ dim-1 ];
00369 const FieldType cxn = FieldType( 1 ) - xn;
00370 const FieldType icxn = FieldType( 1 ) / cxn;
00371 LocalCoordType xb;
00372 for( unsigned int i = 0; i < dim-1; ++i )
00373 xb[ i ] = icxn * x[ i ];
00374 affine = BottomMapping :: Dphi_add( coords, xb, factor, J );
00375
00376 TopMapping :: phi_add( coords, x, factor, q );
00377 BottomMapping :: phi_add( coords, xb, -factor, q );
00378 xb *= factor;
00379 for( unsigned int j = 0; j < dim-1; ++j )
00380 {
00381 for( unsigned int i = 0; i < dimW; ++i )
00382 q[ i ] += J[ j ][ i ] * xb[ j ];
00383 }
00384 }
00385 return affine;
00386 }
00387 };
00388
00389
00390
00391
00392
00393
00394 template< class Mapping, unsigned int codim >
00395 class SubMappingCoords
00396 {
00397 typedef typename Mapping :: GlobalCoordType GlobalCoordType;
00398 typedef typename Mapping :: ReferenceElement ReferenceElement;
00399
00400 static const unsigned int dimension = ReferenceElement :: dimension;
00401
00402 const Mapping &mapping_;
00403 const unsigned int i_;
00404
00405 public:
00406 SubMappingCoords ( const Mapping &mapping, unsigned int i )
00407 : mapping_( mapping ), i_( i )
00408 {}
00409
00410 const GlobalCoordType &operator[] ( unsigned int j ) const
00411 {
00412 const unsigned int k
00413 = ReferenceElement :: template subNumbering< codim, dimension - codim >( i_, j );
00414 return mapping_.corner( k );
00415 }
00416 };
00417
00418
00419
00420
00421
00422
00427 template< class CoordTraits, class Topology, unsigned int dimW >
00428 class CoordStorage
00429 {
00430 typedef CoordStorage< CoordTraits, Topology, dimW > This;
00431
00432 public:
00433 static const unsigned int size = Topology :: numCorners;
00434
00435 static const unsigned int dimWorld = dimW;
00436
00437 typedef typename CoordTraits :: template Vector< dimWorld > :: type
00438 GlobalCoordinate;
00439
00440 template< class SubTopology >
00441 struct SubStorage
00442 {
00443 typedef CoordStorage< CoordTraits, SubTopology, dimWorld > type;
00444 };
00445
00446 private:
00447 GlobalCoordinate coords_[ size ];
00448
00449 public:
00450 template< class CoordVector >
00451 explicit CoordStorage ( const CoordVector &coords )
00452 {
00453 for( unsigned int i = 0; i < size; ++i )
00454 coords_[ i ] = coords[ i ];
00455 }
00456
00457 const GlobalCoordinate &operator[] ( unsigned int i ) const
00458 {
00459 return coords_[ i ];
00460 }
00461 };
00462
00463
00464
00465
00466
00467
00472 template< class CoordTraits, class Topology, unsigned int dimW >
00473 class CoordPointerStorage
00474 {
00475 typedef CoordPointerStorage< CoordTraits, Topology, dimW > This;
00476
00477 public:
00478 static const unsigned int size = Topology :: numCorners;
00479
00480 static const unsigned int dimWorld = dimW;
00481
00482 typedef typename CoordTraits :: template Vector< dimWorld > :: type
00483 GlobalCoordinate;
00484
00485 template< class SubTopology >
00486 struct SubStorage
00487 {
00488 typedef CoordPointerStorage< CoordTraits, SubTopology, dimWorld > type;
00489 };
00490
00491 private:
00492 const GlobalCoordinate *coords_[ size ];
00493
00494 public:
00495 template< class CoordVector >
00496 explicit CoordPointerStorage ( const CoordVector &coords )
00497 {
00498 for( unsigned int i = 0; i < size; ++i )
00499 coords_[ i ] = &(coords[ i ]);
00500 }
00501
00502 const GlobalCoordinate &operator[] ( unsigned int i ) const
00503 {
00504 return *(coords_[ i ]);
00505 }
00506 };
00507
00508
00509
00510
00511
00512
00518 template< class CoordTraits, class Topo, unsigned int dimW,
00519 class CStorage = CoordPointerStorage< CoordTraits, Topo, dimW >,
00520 bool affine = false >
00521 class CornerMapping
00522 {
00523 typedef CornerMapping< CoordTraits, Topo, dimW, CStorage, affine > This;
00524
00525 public:
00526 typedef Topo Topology;
00527 typedef CStorage CornerStorage;
00528 typedef MappingTraits< CoordTraits, Topology :: dimension, dimW > Traits;
00529
00530 static const unsigned int dimension = Traits :: dimension;
00531 static const unsigned int dimWorld = Traits :: dimWorld;
00532
00533 typedef typename Traits :: FieldType FieldType;
00534 typedef typename Traits :: LocalCoordType LocalCoordType;
00535 typedef typename Traits :: GlobalCoordType GlobalCoordType;
00536 typedef typename Traits :: JacobianType JacobianType;
00537 typedef typename Traits :: JacobianTransposedType JacobianTransposedType;
00538
00539 typedef GenericGeometry :: ReferenceElement< Topology, FieldType > ReferenceElement;
00540
00541 template< unsigned int codim, unsigned int i >
00542 struct SubTopology
00543 {
00544 typedef typename GenericGeometry :: SubTopology< Topo, codim, i > :: type Topology;
00545 typedef typename CStorage :: template SubStorage< Topology > :: type CornerStorage;
00546 typedef CornerMapping< CoordTraits, Topology, dimWorld, CornerStorage, affine > Trace;
00547 };
00548
00549 private:
00550 typedef GenericGeometry :: GenericCornerMapping< Topology, Traits, affine > GenericMapping;
00551
00552 public:
00553 static const bool alwaysAffine = GenericMapping :: alwaysAffine;
00554
00555 protected:
00556 CornerStorage coords_;
00557
00558 public:
00559 template< class CoordVector >
00560 explicit CornerMapping ( const CoordVector &coords )
00561 : coords_( coords )
00562 {}
00563
00564 const GlobalCoordType &corner ( int i ) const
00565 {
00566 return coords_[ i ];
00567 }
00568
00569 void global ( const LocalCoordType &x, GlobalCoordType &y ) const
00570 {
00571 GenericMapping :: phi_set( coords_, x, FieldType( 1 ), y );
00572 }
00573
00574 bool jacobianTransposed ( const LocalCoordType &x,
00575 JacobianTransposedType &JT ) const
00576 {
00577 return GenericMapping :: Dphi_set( coords_, x, FieldType( 1 ), JT );
00578 }
00579
00580 template< unsigned int codim, unsigned int i >
00581 typename SubTopology< codim, i > :: Trace trace () const
00582 {
00583 typedef typename SubTopology< codim, i > :: Trace Trace;
00584 typedef SubMappingCoords< This, codim > CoordVector;
00585 return Trace( CoordVector( *this, i ) );
00586 }
00587 };
00588
00589 }
00590
00591 }
00592
00593 #endif