COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
utest-volume-sf.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #define BOOST_TEST_DYN_LINK
8 #define BOOST_TEST_MODULE "Common tests for shape functions that can be used to model the volume of a mesh"
9 
10 #include <boost/mpl/vector.hpp>
11 #include <boost/mpl/for_each.hpp>
12 #include <boost/mpl/transform_view.hpp>
13 #include <boost/assign/list_of.hpp>
14 #include <boost/test/unit_test.hpp>
15 
16 #include <boost/fusion/adapted/mpl.hpp>
17 #include <boost/fusion/support/pair.hpp>
18 #include <boost/fusion/container/map.hpp>
19 #include <boost/fusion/container/map/convert.hpp>
20 #include <boost/fusion/sequence/intrinsic/at_key.hpp>
21 
22 #include "common/Log.hpp"
23 #include "common/OptionList.hpp"
24 #include "common/Core.hpp"
25 #include "common/Environment.hpp"
27 
28 #include "mesh/GeoShape.hpp"
29 #include "mesh/ElementType.hpp"
30 #include "mesh/ElementTypes.hpp"
31 
32 using namespace cf3;
33 using namespace cf3::mesh;
34 using namespace cf3::common;
35 using namespace boost::assign;
36 
38 
39 typedef boost::mpl::vector<
50 
51 typedef boost::mpl::filter_view<TestTypes, IsCellType> TestCellTypes;
52 typedef boost::mpl::filter_view<TestTypes, IsFaceType> TestFaceTypes;
53 typedef boost::mpl::filter_view<TestTypes, IsEdgeType> TestEdgeTypes;
54 
55 
57 
58 template<int Dim>
60 
61 template<>
62 struct FunctorForDim<1>
63 {
64  template<typename ETYPE, typename NodesT, typename FunctorT>
65  void operator()(const Uint segments, const ETYPE& sf, const NodesT& nodes, FunctorT& functor)
66  {
67  const Real step = ((ETYPE::shape == GeoShape::TRIAG || ETYPE::shape == GeoShape::TETRA) ? 1. : 2.) / static_cast<Real>(segments);
68  const Real mapped_coord_min = (ETYPE::shape == GeoShape::TRIAG || ETYPE::shape == GeoShape::TETRA) ? 0. : -1.;
69  for(Uint i = 0; i <= segments; ++i)
70  {
71  typename ETYPE::MappedCoordsT mapped_coord;
72  mapped_coord << mapped_coord_min + i * step;
73  functor(sf, nodes, mapped_coord);
74  }
75  }
76 };
77 
78 template<>
79 struct FunctorForDim<2>
80 {
81  template<typename ETYPE, typename NodesT, typename FunctorT>
82  void operator()(const Uint segments, const ETYPE& sf, const NodesT& nodes, FunctorT& functor)
83  {
84  const Real step = ((ETYPE::shape == GeoShape::TRIAG || ETYPE::shape == GeoShape::TETRA) ? 1. : 2.) / static_cast<Real>(segments);
85  const Real mapped_coord_min = (ETYPE::shape == GeoShape::TRIAG || ETYPE::shape == GeoShape::TETRA) ? 0. : -1.;
86  for(Uint i = 0; i <= segments; ++i)
87  {
88  for(Uint j = 0; j <= segments; ++j)
89  {
90  typename ETYPE::MappedCoordsT mapped_coord;
91  mapped_coord << mapped_coord_min + i * step, mapped_coord_min + j * step;
92  functor(sf, nodes, mapped_coord);
93  }
94  }
95  }
96 };
97 
98 template<>
99 struct FunctorForDim<3>
100 {
101  template<typename ETYPE, typename NodesT, typename FunctorT>
102  void operator()(const Uint segments, const ETYPE& sf, const NodesT& nodes, FunctorT& functor)
103  {
104  const Real step = ((ETYPE::shape == GeoShape::TRIAG || ETYPE::shape == GeoShape::TETRA) ? 1. : 2.) / static_cast<Real>(segments);
105  const Real mapped_coord_min = (ETYPE::shape == GeoShape::TRIAG || ETYPE::shape == GeoShape::TETRA) ? 0. : -1.;
106  for(Uint i = 0; i <= segments; ++i)
107  {
108  for(Uint j = 0; j <= segments; ++j)
109  {
110  for(Uint k = 0; k <= segments; ++k)
111  {
112  typename ETYPE::MappedCoordsT mapped_coord;
113  mapped_coord << mapped_coord_min + i * step, mapped_coord_min + j * step, mapped_coord_min + k * step;
114  functor(sf, nodes, mapped_coord);
115  }
116  }
117  }
118  }
119 };
120 
122 {
124  template<typename SF>
126  {
127  typedef boost::fusion::pair<SF, typename SF::NodesT> type;
128  };
129 
131  typedef boost::fusion::result_of::as_map
132  <
133  boost::mpl::transform_view
134  <
135  TestTypes,
137  >
138  >::type NodesMapT;
139 
142  // If you get a compile error here, you forrgot to add nodes for a new volume shape function type
143  nodes
144  (
145  boost::fusion::make_pair< LagrangeP1::Line1D>( ( LagrangeP1::Line1D::NodesT() <<
146  5.,
147  10.
148  ).finished() ),
149  boost::fusion::make_pair< LagrangeP1::Quad2D>( ( LagrangeP1::Quad2D::NodesT() <<
150  0.5, 0.3,
151  1.1, 1.2,
152  1.35, 1.9,
153  0.8, 2.1
154  ).finished() ),
155  boost::fusion::make_pair< LagrangeP1::Triag2D>( ( LagrangeP1::Triag2D::NodesT() <<
156  0.5, 0.3,
157  1.1, 1.2,
158  0.8, 2.1
159  ).finished() ),
160  boost::fusion::make_pair< LagrangeP1::Hexa3D>( ( LagrangeP1::Hexa3D::NodesT() <<
161  0.5, 0.5, 0.5,
162  1., 0., 0.,
163  1.,1.,0.,
164  0., 1., 0.,
165  0., 0., 1.,
166  1., 0., 1.,
167  1.5, 1.5, 1.5,
168  0., 1., 1.
169  ).finished() ),
170  boost::fusion::make_pair< LagrangeP1::Tetra3D>( ( LagrangeP1::Tetra3D::NodesT() <<
171  0.830434, 0.885201, 0.188108,
172  0.89653, 0.899961, 0.297475,
173  0.888273, 0.821744, 0.211428,
174  0.950439, 0.904872, 0.20736
175  ).finished() ),
176  boost::fusion::make_pair< LagrangeP2::Quad2D>( ( LagrangeP2::Quad2D::NodesT() <<
177  0.5, 0.3,
178  1.1, 1.2,
179  1.35, 1.9,
180  0.8, 2.1,
181  0.9, 0.5,
182  1.2, 1.3,
183  1.0,2.0,
184  0.75,1.6,
185  1.0,1.0
186  ).finished() ),
187  boost::fusion::make_pair< LagrangeP2::Triag2D>( ( LagrangeP2::Triag2D::NodesT() <<
188  0.5, 0.3,
189  1.1, 1.2,
190  0.8, 2.1,
191  0.9, 0.5,
192  1.0, 1.5,
193  0.75,1.6
194  ).finished() ),
195  boost::fusion::make_pair< LagrangeP3::Quad2D>( ( LagrangeP3::Quad2D::NodesT() <<
196  -1., -1.,
197  1., -1.,
198  1., 1.,
199  -1., 1.,
200  -1./3., -1.,
201  1./3., -1.,
202  1., -1./3.,
203  1., 1./3.,
204  1./3., 1.,
205  -1./3., 1.,
206  -1., 1./3.,
207  -1., -1./3.,
208  -1./3., -1./3.,
209  1./3., -1./3.,
210  1./3., 1./3.,
211  -1./3., 1./3.
212  ).finished() ),
213  boost::fusion::make_pair< LagrangeP3::Triag2D>( ( LagrangeP3::Triag2D::NodesT() <<
214  0.5, 0.3,
215  1.1, 1.2,
216  0.8, 2.1,
217  0.9, 0.5,
218  1.0, 1.5,
219  1.0, 1.5,
220  1.0, 1.5,
221  1.0, 1.5,
222  1.0, 1.5,
223  0.75,1.6
224  ).finished() )
225  ) // end nodes(...) construction
226  {
227  }
228 
229  // Store test nodes per shape type
230  const NodesMapT nodes;
231 
233  template<typename FunctorT>
235  {
236  VolumeMPLFunctor(const NodesMapT& nodes) : m_nodes(nodes) {}
237 
238  template<typename ETYPE> void operator()(const ETYPE& T)
239  {
240  FunctorT functor;
242  CFinfo << "---------------------- Start " << allocate_component< ElementTypeT<ETYPE> >("lala")->derived_type_name() << " test ----------------------" << CFendl;
243  const Uint segments = 5; // number of segments in each direction for the mapped coord calculation
244  try
245  {
246  FunctorForDim<ETYPE::dimension>()(segments, T, boost::fusion::at_key<ETYPE>(m_nodes), functor);
247  }
248  catch(...)
249  {
250  CFinfo << " Unimplemented method for " << T.type_name() << CFendl;
251  }
252  }
253 
254  private:
255  const NodesMapT& m_nodes;
256  };
257 };
258 
263 template<typename ETYPE, typename NodesT, typename MappedCoordsT>
264 typename ETYPE::CoordsT gradient(const NodesT& nodes, const MappedCoordsT& mapped_coordinates, const RealVector& function_values)
265 {
266  // Get the gradient in mapped coordinates
267  typename ETYPE::SF::GradientT mapped_grad;
268  ETYPE::SF::compute_gradient(mapped_coordinates,mapped_grad);
269 
270  // The Jacobian adjugate
271  typename ETYPE::JacobianT jacobian_adj;
272  ETYPE::compute_jacobian_adjoint(mapped_coordinates, nodes, jacobian_adj);
273 
274  return ((jacobian_adj * mapped_grad) / ETYPE::jacobian_determinant(mapped_coordinates, nodes)) * function_values;
275 }
276 
279 {
280  template<typename ETYPE, typename NodesT, typename CoordsT>
281  void operator()(const ETYPE& T, const NodesT& nodes, const CoordsT& mapped_coord)
282  {
283  typename ETYPE::JacobianT jacobian;
284  ETYPE::compute_jacobian(mapped_coord, nodes, jacobian);
285  BOOST_CHECK_CLOSE(jacobian.determinant(), ETYPE::jacobian_determinant(mapped_coord, nodes), 1e-6);
286  }
287 };
288 
291 {
292  template<typename ETYPE, typename NodesT, typename CoordsT>
293  void operator()(const ETYPE& T, const NodesT& nodes, const CoordsT& mapped_coord)
294  {
295  typename ETYPE::JacobianT jacobian;
296  ETYPE::compute_jacobian(mapped_coord, nodes, jacobian);
297 
298  typename ETYPE::JacobianT jacobian_adjoint;
299  ETYPE::compute_jacobian_adjoint(mapped_coord, nodes, jacobian_adjoint);
300 
301  typename ETYPE::JacobianT identity;
302  identity = jacobian * jacobian_adjoint / ETYPE::jacobian_determinant(mapped_coord, nodes);
303 
304  for(Uint i = 0; i != ETYPE::dimensionality; ++i)
305  {
306  for(Uint j = 0; j != ETYPE::dimension; ++j)
307  {
308  if(j == i)
309  BOOST_CHECK_CLOSE(identity(i, j), 1., 1e-6);
310  else
311  BOOST_CHECK_SMALL(identity(i, j), 1e-14);
312  }
313  }
314  }
315 };
316 
319 {
320  template<typename ETYPE, typename NodesT, typename CoordsT>
321  void operator()(const ETYPE& T, const NodesT& nodes, const CoordsT& mapped_coord)
322  {
323  // Define the function values
324  RealVector function(ETYPE::nb_nodes);
325  for(Uint i = 0; i != ETYPE::nb_nodes; ++i)
326  function[i] = nodes(i, XX);
327 
328  // Calculate the gradient
329  typename ETYPE::CoordsT grad = gradient<ETYPE>(nodes, mapped_coord, function);
330 
331  // Check the result
332  BOOST_CHECK_CLOSE(grad[0], 1, 1e-6);
333  for(Uint i = 1; i != grad.size(); ++i)
334  BOOST_CHECK_SMALL(grad[i], 1e-14);
335  }
336 };
337 
339 
340 BOOST_FIXTURE_TEST_SUITE( VolumeSFSuite, VolumeSFFixture )
341 
342 
344 BOOST_AUTO_TEST_CASE( TestJacobianDeterminant )
345 {
346  Core::instance().environment().options().set("exception_outputs",false);
347  Core::instance().environment().options().set("exception_backtrace",false);
348  VolumeMPLFunctor<CheckJacobianDeterminant> functor(nodes);
349  boost::mpl::for_each<TestCellTypes>(functor);
350 }
351 
353 
354 BOOST_AUTO_TEST_CASE( TestJacobianInverse )
355 {
356  VolumeMPLFunctor<CheckJacobianInverse> functor(nodes);
357  boost::mpl::for_each<TestCellTypes>(functor);
358 }
359 
361 
362 BOOST_AUTO_TEST_CASE( TestGradientX )
363 {
364  VolumeMPLFunctor<CheckGradientX> functor(nodes);
365  boost::mpl::for_each<TestCellTypes>(functor);
366 }
367 
369 
370 BOOST_AUTO_TEST_SUITE_END()
371 
372 
Functor to create a fusion pair between a shape function and its node matrix.
void operator()(const ETYPE &T, const NodesT &nodes, const CoordsT &mapped_coord)
boost::proto::terminal< SFOp< JacobianOp > >::type const jacobian
boost::mpl::filter_view< TestTypes, IsCellType > TestCellTypes
#define CFinfo
these are always defined
Definition: Log.hpp:104
boost::fusion::result_of::as_map< boost::mpl::transform_view< TestTypes, MakeSFNodesPair< boost::mpl::_1 > > >::type NodesMapT
Map between a shape function and its node matrix. Used to store nodes for each possible test...
static void compute_jacobian_adjoint(const MappedCoordsT &mapped_coord, const NodesT &nodes, JacobianT &result)
Definition: Hexa3D.cpp:308
VolumeSFFixture()
common setup for each test case
void operator()(const Uint segments, const ETYPE &sf, const NodesT &nodes, FunctorT &functor)
Checks if the jacobian_determinant function result is the same as det(jacobian)
void operator()(const Uint segments, const ETYPE &sf, const NodesT &nodes, FunctorT &functor)
2D Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Tetra3D.hpp:36
external boost library namespace
static void compute_jacobian(const MappedCoordsT &mapped_coord, const NodesT &nodes, MatrixType &jacobian)
static Real jacobian_determinant(const MappedCoordsT &mapped_coord, const NodesT &nodes)
Definition: Hexa3D.cpp:169
void operator()(const ETYPE &T, const NodesT &nodes, const CoordsT &mapped_coord)
const NodesMapT nodes
#define cf3_assert(a)
Definition: Assertions.hpp:93
2D Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Triag2D.hpp:36
Applies a functor if the element is a volume element.
#define CFendl
Definition: Log.hpp:109
2D Lagrange P3 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Triag2D.hpp:36
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
boost::proto::terminal< SFOp< NodesOp > >::type const nodes
2D Lagrange P3 Quadrilateral Element type This class provides the lagrangian shape function describin...
Definition: Quad2D.hpp:36
Definition: Defs.hpp:17
boost::mpl::filter_view< TestTypes, IsEdgeType > TestEdgeTypes
boost::mpl::filter_view< TestTypes, IsFaceType > TestFaceTypes
void operator()(const ETYPE &T, const NodesT &nodes, const CoordsT &mapped_coord)
Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing the ...
Definition: Line1D.hpp:36
Basic Classes for Mesh applications used by COOLFluiD.
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealVector
Dynamic sized column vector.
Definition: MatrixTypes.hpp:25
boost::mpl::vector1< mesh::LagrangeP1::Triag2D > LagrangeP1
2D Lagrange P2 Quadrilateral Element type This class provides the lagrangian shape function describin...
Definition: Quad2D.hpp:36
Top-level namespace for coolfluid.
Definition: Action.cpp:18
static std::string type_name()
VolumeMPLFunctor(const NodesMapT &nodes)
ETYPE::CoordsT gradient(const NodesT &nodes, const MappedCoordsT &mapped_coordinates, const RealVector &function_values)
Eigen::Matrix< Real, Hexa3D_traits::dimension, 1 > CoordsT
std::string derived_type_name(ComponentWrapper &self)
BOOST_AUTO_TEST_CASE(TestJacobianDeterminant)
void operator()(const Uint segments, const ETYPE &sf, const NodesT &nodes, FunctorT &functor)
common::Environment & environment() const
Definition: Core.cpp:168
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
boost::mpl::vector< LagrangeP1::Line1D, LagrangeP1::Quad2D, LagrangeP1::Triag2D, LagrangeP1::Hexa3D, LagrangeP1::Tetra3D, LagrangeP2::Quad2D, LagrangeP2::Triag2D, LagrangeP3::Quad2D, LagrangeP3::Triag2D > TestTypes
Check if the gradient of X is one in the X direction and zero in the other directions.
static Core & instance()
Definition: Core.cpp:37
boost::fusion::pair< SF, typename SF::NodesT > type
Checks if the inverse of the jacobian matrix equals jacobian_adjoint / jacobian_determinant.
OptionList & options()
Definition: Component.cpp:856
2D Lagrange P2 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Triag2D.hpp:36
Eigen::Matrix< Real, Hexa3D_traits::SF::dimensionality, Hexa3D_traits::dimension > JacobianT
void set(const std::string &pname, const boost::any &val)
Definition: OptionList.cpp:132
Most basic kernel library.
Definition: Action.cpp:19
2D Lagrange P1 Quadrilateral Element type This class provides the lagrangian shape function describin...
Definition: Quad2D.hpp:37
2D Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Hexa3D.hpp:36
Send comments to:
COOLFluiD Web Admin