COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
Tetrahedralize.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 #include <set>
8 
9 #include <vtkCellType.h>
10 #include <vtkDataSetTriangleFilter.h>
11 #include <vtkIdList.h>
12 #include <vtkGenericCell.h>
13 #include <vtkPoints.h>
14 #include <vtkSmartPointer.h>
15 #include <vtkUnstructuredGrid.h>
16 #include <vtkCell.h>
17 
18 #include "common/Builder.hpp"
19 #include "common/Log.hpp"
20 #include "common/List.hpp"
21 
22 #include "mesh/Connectivity.hpp"
23 #include "mesh/Region.hpp"
24 #include "mesh/Elements.hpp"
25 #include "mesh/Space.hpp"
26 #include "mesh/Dictionary.hpp"
27 #include "mesh/Field.hpp"
28 #include "mesh/Cells.hpp"
29 #include "mesh/Mesh.hpp"
30 #include <mesh/Faces.hpp>
31 
32 #include "vtk/Tetrahedralize.hpp"
33 
35 
36 using namespace cf3;
37 
39 
40 namespace cf3 {
41 namespace vtk {
42 
44 
46 
48 
49 Tetrahedralize::Tetrahedralize ( const std::string& name ) : MeshTransformer ( name )
50 {
51 }
52 
54 {
55 }
56 
58 {
60  const Uint nb_points = coordinates.size();
61 
62  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
63  points->Allocate(nb_points);
64  BOOST_FOREACH(const mesh::Field::ConstRow coord, coordinates.array())
65  {
66  points->InsertNextPoint(coord[XX], coord[YY], coord[ZZ]);
67  }
68 
69  vtkSmartPointer<vtkUnstructuredGrid> vtk_unstruc_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
70  vtk_unstruc_grid->SetPoints(points);
71 
72  std::vector< Handle<common::Component> > to_remove;
73 
74  Handle<mesh::Region> parent_region;
75 
76  BOOST_FOREACH(mesh::Elements& elems, common::find_components_recursively_with_filter<mesh::Elements>(mesh(), mesh::IsElementsVolume()))
77  {
78  int cell_type = 0;
79  mesh::GeoShape::Type shape = elems.element_type().shape();
80 
81  if(shape == mesh::GeoShape::TETRA)
82  continue;
83 
84  if(shape == mesh::GeoShape::HEXA)
85  cell_type = VTK_HEXAHEDRON;
86  else if(shape == mesh::GeoShape::PRISM)
87  cell_type = VTK_WEDGE;
88  else
89  throw common::NotImplemented(FromHere(), "Cells of type " + elems.element_type().name() + " can't be triangulated");
90 
91  to_remove.push_back(elems.handle());
92 
93  const mesh::Connectivity& connectivity = elems.geometry_space().connectivity();
94  const Uint nb_elems = connectivity.size();
95  const Uint nb_elem_nodes = connectivity.row_size();
96  vtkSmartPointer<vtkIdList> id_list = vtkSmartPointer<vtkIdList>::New();
97  id_list->SetNumberOfIds(nb_elem_nodes);
98  for(Uint i = 0; i != nb_elems; ++i)
99  {
100  const mesh::Connectivity::ConstRow row = connectivity[i];
101  for(int j = 0; j != nb_elem_nodes; ++j)
102  id_list->SetId(j, row[j]);
103  vtk_unstruc_grid->InsertNextCell(cell_type, id_list);
104  }
105 
106  parent_region = common::find_parent_component_ptr<mesh::Region>(elems);
107  }
108 
109  vtkSmartPointer<vtkDataSetTriangleFilter> triangulator = vtkSmartPointer<vtkDataSetTriangleFilter>::New();
110  triangulator->SetTetrahedraOnly(true);
111  triangulator->SetInputData(vtk_unstruc_grid);
112 
113  vtkSmartPointer<vtkUnstructuredGrid> out_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
114  triangulator->SetOutput(out_grid);
115  triangulator->Update();
116 
117  cf3_assert(is_not_null(parent_region));
118 
119  CFinfo << "Adding tetrahedralization to region " << parent_region->uri().path() << CFendl;
120  const Uint nb_tets = out_grid->GetNumberOfCells();
121  Handle<mesh::Cells> tetras = parent_region->create_component<mesh::Cells>("Tetras");
122  tetras->initialize("cf3.mesh.LagrangeP1.Tetra3D",mesh().geometry_fields());
123  tetras->resize(nb_tets);
124  common::Table<Uint>& connectivity = tetras->geometry_space().connectivity();
125  vtkSmartPointer<vtkGenericCell> cell = vtkSmartPointer<vtkGenericCell>::New();
126  std::vector< std::set<Uint> > connectivity_sets(nb_points);
127  for(Uint i = 0; i != nb_tets; ++i)
128  {
129  mesh::Connectivity::Row row = connectivity[i];
130  out_grid->GetCell(i, cell);
131  for(Uint j = 0; j != 4; ++j)
132  {
133  row[j] = cell->GetPointId(j);
134  }
135  for(Uint j = 0; j != 4; ++j)
136  {
137  connectivity_sets[row[j]].insert(row.begin(), row.end());
138  }
139  }
140 
141  // Triangulate surface elements (quads only)
142  BOOST_FOREACH(mesh::Elements& elems, common::find_components_recursively_with_filter<mesh::Elements>(mesh(), mesh::IsElementsSurface()))
143  {
144  if(elems.element_type().shape() == mesh::GeoShape::TRIAG)
145  continue;
146 
147  if(elems.element_type().shape() != mesh::GeoShape::QUAD)
148  throw common::NotImplemented(FromHere(), "Cells of type " + elems.element_type().name() + " can't be triangulated");
149 
150  to_remove.push_back(elems.handle());
151 
152  const mesh::Connectivity& connectivity = elems.geometry_space().connectivity();
153  const Uint nb_quads = connectivity.size();
154 
155  Handle<mesh::Faces> triags = common::find_parent_component<mesh::Region>(elems).create_component<mesh::Faces>("TriangulatedFaces");
156  triags->initialize("cf3.mesh.LagrangeP1.Triag3D",mesh().geometry_fields());
157  triags->resize(nb_quads*2);
158  mesh::Connectivity& triag_connectivity = triags->geometry_space().connectivity();
159 
160  for(Uint i = 0; i != nb_quads; ++i)
161  {
162  const mesh::Connectivity::ConstRow quad_row = connectivity[i];
163  mesh::Connectivity::Row triag1_row = triag_connectivity[i*2];
164  mesh::Connectivity::Row triag2_row = triag_connectivity[i*2+1];
165  const mesh::Connectivity::ConstRow row = connectivity[i];
166  if(connectivity_sets[row[0]].count(row[2]) > 0)
167  {
168  triag1_row[0] = quad_row[0]; triag1_row[1] = quad_row[1]; triag1_row[2] = quad_row[2];
169  triag2_row[0] = quad_row[0]; triag2_row[1] = quad_row[2]; triag2_row[2] = quad_row[3];
170  }
171  else
172  {
173  cf3_assert(connectivity_sets[row[1]].count(row[3]) > 0);
174  triag1_row[0] = quad_row[0]; triag1_row[1] = quad_row[1]; triag1_row[2] = quad_row[3];
175  triag2_row[0] = quad_row[1]; triag2_row[1] = quad_row[2]; triag2_row[2] = quad_row[3];
176  }
177  }
178  }
179 
180  // Remove all triangulated elements
181  BOOST_FOREACH(const Handle<common::Component>& comp, to_remove)
182  {
183  comp->parent()->remove_component(*comp);
184  }
185 
187  const Uint nb_procs = comm.size();
188  const Uint rank = comm.rank();
189 
190  // Total number of elements on this rank
191  Uint mesh_nb_elems = 0;
192  BOOST_FOREACH(mesh::Elements& elements , common::find_components_recursively<mesh::Elements>(mesh()))
193  {
194  mesh_nb_elems += elements.size();
195  }
196 
197  std::vector<Uint> nb_elements_accumulated;
198  if(comm.is_active())
199  {
200  // Get the total number of elements on each rank
201  comm.all_gather(mesh_nb_elems, nb_elements_accumulated);
202  }
203  else
204  {
205  nb_elements_accumulated.push_back(mesh_nb_elems);
206  }
207  cf3_assert(nb_elements_accumulated.size() == nb_procs);
208  // Sum up the values
209  for(Uint i = 1; i != nb_procs; ++i)
210  nb_elements_accumulated[i] += nb_elements_accumulated[i-1];
211 
212  // Offset to start with for this rank
213  Uint element_offset = rank == 0 ? 0 : nb_elements_accumulated[rank-1];
214 
215  // Update the element ranks and gids
216  BOOST_FOREACH(mesh::Elements& elements , common::find_components_recursively<mesh::Elements>(mesh()))
217  {
218  const Uint nb_elems = elements.size();
219  elements.rank().resize(nb_elems);
220  elements.glb_idx().resize(nb_elems);
221 
222  for (Uint elem=0; elem != nb_elems; ++elem)
223  {
224  elements.rank()[elem] = rank;
225  elements.glb_idx()[elem] = elem + element_offset;
226  }
227  element_offset += nb_elems;
228  }
229 
232  mesh().check_sanity();
233 }
234 
235 
237 
238 } // namespace vtk
239 } // namespace cf3
240 
#define CFinfo
these are always defined
Definition: Log.hpp:104
std::string name(ComponentWrapper &self)
bool check_sanity() const
Definition: Mesh.cpp:460
Safe pointer to an object. This is the supported method for referring to components.
Definition: Handle.hpp:39
ArrayT & array()
Definition: Table.hpp:92
void resize(const Uint new_size)
Definition: List.hpp:69
Helper class to create the Builder and place it in the factory.
Definition: Builder.hpp:212
Space & geometry_space() const
Definition: Entities.hpp:94
Type
Enumeration of the Shapes recognized in CF.
Definition: GeoShape.hpp:27
Tetrahedralize(const std::string &name)
common::ComponentBuilder< Tetrahedralize, mesh::MeshTransformer, LibVTK > Tetrahedralize_Builder
std::string path() const
Definition: URI.cpp:253
#define cf3_assert(a)
Definition: Assertions.hpp:93
ElementType & element_type() const
return the elementType
Definition: Entities.cpp:116
URI uri() const
Construct the full path.
Definition: Component.cpp:248
void update_structures()
Definition: Mesh.cpp:147
const std::string & name() const
Access the name of the component.
Definition: Component.hpp:146
const Field & coordinates() const
Definition: Dictionary.cpp:481
common::List< Uint > & rank()
Definition: Entities.hpp:71
#define CFendl
Definition: Log.hpp:109
Uint rank() const
Return rank, additionally, if is_init==0.
Definition: Comm.cpp:135
virtual void initialize(const std::string &element_type_name, Dictionary &geometry)
Initialize the Cells using the given type.
Definition: Cells.cpp:39
Definition: Defs.hpp:17
Definition: Defs.hpp:17
Uint size() const
Return the number of processes, or 1 if is_init==0.
Definition: Comm.cpp:145
Uint size() const
Definition: Table.hpp:127
virtual void execute()
execute the action
Uint size() const
return the number of elements
Definition: Entities.cpp:161
common::List< Uint > & glb_idx()
Mutable access to the list of nodes.
Definition: Entities.hpp:66
bool is_active() const
Definition: Comm.hpp:83
Handle< Component > parent() const
Definition: Component.cpp:256
GeoShape::Type shape() const
Definition: ElementType.hpp:64
TableConstRow< Real >::type ConstRow
the const type of a row in the internal structure of the table
Definition: Table.hpp:59
Top-level namespace for coolfluid.
Definition: Action.cpp:18
void resize(const Uint nb_elem)
Definition: Entities.cpp:246
TableRow< Uint >::type Row
the type of a row in the internal structure of the table
Definition: Table.hpp:56
void update_statistics()
Definition: Mesh.cpp:203
virtual void initialize(const std::string &element_type_name, Dictionary &geometry)
Initialize the Faces using the given type.
Definition: Faces.cpp:41
Uint row_size(Uint i=0) const
Definition: Table.hpp:133
boost::proto::terminal< SFOp< CoordinatesOp > >::type const coordinates
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
Definition: Defs.hpp:17
Dictionary & geometry_fields() const
Definition: Mesh.cpp:339
static Comm & instance()
Return a reference to the current PE.
Definition: Comm.cpp:44
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
T * all_gather(const T *in_values, const int in_n, T *out_values, const int stride=1)
Definition: Comm.hpp:192
Uint count(const RangeT &range)
Count the elements in a range.
Connectivity & connectivity()
connectivity table to dictionary entries
Definition: Space.hpp:110
bool is_not_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:147
#define FromHere()
Send comments to:
COOLFluiD Web Admin