1#ifndef DUNE_FEM_SCHEMES_INTEGRANDS_HH
2#define DUNE_FEM_SCHEMES_INTEGRANDS_HH
14#include <dune/fempy/quadrature/cachingpoint.hh>
15#include <dune/fempy/quadrature/elementpoint.hh>
16#include <dune/fem/quadrature/cachingquadrature.hh>
17#include <dune/fem/common/explicitfieldvector.hh>
31 namespace IntegrandsTraits
34 template<
class Integrands >
35 using DomainValueType =
typename std::decay_t< decltype( std::ref( std::declval< const Integrands & >() ).
get() ) >::DomainValueType;
37 template<
class Integrands >
38 using RangeValueType =
typename std::decay_t< decltype( std::ref( std::declval< const Integrands & >() ).
get() ) >::RangeValueType;
40 template<
class Integrands >
41 using GridPartType =
typename std::decay_t< decltype( std::ref( std::declval< const Integrands & >() ).
get() ) >::GridPartType;
44 template<
class Integrands >
45 using EntityType =
typename GridPartType< Integrands >::template Codim< 0 >::EntityType;
47 template<
class Integrands >
51 template<
class Integrands >
52 using InteriorQuadratureType = CachingQuadrature< GridPartType< Integrands >, 0 >;
54 template<
class Integrands >
55 using SurfaceQuadratureType = CachingQuadrature< GridPartType< Integrands >, 1 >;
58 template<
class Integrands >
59 using InteriorQuadraturePointType = QuadraturePointWrapper< InteriorQuadratureType< Integrands > >;
61 template<
class Integrands >
62 using SurfaceQuadraturePointType = QuadraturePointWrapper< SurfaceQuadratureType< Integrands > >;
65 template<
class Integrands >
66 std::true_type
interior (
const Integrands &,
decltype( std::declval< const Integrands & >().
interior( std::declval<
const InteriorQuadraturePointType< Integrands > & >(), std::declval<
const DomainValueType< Integrands > & >() ) ) * =
nullptr );
70 template< class Integrands, std::enable_if_t< std::is_same< decltype( std::declval< const Integrands & >().hasInterior() ),
bool >::value,
int > = 0 >
71 std::true_type hasInterior (
const Integrands & );
73 std::false_type hasInterior ( ... );
75 template< class Integrands, std::enable_if_t< std::is_same< decltype( std::declval< const Integrands & >().nonlinear() ),
bool >::value,
int > = 0 >
76 std::true_type hasNonLinear (
const Integrands & );
78 std::false_type hasNonLinear ( ... );
81 template<
class Integrands >
82 std::true_type boundary (
const Integrands &,
decltype( std::declval< const Integrands & >().boundary( std::declval<
const SurfaceQuadraturePointType< Integrands > & >(), std::declval<
const DomainValueType< Integrands > & >() ) ) * =
nullptr );
84 std::false_type boundary ( ... );
86 template< class Integrands, std::enable_if_t< std::is_same< decltype( std::declval< const Integrands & >().hasBoundary() ),
bool >::value,
int > = 0 >
87 std::true_type hasBoundary (
const Integrands & );
89 std::false_type hasBoundary ( ... );
92 template<
class Integrands >
93 std::true_type skeleton (
const Integrands &,
decltype( std::declval< const Integrands & >().skeleton( std::declval<
const SurfaceQuadraturePointType< Integrands > & >(), std::declval<
const DomainValueType< Integrands > & >(), std::declval<
const SurfaceQuadraturePointType< Integrands > & >(), std::declval<
const DomainValueType< Integrands > & >() ) ) * =
nullptr );
95 std::false_type skeleton ( ... );
97 template< class Integrands, std::enable_if_t< std::is_same< decltype( std::declval< const Integrands & >().hasSkeleton() ),
bool >::value,
int > = 0 >
98 std::true_type hasSkeleton (
const Integrands & );
100 std::false_type hasSkeleton ( ... );
102 template<
class Integrands >
103 using Get = std::decay_t< decltype( std::ref( std::declval< const Integrands & >() ).
get() ) >;
105 template<
class Integrands >
106 using RRangeType =
typename Get<Integrands>::RRangeType;
107 template<
class Integrands >
108 using DirichletComponentType =
typename Get<Integrands>::DirichletComponentType;
113 template<
class Integrands >
114 struct IntegrandsTraits
116 typedef Impl::IntegrandsTraits::DomainValueType< Integrands > DomainValueType;
117 typedef Impl::IntegrandsTraits::RangeValueType< Integrands > RangeValueType;
118 typedef Impl::IntegrandsTraits::GridPartType< Integrands > GridPartType;
120 typedef Impl::IntegrandsTraits::EntityType< Integrands > EntityType;
121 typedef Impl::IntegrandsTraits::IntersectionType< Integrands > IntersectionType;
123 static const bool hasNonLinear =
decltype( Impl::IntegrandsTraits::hasNonLinear( std::declval< const Integrands & >() ) )::value;
125 static const bool interior =
decltype( Impl::IntegrandsTraits::interior( std::declval< const Integrands & >() ) )::value;
126 static const bool hasInterior =
decltype( Impl::IntegrandsTraits::hasInterior( std::declval< const Integrands & >() ) )::value;
128 static const bool boundary =
decltype( Impl::IntegrandsTraits::boundary( std::declval< const Integrands & >() ) )::value;
129 static const bool hasBoundary =
decltype( Impl::IntegrandsTraits::hasBoundary( std::declval< const Integrands & >() ) )::value;
131 static const bool skeleton =
decltype( Impl::IntegrandsTraits::skeleton( std::declval< const Integrands & >() ) )::value;
132 static const bool hasSkeleton =
decltype( Impl::IntegrandsTraits::hasSkeleton( std::declval< const Integrands & >() ) )::value;
134 static_assert( (!hasInterior ||
interior),
"Existence of method 'hasInterior' implies existence of method interior." );
135 static_assert( (!hasBoundary || boundary),
"Existence of method 'hasBoundary' implies existence of method boundary." );
136 static_assert( (!hasSkeleton || skeleton),
"Existence of method 'hasSkeleton' implies existence of method skeleton." );
138 static const bool isFull = hasInterior && hasBoundary && hasSkeleton;
140 typedef Impl::IntegrandsTraits::RRangeType< Integrands > RRangeType;
141 typedef Impl::IntegrandsTraits::DirichletComponentType< Integrands > DirichletComponentType;
149 template<
class Integrands >
150 struct FullIntegrands
152 typedef typename IntegrandsTraits< Integrands >::DomainValueType DomainValueType;
153 typedef typename IntegrandsTraits< Integrands >::RangeValueType RangeValueType;
154 typedef typename IntegrandsTraits< Integrands >::GridPartType GridPartType;
156 typedef typename IntegrandsTraits< Integrands >::EntityType EntityType;
157 typedef typename IntegrandsTraits< Integrands >::IntersectionType IntersectionType;
160 template< class T, std::enable_if_t< IntegrandsTraits< T >::hasNonLinear,
int > = 0 >
161 static bool nonlinear (
const T &integrands )
163 return integrands.nonlinear();
166 template< class T, std::enable_if_t< !IntegrandsTraits< T >::hasNonLinear,
int > = 0 >
167 static bool nonlinear (
const T &integrands )
173 template< class T, std::enable_if_t< IntegrandsTraits< T >::hasInterior,
int > = 0 >
174 static bool hasInterior (
const T &integrands )
176 return integrands.hasInterior();
179 template< class T, std::enable_if_t< !IntegrandsTraits< T >::hasInterior,
int > = 0 >
180 static bool hasInterior (
const T &integrands )
182 return IntegrandsTraits< T >::interior;
185 template< class T, class Point, std::enable_if_t< IntegrandsTraits< T >::interior,
int > = 0 >
186 static RangeValueType
interior (
const T &integrands,
const Point &x,
const DomainValueType &u )
188 return integrands.interior( x, u );
191 template< class T, class Point, std::enable_if_t< !IntegrandsTraits< T >::interior,
int > = 0 >
192 static RangeValueType
interior (
const T &integrands,
const Point &x,
const DomainValueType &u )
194 return RangeValueType();
197 template< class T, class Point, std::enable_if_t< IntegrandsTraits< T >::interior,
int > = 0 >
198 static auto linearizedInterior (
const T &integrands,
const Point &x,
const DomainValueType &u )
200 return integrands.linearizedInterior( x, u );
203 template< class T, class Point, std::enable_if_t< !IntegrandsTraits< T >::interior,
int > = 0 >
204 static auto linearizedInterior (
const T &integrands,
const Point &x,
const DomainValueType &u )
206 return [] (
const DomainValueType & ) {
return RangeValueType(); };
209 template< class T, std::enable_if_t< IntegrandsTraits< T >::hasBoundary,
int > = 0 >
210 static bool hasBoundary (
const T &integrands )
212 return integrands.hasBoundary();
215 template< class T, std::enable_if_t< !IntegrandsTraits< T >::hasBoundary,
int > = 0 >
216 static bool hasBoundary (
const T &integrands )
218 return IntegrandsTraits< T >::boundary;
221 template< class T, class Point, std::enable_if_t< IntegrandsTraits< T >::boundary,
int > = 0 >
222 static RangeValueType boundary (
const T &integrands,
const Point &x,
const DomainValueType &u )
224 return integrands.boundary( x, u );
227 template< class T, class Point, std::enable_if_t< !IntegrandsTraits< T >::boundary,
int > = 0 >
228 static RangeValueType boundary (
const T &integrands,
const Point &x,
const DomainValueType &u )
230 return RangeValueType();
233 template< class T, class Point, std::enable_if_t< IntegrandsTraits< T >::boundary,
int > = 0 >
234 static auto linearizedBoundary (
const T &integrands,
const Point &x,
const DomainValueType &u )
236 return integrands.linearizedBoundary( x, u );
239 template< class T, class Point, std::enable_if_t< !IntegrandsTraits< T >::boundary,
int > = 0 >
240 static auto linearizedBoundary (
const T &integrands,
const Point &x,
const DomainValueType &u )
242 return [] (
const DomainValueType & ) {
return RangeValueType(); };
245 template< class T, std::enable_if_t< IntegrandsTraits< T >::hasSkeleton,
int > = 0 >
246 static bool hasSkeleton (
const T &integrands )
248 return integrands.hasSkeleton();
251 template< class T, std::enable_if_t< !IntegrandsTraits< T >::hasSkeleton,
int > = 0 >
252 static bool hasSkeleton (
const T &integrands )
254 return IntegrandsTraits< T >::skeleton;
257 template< class T, class Point, std::enable_if_t< IntegrandsTraits< T >::skeleton,
int > = 0 >
258 static std::pair< RangeValueType, RangeValueType > skeleton (
const T &integrands,
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
260 return integrands.skeleton( xIn, uIn, xOut, uOut );
263 template< class T, class Point, std::enable_if_t< !IntegrandsTraits< T >::skeleton,
int > = 0 >
264 static std::pair< RangeValueType, RangeValueType > skeleton (
const T &integrands,
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
266 return std::make_pair( RangeValueType(), RangeValueType() );
269 template< class T, class Point, std::enable_if_t< IntegrandsTraits< T >::skeleton,
int > = 0 >
270 static auto linearizedSkeleton (
const T &integrands,
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
272 return integrands.linearizedSkeleton( xIn, uIn, xOut, uOut );
275 template< class T, class Point, std::enable_if_t< !IntegrandsTraits< T >::skeleton,
int > = 0 >
276 static auto linearizedSkeleton (
const T &integrands,
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
278 auto zero = [] (
const DomainValueType & ) {
return std::make_pair( RangeValueType(), RangeValueType() ); };
279 return std::make_pair( zero, zero );
283 template<
class... Args >
284 explicit FullIntegrands ( Args &&... args )
285 : integrands_(
std::forward< Args >( args )... ),
286 rInt_(
std::ref( integrands_ ).
get() )
290 bool init (
const EntityType &entity ) {
return integrands().init( entity ); }
291 bool init (
const IntersectionType &intersection ) {
return integrands().init( intersection ); }
292 void unbind ( ) { integrands().unbind( ); }
294 bool nonlinear()
const {
return nonlinear( integrands() ); }
296 bool hasInterior ()
const {
return hasInterior( integrands() ); }
298 template<
class Po
int >
299 RangeValueType
interior (
const Point &x,
const DomainValueType &u )
const
301 return interior( integrands(), x, u );
304 template<
class Po
int >
305 auto linearizedInterior (
const Point &x,
const DomainValueType &u )
const
307 return linearizedInterior( integrands(), x, u );
310 bool hasBoundary ()
const {
return hasBoundary( integrands() ); }
312 template<
class Po
int >
313 RangeValueType boundary (
const Point &x,
const DomainValueType &u )
const
315 return boundary( integrands(), x, u );
318 template<
class Po
int >
319 auto linearizedBoundary (
const Point &x,
const DomainValueType &u )
const
321 return linearizedBoundary( integrands(), x, u );
324 bool hasSkeleton ()
const {
return hasSkeleton( integrands() ); }
326 template<
class Po
int >
327 std::pair< RangeValueType, RangeValueType > skeleton (
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
const
329 return skeleton( integrands(), xIn, uIn, xOut, uOut );
332 template<
class Po
int >
333 auto linearizedSkeleton (
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
const
335 return linearizedSkeleton( integrands(), xIn, uIn, xOut, uOut );
339 typedef typename Integrands::type RealIntegrands;
342 RealIntegrands& integrands () {
return rInt_; }
343 const RealIntegrands& integrands ()
const {
return rInt_; }
347 Integrands integrands_;
348 RealIntegrands rInt_;
351 typedef typename IntegrandsTraits< Integrands >::RRangeType RRangeType;
352 typedef typename IntegrandsTraits< Integrands >::DirichletComponentType DirichletComponentType;
353 bool hasDirichletBoundary ()
const
355 return integrands().hasDirichletBoundary();
357 bool isDirichletIntersection(
const IntersectionType& inter, DirichletComponentType &dirichletComponent )
const
359 return integrands().isDirichletIntersection(inter,dirichletComponent);
361 template <
class Po
int>
362 void dirichlet(
int bndId,
const Point &x, RRangeType &value)
const
364 return integrands().dirichlet(bndId,x,value);
377 template <
class FT,
int r>
378 struct GetDimRange<
Dune::FieldVector<FT,r>>
381 static const int value = r;
383 template <
class FT,
int r,
int c>
384 struct GetDimRange<
Dune::FieldMatrix<FT,r,c>>
387 static const int value = r;
389 template <
class FT,
int r,
int c>
390 struct GetDimRange<
Dune::Fem::ExplicitFieldVector<Dune::FieldMatrix<FT,c,c>,r>>
393 static const int value = r;
397 template<
class Gr
idPart,
class DomainValue,
class RangeValue = DomainValue >
398 class VirtualizedIntegrands
400 typedef VirtualizedIntegrands< GridPart, DomainValue, RangeValue > This;
403 typedef GridPart GridPartType;
404 typedef DomainValue DomainValueType;
405 typedef RangeValue RangeValueType;
407 typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
410 using RRangeType =
typename detail::GetDimRange<std::tuple_element_t<0,RangeValueType>>::type;
411 typedef std::array<int,RRangeType::dimension> DirichletComponentType;
412 typedef typename EntityType::Geometry::LocalCoordinate DomainType;
415 typedef typename EntityType::Geometry::LocalCoordinate LocalCoordinateType;
417 typedef FemPy::CachingPoint< GridPart, LocalCoordinateType, 0 > InteriorCachingPointType;
418 typedef FemPy::ElementPoint< GridPart, LocalCoordinateType, 0 > InteriorElementPointType;
419 typedef FemPy::CachingPoint< GridPart, LocalCoordinateType, 1 > SurfaceCachingPointType;
420 typedef FemPy::ElementPoint< GridPart, LocalCoordinateType, 1 > SurfaceElementPointType;
423 static Fem::QuadraturePointWrapper< QP > asQP (
const QP &qp )
425 return static_cast< Fem::QuadraturePointWrapper< QP >
>( qp );
429 using Linearization = std::function< R(
const DomainValueType & ) >;
432 using LinearizationPair = std::pair< Linearization< std::pair< R, R > >, Linearization< std::pair< R, R > > >;
436 virtual ~Interface () {}
437 virtual Interface *clone ()
const = 0;
439 virtual bool init (
const EntityType &entity ) = 0;
440 virtual bool init (
const IntersectionType &intersection ) = 0;
441 virtual void unbind ( ) = 0;
443 virtual bool nonlinear()
const = 0;
445 virtual bool hasInterior ()
const = 0;
446 virtual RangeValueType
interior (
const InteriorCachingPointType &x,
const DomainValueType &u )
const = 0;
447 virtual RangeValueType
interior (
const InteriorElementPointType &x,
const DomainValueType &u )
const = 0;
448 virtual Linearization< RangeValueType > linearizedInterior (
const InteriorCachingPointType &x,
const DomainValueType &u )
const = 0;
449 virtual Linearization< RangeValueType > linearizedInterior (
const InteriorElementPointType &x,
const DomainValueType &u )
const = 0;
451 virtual bool hasBoundary ()
const = 0;
452 virtual RangeValueType boundary (
const SurfaceCachingPointType &x,
const DomainValueType &u )
const = 0;
453 virtual RangeValueType boundary (
const SurfaceElementPointType &x,
const DomainValueType &u )
const = 0;
454 virtual Linearization< RangeValueType > linearizedBoundary (
const SurfaceCachingPointType &x,
const DomainValueType &u )
const = 0;
455 virtual Linearization< RangeValueType > linearizedBoundary (
const SurfaceElementPointType &x,
const DomainValueType &u )
const = 0;
457 virtual bool hasSkeleton ()
const = 0;
458 virtual std::pair< RangeValueType, RangeValueType > skeleton (
const SurfaceCachingPointType &xIn,
const DomainValueType &uIn,
const SurfaceCachingPointType &xOut,
const DomainValueType &uOut )
const = 0;
459 virtual std::pair< RangeValueType, RangeValueType > skeleton (
const SurfaceElementPointType &xIn,
const DomainValueType &uIn,
const SurfaceElementPointType &xOut,
const DomainValueType &uOut )
const = 0;
460 virtual LinearizationPair< RangeValueType > linearizedSkeleton (
const SurfaceCachingPointType &xIn,
const DomainValueType &uIn,
const SurfaceCachingPointType &xOut,
const DomainValueType &uOut )
const = 0;
461 virtual LinearizationPair< RangeValueType > linearizedSkeleton (
const SurfaceElementPointType &xIn,
const DomainValueType &uIn,
const SurfaceElementPointType &xOut,
const DomainValueType &uOut )
const = 0;
463 virtual bool hasDirichletBoundary ()
const = 0;
464 virtual bool isDirichletIntersection(
const IntersectionType& inter, DirichletComponentType &dirichletComponent )
const = 0;
465 virtual void dirichlet(
int bndId,
const DomainType &x,RRangeType &value)
const = 0;
468 template<
class Impl >
472 Implementation ( Impl impl ) : impl_(
std::move( impl ) )
475 virtual Interface *clone ()
const override {
return new Implementation( *
this ); }
477 virtual bool init (
const EntityType &entity )
override {
return impl().init( entity ); }
478 virtual bool init (
const IntersectionType &intersection )
override {
return impl().init( intersection ); }
479 virtual void unbind ( )
override { impl().unbind( ); }
481 virtual bool nonlinear ()
const override {
return impl().nonlinear(); }
483 virtual bool hasInterior ()
const override {
return impl().hasInterior(); }
484 virtual RangeValueType
interior (
const InteriorCachingPointType &x,
const DomainValueType &u )
const override {
return impl().interior( asQP( x ), u ); }
485 virtual RangeValueType
interior (
const InteriorElementPointType &x,
const DomainValueType &u )
const override {
return impl().interior( asQP( x ), u ); }
486 virtual Linearization< RangeValueType > linearizedInterior (
const InteriorCachingPointType &x,
const DomainValueType &u )
const override {
return impl().linearizedInterior( asQP( x ), u ); }
487 virtual Linearization< RangeValueType > linearizedInterior (
const InteriorElementPointType &x,
const DomainValueType &u )
const override {
return impl().linearizedInterior( asQP( x ), u ); }
489 virtual bool hasBoundary ()
const override {
return impl().hasBoundary(); }
490 virtual RangeValueType boundary (
const SurfaceCachingPointType &x,
const DomainValueType &u )
const override {
return impl().boundary( asQP( x ), u ); }
491 virtual RangeValueType boundary (
const SurfaceElementPointType &x,
const DomainValueType &u )
const override {
return impl().boundary( asQP( x ), u ); }
492 virtual Linearization< RangeValueType > linearizedBoundary (
const SurfaceCachingPointType &x,
const DomainValueType &u )
const override {
return impl().linearizedBoundary( asQP( x ), u ); }
493 virtual Linearization< RangeValueType > linearizedBoundary (
const SurfaceElementPointType &x,
const DomainValueType &u )
const override {
return impl().linearizedBoundary( asQP( x ), u ); }
495 virtual bool hasSkeleton ()
const override {
return impl().hasSkeleton(); }
496 virtual std::pair< RangeValueType, RangeValueType > skeleton (
const SurfaceCachingPointType &xIn,
const DomainValueType &uIn,
const SurfaceCachingPointType &xOut,
const DomainValueType &uOut )
const override {
return impl().skeleton( asQP( xIn ), uIn, asQP( xOut ), uOut ); }
497 virtual std::pair< RangeValueType, RangeValueType > skeleton (
const SurfaceElementPointType &xIn,
const DomainValueType &uIn,
const SurfaceElementPointType &xOut,
const DomainValueType &uOut )
const override {
return impl().skeleton( asQP( xIn ), uIn, asQP( xOut ), uOut ); }
498 virtual LinearizationPair< RangeValueType > linearizedSkeleton (
const SurfaceCachingPointType &xIn,
const DomainValueType &uIn,
const SurfaceCachingPointType &xOut,
const DomainValueType &uOut )
const override {
return impl().linearizedSkeleton( asQP( xIn ), uIn, asQP( xOut ), uOut ); }
499 virtual LinearizationPair< RangeValueType > linearizedSkeleton (
const SurfaceElementPointType &xIn,
const DomainValueType &uIn,
const SurfaceElementPointType &xOut,
const DomainValueType &uOut )
const override {
return impl().linearizedSkeleton( asQP( xIn ), uIn, asQP( xOut ), uOut ); }
501 virtual bool hasDirichletBoundary ()
const override {
return impl().hasDirichletBoundary(); }
502 virtual bool isDirichletIntersection(
const IntersectionType& inter, DirichletComponentType &dirichletComponent )
const override {
return impl().isDirichletIntersection(inter,dirichletComponent); }
503 virtual void dirichlet(
int bndId,
const DomainType &x,RRangeType &value)
const override { impl().dirichlet(bndId,x,value); }
506 const auto &impl ()
const {
return std::cref( impl_ ).get(); }
507 auto &impl () {
return std::ref( impl_ ).get(); }
512 template<
class Integrands >
513 using isVirtualized = std::is_same< std::decay_t< decltype( std::ref( std::declval< Integrands & >() ).
get() ) >, This >;
516 template<
class Integrands, std::enable_if_t< IntegrandsTraits< std::decay_t< Integrands > >::isFull && !isVirtualized< Integrands >::value,
int > = 0 >
517 explicit VirtualizedIntegrands ( Integrands integrands )
518 : impl_( new Implementation< Integrands >(
std::move( integrands ) ) )
521 template< class Integrands, std::enable_if_t< !IntegrandsTraits< Integrands >::isFull && !isVirtualized< Integrands >::value,
int > = 0 >
522 explicit VirtualizedIntegrands ( Integrands integrands )
523 : VirtualizedIntegrands( FullIntegrands<
std::decay_t< Integrands > >(
std::move( integrands ) ) )
526 VirtualizedIntegrands (
const This &other ) : impl_( other ? other.impl().clone() : nullptr )
529 VirtualizedIntegrands ( This && ) =
default;
531 VirtualizedIntegrands &operator= (
const This &other )
533 impl_.reset( other ? other.impl().clone() :
nullptr );
536 VirtualizedIntegrands &operator= ( This && ) =
default;
538 explicit operator bool ()
const {
return static_cast< bool >( impl_ ); }
540 bool init (
const EntityType &entity ) {
return impl().init( entity ); }
541 bool init (
const IntersectionType &intersection ) {
return impl().init( intersection ); }
542 void unbind ( ) { impl().unbind( ); }
544 bool nonlinear()
const {
return impl().nonlinear(); }
546 bool hasInterior ()
const {
return impl().hasInterior(); }
548 template< class Quadrature, std::enable_if_t< std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
549 RangeValueType
interior (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
551 return impl().interior( InteriorCachingPointType( x ), u );
554 template< class Quadrature, std::enable_if_t< !std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
555 RangeValueType
interior (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
557 return impl().interior( InteriorElementPointType( x ), u );
560 template< class Quadrature, std::enable_if_t< std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
561 auto linearizedInterior (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
563 return impl().linearizedInterior( InteriorCachingPointType( x ), u );
566 template< class Quadrature, std::enable_if_t< !std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
567 auto linearizedInterior (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
569 return impl().linearizedInterior( InteriorElementPointType( x ), u );
572 bool hasBoundary ()
const {
return impl().hasBoundary(); }
574 template< class Quadrature, std::enable_if_t< std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
575 RangeValueType boundary (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
577 return impl().boundary( SurfaceCachingPointType( x ), u );
580 template< class Quadrature, std::enable_if_t< !std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
581 RangeValueType boundary (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
583 return impl().boundary( SurfaceElementPointType( x ), u );
586 template< class Quadrature, std::enable_if_t< std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
587 auto linearizedBoundary (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
589 return impl().linearizedBoundary( SurfaceCachingPointType( x ), u );
592 template< class Quadrature, std::enable_if_t< !std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
593 auto linearizedBoundary (
const Fem::QuadraturePointWrapper< Quadrature > &x,
const DomainValueType &u )
const
595 return impl().linearizedBoundary( SurfaceElementPointType( x ), u );
598 bool hasSkeleton ()
const {
return impl().hasSkeleton(); }
600 template< class Quadrature, std::enable_if_t< std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
601 std::pair< RangeValueType, RangeValueType > skeleton (
const Fem::QuadraturePointWrapper< Quadrature > &xIn,
const DomainValueType &uIn,
const Fem::QuadraturePointWrapper< Quadrature > &xOut,
const DomainValueType &uOut )
const
603 return impl().skeleton( SurfaceCachingPointType( xIn ), uIn, SurfaceCachingPointType( xOut ), uOut );
606 template< class Quadrature, std::enable_if_t< !std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
607 std::pair< RangeValueType, RangeValueType > skeleton (
const Fem::QuadraturePointWrapper< Quadrature > &xIn,
const DomainValueType &uIn,
const Fem::QuadraturePointWrapper< Quadrature > &xOut,
const DomainValueType &uOut )
const
609 return impl().skeleton( SurfaceElementPointType( xIn ), uIn, SurfaceElementPointType( xOut ), uOut );
612 template< class Quadrature, std::enable_if_t< std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
613 auto linearizedSkeleton (
const Fem::QuadraturePointWrapper< Quadrature > &xIn,
const DomainValueType &uIn,
const Fem::QuadraturePointWrapper< Quadrature > &xOut,
const DomainValueType &uOut )
const
615 return impl().linearizedSkeleton( SurfaceCachingPointType( xIn ), uIn, SurfaceCachingPointType( xOut ), uOut );
618 template< class Quadrature, std::enable_if_t< !std::is_convertible< Quadrature, Fem::CachingInterface >::value,
int > = 0 >
619 auto linearizedSkeleton (
const Fem::QuadraturePointWrapper< Quadrature > &xIn,
const DomainValueType &uIn,
const Fem::QuadraturePointWrapper< Quadrature > &xOut,
const DomainValueType &uOut )
const
621 return impl().linearizedSkeleton( SurfaceElementPointType( xIn ), uIn, SurfaceElementPointType( xOut ), uOut );
624 bool hasDirichletBoundary ()
const
626 return impl().hasDirichletBoundary();
628 bool isDirichletIntersection(
const IntersectionType& inter, DirichletComponentType &dirichletComponent )
const
630 return impl().isDirichletIntersection(inter,dirichletComponent);
632 void dirichlet(
int bndId,
const DomainType &x,RRangeType &value)
const
634 return impl().dirichlet(bndId,x,value);
638 const Interface &impl ()
const { assert( impl_ );
return *impl_; }
639 Interface &impl () { assert( impl_ );
return *impl_; }
641 std::unique_ptr< Interface > impl_;
649 template<
class Model >
650 struct ConservationLawModelIntegrands
652 typedef Model ModelType;
653 typedef typename Model::GridPartType GridPartType;
655 typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
658 typedef typename Model::RangeType RangeType;
659 typedef typename Model::JacobianRangeType JacobianRangeType;
661 typedef std::tuple< RangeType, JacobianRangeType > DomainValueType;
662 typedef std::tuple< RangeType, JacobianRangeType > RangeValueType;
664 explicit ConservationLawModelIntegrands (
const Model &model ) : model_( &model ) {}
666 bool init (
const EntityType &entity ) {
return model().init( entity ); }
668 bool init (
const IntersectionType &intersection )
670 return (intersection.boundary() && model().hasNeumanBoundary() && model().init( intersection.inside() ));
673 void unbind ( ) { model().unbind( ); }
675 template<
class Po
int >
676 RangeValueType
interior (
const Point &x,
const DomainValueType &u )
const
678 RangeType source( 0 );
679 model().source( x, std::get< 0 >( u ), std::get< 1 >( u ), source );
680 JacobianRangeType dFlux( 0 );
681 model().flux( x, std::get< 0 >( u ), std::get< 1 >( u ), dFlux );
682 return std::make_tuple( source, dFlux );
685 template<
class Po
int >
686 auto linearizedInterior (
const Point &x,
const DomainValueType &u )
const
688 return [
this, x, u ] (
const DomainValueType &phi ) {
689 RangeType source( 0 );
690 model().linSource( std::get< 0 >( u ), std::get< 1 >( u ), x, std::get< 0 >( phi ), std::get< 1 >( phi ), source );
691 JacobianRangeType dFlux( 0 );
692 model().linFlux( std::get< 0 >( u ), std::get< 1 >( u ), x, std::get< 0 >( phi ), std::get< 1 >( phi ), dFlux );
693 return std::make_tuple( source, dFlux );
697 template<
class Po
int >
698 RangeValueType boundary (
const Point &x,
const DomainValueType &u )
const
700 RangeType alpha( 0 );
701 model().alpha( x, std::get< 0 >( u ), alpha );
702 return std::make_tuple( alpha, 0 );
705 template<
class Po
int >
706 auto linearizedBoundary (
const Point &x,
const DomainValueType &u )
const
708 return [
this, x, u ] (
const DomainValueType &phi ) {
709 RangeType alpha( 0 );
710 model().linAlpha( std::get< 0 >( u ), x, std::get< 0 >( phi ), alpha );
711 return std::make_tuple( alpha, 0 );
715 const Model &model ()
const {
return *model_; }
718 const Model *model_ =
nullptr;
726 template<
class Model >
727 struct DGConservationLawModelIntegrands
729 typedef Model ModelType;
730 typedef typename Model::GridPartType GridPartType;
732 typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
735 typedef typename Model::RangeType RangeType;
736 typedef typename Model::JacobianRangeType JacobianRangeType;
738 typedef typename FieldTraits< RangeType >::field_type RangeFieldType;
740 typedef std::tuple< RangeType, JacobianRangeType > DomainValueType;
741 typedef std::tuple< RangeType, JacobianRangeType > RangeValueType;
743 DGConservationLawModelIntegrands (
const Model &model, RangeFieldType penalty )
744 : model_( &model ), penalty_( penalty )
747 bool init (
const EntityType &entity )
749 intersection_ =
nullptr;
750 return model().init( entity );
753 bool init (
const IntersectionType &intersection )
755 intersection_ = &intersection;
756 if( intersection.boundary() )
758 const EntityType inside = intersection.inside();
759 beta_ = penalty_ * intersection.geometry().volume() / inside.geometry().volume();
760 return (model().hasNeumanBoundary() && model().init( inside ));
762 else if( intersection.neighbor() )
764 const auto volIn = intersection.inside().geometry().volume();
765 const auto volOut = intersection.outside().geometry().volume();
766 beta_ = penalty_ * intersection.geometry().volume() / std::min( volIn, volOut );
776 template<
class Po
int >
777 RangeValueType
interior (
const Point &x,
const DomainValueType &u )
const
779 RangeType source( 0 );
780 model().source( x, std::get< 0 >( u ), std::get< 1 >( u ), source );
781 JacobianRangeType dFlux( 0 );
782 model().flux( x, std::get< 0 >( u ), std::get< 1 >( u ), dFlux );
783 return RangeValueType( source, dFlux );
786 template<
class Po
int >
787 auto linearizedInterior (
const Point &x,
const DomainValueType &u )
const
789 return [
this, x, u ] (
const DomainValueType &phi ) {
790 RangeType source( 0 );
791 model().linSource( std::get< 0 >( u ), std::get< 1 >( u ), x, std::get< 0 >( phi ), std::get< 1 >( phi ), source );
792 JacobianRangeType dFlux( 0 );
793 model().linFlux( std::get< 0 >( u ), std::get< 1 >( u ), x, std::get< 0 >( phi ), std::get< 1 >( phi ), dFlux );
794 return RangeValueType( source, dFlux );
798 template<
class Po
int >
799 RangeValueType boundary (
const Point &x,
const DomainValueType &u )
const
801 RangeType alpha( 0 );
802 model().alpha( x, std::get< 0 >( u ), alpha );
803 return RangeValueType( alpha, 0 );
806 template<
class Po
int >
807 auto linearizedBoundary (
const Point &x,
const DomainValueType &u )
const
809 return [
this, x, u ] (
const DomainValueType &phi ) {
810 RangeType alpha( 0 );
811 model().linAlpha( std::get< 0 >( u ), x, std::get< 0 >( phi ), alpha );
812 return RangeValueType( alpha, 0 );
816 template<
class Po
int >
817 std::pair< RangeValueType, RangeValueType > skeleton (
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
const
819 const EntityType inside = intersection().inside();
820 const EntityType outside = intersection().outside();
822 const RangeFieldType half = RangeFieldType( 1 ) / RangeFieldType( 2 );
823 const auto normal = intersection().unitOuterNormal( xIn.localPosition() );
825 DomainValueType uJump( 0, 0 );
826 std::get< 0 >( uJump ) = std::get< 0 >( uOut ) - std::get< 0 >( uIn );
827 for(
int i = 0; i < RangeType::dimension; ++i )
828 std::get< 1 >( uJump )[ i ].axpy( std::get< 0 >( uJump )[ i ], normal );
830 model().init( outside );
831 JacobianRangeType dFluxOut( 0 ), dFluxPrimeOut( 0 );
832 model().flux( xOut, std::get< 0 >( uOut ), std::get< 1 >( uJump ), dFluxPrimeOut );
833 model().flux( xOut, std::get< 0 >( uOut ), 0, dFluxOut );
834 dFluxPrimeOut -= dFluxOut;
836 model().flux( xOut, std::get< 0 >( uOut ), std::get< 1 >( uOut ), dFluxOut );
838 model().init( inside );
839 JacobianRangeType dFluxIn( 0 ), dFluxPrimeIn( 0 );
840 model().flux( xIn, std::get< 0 >( uIn ), std::get< 1 >( uJump ), dFluxPrimeIn );
841 model().flux( xIn, std::get< 0 >( uIn ), 0, dFluxIn );
842 dFluxPrimeIn -= dFluxIn;
844 model().flux( xIn, std::get< 0 >( uIn ), std::get< 1 >( uIn ), dFluxIn );
846 RangeType int0 = std::get< 0 >( uJump );
849 dFluxIn.usmv( -half, normal, int0 );
851 dFluxPrimeIn *= -half;
852 dFluxPrimeOut *= -half;
854 return std::make_pair( RangeValueType( -int0, dFluxPrimeIn ), RangeValueType( int0, dFluxPrimeOut ) );
857 template<
class Po
int >
858 auto linearizedSkeleton (
const Point &xIn,
const DomainValueType &uIn,
const Point &xOut,
const DomainValueType &uOut )
const
860 const auto normal = intersection().unitOuterNormal( xIn.localPosition() );
862 DomainValueType uJump( 0, 0 );
863 std::get< 0 >( uJump ) = std::get< 0 >( uOut ) - std::get< 0 >( uIn );
864 for(
int i = 0; i < RangeType::dimension; ++i )
865 std::get< 1 >( uJump )[ i ].axpy( std::get< 0 >( uJump )[ i ], normal );
867 auto intIn = [
this, xIn, uIn, xOut, uOut, normal, uJump ] (
const DomainValueType &phiIn ) {
868 const EntityType inside = intersection().inside();
869 const EntityType outside = intersection().outside();
871 const RangeFieldType half = RangeFieldType( 1 ) / RangeFieldType( 2 );
873 DomainValueType phiJump( 0, 0 );
874 std::get< 0 >( phiJump ) -= std::get< 0 >( phiIn );
875 for(
int i = 0; i < RangeType::dimension; ++i )
876 std::get< 1 >( phiJump )[ i ].axpy( std::get< 0 >( phiJump )[ i ], normal );
878 model().init( outside );
879 JacobianRangeType dFluxPrimeOut( 0 );
880 model().linFlux( std::get< 0 >( uOut ), std::get< 1 >( uJump ), xOut, 0, std::get< 1 >( phiJump ), dFluxPrimeOut );
882 model().init( inside );
883 JacobianRangeType dFluxIn( 0 ), dFluxPrimeIn( 0 );
884 model().linFlux( std::get< 0 >( uIn ), std::get< 1 >( uJump ), xIn, std::get< 0 >( phiIn ), std::get< 1 >( phiJump ), dFluxPrimeIn );
885 model().linFlux( std::get< 0 >( uIn ), 0, xIn, std::get< 0 >( phiIn ), 0, dFluxIn );
886 dFluxPrimeIn -= dFluxIn;
888 model().linFlux( std::get< 0 >( uIn ), std::get< 1 >( uIn ), xIn, std::get< 0 >( phiIn ), std::get< 1 >( phiIn ), dFluxIn );
890 RangeType int0 = std::get< 0 >( phiJump );
892 dFluxIn.usmv( -half, normal, int0 );
894 dFluxPrimeIn *= -half;
895 dFluxPrimeOut *= -half;
897 return std::make_pair( RangeValueType( -int0, dFluxPrimeIn ), RangeValueType( int0, dFluxPrimeOut ) );
900 auto intOut = [
this, xIn, uIn, xOut, uOut, normal, uJump ] (
const DomainValueType &phiOut ) {
901 const EntityType inside = intersection().inside();
902 const EntityType outside = intersection().outside();
904 const RangeFieldType half = RangeFieldType( 1 ) / RangeFieldType( 2 );
906 DomainValueType phiJump( 0, 0 );
907 std::get< 0 >( phiJump ) = std::get< 0 >( phiOut );
908 for(
int i = 0; i < RangeType::dimension; ++i )
909 std::get< 1 >( phiJump )[ i ].axpy( std::get< 0 >( phiJump )[ i ], normal );
911 model().init( outside );
912 JacobianRangeType dFluxOut( 0 ), dFluxPrimeOut( 0 );
913 model().linFlux( std::get< 0 >( uOut ), std::get< 1 >( uJump ), xOut, std::get< 0 >( phiOut ), std::get< 1 >( phiJump ), dFluxPrimeOut );
914 model().linFlux( std::get< 0 >( uOut ), 0, xOut, std::get< 0 >( phiOut ), 0, dFluxOut );
915 dFluxPrimeOut -= dFluxOut;
917 model().linFlux( std::get< 0 >( uOut ), std::get< 1 >( uOut ), xOut, std::get< 0 >( phiOut ), std::get< 1 >( phiOut ), dFluxOut );
919 model().init( inside );
920 JacobianRangeType dFluxPrimeIn( 0 );
921 model().linFlux( std::get< 0 >( uIn ), std::get< 1 >( uJump ), xIn, 0, std::get< 1 >( phiJump ), dFluxPrimeIn );
923 RangeType int0 = std::get< 0 >( phiJump );
925 dFluxOut.usmv( -half, normal, int0 );
927 dFluxPrimeIn *= -half;
928 dFluxPrimeOut *= -half;
930 return std::make_pair( RangeValueType( -int0, dFluxPrimeIn ), RangeValueType( int0, dFluxPrimeOut ) );
933 return std::make_pair( intIn, intOut );
936 const Model &model ()
const {
return *model_; }
939 const IntersectionType &intersection ()
const { assert( intersection_ );
return *intersection_; }
941 const Model *model_ =
nullptr;
942 RangeFieldType penalty_;
943 const IntersectionType *intersection_ =
nullptr;
944 RangeFieldType beta_;
IntersectionIteratorType::Intersection IntersectionType
type of intersection
Definition: adaptiveleafgridpart.hh:95
vector space out of a tensor product of fields.
Definition: fvector.hh:95
Type traits to determine the type of reals (when working with complex numbers)
constexpr Interior interior
PartitionSet for the interior partition.
Definition: partitionset.hh:271
Dune namespace.
Definition: alignedallocator.hh:13
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22
#define DUNE_PRIVATE
Mark a symbol as being for internal use within the current DSO only.
Definition: visibility.hh:28