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
11
12#include <dune/geometry/referenceelements.hh>
13
14#include <dune/fem/function/localfunction/const.hh>
15
16namespace 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
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.111.3 (Jul 24, 22:29, 2024)