COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
utest-connectivity-data.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 "Test module for ConnectivityData"
9 
10 #include <boost/assign/list_of.hpp>
11 #include <boost/test/unit_test.hpp>
12 
13 #include "common/Log.hpp"
14 #include "common/Core.hpp"
16 
17 
18 #include "mesh/Mesh.hpp"
19 #include "mesh/Region.hpp"
20 #include "mesh/Elements.hpp"
21 #include "common/Table.hpp"
22 #include "mesh/MeshReader.hpp"
23 #include "mesh/MeshWriter.hpp"
25 
30 
31 using namespace cf3;
32 using namespace cf3::mesh;
33 using namespace cf3::common;
34 using namespace cf3::Tools::Testing;
35 using namespace cf3::Tools::MeshGeneration;
36 
38 
41 
44 {
47  {
50 
51  // Read the a .neu mesh as 2D mixed mesh
52  boost::shared_ptr< MeshReader > meshreader = build_component_abstract_type<MeshReader>("cf3.mesh.neu.Reader","meshreader");
53 
54  // Read the mesh
55  meshreader->read_mesh_into("../../resources/quadtriag.neu",*mesh2d);
56  meshreader->read_mesh_into("../../resources/hextet.neu",*mesh3d);
57  }
58 
61 };
62 
65  public ProfiledTestFixture, // NOTE: Inheritance order matters, this way the timing is profiled,
66  public TimedTestFixture // but the profiling is not timed. Important since especially profile processing takes time.
67 {
68  ProfiledFixture() : grid2D(MeshSource::grid2()) {}
69 
70  const Mesh& grid2D;
71 };
72 
74 void print_connectivity(const Component& root, const bool print_empty = true)
75 {
76  BOOST_FOREACH(const FaceConnectivity& face_connectivity, find_components_recursively<FaceConnectivity>(root))
77  {
78  CFinfo << "------------------------- Connectivity for " << face_connectivity.parent()->uri().base_path().string() << "/" << face_connectivity.parent()->name() << " -------------------------" << CFendl;
79  Handle<Elements const> celements(face_connectivity.parent());
80  const Uint nb_elements = celements->geometry_space().connectivity().array().size();
81  const Uint nb_faces = celements->element_type().nb_faces();
82  for(Uint elem = 0; elem != nb_elements; ++elem)
83  {
84  for(Uint face = 0; face != nb_faces; ++face)
85  {
86  if(face_connectivity.has_adjacent_element(elem, face))
87  {
88  NodeConnectivity::ElementReferenceT connected = face_connectivity.adjacent_element(elem, face);
89  const mesh::Entities& connected_entities = *face_connectivity.node_connectivity().entities()[connected.first];
90  CFinfo << "Face " << face << " of element " << elem << " is connected to face " << face_connectivity.adjacent_face(elem, face) << " of element " << connected.second << " of Elements " << connected_entities.uri().string() << CFendl;
91  }
92  else if(print_empty)
93  {
94  CFinfo << "Face " << face << " of element " << elem << " has no neighbour" << CFendl;
95  }
96  }
97  }
98  }
99 }
100 
102 
104 
105 
107 BOOST_AUTO_TEST_SUITE( ConnectivityDataSuite )
108 
110 
112 {
113  boost::shared_ptr<NodeConnectivity> node_conn = common::allocate_component<NodeConnectivity>("node_conn");
114  node_conn->initialize(find_components_recursively<Elements>(*mesh2d));
115 
116  for(Uint i = 0; i != node_conn->entities().size(); ++i)
117  CFinfo << node_conn->entities()[i]->name() << CFendl;
118 
119  // Should have 6 element regions
120  BOOST_CHECK_EQUAL(node_conn->entities().size(), static_cast<Uint>(6));
121 }
122 
124 {
126  BOOST_FOREACH(const mesh::Entities& ent, find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsVolume()))
127  {
128  entities.push_back(ent.handle<mesh::Entities const>());
129  }
130 
131  const Table<Real>& coordinates = find_component_recursively_with_name<Table<Real> >(*mesh2d, mesh::Tags::coordinates());
132  NodeConnectivity::IndicesT node_first_elements;
133  NodeConnectivity::CountsT node_element_counts;
134  NodeConnectivity::NodeElementsT node_elements;
135  create_node_element_connectivity(coordinates.array().size(), entities, node_first_elements, node_element_counts, node_elements);
136 
137  for(Uint i = 0; i != node_first_elements.size(); ++i)
138  {
139  CFinfo << "Node " << i << " is used by elements";
140  const Uint elements_begin = node_first_elements[i];
141  const Uint elements_end = elements_begin + node_element_counts[i];
142  for(Uint j = elements_begin; j != elements_end; ++j)
143  {
144  CFinfo << " " << node_elements[j].first << ", " << node_elements[j].second;
145  }
146  CFinfo << CFendl;
147  }
148  CFinfo << "node_elements = ";
149  for(Uint i = 0; i != node_elements.size(); ++i)
150  CFinfo << "(std::make_pair(" << node_elements[i].first << ", " << node_elements[i].second << "))";
151  CFinfo << CFendl;
152 
153  NodeConnectivity::NodeElementsT reference = boost::assign::list_of(std::make_pair(1, 0))(std::make_pair(1, 1))(std::make_pair(1, 0))(std::make_pair(1, 1))(std::make_pair(1, 1))(std::make_pair(2, 2))(std::make_pair(2, 3))(std::make_pair(1, 0))(std::make_pair(2, 1))(std::make_pair(1, 0))(std::make_pair(1, 1))(std::make_pair(2, 0))(std::make_pair(2, 1))(std::make_pair(2, 3))(std::make_pair(0, 4))(std::make_pair(0, 5))(std::make_pair(2, 0))(std::make_pair(2, 1))(std::make_pair(0, 0))(std::make_pair(0, 1))(std::make_pair(2, 2))(std::make_pair(0, 0))(std::make_pair(0, 4))(std::make_pair(0, 9))(std::make_pair(2, 0))(std::make_pair(2, 2))(std::make_pair(2, 3))(std::make_pair(0, 5))(std::make_pair(0, 6))(std::make_pair(0, 1))(std::make_pair(0, 2))(std::make_pair(0, 6))(std::make_pair(0, 7))(std::make_pair(0, 3))(std::make_pair(0, 7))(std::make_pair(0, 8))(std::make_pair(0, 2))(std::make_pair(0, 3))(std::make_pair(0, 0))(std::make_pair(0, 1))(std::make_pair(0, 2))(std::make_pair(0, 3))(std::make_pair(0, 8))(std::make_pair(0, 9))(std::make_pair(0, 4))(std::make_pair(0, 5))(std::make_pair(0, 6))(std::make_pair(0, 7))(std::make_pair(0, 8))(std::make_pair(0, 9));
154  Accumulator accumulator;
155  vector_test(node_elements, reference, accumulator);
156  BOOST_CHECK_EQUAL(boost::accumulators::min(accumulator.exact), true);
157 }
158 
160 {
161  // Vector of the elements that are concerned
163  BOOST_FOREACH(const mesh::Entities& ent, find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsVolume()))
164  {
165  entities.push_back(ent.handle<mesh::Entities const>());
166  }
167 
168  // Get the coordinates array
169  const Table<Real>& coordinates = find_component_recursively_with_name<Table<Real> >(*mesh2d, mesh::Tags::coordinates());
170 
171  // Link nodes to the elements
172  NodeConnectivity::IndicesT node_first_elements;
173  NodeConnectivity::CountsT node_element_counts;
174  NodeConnectivity::NodeElementsT node_elements;
175  create_node_element_connectivity(coordinates.array().size(), entities, node_first_elements, node_element_counts, node_elements);
176 
177  // Create the face connectivity data for the last Elements
178  FaceConnectivity::BoolsT face_has_neighbour;
179  NodeConnectivity::NodeElementsT face_element_connectivity;
180  NodeConnectivity::IndicesT face_face_connectivity;
181  create_face_element_connectivity(*entities.back(), entities, node_first_elements, node_element_counts, node_elements, face_has_neighbour, face_element_connectivity, face_face_connectivity);
182 
183  // Output data
184  const Entities& elements = *entities.back();
185  for(Uint element_idx = 0; element_idx != elements.geometry_space().connectivity().array().size(); ++element_idx)
186  {
187  const Uint nb_faces = elements.element_type().nb_faces();
188  for(Uint face_idx = 0; face_idx != nb_faces; ++face_idx)
189  {
190  const Uint global_face_idx = element_idx*nb_faces + face_idx;
191  if(face_has_neighbour[global_face_idx]) // face has a neighbour
192  {
193  const NodeConnectivity::ElementReferenceT neighbour_elem_ref = face_element_connectivity[global_face_idx];
194  const Uint neighbour_entities_idx = neighbour_elem_ref.first;
195  const Uint neighbour_local_idx = neighbour_elem_ref.second;
196  CFinfo << "Face " << face_idx << " of element " << element_idx << " is connected to face " << face_face_connectivity[global_face_idx] << " of element (" << neighbour_entities_idx << ", " << neighbour_local_idx << ")" << CFendl;
197  }
198  else // no neighbour for this face
199  {
200  CFinfo << "Face " << face_idx << " of element " << element_idx << " has no neighbour" << CFendl;
201  }
202  }
203  }
204  CFinfo << "face_element_connectivity = ";
205  for(Uint i = 0; i != face_element_connectivity.size(); ++i)
206  CFinfo << "(std::make_pair(" << face_element_connectivity[i].first << ", " << face_element_connectivity[i].second << "))";
207  CFinfo << CFendl;
208 
209  // Check result
210  NodeConnectivity::NodeElementsT reference = boost::assign::list_of(std::make_pair(2, 3))(std::make_pair(0, 4))(std::make_pair(2, 1))(std::make_pair(2, 0))(std::make_pair(0, 0))(std::make_pair(1, 0))(std::make_pair(0, 0))(std::make_pair(0, 0))(std::make_pair(2, 3))(std::make_pair(2, 2))(std::make_pair(2, 0))(std::make_pair(1, 1));
211  Accumulator accumulator;
212  vector_test(face_element_connectivity, reference, accumulator);
213  BOOST_CHECK_EQUAL(boost::accumulators::min(accumulator.exact), true);
214 }
215 
216 // BOOST_FIXTURE_TEST_CASE( ProfileFaceConnectivity, ProfiledFixture )
217 // {
218 // // Vector of the elements that are concerned
219 // NodeConnectivity::EntitiesT entities;
220 // NodeConnectivity::IndicesT celements_first_elements;
221 // create_entities(find_components_recursively_with_filter<Elements>(grid2D, IsElementsVolume()), entities, celements_first_elements);
222 //
223 // // Get the coordinates array
224 // const Table<Real>& coordinates = find_component_recursively_with_name<Table<Real> >(grid2D, mesh::Tags::coordinates());
225 //
226 // // Link nodes to the elements
227 // NodeConnectivity::IndicesT node_first_elements;
228 // NodeConnectivity::CountsT node_element_counts;
229 // NodeConnectivity::IndicesT node_elements;
230 // create_node_element_connectivity(coordinates.array().size(), entities, celements_first_elements, node_first_elements, node_element_counts, node_elements);
231 //
232 // // Create the face connectivity data
233 // FaceConnectivity::BoolsT face_has_neighbour;
234 // NodeConnectivity::IndicesT face_element_connectivity;
235 // create_face_element_connectivity(*entities.back(), entities, celements_first_elements, node_first_elements, node_element_counts, node_elements, face_has_neighbour, face_element_connectivity);
236 //
237 // // Face-face connectivity
238 // NodeConnectivity::IndicesT face_face_connectivity;
239 // create_face_face_connectivity(*entities.back(), entities, celements_first_elements, face_has_neighbour, face_element_connectivity, face_face_connectivity);
240 //
241 // BOOST_CHECK_EQUAL(face_has_neighbour[3], false);
242 // BOOST_CHECK_EQUAL(face_has_neighbour[1], true);
243 // BOOST_CHECK_EQUAL(face_element_connectivity[1], (Uint) 1);
244 // BOOST_CHECK_EQUAL(face_element_connectivity[7], (Uint) 0);
245 // }
246 
248 BOOST_FIXTURE_TEST_CASE( CreateVolumeToVolumeConnectivity, ConnectivityFixture )
249 {
250  // Add node connectivity data at the mesh level
251  Handle<NodeConnectivity> node_connectivity = mesh2d->create_component<NodeConnectivity>("node_connectivity");
252  node_connectivity->initialize(find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsVolume()));
253 
254  // Add face connectivity data for each Elements. Note that we can choose any Elements here, we don't have to do this
255  // for the same set as used in node_connectivity
256  BOOST_FOREACH(Elements& celements, find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsVolume()))
257  {
258  celements.create_component<FaceConnectivity>("face_connectivity")->initialize(*node_connectivity);
259  }
260 
262 }
263 
265 BOOST_FIXTURE_TEST_CASE( CreateSurfaceToVolumeConnectivity, ConnectivityFixture )
266 {
267  // Add node connectivity data at the mesh level
268  Handle<NodeConnectivity> node_connectivity = mesh2d->create_component<NodeConnectivity>("node_connectivity");
269  node_connectivity->initialize(find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsVolume()));
270 
271  // Add face connectivity data for surface elements
272  BOOST_FOREACH(Elements& celements, find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsSurface()))
273  {
274  celements.create_component<FaceConnectivity>("face_connectivity")->initialize(*node_connectivity);
275  }
276 
278 // CFinfo << mesh2d->tree() << CFendl;
279 
280 }
281 
283 BOOST_FIXTURE_TEST_CASE( CreateVolumeToSurfaceConnectivity, ConnectivityFixture )
284 {
285  // Add node connectivity data at the mesh level, for surface elements only
286  Handle<NodeConnectivity> node_connectivity = mesh2d->create_component<NodeConnectivity>("node_connectivity");
287  node_connectivity->initialize(find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsSurface()));
288 
289  // Add face connectivity data for volume elements
290  BOOST_FOREACH(Elements& celements, find_components_recursively_with_filter<Elements>(*mesh2d, IsElementsVolume()))
291  {
292  celements.create_component<FaceConnectivity>("face_connectivity")->initialize(*node_connectivity);
293  }
294 
295  print_connectivity(*mesh2d, false);
296  //CFinfo << mesh2d->tree() << CFendl;
297 }
298 
299 
301 BOOST_FIXTURE_TEST_CASE( CreateSurfaceToVolumeConnectivity3D, ConnectivityFixture )
302 {
303  // Add node connectivity data at the mesh level
304  Handle<NodeConnectivity> node_connectivity = mesh3d->create_component<NodeConnectivity>("node_connectivity");
305  node_connectivity->initialize(find_components_recursively_with_filter<Elements>(*mesh3d, IsElementsVolume()));
306 
307 
308  for(Uint i = 0; i != node_connectivity->node_first_elements().size(); ++i)
309  {
310  CFinfo << "Node " << i << " is used by elements";
311  const Uint elements_begin = node_connectivity->node_first_elements()[i];
312  const Uint elements_end = elements_begin + node_connectivity->node_element_counts()[i];
313  for(Uint j = elements_begin; j != elements_end; ++j)
314  {
315  CFinfo << " " << node_connectivity->node_elements()[j].first << ", " << node_connectivity->node_elements()[j].second << " ";
316  }
317  CFinfo << CFendl;
318  }
319 
320 // CFinfo << mesh3d->tree() << CFendl;
321 
322 
323 
324  // Add face connectivity data for surface elements
325  BOOST_FOREACH(Elements& celements, find_components_recursively_with_filter<Elements>(*mesh3d, IsElementsSurface()))
326  {
327  CFinfo << "surface type = " << celements.uri().string() << CFendl;
328  celements.create_component<FaceConnectivity>("face_connectivity")->initialize(*node_connectivity);
329  }
330 
332 // CFinfo << mesh3d->tree() << CFendl;
333 
334 }
335 
337 
338 BOOST_AUTO_TEST_SUITE_END()
339 
340 
std::vector< ElementReferenceT > NodeElementsT
Type of the container used to store the actual connectivity.
#define CFinfo
these are always defined
Definition: Log.hpp:104
boost::accumulators::accumulator_set< bool, boost::accumulators::stats< boost::accumulators::tag::count, boost::accumulators::tag::min, boost::accumulators::tag::max > > exact
Stores statistics for comparisons of exact (string and integer) types, including the number of tests...
Definition: Difference.hpp:53
ArrayT & array()
Definition: Table.hpp:92
void initialize(const EntitiesT &entities)
const EntitiesT & entities() const
Access to the raw data.
Fixture providing a simple mesh read from a .neu file. Unprofiled.
ElementType & element_type() const
return the elementType
Definition: Entities.cpp:116
URI uri() const
Construct the full path.
Definition: Component.cpp:248
std::vector< bool > BoolsT
Storage for a list of boolean values.
Uint nb_faces() const
Definition: ElementType.hpp:67
std::vector< Uint > CountsT
Storage for counted numbers.
std::vector< Handle< Entities const > > EntitiesT
Storage for a list of Entities components.
tuple root
Definition: coolfluid.py:24
#define CFendl
Definition: Log.hpp:109
Profile and time tests using this fixture.
Any test using this fixture (or a derivative) will be timed.
Any test using this fixture (or a derivative) will be profiled.
void create_face_element_connectivity(const Entities &own_celements, const NodeConnectivity::EntitiesT &entities, const NodeConnectivity::IndicesT &node_first_elements, const NodeConnectivity::CountsT &node_element_counts, const NodeConnectivity::NodeElementsT &node_elements, FaceConnectivity::BoolsT &face_has_neighbour, NodeConnectivity::NodeElementsT &face_element_connectivity, NodeConnectivity::IndicesT &face_face_connectivity)
std::vector< Uint > IndicesT
Storage for indices into other arrays.
Real min(const Real a, const Real b)
Minimum between two scalars.
Definition: Terminals.hpp:234
ConnectivityFixture()
common setup for each test case
Handle< Component > parent() const
Definition: Component.cpp:256
Basic Classes for Mesh applications used by COOLFluiD.
ElementReferenceT adjacent_element(const Uint element, const Uint face) const
Get the element that is adjacent to the given face of the given element.
MeshSourceGlobalFixture< 1000 > MeshSource
Define the global fixture type.
std::pair< Uint, Uint > ElementReferenceT
Uniquely refer an element by its index into the list of entities and it's local element index...
Top-level namespace for coolfluid.
Definition: Action.cpp:18
BOOST_FIXTURE_TEST_CASE(CreateElementVector, ConnectivityFixture)
const NodeConnectivity & node_connectivity() const
boost::proto::terminal< SFOp< CoordinatesOp > >::type const coordinates
common::Component & root() const
Gives the default root component.
Definition: Core.cpp:145
const CountsT & node_element_counts() const
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
BOOST_GLOBAL_FIXTURE(GlobalFixture) BOOST_AUTO_TEST_CASE(MeshStats)
Accumulate some statistics about the cell volumes.
const NodeElementsT & node_elements() const
static Core & instance()
Definition: Core.cpp:37
const IndicesT & node_first_elements() const
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
Uint adjacent_face(const Uint element, const Uint face) const
Get the face that is adjacent to the given face of the given element.
void vector_test(const VectorT &A, const VectorT &B, Accumulator &Result)
Compares vector-like sequences.
Definition: Difference.hpp:139
Base class for defining CF components.
Definition: Component.hpp:82
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
void create_node_element_connectivity(const Uint nb_nodes, const NodeConnectivity::EntitiesT &entities, NodeConnectivity::IndicesT &node_first_elements, NodeConnectivity::CountsT &node_element_counts, NodeConnectivity::NodeElementsT &node_elements)
Most basic kernel library.
Definition: Action.cpp:19
std::string string() const
Definition: URI.cpp:258
bool has_adjacent_element(const Uint element, const Uint face) const
True if the given face of the given element has an adjacent element.
Stores the results of the difference::test() function.
Definition: Difference.hpp:49
void print_connectivity(const Component &root, const bool print_empty=true)
Print out the connectivity information.
Send comments to:
COOLFluiD Web Admin