FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
adaptive_export_vtu.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7#ifndef KERNEL_GEOMETRY_ADAPTIVE_EXPORT_VTU_HPP
8#define KERNEL_GEOMETRY_ADAPTIVE_EXPORT_VTU_HPP 1
9
10#include <kernel/geometry/adaptive_mesh.hpp>
11#include <kernel/geometry/adaptive_mesh_layer.hpp>
12#include <kernel/geometry/export_vtk.hpp>
13
14namespace FEAT
15{
16 namespace Geometry
17 {
18 template<typename MeshType_>
20
21 template<typename TemplateSet_, typename Shape_>
22 class AdaptiveExportVTU<Geometry::AdaptiveMesh<TemplateSet_, Shape_>>
23 {
24 public:
25 typedef Shape_ ShapeType;
27
29 typedef Intern::VTKShape<ShapeType> VTKShapeType;
30
31 static constexpr int shape_dim = ShapeType::dimension;
32
33 protected:
38
39 // number of vertices in regular/adaptive mesh
40 Index _num_verts_reg, _num_verts_ada, _num_verts_total;
41 // number of elements in regular/adaptive mesh
42 Index _num_elems_reg, _num_elems_ada, _num_elems_total;
43
44 // regular element mask
45 std::vector<char> _reg_elem_mask;
46
47 std::deque<std::pair<String, std::vector<double>>> _vertex_scalars;
48 std::deque<std::pair<String, std::vector<double>>> _cell_scalars;
49
50 public:
52 _mesh_reg(mesh.foundation_mesh()),
53 _mesh_ada(mesh),
54 _num_verts_reg(_mesh_reg.get_num_entities(0)),
55 _num_verts_ada(mesh.get_num_entities(0)),
56 _num_verts_total(_num_verts_reg + _num_verts_ada),
57 _num_elems_reg(_mesh_reg.get_num_entities(shape_dim)),
58 _num_elems_ada(mesh.get_num_entities(shape_dim)),
59 _num_elems_total(
60 _num_elems_reg + _num_elems_ada - mesh.adaptive_mesh().get_num_entities(Geometry::Layer{0}, shape_dim)),
61 _reg_elem_mask(_num_elems_reg, 1)
62 {
63 // figure out which regular elements are refined adaptively and mask them out
64 Index count = _num_elems_ada;
65 for(Index i(0); i < _num_elems_reg; ++i)
66 count += Index(_reg_elem_mask[i] = (mesh.adaptive_mesh().get_overlap_cell(i).has_value() ? 0 : 1));
67 XASSERTM(_num_elems_total == count, "invalid element count");
68 }
69
70 virtual ~AdaptiveExportVTU()
71 {
72 }
73
74 // no copy, no problems
75 AdaptiveExportVTU(const AdaptiveExportVTU&) = delete;
76 AdaptiveExportVTU& operator=(const AdaptiveExportVTU&) = delete;
77
78 template<typename BridgeVector_>
79 void add_vertex_scalar(const String& name, const BridgeVector_& bridge_vector)
80 {
81 XASSERTM(bridge_vector.regular().size() == _num_verts_reg, "invalid number of regular values in bridge vector");
83 bridge_vector.adaptive().size() == _num_verts_ada,
84 "invalid number of adaptive values in bridge vector");
85
86 const auto* val_reg = bridge_vector.regular().elements();
87 const auto* val_ada = bridge_vector.adaptive().elements();
88
89 std::vector<double> values(_num_verts_total);
90
91 for(Index i(0); i < _num_verts_reg; ++i)
92 values[i] = double(val_reg[i]);
93 for(Index i(0); i < _num_verts_ada; ++i)
94 values[_num_verts_reg + i] = double(val_ada[i]);
95
96 _vertex_scalars.push_back(std::make_pair(name, std::move(values)));
97 }
98
99 template<typename BridgeVector_>
100 void add_cell_scalar(const String& name, const BridgeVector_& bridge_vector)
101 {
102 XASSERTM(bridge_vector.regular().size() == _num_elems_reg, "invalid number of regular values in bridge vector");
103 XASSERTM(
104 bridge_vector.adaptive().size() == _num_elems_ada,
105 "invalid number of adaptive values in bridge vector");
106
107 const auto* val_reg = bridge_vector.regular().elements();
108 const auto* val_ada = bridge_vector.adaptive().elements();
109
110 std::vector<double> values(_num_elems_total);
111
112 Index j(0);
113 for(Index i(0); i < _num_elems_reg; ++i)
114 {
115 if(_reg_elem_mask[i] > 0)
116 {
117 values[j] = double(val_reg[i]);
118 ++j;
119 }
120 }
121 for(Index i(0); i < _num_elems_ada; ++i, ++j)
122 values[j] = double(val_ada[i]);
123 XASSERT(j == _num_elems_total);
124
125 _cell_scalars.push_back(std::make_pair(name, std::move(values)));
126 }
127
128 void write(const String& filename) const
129 {
130 String vtu_name(filename + ".vtu");
131 std::ofstream ofs(vtu_name.c_str());
132 if(!(ofs.is_open() && ofs.good()))
133 throw FileError("Failed to create '" + vtu_name + "'");
134
135 // write
136 write_vtu(ofs);
137
138 // and close
139 ofs.close();
140 }
141
142 void write_vtu(std::ostream& os) const
143 {
144 // fetch basic information
145 const int verts_per_cell = Shape::FaceTraits<ShapeType, 0>::count;
146
147 // write VTK header
148 os << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\">\n";
149
150 // write mesh header
151 os << "<UnstructuredGrid>\n";
152 os << "<Piece NumberOfPoints=\"" << _num_verts_total << "\" NumberOfCells=\"" << _num_elems_total << "\">\n";
153
154 // write point data
155 if((!_vertex_scalars.empty()) /*|| (!_vertex_vectors.empty())*/)
156 {
157 os << "<PointData>\n";
158
159 // write vertex variables
160 for(Index i(0); i < Index(_vertex_scalars.size()); ++i)
161 {
162 const auto& var(_vertex_scalars[i]);
163 os << "<DataArray type=\"Float64\" Name=\"" << var.first << "\" Format=\"ascii\">\n";
164 for(Index j(0); j < _num_verts_total; ++j)
165 {
166 os << stringify_fp_sci(var.second[j]) << "\n";
167 }
168 os << "</DataArray>\n";
169 }
170 // write vertex fields
171 /*for(Index i(0); i < Index(_vertex_vectors.size()); ++i)
172 {
173 const auto& var(_vertex_vectors[i]);
174 os << "<DataArray type=\"Float64\" Name=\"" << var.first;
175 os <<"\" NumberOfComponents=\"3\" Format=\"ascii\">\n";
176 for(Index j(0); j < _num_verts_total; ++j)
177 {
178 os << stringify_fp_sci(var.second[3*j+0], _var_prec) << " ";
179 os << stringify_fp_sci(var.second[3*j+1], _var_prec) << " ";
180 os << stringify_fp_sci(var.second[3*j+2], _var_prec) << "\n";
181 }
182 os << "</DataArray>\n";
183 }*/
184
185 os << "</PointData>\n";
186 }
187
188 // write cell data
189 if(!_cell_scalars.empty() /*|| !_cell_vectors.empty()*/)
190 {
191 os << "<CellData>\n";
192 if(!_cell_scalars.empty())
193 {
194 for(Index i(0); i < Index(_cell_scalars.size()); ++i)
195 {
196 const auto& var(_cell_scalars[i]);
197 os << "<DataArray type=\"Float64\" Name=\"" << var.first << "\" Format=\"ascii\">\n";
198 for(Index j(0); j < _num_elems_total; ++j)
199 {
200 os << stringify_fp_sci(var.second[j]) << "\n";
201 }
202 os << "</DataArray>\n";
203 }
204 }
205
206 /*if(!_cell_vectors.empty())
207 {
208 // write cell fields
209 for(Index i(0); i < Index(_cell_vectors.size()); ++i)
210 {
211 const auto& var(_cell_vectors[i]);
212 os << "<DataArray type=\"Float64\" Name=\"" << var.first;
213 os <<"\" NumberOfComponents=\"3\" Format=\"ascii\">\n";
214 for(Index j(0); j < _num_elems_total; ++j)
215 {
216 os << stringify_fp_sci(var.second[3*j+0], _var_prec) << " ";
217 os << stringify_fp_sci(var.second[3*j+1], _var_prec) << " ";
218 os << stringify_fp_sci(var.second[3*j+2], _var_prec) << "\n";
219 }
220 os << "</DataArray>\n";
221 }
222 }*/
223 os << "</CellData>\n";
224 }
225
226 // write vertices
227 const auto& vtx_reg = _mesh_reg.get_vertex_set();
228 const auto& vtx_ada = _mesh_ada.get_vertex_set();
229
230 os << "<Points>\n";
231 os << "<DataArray type=\"Float32\" NumberOfComponents=\"3\" Format=\"ascii\">\n";
232 // write regular vertices
233 for(Index i(0); i < _num_verts_reg; ++i)
234 {
235 os << vtx_reg[i][0];
236 for(int j(1); j < shape_dim; ++j)
237 {
238 os << " " << vtx_reg[i][j];
239 }
240 for(int j(shape_dim); j < 3; ++j)
241 {
242 os << " 0";
243 }
244 os << "\n";
245 }
246 // write adaptive vertices
247 for(Index i(0); i < _num_verts_ada; ++i)
248 {
249 os << vtx_ada[i][0];
250 for(int j(1); j < shape_dim; ++j)
251 {
252 os << " " << vtx_ada[i][j];
253 }
254 for(int j(shape_dim); j < 3; ++j)
255 {
256 os << " 0";
257 }
258 os << "\n";
259 }
260 os << "</DataArray>\n";
261 os << "</Points>\n";
262
263 // write cells
264 const auto& idx_reg = _mesh_reg.template get_index_set<shape_dim, 0>();
265 const auto& idx_ada = _mesh_ada.template get_index_set<shape_dim, 0>();
266 os << "<Cells>\n";
267 os << "<DataArray type=\"UInt32\" Name=\"connectivity\">\n";
268 // write regular vertices
269 for(Index i(0); i < _num_elems_reg; ++i)
270 {
271 // is this element masked?
272 if(_reg_elem_mask[i] > 0)
273 {
274 os << idx_reg(i, VTKShapeType::map(0));
275 for(int j(1); j < verts_per_cell; ++j)
276 {
277 os << " " << idx_reg(i, VTKShapeType::map(j));
278 }
279 os << "\n";
280 }
281 }
282 // write adaptive vertices
283 for(Index i(0); i < _num_elems_ada; ++i)
284 {
285 os << (_num_verts_reg + idx_ada(i, VTKShapeType::map(0)));
286 for(int j(1); j < verts_per_cell; ++j)
287 {
288 os << " " << (_num_verts_reg + idx_ada(i, VTKShapeType::map(j)));
289 }
290 os << "\n";
291 }
292 os << "</DataArray>\n";
293 os << "<DataArray type=\"UInt32\" Name=\"offsets\">\n";
294 for(Index i(0); i < _num_elems_total; ++i)
295 {
296 os << ((i + 1) * verts_per_cell) << "\n";
297 }
298 os << "</DataArray>\n";
299 os << "<DataArray type=\"UInt32\" Name=\"types\">\n";
300 for(Index i(0); i < _num_elems_total; ++i)
301 {
302 os << VTKShapeType::type << "\n";
303 }
304 os << "</DataArray>\n";
305 os << "</Cells>\n";
306
307 // finish
308 os << "</Piece>\n";
309 os << "</UnstructuredGrid>\n";
310 os << "</VTKFile>\n";
311 }
312 }; // class AdaptiveExportVTU<Geometry::AdaptiveMesh<...>>
313 } // namespace Geometry
314} // namespace FEAT
315
316#endif // KERNEL_GEOMETRY_ADAPTIVE_EXPORT_VTU_HPP
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
const Geometry::AdaptiveMeshLayer< MeshType > & _mesh_ada
the chosen adaptive mesh layer
const MeshType::FoundationMeshType & _mesh_reg
the underlying regular mesh
Dynamic mesh data structure.
ConformalMesh interface for adaptive meshes.
AdaptiveMeshType & adaptive_mesh()
accessor for adaptive mesh
VertexSetType & get_vertex_set()
Returns the vertex set of this mesh.
Conformal mesh class template.
VertexSetType & get_vertex_set()
Returns a reference to the vertex set of the mesh.
String class implementation.
Definition: string.hpp:46
FEAT namespace.
Definition: adjactor.hpp:12
String stringify_fp_sci(DataType_ value, int precision=0, int width=0, bool sign=false)
Prints a floating point value to a string in scientific notation.
Definition: string.hpp:1088
std::uint64_t Index
Index data type.
Newtype wrapper for mesh layers.