1 #include <config.h>
2
3 #include <algorithm>
4 #include <cstdlib>
5 #include <ctime>
6 #include <iostream>
7
8 #include <dune/common/exceptions.hh>
9 #include <dune/common/fmatrix.hh>
10 #include <dune/common/fvector.hh>
11
12 #include <dune/fem/gridpart/adaptiveleafgridpart.hh>
13 #include <dune/fem/io/parameter.hh>
14 #include <dune/fem/misc/mpimanager.hh>
15 #include <dune/fem/quadrature/cachingquadrature.hh>
16 #include <dune/fem/space/basisfunctionset/vectorial.hh>
17 #include <dune/fem/space/common/adaptationmanager.hh>
18 #include <dune/fem/space/common/functionspace.hh>
19 #include <dune/fem/space/lagrange.hh>
20 #include <dune/fem/test/testgrid.hh>
21
22
23
24 // Evaluate
25 // --------
26
27 template< class FunctionSpace >
28 struct Evaluate
29 {
30 typedef FunctionSpace FunctionSpaceType;
31 typedef typename FunctionSpaceType::RangeType Vector;
32
33 template< class BasisFunctionSet, class Point, class DofVector >
applyEvaluate34 static void apply ( const BasisFunctionSet &basisFunctionSet,
35 const Point &x, const DofVector &dofs, Vector &vector )
36 {
37 basisFunctionSet.evaluateAll( x, dofs, vector );
38 }
39
40 template< class BasisFunctionSet, class Point, class Array >
applyEvaluate41 static void apply ( const BasisFunctionSet &basisFunctionSet,
42 const Point &x, Array &array )
43 {
44 basisFunctionSet.evaluateAll( x, array );
45 }
46 };
47
48
49
50 // Jacobian
51 // --------
52
53 template< class FunctionSpace >
54 struct Jacobian
55 {
56 typedef FunctionSpace FunctionSpaceType;
57 typedef typename FunctionSpaceType::JacobianRangeType Vector;
58
59 template< class BasisFunctionSet, class Point, class DofVector >
applyJacobian60 static void apply ( const BasisFunctionSet &basisFunctionSet,
61 const Point &x, const DofVector &dofs, Vector &vector )
62 {
63 basisFunctionSet.jacobianAll( x, dofs, vector );
64 }
65
66 template< class BasisFunctionSet, class Point, class Array >
applyJacobian67 static void apply ( const BasisFunctionSet &basisFunctionSet,
68 const Point &x, Array &array )
69 {
70 basisFunctionSet.jacobianAll( x, array );
71 }
72 };
73
74
75
76 // Hessian
77 // -------
78
79 template< class FunctionSpace >
80 struct Hessian
81 {
82 typedef FunctionSpace FunctionSpaceType;
83 typedef typename FunctionSpaceType::HessianRangeType Vector;
84
85 template< class BasisFunctionSet, class Point, class DofVector >
applyHessian86 static void apply ( const BasisFunctionSet &basisFunctionSet,
87 const Point &x, const DofVector &dofs, Vector &vector )
88 {
89 basisFunctionSet.hessianAll( x, dofs, vector );
90 }
91
92 template< class BasisFunctionSet, class Point, class Array >
applyHessian93 static void apply ( const BasisFunctionSet &basisFunctionSet,
94 const Point &x, Array &array )
95 {
96 basisFunctionSet.hessianAll( x, array );
97 }
98 };
99
100
101
102 // DofConversion
103 // -------------
104
105 template< class DofAlignmentType >
106 struct DofConversion;
107
108 template< class ShapeFunctionSet, class Range >
109 struct DofConversion< Dune::Fem::HorizontalDofAlignment< ShapeFunctionSet, Range > >
110 {
111 typedef Dune::Fem::HorizontalDofAlignment< ShapeFunctionSet, Range > DofAlignmentType;
applyDofConversion112 static std::size_t apply ( const DofAlignmentType &dofAlignment, std::size_t globalDof )
113 {
114 Dune::Fem::VerticalDofAlignment< ShapeFunctionSet, Range > conversion;
115 return dofAlignment.globalDof( conversion.localDof( globalDof ) );
116 }
117 };
118
119 template< class ShapeFunctionSet, class Range >
120 struct DofConversion< Dune::Fem::VerticalDofAlignment< ShapeFunctionSet, Range > >
121 {
122 typedef Dune::Fem::VerticalDofAlignment< ShapeFunctionSet, Range > DofAlignmentType;
123
applyDofConversion124 static std::size_t apply ( const DofAlignmentType &, std::size_t globalDof )
125 {
126 return globalDof;
127 }
128 };
129
130
131
132 // Error
133 // -----
134
135 template< class Vector >
136 struct Error;
137
138 template< class RangeFieldType, int dim >
139 struct Error< Dune::FieldVector< RangeFieldType, dim > >
140 {
141 typedef Dune::FieldVector< RangeFieldType, dim > Vector;
142
applyError143 static RangeFieldType apply ( const Vector &a, const Vector &b )
144 {
145 return (a - b).two_norm();
146 }
147 };
148
149 template< class RangeFieldType, int dimDomain, int dimRange >
150 struct Error< Dune::FieldMatrix< RangeFieldType, dimRange, dimDomain > >
151 {
152 typedef Dune::FieldMatrix< RangeFieldType, dimRange, dimDomain > Vector;
153
applyError154 static RangeFieldType apply ( const Vector &a, const Vector &b )
155 {
156 Vector c = a;
157 c -= b;
158 return c.frobenius_norm();
159 }
160 };
161
162 template< class RangeFieldType, int dimDomain, int dimRange >
163 struct Error< Dune::Fem::ExplicitFieldVector< Dune::FieldMatrix< RangeFieldType, dimDomain, dimDomain >, dimRange > >
164 {
165 typedef Dune::FieldVector< Dune::FieldMatrix< RangeFieldType, dimDomain, dimDomain >, dimRange > Vector;
166
applyError167 static RangeFieldType apply ( const Vector &a, const Vector &b )
168 {
169 Dune::FieldVector< RangeFieldType, dimRange > error;
170 for( int r = 0; r < dimRange; ++r )
171 error[ r ] = Error< Dune::FieldMatrix< RangeFieldType, dimDomain, dimDomain > >::apply( a[ r ], b[ r ] );
172 return error.infinity_norm();
173 }
174 };
175
176
177
178 // random
179 // ------
180
181 template< class FieldType >
random(FieldType a,FieldType b)182 FieldType random ( FieldType a, FieldType b )
183 {
184 FieldType delta = FieldType( rand() )/FieldType( RAND_MAX );
185 return ( a + delta*( b - a ) );
186 }
187
188
189
190 // evaluateAll
191 // -----------
192
193 template< class Evaluate,
194 class BasisFunctionSet, class VectorialBasisFunctionSet,
195 class Point, class DofVector >
196 typename Evaluate::FunctionSpaceType::RangeFieldType
evaluateAll(const BasisFunctionSet & basisFunctionSet,const VectorialBasisFunctionSet & vectorialBasisFunctionSet,const Point & x,const DofVector & dofs)197 evaluateAll ( const BasisFunctionSet &basisFunctionSet,
198 const VectorialBasisFunctionSet &vectorialBasisFunctionSet,
199 const Point &x, const DofVector &dofs )
200 {
201 typedef typename Evaluate::FunctionSpaceType FunctionSpaceType;
202
203 typedef typename VectorialBasisFunctionSet::DofAlignmentType DofAlignmentType;
204 DofAlignmentType dofAlignment = vectorialBasisFunctionSet.dofAlignment();
205
206 const std::size_t size = dofs.size();
207 std::vector< typename FunctionSpaceType::RangeFieldType > convertedDofs( size );
208 for( std::size_t i = 0; i < size; ++i )
209 {
210 const std::size_t j = DofConversion< DofAlignmentType >::apply( dofAlignment, i );
211 convertedDofs.at( j ) = dofs[ i ];
212 }
213
214 typename Evaluate::Vector a, b;
215 Evaluate::apply( basisFunctionSet, x, dofs, a );
216 Evaluate::apply( vectorialBasisFunctionSet, x, convertedDofs, b );
217
218 return Error< typename Evaluate::Vector >::apply( a, b );
219 }
220
221
222
223 // evaluateAll
224 // -----------
225
226 template< class Evaluate,
227 class BasisFunctionSet, class VectorialBasisFunctionSet,
228 class Point >
229 typename Evaluate::FunctionSpaceType::RangeFieldType
evaluateAll(const BasisFunctionSet & basisFunctionSet,const VectorialBasisFunctionSet & vectorialBasisFunctionSet,const Point & x)230 evaluateAll ( const BasisFunctionSet &basisFunctionSet,
231 const VectorialBasisFunctionSet &vectorialBasisFunctionSet,
232 const Point &x )
233 {
234 typedef typename Evaluate::Vector Vector;
235 const std::size_t size = basisFunctionSet.size();
236 std::vector< Vector > a( size ), b( size );
237
238 Evaluate::apply( basisFunctionSet, x, a );
239 Evaluate::apply( vectorialBasisFunctionSet, x, b );
240
241 typedef typename VectorialBasisFunctionSet::DofAlignmentType DofAlignmentType;
242 DofAlignmentType dofAlignment = vectorialBasisFunctionSet.dofAlignment();
243
244 typedef typename Evaluate::FunctionSpaceType::RangeFieldType RangeFieldType;
245 RangeFieldType error( 0 );
246 for( std::size_t i = 0; i < size; ++i )
247 {
248 std::size_t j = DofConversion< DofAlignmentType >::apply( dofAlignment, i );
249 error = std::max( error, Error< Vector >::apply( a[ i ], b[ j ] ) );
250 }
251 return error;
252 }
253
254
255 // compareQuadrature
256 // -----------------
257
258 template< class BasisFunctionSetType, class VectorialBasisFunctionSetType, class QuadratureType >
259 Dune::FieldVector< typename BasisFunctionSetType::RangeType::value_type, 3 >
compareQuadrature(const BasisFunctionSetType & basisFunctionSet,const VectorialBasisFunctionSetType & vectorialBasisFunctionSet,const QuadratureType & quadrature)260 compareQuadrature ( const BasisFunctionSetType &basisFunctionSet,
261 const VectorialBasisFunctionSetType &vectorialBasisFunctionSet,
262 const QuadratureType &quadrature )
263 {
264 // check order of basis function set
265 if( vectorialBasisFunctionSet.order() != basisFunctionSet.order() )
266 DUNE_THROW( Dune::InvalidStateException, "order() does not match" );
267
268 // check size of basis function set
269 const std::size_t size = basisFunctionSet.size();
270 if( vectorialBasisFunctionSet.size() != basisFunctionSet.size() )
271 DUNE_THROW( Dune::InvalidStateException, "size() does not match" );
272
273 // get types
274 typedef typename BasisFunctionSetType::FunctionSpaceType FunctionSpaceType;
275 typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;
276
277 // init random dof vectors
278 std::vector< RangeFieldType > dofs( size );
279 for( std::size_t i = 0; i < size; ++i )
280 dofs[ i ] = random< RangeFieldType >( 1e-3, 1e3 );
281
282 // return value
283 Dune::FieldVector< RangeFieldType, 3 > ret;
284
285 const std::size_t nop = quadrature.nop();
286 for( std::size_t qp = 0; qp < nop; ++qp )
287 {
288 // check evaluate methods
289 {
290 RangeFieldType error = 0;
291 error += evaluateAll< Evaluate< FunctionSpaceType > >( basisFunctionSet, vectorialBasisFunctionSet, quadrature[ qp ], dofs );
292 error += evaluateAll< Evaluate< FunctionSpaceType > >( basisFunctionSet, vectorialBasisFunctionSet, quadrature[ qp ] );
293 ret[ 0 ] = std::max( ret[ 0 ], error );
294 }
295
296 // check jacobian methods
297 {
298 RangeFieldType error = 0;
299 error += evaluateAll< Jacobian< FunctionSpaceType > >( basisFunctionSet, vectorialBasisFunctionSet, quadrature[ qp ], dofs );
300 error += evaluateAll< Jacobian< FunctionSpaceType > >( basisFunctionSet, vectorialBasisFunctionSet, quadrature[ qp ] );
301 ret[ 1 ] = std::max( ret[ 1 ], error );
302 }
303
304 // check hessian methods
305 {
306 RangeFieldType error = 0;
307 error += evaluateAll< Hessian< FunctionSpaceType > >( basisFunctionSet, vectorialBasisFunctionSet, quadrature[ qp ], dofs );
308 error += evaluateAll< Hessian< FunctionSpaceType > >( basisFunctionSet, vectorialBasisFunctionSet, quadrature[ qp ] );
309 ret[ 2 ] = std::max( ret[ 1 ], error );
310 }
311 }
312
313 return ret;
314 }
315
316
317 template< class GridPartType >
traverse(GridPartType & gridPart)318 void traverse ( GridPartType &gridPart )
319 {
320 static const int dimDomain = GridPartType::dimensionworld;
321 static const int dimRange = DIMRANGE;
322
323 typedef Dune::Fem::FunctionSpace< typename GridPartType::ctype, double, dimDomain, dimRange > FunctionSpaceType;
324
325 // create discrete function space
326 typedef Dune::Fem::LagrangeDiscreteFunctionSpace< FunctionSpaceType, GridPartType, POLORDER > DiscreteFunctionSpaceType;
327 DiscreteFunctionSpaceType space( gridPart );
328
329 // create scalar discrete function space
330 typedef Dune::Fem::LagrangeDiscreteFunctionSpace< typename FunctionSpaceType::ScalarFunctionSpaceType, GridPartType, POLORDER > ScalarDiscreteFunctionSpaceType;
331 ScalarDiscreteFunctionSpaceType scalarSpace( gridPart );
332
333 typedef Dune::FieldVector< typename FunctionSpaceType::RangeFieldType, 3 > ErrorType;
334 ErrorType error( 0 );
335
336 for( const auto& entity : space )
337 {
338 // get basis function set
339 typedef typename DiscreteFunctionSpaceType::BasisFunctionSetType BasisFunctionSetType;
340 const BasisFunctionSetType basisFunctionSet = space.basisFunctionSet( entity );
341
342 // get scalar basis function set
343 typedef typename ScalarDiscreteFunctionSpaceType::BasisFunctionSetType ScalarBasisFunctionSetType;
344 const ScalarBasisFunctionSetType scalarBasisFunctionSet = scalarSpace.basisFunctionSet( entity );
345
346 // create vectorial basis function set
347 #if USE_VERTICAL_DOF_ALIGNMENT == 1
348 typedef Dune::Fem::VectorialBasisFunctionSet< ScalarBasisFunctionSetType, typename BasisFunctionSetType::RangeType, Dune::Fem::VerticalDofAlignment > VectorialBasisFunctionSetType;
349 #else
350 typedef Dune::Fem::VectorialBasisFunctionSet< ScalarBasisFunctionSetType, typename BasisFunctionSetType::RangeType, Dune::Fem::HorizontalDofAlignment > VectorialBasisFunctionSetType;
351 #endif
352 VectorialBasisFunctionSetType vectorialBasisFunctionSet( scalarBasisFunctionSet );
353
354 // create quadrature
355 assert( basisFunctionSet.order() == vectorialBasisFunctionSet.order() );
356 typedef Dune::Fem::CachingQuadrature< GridPartType, 0 > QuadratureType;
357 QuadratureType quadrature( basisFunctionSet.entity(), basisFunctionSet.order() );
358
359 // compare basis function sets in quadrature points
360 ErrorType localError = compareQuadrature( basisFunctionSet, vectorialBasisFunctionSet, quadrature );
361
362 // update error
363 for( int i = 0; i < 3; ++i )
364 error[ i ] = std::max( error[ i ], localError[ i ] );
365 }
366
367
368 const double eps = 1e-8;
369 // print error
370 if( error.two_norm() > eps )
371 {
372 std::cerr << "Errors( evaluateAll, jacobianAll, hessianAll ): " << error << std::endl;
373 #if USE_VERTICAL_DOF_ALIGNMENT == 1
374 DUNE_THROW( Dune::InvalidStateException, "VectorialBasisFunctionSet< VerticalDofAlignment > test failed." );
375 #else
376 DUNE_THROW( Dune::InvalidStateException, "VectorialBasisFunctionSet< HorizontalDofAlignment > test failed." );
377 #endif
378 }
379 }
380
381
main(int argc,char ** argv)382 int main ( int argc, char **argv )
383 {
384 Dune::Fem::MPIManager::initialize( argc, argv );
385
386 Dune::Fem::Parameter::append( argc, argv );
387 Dune::Fem::Parameter::append( argc >= 2 ? argv[ 1 ] : "parameter" );
388
389 srand( time( NULL ) );
390
391 typedef Dune::GridSelector::GridType GridType;
392 GridType &grid = Dune::Fem::TestGrid::grid();
393
394 int refCount = Dune::Fem::Parameter::getValue< int >( "startLevel", 0 );
395 const int refineStepsForHalf = Dune::Fem::TestGrid::refineStepsForHalf();
396 Dune::Fem::GlobalRefine::apply( grid, refCount*refineStepsForHalf );
397
398 typedef Dune::Fem::LeafGridPart< GridType > GridPartType;
399 GridPartType gridPart( grid );
400 traverse( gridPart );
401
402 return 0;
403 }
404