COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
utest-proto-components.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 operations related to components"
9 
10 #include <map>
11 
12 #include <boost/foreach.hpp>
13 #include <boost/test/unit_test.hpp>
14 
16 #include "common/Core.hpp"
17 #include "common/Log.hpp"
19 #include <common/Environment.hpp>
20 
21 #include "math/MatrixTypes.hpp"
22 
23 #include "mesh/Domain.hpp"
24 #include "mesh/Mesh.hpp"
25 #include "mesh/Field.hpp"
26 #include "mesh/FieldManager.hpp"
27 
28 #include "physics/PhysModel.hpp"
29 
30 #include "solver/Model.hpp"
31 #include "solver/SimpleSolver.hpp"
32 
39 
41 #include "solver/Tags.hpp"
42 
43 using namespace cf3;
44 using namespace cf3::common;
45 using namespace cf3::mesh;
46 using namespace cf3::solver;
47 using namespace cf3::solver::actions;
48 using namespace cf3::solver::actions::Proto;
49 
51 inline void check_close(const RealMatrix2& a, const RealMatrix2& b, const Real threshold)
52 {
53  for(Uint i = 0; i != a.rows(); ++i)
54  for(Uint j = 0; j != a.cols(); ++j)
55  BOOST_CHECK_CLOSE(a(i,j), b(i,j), threshold);
56 }
57 
58 static boost::proto::terminal< void(*)(const RealMatrix2&, const RealMatrix2&, Real) >::type const _check_close = {&check_close};
59 
61 
62 BOOST_AUTO_TEST_SUITE( ProtoComponentsSuite )
63 
64 using boost::proto::lit;
65 
67 struct SimpleGrammar :
68  boost::proto::or_
69  <
70  Scalar,
72  boost::proto::otherwise< boost::proto::_default<SimpleGrammar> >
73  >
74 {
75 };
76 
78 inline void check_equal(const Uint a, const Uint b)
79 {
80  BOOST_CHECK_EQUAL(a, b);
81 }
82 
83 static boost::proto::terminal< void(*)(const Uint, const Uint) >::type const _check_equal = {&check_equal};
84 
85 
87 
89 BOOST_AUTO_TEST_CASE( CopiedReference )
90 {
91  Core::instance().environment().options().set("log_level", 4);
92 
93  Uint a = 1;
94  Uint b = 2;
95  Uint& b_ref = b;
96  b = 1;
97  SimpleGrammar()( DeepCopy()(_check_equal(a, b_ref)) );
98 }
99 
100 BOOST_AUTO_TEST_CASE( UseConfigurableConstant )
101 {
102  ConstantStorage constant_values;
103 
104  ConfigurableConstant<Real> c("SomeConst", "SomeDescription", 1.);
105  Real result;
106 
107  // Check if the default value is used
108  SimpleGrammar()(ReplaceConfigurableConstants()(lit(result) = c, constant_values));
109  BOOST_CHECK_EQUAL(result, 1.);
110  BOOST_CHECK_EQUAL(constant_values.m_scalars["SomeConst"], 1.);
111  BOOST_CHECK_EQUAL(constant_values.descriptions["SomeConst"], "SomeDescription");
112  Real* orig_address = &constant_values.m_scalars["SomeConst"];
113 
114  // Mimic a change to the value
115  constant_values.m_scalars["SomeConst"] = 2.;
116  SimpleGrammar()(ReplaceConfigurableConstants()(lit(result) = c, constant_values));
117  BOOST_CHECK_EQUAL(orig_address, &constant_values.m_scalars["SomeConst"]);
118  BOOST_CHECK_EQUAL(result, 2.);
119  BOOST_CHECK_EQUAL(constant_values.m_scalars["SomeConst"], 2.);
120 }
121 
123 BOOST_AUTO_TEST_CASE( SetupModel )
124 {
126  model.create_physics("cf3.physics.DynamicModel");
127  Domain& dom = model.create_domain("Domain");
128  Mesh& mesh = *dom.create_component<Mesh>("mesh");
130 }
131 
133 BOOST_AUTO_TEST_CASE( ExpressionOptions )
134 {
135  Real result = 0;
136  RealVector default_a(3);
137  default_a.setZero();;
138  ConfigurableConstant<RealVector> a("a", "Multiplication factor", default_a);
139 
140  // Create an expression that sums the volume of a mesh, multiplied with a configurable factor
141  boost::shared_ptr<Expression> expression = elements_expression(lit(result) += boost::proto::lit(a)[0]*volume);
142 
144 
145  expression->add_options(model->options());
146  BOOST_CHECK(model->options().check("a"));
147 
148  // a is zero by default, so the result should be zero
149  expression->loop(model->domain().get_child("mesh")->handle<Mesh>()->topology());
150  BOOST_CHECK_EQUAL(result, 0.);
151 
152  // reconfigure a as 1, and check result
153  model->options().option("a").change_value(std::vector<Real>(1, 1.));
154  expression->loop(model->domain().get_child("mesh")->handle<Mesh>()->topology());
155  BOOST_CHECK_EQUAL(result, 1.);
156 }
157 
159 BOOST_AUTO_TEST_CASE( PhysicalModelUsage )
160 {
161  const Uint nb_segments = 5;
163  Handle<Mesh> mesh(model->domain().get_child("mesh"));
164 
165  // Declare a mesh variable
166  FieldVariable<0, ScalarField> T("Temperature", "solution");
167 
168  // Expression to set the temperature field
169  boost::shared_ptr<Expression> init_temp = nodes_expression(T = 288.);
170  // Register the variables
171  init_temp->register_variables(model->physics());
172 
173  // Create the fields
174  FieldManager& field_manager = *model->create_component<FieldManager>("FieldManager");
175  field_manager.options().set("variable_manager", model->physics().variable_manager().handle<math::VariableManager>());
176  field_manager.create_field("solution", mesh->geometry_fields());
177  BOOST_CHECK(find_component_ptr_with_tag<Field>(mesh->geometry_fields(), "solution"));
178 
179  // Do the initialization
180  init_temp->loop(model->domain().get_child("mesh")->handle<Mesh>()->topology());
181 
182  // Sum up the values for the temperature
183  Real temp_sum = 0.;
184  nodes_expression(lit(temp_sum) += T)->loop(model->domain().get_child("mesh")->handle<Mesh>()->topology());
185  BOOST_CHECK_EQUAL(temp_sum / static_cast<Real>(1+nb_segments), 288.);
186 }
187 
189 BOOST_AUTO_TEST_CASE( ProtoActionTest )
190 {
191  const Uint nb_segments = 5;
193  Handle<Mesh> mesh(model->domain().get_child("mesh"));
194  Handle<FieldManager> field_manager(model->get_child("FieldManager"));
195 
196  // Declare a mesh variable
197  FieldVariable<0, ScalarField> T("Temperature2", "T2");
198 
200 
201  // Create an action that can wrap an expression
202  Handle<ProtoAction> action = parent.create_component<ProtoAction>("Action");
203  action->set_expression(nodes_expression(T = 288.));
204  action->options().set("physical_model", model->physics().handle<physics::PhysModel>());
205  action->options().set(solver::Tags::regions(), std::vector<URI>(1, model->domain().get_child("mesh")->handle<Mesh>()->topology().uri()));
206 
207  // Create the fields
208  field_manager->create_field("T2", mesh->geometry_fields());
209  BOOST_CHECK(find_component_ptr_with_tag<Field>(mesh->geometry_fields(), "T2"));
210 
211  // Run the action
212  action->execute();
213 
214  // Sum up the values for the temperature
215  Real temp_sum = 0.;
216  nodes_expression(lit(temp_sum) += T)->loop(model->domain().get_child("mesh")->handle<Mesh>()->topology());
217  BOOST_CHECK_EQUAL(temp_sum / static_cast<Real>(1+nb_segments), 288.);
218 }
219 
221 BOOST_AUTO_TEST_CASE( SimpleSolverTest )
222 {
223  const Uint nb_segments = 5;
225  Handle<Mesh> mesh(model->domain().get_child("mesh"));
226 
227  // Declare a mesh variable
228  FieldVariable<0, ScalarField> T("Temperature3", "T3");
229 
230  Solver& solver = *model->create_component<SimpleSolver>("GenericSolver");
231 
232  // Storage for the result check
233  Real temp_sum = 0.;
234 
235  // Add the actions to run on the domain
236  solver << create_proto_action( "SetTemp", nodes_expression(T = 288.) )
237  << create_proto_action( "CheckResult", nodes_expression(lit(temp_sum) += T));
238 
239  solver.configure_option_recursively(solver::Tags::regions(), std::vector<URI>(1, mesh->topology().uri()));
240  solver.configure_option_recursively("physical_model", model->physics().handle<physics::PhysModel>());
241  solver.mesh_loaded(*mesh);
242 
243  solver.field_manager().create_field("T3", mesh->geometry_fields());
244 
245  // Run the actions
246  model->simulate();
247 
248  // Check result
249  BOOST_CHECK_EQUAL(temp_sum / static_cast<Real>(1+nb_segments), 288.);
250 
251  model->remove_component("GenericSolver");
252 }
253 
255 BOOST_AUTO_TEST_CASE( PhysicsSolverTest )
256 {
257  const Uint nb_segments = 5;
259  Handle<Mesh> mesh(model->domain().get_child("mesh"));
260 
261  model->physics().options().add("input_temperature", 288.);
262 
263  // Declare a mesh variable
264  FieldVariable<0, ScalarField> T("TemperaturePhysics", "TP");
265  PhysicsConstant Tin("input_temperature");
266 
267  Solver& solver = *model->create_component<SimpleSolver>("PhysicsSolver");
268 
269  // Storage for the result check
270  Real temp_sum = 0.;
271 
272  // Add the actions to run on the domain
273  solver << create_proto_action( "SetTemp", nodes_expression(T = Tin) )
274  << create_proto_action( "CheckResult", nodes_expression(lit(temp_sum) += T));
275 
276  solver.configure_option_recursively(solver::Tags::regions(), std::vector<URI>(1, mesh->topology().uri()));
277  solver.configure_option_recursively("physical_model", model->physics().handle<physics::PhysModel>());
278  solver.mesh_loaded(*mesh);
279 
280  solver.field_manager().create_field("TP", mesh->geometry_fields());
281 
282  // Run the actions
283  model->simulate();
284 
285  // Check result
286  BOOST_CHECK_EQUAL(temp_sum / static_cast<Real>(1+nb_segments), 288.);
287 
288  // Change value and re-run
289  temp_sum = 0;
290  model->physics().options().set("input_temperature", 100.);
291  model->simulate();
292  BOOST_CHECK_EQUAL(temp_sum / static_cast<Real>(1+nb_segments), 100.);
293 
294 
295  model->remove_component("PhysicsSolver");
296 }
297 
300 {
301 public:
302  CustomProtoSolver(const std::string& name) :
303  SimpleSolver(name),
304  T("Temperature4", "T4"),
305  temp_sum(0.)
306  {
307  // Add the expressions
308  *this << create_proto_action( "SetTemp", nodes_expression(T = 288.) )
309  << create_proto_action( "Output", nodes_expression(_cout << T << "\n"))
310  << create_proto_action( "SumTemps", nodes_expression(lit(temp_sum) += T));
311  }
312 
313  virtual void mesh_loaded(Mesh& mesh)
314  {
315  field_manager().create_field("T4", mesh.geometry_fields());
316  }
317 
319  Real temp_sum;
320 
321  static std::string type_name() { return "CustomProtoSolver"; }
322 };
323 
324 BOOST_AUTO_TEST_CASE( ProtoCustomSolver )
325 {
326  const Uint nb_segments = 5;
328 
330  solver->configure_option_recursively(solver::Tags::regions(), std::vector<URI>(1, model->domain().get_child("mesh")->handle<Mesh>()->topology().uri()));
331  solver->configure_option_recursively(solver::Tags::physical_model(), model->physics().handle<physics::PhysModel>());
332  solver->mesh_loaded(*model->domain().get_child("mesh")->handle<Mesh>());
333 
334  // Run the actions
335  model->simulate();
336  print_timing_tree(*model);
337 
338  // Check
339  BOOST_CHECK_EQUAL(solver->temp_sum / static_cast<Real>(1+nb_segments), 288.);
340 }
341 
342 // Check if references inside terminals are kept corectly
343 BOOST_AUTO_TEST_CASE( CopyExpression )
344 {
345  const Uint nb_segments = 5;
346  Handle<Mesh> mesh(Core::instance().root().get_child("Model")->handle<Model>()->domain().get_child("mesh"));
347 
348  Real a = 1.;
349  Real result = 0.;
350 
351  // Create an expression that sums the volume of a mesh, multiplied with a configurable factor
352  boost::shared_ptr<Expression> expression = elements_expression(lit(result) += a*volume + 2. * boost::proto::lit(1.));
353 
354  expression->loop(mesh->topology());
355 
356  // default result
357  BOOST_CHECK_EQUAL(result, 11.);
358 
359  // reconfigure a as 2, and check result
360  a = 2.;
361  result = 0;
362  expression->loop(mesh->topology());
363  BOOST_CHECK_EQUAL(result, 12.);
364 }
365 
366 // Primitive transform that prints a component URI when given a ComponentWrapper terminal
368  boost::proto::transform< ComponentURIPrinter >
369 {
370  template<typename ExprT, typename StateT, typename DataT>
371  struct impl : boost::proto::transform_impl<ExprT, StateT, DataT>
372  {
373  typedef void result_type;
374 
375  result_type operator ()(typename impl::expr_param expr, typename impl::state_param state, typename impl::data_param data) const
376  {
377  std::cout << boost::proto::value(boost::proto::left(expr)).component().uri().string();
378  }
379  };
380 };
381 
383 struct SomeTag {};
384 
385 BOOST_AUTO_TEST_CASE( ComponentWrapperURI )
386 {
388 
389  BOOST_CHECK_EQUAL(model->physics().uri().string(), "cpath:/Model/DynamicModel");
390 
391  ComponentWrapper<physics::PhysModel, SomeTag> wrapped_phys_model(model->get_child("CustomSolver")->options().option(solver::Tags::physical_model()));
392 
393  BOOST_CHECK_EQUAL(boost::proto::value(wrapped_phys_model).component().uri().string(), "cpath:/Model/DynamicModel");
394 
395  ComponentURIPrinter()(DeepCopy()(wrapped_phys_model + 1));
396 }
397 
399 
400 BOOST_AUTO_TEST_SUITE_END()
401 
402 
std::string name(ComponentWrapper &self)
boost::python::object get_child(ComponentWrapper &self, const std::string &name)
void check_equal(const Uint a, const Uint b)
Check_equal function for use inside expressions.
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
external boost library namespace
virtual physics::PhysModel & create_physics(const std::string &builder)
Definition: Model.cpp:182
void set_expression(const boost::shared_ptr< Expression > &expression)
Class to encapsulate Proto actions.
Definition: ProtoAction.hpp:26
void configure_option_recursively(const std::string &optname, const boost::any &val)
Definition: Component.cpp:1157
virtual physics::PhysModel & physics()
gets the physics from this model
Definition: Model.cpp:154
Refers to a configurable constant value.
boost::proto::terminal< SFOp< VolumeOp > >::type const volume
Static terminals that can be used in proto expressions.
static boost::proto::terminal< void(*)(const RealMatrix2 &, const RealMatrix2 &, Real) >::type const _check_close
mesh::FieldManager & field_manager()
Access to the FieldManager, which is a static subcomponent of Solver.
Definition: Solver.cpp:115
static std::string type_name()
Basic Classes for Solver applications used by CF.
Definition: Action.cpp:29
URI uri() const
Construct the full path.
Definition: Component.cpp:248
common::URI uri(ComponentWrapper &self)
BOOST_AUTO_TEST_CASE(CopiedReference)
Check if copying references works as expected.
tuple root
Definition: coolfluid.py:24
boost::shared_ptr< ElementsExpression< ExprT, ElementTypes > > elements_expression(ElementTypes, const ExprT &expr)
Definition: Expression.hpp:292
static boost::proto::terminal< std::ostream & >::type _cout
Wrap std::cout.
Definition: Terminals.hpp:219
Refers to a value from the physical model.
void print_timing_tree(cf3::common::Component &root, const bool print_untimed, const std::string &prefix)
Print timing tree based on the existing properties.
virtual mesh::Domain & domain()
gets the domain from this model
Definition: Model.cpp:161
virtual void change_value(const boost::any &value)
change the value of this option
Definition: Option.cpp:89
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.
Matches scalar terminals.
Definition: Transforms.hpp:164
Storage for the values pointed to by a ConfigurableConstant.
Handle< Component > get_child(const std::string &name)
Definition: Component.cpp:441
Top-level namespace for coolfluid.
Definition: Action.cpp:18
virtual void mesh_loaded(Mesh &mesh)
void check_close(const RealMatrix2 &a, const RealMatrix2 &b, const Real threshold)
Check close, for testing purposes.
CustomProtoSolver(const std::string &name)
Define a tag (not used here)
common::Component & root() const
Gives the default root component.
Definition: Core.cpp:145
Grammar replacing ConfigurableConstants in an expression.
common::Environment & environment() const
Definition: Core.cpp:168
boost::shared_ptr< Component > remove_component(const std::string &name)
Remove a (sub)component of this component.
Definition: Component.cpp:357
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
virtual void simulate()
Simulates this model.
Definition: Model.cpp:132
Eigen::Matrix< Real, 2, 2 > RealMatrix2
Fixed size 2x2 matrix.
Definition: MatrixTypes.hpp:34
bool check(const std::string &opt_name) const
Definition: OptionList.hpp:111
Proto-ready terminal type for wrapping a component.
virtual void mesh_loaded(mesh::Mesh &mesh)
Called when a mesh is loaded into the domain that is associated with this solver. ...
Definition: Solver.cpp:111
boost::shared_ptr< ProtoAction > create_proto_action(const std::string &name, const boost::shared_ptr< Expression > &expression)
Create a new ProtoAction, immediatly setting the expression.
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
math::VariableManager & variable_manager()
Access to the VariableManager.
Definition: PhysModel.cpp:42
OptionList & options()
Definition: Component.cpp:856
Simple test grammar.
SelectOptionType< T >::type & add(const std::string &name, const T &default_value=T())
Definition: OptionList.hpp:45
static boost::proto::terminal< void(*)(const Uint, const Uint) >::type const _check_equal
Dictionary & geometry_fields() const
Definition: Mesh.cpp:339
Create a custom actiondomain.
Transform to copy an expression, keeping terminals that store a value by reference unchanged (thanks ...
Definition: Transforms.hpp:287
virtual void execute()
execute the action
Base class for defining CF components.
Definition: Component.hpp:82
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
const Option & option(const std::string &pname) const
get a constant option from the list
Definition: OptionList.cpp:52
Most basic kernel library.
Definition: Action.cpp:19
std::string string() const
Definition: URI.cpp:258
FieldVariable< 0, ScalarField > T
Send comments to:
COOLFluiD Web Admin