COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
utest-proto-operators.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2011 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 "Test module for proto operators"
9 
10 #include <boost/accumulators/accumulators.hpp>
11 #include <boost/accumulators/statistics/stats.hpp>
12 #include <boost/accumulators/statistics/mean.hpp>
13 #include <boost/accumulators/statistics/max.hpp>
14 
15 #include <boost/foreach.hpp>
16 #include <boost/test/unit_test.hpp>
17 #include <boost/proto/debug.hpp>
18 
19 #include "solver/Model.hpp"
20 #include "solver/Solver.hpp"
21 
28 
29 #include "common/Core.hpp"
30 #include "common/Log.hpp"
31 
32 #include "math/MatrixTypes.hpp"
33 
34 #include "mesh/Domain.hpp"
35 #include "mesh/Mesh.hpp"
36 #include "mesh/Region.hpp"
37 #include "mesh/Elements.hpp"
38 #include "mesh/MeshReader.hpp"
39 #include "mesh/ElementData.hpp"
40 #include "mesh/FieldManager.hpp"
41 #include "mesh/Dictionary.hpp"
42 
44 #include "mesh/ElementTypes.hpp"
45 
46 #include "physics/PhysModel.hpp"
47 
51 
52 using namespace cf3;
53 using namespace cf3::solver;
54 using namespace cf3::solver::actions;
55 using namespace cf3::solver::actions::Proto;
56 using namespace cf3::mesh;
57 using namespace cf3::common;
58 
59 using namespace cf3::math::Consts;
60 
62 inline void check_close(const RealMatrix2& a, const RealMatrix2& b, const Real threshold)
63 {
64  for(Uint i = 0; i != a.rows(); ++i)
65  for(Uint j = 0; j != a.cols(); ++j)
66  BOOST_CHECK_CLOSE(a(i,j), b(i,j), threshold);
67 }
68 
69 static boost::proto::terminal< void(*)(const RealMatrix2&, const RealMatrix2&, Real) >::type const _check_close = {&check_close};
70 
72 
74 typedef boost::mpl::vector3< LagrangeP1::Line1D,
78 
79 typedef boost::mpl::vector5< LagrangeP1::Line1D,
85 
86 BOOST_AUTO_TEST_SUITE( ProtoOperatorsSuite )
87 
88 using boost::proto::lit;
89 
91 
92 BOOST_AUTO_TEST_CASE( ProtoBasics )
93 {
95  Tools::MeshGeneration::create_rectangle(*mesh, 5, 5, 5, 5);
96 
97  RealVector center_coords(2);
98  center_coords.setZero();
99 
100  // Use the volume function
101  for_each_element<VolumeTypes>(mesh->topology(), _cout << "Volume = " << volume << ", centroid = " << transpose(coordinates(center_coords)) << "\n");
102  std::cout << std::endl; // Can't be in expression
103 
104  // volume calculation
105  Real vol1 = 0.;
106  for_each_element<VolumeTypes>(mesh->topology(), vol1 += volume);
107 
108  CFinfo << "Mesh volume: " << vol1 << CFendl;
109 
110  // For an all-quad mesh, this is the same... cool or what?
111  Real vol2 = 0.;
112  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
113  (
114  mesh->topology(),
115  vol2 += 0.5*((nodes[2][0] - nodes[0][0]) * (nodes[3][1] - nodes[1][1])
116  - (nodes[2][1] - nodes[0][1]) * (nodes[3][0] - nodes[1][0]))
117  );
118  BOOST_CHECK_CLOSE(vol1, vol2, 1e-5);
119 }
120 
121 BOOST_AUTO_TEST_CASE( MatrixAccess )
122 {
124  Tools::MeshGeneration::create_rectangle(*mesh, 1., 1., 1, 1);
125 
126  mesh->geometry_fields().create_field( "solution", "u[vector]" ).add_tag("solution");
127 
128  FieldVariable<0, VectorField > u("u", "solution");
129 
130  for_each_node(mesh->topology(), group(u[0] = 0., u[1] = 1.));
131 
132  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
133  (
134  mesh->topology(),
135  group
136  (
137  _cout << "column " << _i << ": " << transpose(_col(nodal_values(u), _i)) << "\n",
138  _cout << "row 3: " << _row(nodal_values(u), 3) << "\n"
139  )
140  );
141 }
142 
143 BOOST_AUTO_TEST_CASE( MatrixProducts )
144 {
147 
148  mesh->geometry_fields().create_field( "solution", "Temperature" ).add_tag("solution");
149 
150  FieldVariable<0, ScalarField > temperature("Temperature", "solution");
151 
152  for_each_node(mesh->topology(), temperature = 5.);
153 
154  RealVector1 mapped_coords;
155  mapped_coords.setZero();
156 
157  RealMatrix2 exact; exact << 1., -1., -1., 1;
158  RealMatrix2 result;
159 
160  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
161  (
162  mesh->topology(),
163  boost::proto::lit(result) = 0.5 * integral<1>(transpose(nabla(temperature))*nabla(temperature)) * integral<1>(transpose(nabla(temperature))*nabla(temperature)) * transpose(nabla(temperature, mapped_coords)) * nabla(temperature, mapped_coords)
164  );
165 
166  check_close(result, 8*exact, 1e-10);
167 
168  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
169  (
170  mesh->topology(),
171  boost::proto::lit(result) = integral<1>(transpose(nabla(temperature))*nabla(temperature)) * 0.5
172  );
173 
174  check_close(result, exact, 1e-10);
175 
176  result.setZero();
177 
178  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
179  (
180  mesh->topology(),
181  element_quadrature( boost::proto::lit(result) += transpose(N(temperature))*N(temperature) * (1. / temperature) * boost::proto::lit(3.) )
182  );
183 
184  exact << 0.2, 0.1, 0.1, 0.2;
185  check_close(result, exact, 1e-10);
186 }
187 
188 BOOST_AUTO_TEST_CASE( RotatingCylinder )
189 {
190  const Real radius = 1.;
191  const Uint segments = 1000;
192  const Real u = 300.;
193  const Real circulation = 975.;
194  const Real rho = 1.225;
195 
197  Tools::MeshGeneration::create_circle_2d(*mesh, radius, segments);
198 
199  typedef boost::mpl::vector1< LagrangeP1::Line2D> SurfaceTypes;
200 
201  RealVector2 force;
202  force.setZero();
203 
204  for_each_element<SurfaceTypes>
205  (
206  mesh->topology(),
207  force += integral<1>
208  (
209  pow<2>
210  (
211  2. * u * _sin( _atan2(coordinates[1], coordinates[0]) ) + circulation / (2. * pi() * radius)
212  ) * 0.5 * rho * normal
213  )
214  );
215 
216  BOOST_CHECK_CLOSE(force[YY], rho*u*circulation, 0.001); // lift according to theory
217  BOOST_CHECK_SMALL(force[XX], 1e-8); // Drag should be zero
218 }
219 
221 BOOST_AUTO_TEST_CASE( RotatingCylinderField )
222 {
223  const Real radius = 1.;
224  const Uint segments = 1000;
225  const Real u = 300.;
226  const Real circulation = 975.;
227  const Real rho = 1.225;
228 
230  Tools::MeshGeneration::create_circle_2d(*mesh, radius, segments);
231 
232  mesh->geometry_fields().create_field( "Pressure", "Pressure" ).add_tag("solution");
233 
234  FieldVariable<1, ScalarField > p("Pressure", "solution"); // Pressure field
235 
236  typedef boost::mpl::vector1< LagrangeP1::Line2D> SurfaceTypes;
237 
238  // Set a field with the pressures
239  for_each_node<2>
240  (
241  mesh->topology(),
242  p += pow<2>
243  (
244  2. * u * _sin( _atan2(coordinates[1], coordinates[0]) ) + circulation / (2. * pi() * radius)
245  ) * 0.5 * rho
246  );
247 
248  RealVector2 force;
249  force.setZero();
250 
251  RealVector1 mc;
252  mc.setZero();
253 
254  for_each_element<SurfaceTypes>
255  (
256  mesh->topology(),
257  force += integral<1>(p * normal)
258  );
259 
260  BOOST_CHECK_CLOSE(force[YY], rho*u*circulation, 0.001); // lift according to theory
261  BOOST_CHECK_SMALL(force[XX], 1e-8); // Drag should be zero
262 }
263 
265 {
267  template<typename Signature>
268  struct result;
269 
270  template<typename This, typename FieldDataT>
271  struct result<This(FieldDataT)>
272  {
273  typedef const Eigen::Matrix<Real, FieldDataT::dimension*FieldDataT::EtypeT::nb_nodes, FieldDataT::dimension*FieldDataT::EtypeT::nb_nodes>& type;
274  };
275 
276  template<typename StorageT, typename FieldDataT>
277  const StorageT& operator()(StorageT& result, const FieldDataT& field) const
278  {
279  typedef typename FieldDataT::EtypeT EtypeT;
280  const Eigen::Matrix<Real, EtypeT::nb_nodes, EtypeT::nb_nodes> m = field.nabla().transpose() * field.nabla();
281  for(Uint d = 0; d != FieldDataT::dimension; ++d)
282  {
283  result.template block<EtypeT::nb_nodes, EtypeT::nb_nodes>(EtypeT::nb_nodes*d, EtypeT::nb_nodes*d).noalias() = m;
284  }
285  return result;
286  }
287 };
288 
290 
292 {
295 
296  mesh->geometry_fields().create_field( "Temperature", "Temperature" ).add_tag("solution");
297 
298  FieldVariable<0, ScalarField > temperature("Temperature", "solution");
299 
300  RealMatrix2 exact; exact << 1., -1., -1., 1;
301  RealMatrix2 result;
302 
303  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
304  (
305  mesh->topology(),
306  boost::proto::lit(result) = integral<1>(laplacian_cust(temperature)) * 0.5
307  );
308 
309  check_close(result, exact, 1e-10);
310 
311 }
312 
314 struct Counter : boost::noncopyable
315 {
316  Counter() : increment(0.)
317  {
318  }
319 
321  typedef void result_type;
322 
323  result_type operator()(int& arg) const
324  {
325  arg += increment;
326  }
327 
328  Real increment;
329 };
330 
333 {
335  Tools::MeshGeneration::create_line(*mesh, 1., 10);
336 
338  MakeSFOp<Counter>::reference_type add_count = boost::proto::as_child(counter);
339 
340  counter.op.increment = 2.;
341 
342  // Check if the counter really counts
343  int count = 0;
344 
346  (
347  boost::mpl::vector1<LagrangeP1::Line1D>(),
348  add_count(lit(count))
349  )->loop(mesh->topology());
350 
351  BOOST_CHECK_EQUAL(count, 20);
352 }
353 
354 BOOST_AUTO_TEST_CASE( ElementGaussQuadrature )
355 {
356  Handle<Mesh> mesh = Core::instance().root().create_component<Mesh>("GaussQuadratureLine");
358 
359  mesh->geometry_fields().create_field("Temperature", "Temperature").add_tag("solution");
360 
361  FieldVariable<0, ScalarField > temperature("Temperature", "solution");
362 
363  RealVector1 mapped_coords;
364  mapped_coords.setZero();
365 
366  RealMatrix2 exact; exact << 1., -1., -1., 1;
367  RealMatrix2 result;
368  RealMatrix2 zero; zero.setZero();
369 
370  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
371  (
372  mesh->topology(),
373  group
374  (
375  boost::proto::lit(result) = zero,
376  element_quadrature( boost::proto::lit(result) += transpose(nabla(temperature))*nabla(temperature) )
377  )
378  );
379 
380  check_close(result, exact, 1e-10);
381 
382  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
383  (
384  mesh->topology(),
385  group
386  (
387  boost::proto::lit(result) = zero,
389  (
390  boost::proto::lit(result) += transpose(nabla(temperature))*nabla(temperature),
391  boost::proto::lit(result) += transpose(nabla(temperature))*nabla(temperature)
392  )
393  )
394  );
395 
396  check_close(result, 2.*exact, 1e-10);
397 }
398 
399 
401 {
402  Handle<Mesh> mesh = Core::instance().root().create_component<Mesh>("GaussQuadratureLine");
404 
405  mesh->geometry_fields().create_field("Temperature", "Temperature").add_tag("solution");
406 
407  Real total = 0;
408 
409  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
410  (
411  mesh->topology(),
412  group
413  (
414  boost::proto::lit(total) += volume,
415  boost::proto::lit(total) += volume
416  )
417  );
418 
419  BOOST_CHECK_CLOSE(total, 2., 1e-10);
420 }
421 
423 
424 template<int I>
426  boost::proto::when
427  <
428  boost::proto::terminal<IntegralConstantTag>,
429  boost::proto::_make_terminal(boost::mpl::int_<I>())
430  >
431 {
432 };
433 
435 BOOST_AUTO_TEST_CASE(IntegralConstant)
436 {
437  boost::proto::terminal<IntegralConstantTag>::type integral_const;
438  BOOST_CHECK_EQUAL(boost::proto::value(IntegralConstantGrammar<3>()(integral_const)), 3);
439 }
440 
442 {
444  Tools::MeshGeneration::create_rectangle(*mesh, 1., 1., 1, 1);
445 
446  const RealVector2 idx(1.,2.);
447 
448  Real result_i = 0;
449  Real result_j = 0;
450  Real result_ij = 0;
451 
452  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
453  (
454  mesh->topology(),
455  group
456  (
457  boost::proto::lit(result_i) += boost::proto::lit(idx)[_i], // Loop with _i in (0, 1)
458  boost::proto::lit(result_j) += boost::proto::lit(idx)[_j], // Loop with _j in (0, 1)
459  boost::proto::lit(result_ij) += boost::proto::lit(idx)[_i] + boost::proto::lit(idx)[_j] // Nested loop forall(_i): forall(_j)
460  )
461  );
462 
463  BOOST_CHECK_EQUAL(result_i, 3.);
464  BOOST_CHECK_EQUAL(result_j, 3.);
465  BOOST_CHECK_EQUAL(result_ij, 12.);
466 
467  Mesh& line = *Core::instance().root().create_component<Mesh>("Line");
469 
470  FieldVariable<0, VectorField> u("Velocity", "solution");
471  line.geometry_fields().create_field( "solution", "Velocity[v]" ).add_tag("solution");
472 
473  RealVector1 center;
474  center.setZero();
475 
476  RealVector2 result1d;
477  result1d.setZero();
478 
479 
480  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
481  (
482  line.topology(),
483  group
484  (
485  group(_cout << "i: " << _i << ", j: " << _j << "\n"),
486  result1d += nabla(u, center)[_i]
487  )
488  );
489 
490  BOOST_CHECK_CLOSE(result1d[0], -1., 1e-6);
491  BOOST_CHECK_CLOSE(result1d[1], 1., 1e-6);
492 }
493 
494 BOOST_AUTO_TEST_CASE( VectorMultiplication )
495 {
496  FieldVariable<0, VectorField> u("Velocity", "solution");
497  FieldVariable<0, ScalarField> T("Temperature", "solution");
498 
500  Domain& dom = model.create_domain("Domain");
501  Mesh& mesh = *dom.create_component<Mesh>("QuadGrid2");
502  Tools::MeshGeneration::create_rectangle(mesh, 1., 1., 5, 5);
503 
504  physics::PhysModel& physics = model.create_physics("cf3.physics.DynamicModel");
505  physics.options().set(common::Tags::dimension(), 2u);
506 
507  // Create the initialization expression
508  boost::shared_ptr< Expression > init = nodes_expression(u = coordinates);
509  boost::shared_ptr< Expression > init_temp = nodes_expression(T = coordinates[0]);
510 
511  FieldManager& field_manager = *dom.create_component<FieldManager>("FieldManager");
512  field_manager.options().set("variable_manager", physics.variable_manager().handle<math::VariableManager>());
513 
514  // set up fields
515  init->register_variables(physics);
516  init_temp->register_variables(physics);
517  field_manager.create_field("solution", mesh.geometry_fields());
518 
519  // Do the initialization
520  init->loop(mesh.topology());
521  init_temp->loop(mesh.topology());
522 
523  RealVector4 result;
524  result.setZero();
525 
526  // Run a vector product
528  (
529  boost::mpl::vector1<LagrangeP1::Quad2D>(),
530  element_quadrature(boost::proto::lit(result) += u*nabla(u))
531  )->loop(mesh.topology());
532 
533  std::cout << "advection: " << result.transpose() << std::endl;
534 
535  //RealMatrix4 gradient_result; gradient_result.setZero();
536  Real gradient_result = 0.;
537  // Gradient calculation for a scalar
539  (
540  boost::mpl::vector1<LagrangeP1::Quad2D>(),
541  element_quadrature(boost::proto::lit(gradient_result) += _norm(transpose(N(T))*transpose(nabla(T)*nodal_values(T))*nabla(T)))
542  )->loop(mesh.topology());
543 
544  std::cout << "gradient: " << gradient_result << std::endl;
545 }
546 
547 
548 BOOST_AUTO_TEST_CASE( NodeExprGrouping )
549 {
552 
553  mesh->geometry_fields().create_field( "solution", "Temperature" ).add_tag("solution");
554 
555  FieldVariable<0, ScalarField > T("Temperature", "solution");
556  Real total = 0.;
557 
558  boost::shared_ptr< Expression > test_expr = nodes_expression
559  (
560  group
561  (
562  T = 6.,
563  T += 4.,
564  _cout << T << "\n",
565  boost::proto::lit(total) += T
566  )
567  );
568 
569  test_expr->loop(mesh->topology());
570 
571  BOOST_CHECK_EQUAL(total, 50.);
572 }
573 
574 BOOST_AUTO_TEST_CASE( NodeExprFunctionParsing )
575 {
578 
579  mesh->geometry_fields().create_field( "solution", "Temperature" ).add_tag("solution");
580 
581  FieldVariable<0, VectorField > T("Temperature", "solution");
582  RealVector total(1); total.setZero();
583 
585  f.variables("x");
586  f.functions(std::vector<std::string>(1, "x+1"));
587  f.parse();
588  f.predefined_values.resize(1);
589 
590  RealVector one(1); one.setConstant(1.);
591 
592  boost::shared_ptr< Expression > test_expr = nodes_expression
593  (
594  group
595  (
596  T = boost::proto::lit(f) + one,
597  _cout << T << "\n",
598  boost::proto::lit(total) += T
599  )
600  );
601 
602  test_expr->loop(mesh->topology());
603 
604  BOOST_CHECK_EQUAL(total[0], 20.);
605 }
606 
608 
609 BOOST_AUTO_TEST_CASE( ProtoAccumulators )
610 {
612  Tools::MeshGeneration::create_line(*mesh, 4., 400);
613 
614  boost::accumulators::accumulator_set< Real, boost::accumulators::stats<boost::accumulators::tag::mean, boost::accumulators::tag::max> > acc;
615 
616  mesh->geometry_fields().create_field( "solution", "Temperature" ).add_tag("solution");
617  FieldVariable<0, VectorField > T("Temperature", "solution");
618 
619  boost::shared_ptr<Expression> init_expr = nodes_expression(T = coordinates);
620  init_expr->loop(mesh->topology());
621 
622  boost::shared_ptr<Expression> test_expr = nodes_expression(boost::proto::lit(acc)(_norm(T)));
623 
624  test_expr->loop(mesh->topology());
625 
626  BOOST_CHECK_EQUAL(boost::accumulators::max(acc), 4.);
627  BOOST_CHECK_CLOSE(boost::accumulators::mean(acc), 2., 1e-6);
628 }
629 
630 BOOST_AUTO_TEST_CASE( AssignMatrix )
631 {
634 
635  mesh->geometry_fields().create_field( "Temperature", "Temperature" ).add_tag("solution");
636 
637  FieldVariable<0, ScalarField > T("Temperature", "solution");
638 
639  RealMatrix tmp;
640 
641  for_each_element< boost::mpl::vector1<LagrangeP1::Line1D> >
642  (
643  mesh->topology(),
644  boost::proto::lit(tmp) = integral<1>(transpose(nabla(T))*nabla(T))
645  );
646 
647  std::cout << "tmp=\n" << tmp << std::endl;
648 
649 }
650 
651 BOOST_AUTO_TEST_CASE( GaussPointAccess )
652 {
654  Tools::MeshGeneration::create_rectangle(*mesh, 5., 5., 2, 2);
655 
656  RealVector center_coords(2);
657  center_coords.setZero();
658 
659  for_each_element<VolumeTypes>(mesh->topology(), _cout << "point = " << transpose(gauss_points_1) << ", weight = " << gauss_weights_1 << "\n");
660  std::cout << std::endl;
661 
662  for_each_element<VolumeTypes>(mesh->topology(), _cout << "point = " << transpose(gauss_points_2) << ", weight = " << gauss_weights_2 << "\n");
663  std::cout << std::endl;
664 }
665 
666 BOOST_AUTO_TEST_CASE( RestrictToEtype )
667 {
668  Handle<Mesh> mesh = Core::instance().root().create_component<Mesh>("rect_etypecheck");
669  Tools::MeshGeneration::create_rectangle(*mesh, 5., 5., 5, 2);
670 
671  boost::proto::terminal< RestrictToElementTypeTag< boost::mpl::vector1<LagrangeP1::Quad2D> > >::type quads_only;
672  boost::proto::terminal< RestrictToElementTypeTag< boost::mpl::vector1<LagrangeP1::Line2D> > >::type lines_only;
673 
674  Uint nb_cells = 0;
675  Uint nb_faces = 0;
676 
677  for_each_element< boost::mpl::vector2<LagrangeP1::Quad2D, LagrangeP1::Line2D> >(mesh->topology(),
678  group
679  (
680  quads_only(boost::proto::lit(nb_cells) += 1),
681  lines_only(boost::proto::lit(nb_faces) += 1)
682  )
683  );
684 
685  BOOST_CHECK_EQUAL(nb_cells, 10);
686  BOOST_CHECK_EQUAL(nb_faces, 16);
687 
688  std::cout << "mesh has " << nb_cells << " cells and " << nb_faces << " faces" << std::endl;
689 }
690 
691 BOOST_AUTO_TEST_CASE( AddElementValues )
692 {
693  Handle<Mesh> mesh = Core::instance().root().create_component<Mesh>("add_elems_mesh");
694  Tools::MeshGeneration::create_rectangle(*mesh, 6., 3., 3, 3);
695 
696  mesh->geometry_fields().create_field( "solution", "Temperature[v]" ).add_tag("solution");
697 
698  FieldVariable<0, VectorField > T("Temperature", "solution");
699 
700  Eigen::Matrix<Real, 8, 8> vals; vals.setConstant(0.125);
701 
702  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
703  (
704  mesh->topology(),
705  group
706  (
707  lump(vals),
708  T += diagonal(vals)
709  )
710  );
711 
712  Real check = 0;
713  for_each_node(mesh->topology(), group(boost::proto::lit(check) += T[_i], _cout << "summed nodal value: " << transpose(T) << "\n"));
714 
715  for_each_node(mesh->topology(), T[_i] = 0.);
716 
717  BOOST_CHECK_EQUAL(check, 72);
718 
719  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
720  (
721  mesh->topology(),
722  group
723  (
724  T[_i] += nabla(T, gauss_points_1)[_i],
725  _cout << nabla(T, gauss_points_1)[_i] << "\n"
726  )
727  );
728 
729  Real x_check = 0.;
730  Real y_check = 0.;
731 
732  for_each_node<2>(mesh->topology(), group
733  (
734  boost::proto::lit(x_check) += T[0],
735  boost::proto::lit(y_check) += T[1],
736  _cout << "checked nodal value: " << transpose(T) << " at (" << transpose(coordinates) << ")\n"
737  ));
738 
739  BOOST_CHECK_EQUAL(x_check, 0.);
740  BOOST_CHECK_EQUAL(y_check, 0.);
741 }
742 
743 
744 BOOST_AUTO_TEST_CASE( NodeIndexLoop )
745 {
746  Handle<Mesh> mesh = Core::instance().root().create_component<Mesh>("ArrayOpsGrid");
747  Tools::MeshGeneration::create_rectangle(*mesh, 1., 1., 1, 1);
748 
749  FieldVariable<0, VectorField> u("Velocity", "solution");
750  mesh->geometry_fields().create_field( "solution", "Velocity[v]" ).add_tag("solution");
751 
752  RealVector v(2); v << 2. , 4.;
753  RealVector v2(2); v2.setZero();
754 
756  (
757  mesh->topology(),
758  group
759  (
760  lit(v2)[_i] += lit(v)[_i],
761  u[_i] = lit(v)[_i]
762  )
763  );
764 
765  BOOST_CHECK_EQUAL(v2[0], 8.);
766  BOOST_CHECK_EQUAL(v2[1], 16.);
767 
768  Real x_sum = 0.;
769  Real y_sum = 0.;
770  Real total_sum = 0.;
771 
773  (
774  mesh->topology(),
775  group
776  (
777  lit(x_sum) += u[0],
778  lit(y_sum) += u[1],
779  lit(total_sum) += u[_i]
780  )
781  );
782 
783  BOOST_CHECK_EQUAL(x_sum, 8.);
784  BOOST_CHECK_EQUAL(y_sum, 16.);
785  BOOST_CHECK_EQUAL(total_sum, 24.);
786 }
787 
789 {
790  Handle<Mesh> mesh = Core::instance().root().create_component<Mesh>("ElementVector");
791  Tools::MeshGeneration::create_rectangle(*mesh, 1., 1., 1, 1);
792 
793  FieldVariable<0, VectorField> u("Velocity", "solution");
794  mesh->geometry_fields().create_field( "solution", "Velocity[v]" ).add_tag("solution");
795 
797  (
798  mesh->topology(),
799  u = coordinates
800  );
801 
802  RealVector elvec;
803 
804  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
805  (
806  mesh->topology(),
807  lit(elvec) = element_vector(u)
808  );
809 
810  std::cout << elvec.transpose() << std::endl;
811  BOOST_CHECK_EQUAL(elvec.rows(), 8);
812  RealVector ref(8);
813  ref << 0,1,1,0,0,0,1,1;
814  BOOST_CHECK_EQUAL(elvec, ref);
815 }
816 
817 
819 {
821  Tools::MeshGeneration::create_rectangle(*mesh, 1., 1., 1, 1);
822 
823  mesh->geometry_fields().create_field( "solution", "u[scalar]" ).add_tag("solution");
824 
825  FieldVariable<0, ScalarField > u("u", "solution");
826 
827  for_each_node(mesh->topology(), group(u = 2.*coordinates[0]));
828 
830  result1.setZero(); result2.setZero();
831 
832  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
833  (
834  mesh->topology(),
835  group
836  (
837  _cout << "u*gradient(u): " << u(result1) * gradient(u, result1) << "\n",
838  element_quadrature(lit(result1) += gradient(u)),
839  lit(result1) = result1 / volume,
840  lit(result2) = gradient(u, result2)
841  )
842  );
843 
844  BOOST_CHECK_EQUAL(result1[0], 2.);
845  BOOST_CHECK_EQUAL(result2[0], 2.);
846  BOOST_CHECK_EQUAL(result1[1], 0.);
847  BOOST_CHECK_EQUAL(result2[1], 0.);
848 }
849 
851 {
853  Tools::MeshGeneration::create_rectangle(*mesh, 1., 1., 1, 1);
854 
855  mesh->geometry_fields().create_field( "solution", "u[vector]" ).add_tag("solution");
856 
857  FieldVariable<0, VectorField > u("u", "solution");
858 
859  for_each_node(mesh->topology(), group(u[0] = 2.*coordinates[0], u[1] = 1.));
860 
861  Real result1 = 0.;
862  Real result2 = 1.;
863  RealVector2 centroid; centroid.setZero();
864 
865  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
866  (
867  mesh->topology(),
868  group
869  (
870  element_quadrature(lit(result1) += divergence(u)),
871  lit(result1) = result1 / volume,
872  lit(result2) = divergence(u, centroid)
873  )
874  );
875 
876  BOOST_CHECK_EQUAL(result1, 2.);
877  BOOST_CHECK_EQUAL(result2, 2.);
878 }
879 
880 
882 {
884  template<typename Signature>
885  struct result;
886 
887  template<typename This, typename DataT>
888  struct result<This(DataT)>
889  {
890  typedef const typename DataT::SupportShapeFunction::JacobianT& type;
891  };
892 
893  template<typename StorageT, typename DataT>
894  const StorageT& operator()(StorageT& result, const DataT& data) const
895  {
897  data.support().compute_jacobian(GaussT::instance().coords.col(0));
898  result = data.support().jacobian_inverse().transpose() * data.support().jacobian_inverse();
899  return result;
900  }
901 };
902 
903 BOOST_AUTO_TEST_CASE( MetricTensorTest )
904 {
906  Tools::MeshGeneration::create_rectangle(*mesh, 0.2, 2., 1, 1);
907 
908  SFOp< CustomSFOp<MetricTensor> > metric_tensor;
909 
910  for_each_element< boost::mpl::vector1<LagrangeP1::Quad2D> >
911  (
912  mesh->topology(),
913  _cout << metric_tensor << "\n"
914  );
915 }
916 
917 
918 BOOST_AUTO_TEST_CASE( NodeIdxOutput )
919 {
921  Tools::MeshGeneration::create_rectangle(*mesh, 0.2, 2., 1, 1);
922 
923  Uint idx_total = 0;
924 
925  for_each_node(mesh->topology(), lit(idx_total) += node_index);
926 
927  BOOST_CHECK_EQUAL(idx_total, 6);
928 }
929 
930 BOOST_AUTO_TEST_SUITE_END()
931 
932 
boost::proto::terminal< SFOp< ShapeFunctionOp > >::type const N
static boost::proto::terminal< void(*)(const RealMatrix2 &, const RealMatrix2 &, Real) >::type const _check_close
#define CFinfo
these are always defined
Definition: Log.hpp:104
static boost::proto::terminal< LumpTag >::type const lump
Eigen::Matrix< Real, 1, 1 > RealVector1
Fixed size 1x1 column vector.
Definition: MatrixTypes.hpp:39
cf3::Real result2[213]
boost::proto::terminal< SFOp< NormalOp > >::type const normal
Field & create_field(const std::string &name, const Uint cols)
Create a new field in this group.
Definition: Dictionary.cpp:178
boost::proto::terminal< SFOp< CustomSFOp< OpT > > & >::type reference_type
void create_line(Mesh &mesh, const Real x_len, const Uint x_segments)
Create a 1D line mesh.
virtual mesh::Domain & create_domain(const std::string &name)
creates a domain in this model
Definition: Model.cpp:201
2D Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Tetra3D.hpp:36
external boost library namespace
virtual physics::PhysModel & create_physics(const std::string &builder)
Definition: Model.cpp:182
Stores pre-computed mapped coords and weights for all gauss point locations.
void create_circle_2d(Mesh &mesh, const Real radius, const Uint segments, const Real start_angle, const Real end_angle)
Creates a 2D circular arc.
boost::proto::terminal< SFOp< VolumeOp > >::type const volume
Static terminals that can be used in proto expressions.
Definition: check.py:1
2D Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Triag2D.hpp:36
Basic Classes for Solver applications used by CF.
Definition: Action.cpp:29
void result_type
Dummy result.
static boost::proto::terminal< GaussPointTag< GaussOrder< 1 > > >::type gauss_points_1
Definition: GaussPoints.hpp:83
static boost::proto::terminal< NodalValuesTag >::type const nodal_values
cf3::Real result1[201]
static boost::proto::terminal< ElementQuadratureTag >::type element_quadrature
Use element_quadrature(expr1, expr2, ..., exprN) to evaluate a group of expressions.
boost::mpl::vector3< LagrangeP1::Line1D, LagrangeP1::Quad2D, LagrangeP1::Hexa3D > HigherIntegrationElements
List of all supported shapefunctions that allow high order integration.
BOOST_AUTO_TEST_CASE(ProtoBasics)
boost::shared_ptr< ElementsExpression< ExprT, ElementTypes > > elements_expression(ElementTypes, const ExprT &expr)
Definition: Expression.hpp:292
result_type operator()(int &arg) const
void create_rectangle(Mesh &mesh, const Real x_len, const Real y_len, const Uint x_segments, const Uint y_segments)
Create a rectangular, 2D, quad-only mesh. No buffer for creation.
static boost::proto::terminal< ColTag >::type _col
#define CFendl
Definition: Log.hpp:109
static boost::proto::terminal< RowTag >::type _row
Real max(const Real a, const Real b)
Maximum between two scalars.
Definition: Terminals.hpp:228
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
boost::proto::terminal< SFOp< NodesOp > >::type const nodes
void for_each_node(mesh::Region &root_region, const ExprT &expr)
Definition: NodeLooper.hpp:239
static boost::proto::terminal< std::ostream & >::type _cout
Wrap std::cout.
Definition: Terminals.hpp:219
Static functions for mathematical constants.
Definition: Consts.hpp:25
Definition: Defs.hpp:17
boost::proto::terminal< SFOp< CustomSFOp< OpT > > >::type type
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealMatrix
Dynamic sized matrix of Real scalars.
Definition: MatrixTypes.hpp:22
static boost::proto::terminal< IndexTag< boost::mpl::int_< 1 > > >::type const _j
Index looping over the dimensions of a variable.
Represents an element vector.
void check_close(const RealMatrix2 &a, const RealMatrix2 &b, const Real threshold)
Check close, for testing purposes.
boost::proto::terminal< TransposeFunction >::type const transpose
boost::proto::terminal< SFOp< NablaOp > >::type const nabla
Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing the ...
Definition: Line1D.hpp:36
Real pi()
Definition of the Pi constant.
Definition: Consts.hpp:48
Custom ops must implement the TR1 result_of protocol.
void variables(const std::vector< std::string > &vars)
sets the variable strings to be parsed
const StorageT & operator()(StorageT &result, const FieldDataT &field) const
boost::proto::terminal< NodeIdxOp >::type const node_index
Definition: NodeGrammar.hpp:72
Basic Classes for Mesh applications used by COOLFluiD.
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealVector
Dynamic sized column vector.
Definition: MatrixTypes.hpp:25
tuple model
Global confifuration.
Custom ops must implement the TR1 result_of protocol.
static boost::proto::terminal< GaussWeightTag< GaussOrder< 2 > > >::type gauss_weights_2
Definition: GaussPoints.hpp:93
static MakeSFOp< DivOp >::type const divergence
static const char * dimension()
Tag for options related to the dimension of something.
Definition: Tags.cpp:14
Top-level namespace for coolfluid.
Definition: Action.cpp:18
static boost::proto::terminal< double(*)(double, double) >::type const _atan2
Definition: Terminals.hpp:241
MakeSFOp< CustomLaplacian >::type laplacian_cust
static boost::proto::terminal< IndexTag< boost::mpl::int_< 0 > > >::type const _i
Index looping over the dimensions of a variable.
boost::mpl::vector5< LagrangeP1::Line1D, LagrangeP1::Triag2D, LagrangeP1::Quad2D, LagrangeP1::Hexa3D, LagrangeP1::Tetra3D > VolumeTypes
void add_tag(const std::string &tag)
const StorageT & operator()(StorageT &result, const DataT &data) const
boost::proto::terminal< SFOp< CoordinatesOp > >::type const coordinates
static boost::proto::terminal< double(*)(double) >::type const _sin
Definition: Terminals.hpp:240
Wrap all operations in a template, so we can detect ops using a wildcard.
const DataT::SupportShapeFunction::JacobianT & type
static boost::proto::terminal< GaussPointTag< GaussOrder< 2 > > >::type gauss_points_2
Definition: GaussPoints.hpp:84
common::Component & root() const
Gives the default root component.
Definition: Core.cpp:145
static boost::proto::terminal< ElementVectorTag >::type const element_vector
boost::proto::terminal< ExtractDiagTag >::type const diagonal
static boost::proto::terminal< ExpressionGroupTag >::type group
Use group(expr1, expr2, ..., exprN) to evaluate a group of expressions.
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
Eigen::Matrix< Real, 2, 2 > RealMatrix2
Fixed size 2x2 matrix.
Definition: MatrixTypes.hpp:34
Eigen::Matrix< Real, 4, 1 > RealVector4
Fixed size 4x1 column vector.
Definition: MatrixTypes.hpp:42
static MakeSFOp< GradientOp >::type const gradient
void functions(const std::vector< std::string > &functions)
sets the function strings to be parsed
Eigen::Matrix< Real, 2, 1 > RealVector2
Fixed size 2x1 column vector.
Definition: MatrixTypes.hpp:40
static boost::proto::terminal< NormTag >::type const _norm
Region & topology() const
Definition: Mesh.hpp:51
static Core & instance()
Definition: Core.cpp:37
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
void create_field(const std::string &tag, cf3::mesh::Dictionary &dict)
Create fields. Looks up the VariablesDescriptor with the given tag, and creates a field with the same...
boost::shared_ptr< NodesExpression< ExprT, boost::mpl::range_c< Uint, 1, 4 > > > nodes_expression(const ExprT &expr)
Definition: Expression.hpp:308
Definition: Defs.hpp:17
math::VariableManager & variable_manager()
Access to the VariableManager.
Definition: PhysModel.cpp:42
OptionList & options()
Definition: Component.cpp:856
Dictionary & geometry_fields() const
Definition: Mesh.cpp:339
static boost::proto::terminal< GaussWeightTag< GaussOrder< 1 > > >::type gauss_weights_1
Definition: GaussPoints.hpp:92
const Eigen::Matrix< Real, FieldDataT::dimension *FieldDataT::EtypeT::nb_nodes, FieldDataT::dimension *FieldDataT::EtypeT::nb_nodes > & type
void set(const std::string &pname, const boost::any &val)
Definition: OptionList.cpp:132
Handle< Component > create_component(const std::string &name, const std::string &builder)
Build a (sub)component of this component using the extended type_name of the component.
Definition: Component.cpp:568
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
Uint count(const RangeT &range)
Count the elements in a range.
2D Lagrange P1 Triangular Element type This class provides the lagrangian shape function describing t...
Definition: Hexa3D.hpp:36
Custom op that just modifies its argument.
Real mean(const T &vector)
Definition: SUPG.hpp:40
Send comments to:
COOLFluiD Web Admin