DUNE-FEM (unstable)

linesegmentsampler.hh
1 #ifndef DUNE_FEM_LINESEGMENTSAMPLER_HH
2 #define DUNE_FEM_LINESEGMENTSAMPLER_HH
3 
4 #include <limits>
5 #include <vector>
6 #include <cmath>
7 #include <type_traits>
8 #include <new>
9 
10 #include <dune/common/fvector.hh>
11 
12 #include <dune/geometry/referenceelements.hh>
13 
14 #include <dune/fem/function/localfunction/const.hh>
15 
16 namespace Dune
17 {
18 
19  namespace Fem
20  {
21 
22  // LineSegmentSampler
23  // ------------------
24 
38  template< class GridPart >
40  {
41  typedef GridPart GridPartType;
42 
43  typedef typename GridPartType::GridType::ctype DomainFieldType;
44 
45  static const int dimDomain = GridPartType::dimensionworld;
46  static const int dimGrid = GridPartType::dimension;
47 
50 
51  private:
52  static_assert( dimDomain == dimGrid, "LineSegmentSampler supports only flat grids." );
53 
54  template< class Vector >
55  struct Reduce;
56 
58 
59  public:
70  LineSegmentSampler ( const GridPart &gridPart, const DomainType &left, const DomainType &right )
71  : gridPart_( gridPart ), left_( left ), right_( right )
72  {}
73 
84  template< class GridFunction >
85  void operator() ( const GridFunction &f, std::vector< typename GridFunction::RangeType > &samples, std::nothrow_t ) const;
86  template< class GridFunction >
87  void operator() ( const GridFunction &f, std::vector< typename GridFunction::RangeType > &samples ) const;
88 
98  void samplePoints( std::vector< DomainType > &points ) const;
99 
101  const GridPart &gridPart () const { return gridPart_; }
102 
103  private:
104  const GridPart &gridPart_;
105  DomainType left_, right_;
106  };
107 
108 
109 
110  // LineSegmentSampler::Reduce
111  // --------------------------
112 
113  template< class GridPart >
114  template< class Vector >
115  struct LineSegmentSampler< GridPart >::Reduce
116  {
117  Vector operator() ( const Vector &a, const Vector &b ) const
118  {
119  Vector c;
120  for( int k = 0; k < Vector::dimension; ++k )
121  c[ k ] = std::min( a[ k ], b[ k ] );
122  return c;
123  }
124  };
125 
126 
127 
128  // Implementation of LineSegmentSampler
129  // ------------------------------------
130 
131  template< class GridPart >
132  template< class GridFunction >
134  ::operator() ( const GridFunction &f, std::vector< typename GridFunction::RangeType > &samples,
135  std::nothrow_t) const
136  {
137  typedef typename GridPartType::template Codim< 0 >::IteratorType IteratorType;
138  typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
139  typedef typename GridFunction::RangeFieldType RangeFieldType;
140 
141  const int numSamples = samples.size();
142  DomainType ds = right_ - left_;
143  ds /= DomainFieldType( numSamples - 1 );
144 
145  const RangeFieldType invalid
146  = std::numeric_limits< RangeFieldType >::quiet_NaN();
147  for( int i = 0; i < numSamples; ++i )
148  samples[ i ] = typename GridFunction::RangeType( invalid );
149 
150  ConstLocalFunction< GridFunction > lf( f );
151  const IteratorType end = gridPart().template end< 0 >();
152  for( IteratorType it = gridPart().template begin< 0 >(); it != end; ++it )
153  {
154  const EntityType &entity = *it;
155  const typename EntityType::Geometry &geometry = entity.geometry();
156 
157  DomainFieldType lower = std::numeric_limits< DomainFieldType >::min();
158  DomainFieldType upper = std::numeric_limits< DomainFieldType >::max();
159 
160  auto &refElement = ReferenceElements::general( geometry.type() );
161  const int numFaces = refElement.size( 1 );
162  for( int face = 0; face < numFaces; ++face )
163  {
164  const LocalDomainType &center = refElement.position( face, 1 );
165 
166  DomainType normal;
167  const LocalDomainType &refNormal = refElement.integrationOuterNormal( face );
168  geometry.jacobianInverseTransposed( center ).mv( refNormal, normal );
169 
170  const DomainFieldType nds = normal * ds;
171  const DomainFieldType ncl = normal * (geometry.global( center ) - left_);
172  if( std::abs( nds ) > 1e-8 )
173  {
174  // ds is not parallel to the face
175  const DomainFieldType alpha = ncl / nds;
176  if( nds > 0 )
177  upper = std::min( upper, alpha );
178  else
179  lower = std::max( lower, alpha );
180  }
181  else if( ncl < -1e-8 )
182  {
183  // ds is parallel to the face and the line lies on the outside
186  }
187  }
188 
189  if( lower <= upper )
190  {
191  lf.bind( entity );
192  const int i_upper = std::min( int( std::floor( upper + 1e-8 ) ), numSamples - 1 );
193  const int i_lower = std::max( int( std::ceil( lower - 1e-8 ) ), 0 );
194  for( int i = i_lower; i <= i_upper; ++i )
195  {
196  DomainType xi = left_;
197  xi.axpy( DomainFieldType( i ), ds );
198  lf.evaluate( geometry.local( xi ), samples[ i ] );
199  }
200  lf.unbind();
201  }
202  }
203 
204  typedef Reduce< typename GridFunction::RangeType > Op;
205  gridPart().comm().template allreduce< Op >( &(samples[ 0 ]), numSamples );
206  }
207 
208  template< class GridPart >
209  template< class GridFunction >
211  ::operator() ( const GridFunction &f, std::vector< typename GridFunction::RangeType > &samples ) const
212  {
213  typedef typename GridFunction::RangeFieldType RangeFieldType;
214 
215  const int numSamples = samples.size();
216  if( numSamples < 2 )
217  DUNE_THROW( InvalidStateException, "LineSegmentSampler cannot sample less than 2 points." );
218 
219  (*this)(f,samples,std::nothrow);
220 
221  bool valid = true;
222 
223  // only use isnan when field type is a floating point
224  if constexpr ( std::is_floating_point< RangeFieldType >::value )
225  {
226  for( int i = 0; i < numSamples; ++i )
227  {
228  for( int d=0; d<GridFunction::RangeType::dimension; ++d )
229  {
230  valid &= ! std::isnan( samples[ i ][ d ] );
231  }
232  }
233  }
234 
235  if( !valid )
236  DUNE_THROW( InvalidStateException, "LineSegmentSampler could not find all samples." );
237  }
238 
239 
240  template< class GridPart >
242  :: samplePoints ( std::vector< DomainType > &points ) const
243  {
244  const int numSamples = points.size();
245  if( numSamples < 2 )
246  DUNE_THROW( InvalidStateException, "LineSegmentSampler cannot sample less than 2 points." );
247  DomainType ds = right_ - left_;
248  ds /= DomainFieldType( numSamples - 1 );
249 
250  for( int i = 0; i < numSamples; ++i )
251  {
252  points[ i ] = left_;
253  points[ i ].axpy( DomainFieldType( i ), ds );
254  }
255  }
256 
257  } // namespace Fem
258 
259 } // namespace Dune
260 
261 #endif // #ifndef DUNE_FEM_LINESEGMENTSAMPLER_HH
derived_type & axpy(const field_type &a, const DenseVector< Other > &x)
vector space axpy operation ( *this += a x )
Definition: densevector.hh:575
Default exception if a function was called while the object is not in a valid state for that function...
Definition: exceptions.hh:281
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
concept Geometry
Model of a geometry object.
Definition: geometry.hh:29
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
constexpr auto min
Function object that returns the smaller of the given values.
Definition: hybridutilities.hh:506
Dune namespace.
Definition: alignedallocator.hh:13
Static tag representing a codimension.
Definition: dimension.hh:24
samples values of a discrete function along a given line segment
Definition: linesegmentsampler.hh:40
void samplePoints(std::vector< DomainType > &points) const
returns sampling points
Definition: linesegmentsampler.hh:242
const GridPart & gridPart() const
obtain grid part on which the LineSegmentSampler works
Definition: linesegmentsampler.hh:101
void operator()(const GridFunction &f, std::vector< typename GridFunction::RangeType > &samples, std::nothrow_t) const
sample a given function
Definition: linesegmentsampler.hh:134
LineSegmentSampler(const GridPart &gridPart, const DomainType &left, const DomainType &right)
constructor
Definition: linesegmentsampler.hh:70
Class providing access to the singletons of the reference elements.
Definition: referenceelements.hh:128
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:156
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)