FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
mesh_file_writer.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
8#include <kernel/geometry/mesh_atlas.hpp>
9#include <kernel/geometry/conformal_mesh.hpp>
10#include <kernel/geometry/mesh_part.hpp>
11#include <kernel/geometry/mesh_node.hpp>
12#include <kernel/geometry/partition_set.hpp>
13#include <kernel/util/xml_scanner.hpp>
14
15namespace FEAT
16{
17 namespace Geometry
18 {
20 namespace Intern
21 {
22 template<typename Shape_, int dim_ = Shape_::dimension>
23 class TopoWriteHelper
24 {
25 public:
26 static void write_topology(std::ostream& os, const IndexSetHolder<Shape_>& ish, const String& sindent, bool skip_empty)
27 {
28 // recurse down
29 TopoWriteHelper<Shape_, dim_-1>::write_topology(os, ish, sindent, skip_empty);
30
31 String sind(sindent);
32 if(!sind.empty())
33 sind.append(" ");
34
35 const auto& index_set = ish.template get_index_set<dim_, 0>();
36
37 // empty topology?
38 // Note: this case is valid for MeshPart topologies
39 if(skip_empty && (index_set.get_num_entities() == Index(0)))
40 return;
41
42 os << sindent << "<Topology dim=\"" << dim_ << "\">\n";
43 for(Index i(0); i < index_set.get_num_entities(); ++i)
44 {
45 const auto& idx = index_set[i];
46 os << sind << idx[0];
47 for(int j(1); j < index_set.num_indices; ++j)
48 os << ' ' << idx[j];
49 os << '\n';
50 }
51 os << sindent << "</Topology>\n";
52 }
53 };
54
55 template<typename Shape_>
56 class TopoWriteHelper<Shape_, 0>
57 {
58 public:
59 static void write_topology(std::ostream&, const IndexSetHolder<Shape_>&, const String&, bool)
60 {
61 // nothing to do here
62 }
63 };
64
65 template<typename Shape_, int dim_ = Shape_::dimension>
66 class MappWriteHelper
67 {
68 public:
69 static void write_mapping(std::ostream& os, const TargetSetHolder<Shape_>& tsh, const String& sindent, bool skip_empty)
70 {
71 // recurse down
72 MappWriteHelper<Shape_, dim_-1>::write_mapping(os, tsh, sindent, skip_empty);
73
74 String sind(sindent);
75 if(!sind.empty())
76 sind.append(" ");
77
78 const auto& target_set = tsh.template get_target_set<dim_>();
79
80 // empty mapping?
81 if(skip_empty && (target_set.get_num_entities() == Index(0)))
82 return;
83
84 os << sindent << "<Mapping dim=\"" << dim_ << "\">\n";
85 for(Index i(0); i < target_set.get_num_entities(); ++i)
86 os << sind << target_set[i] << '\n';
87 os << sindent << "</Mapping>\n";
88 }
89 };
90
91 template<typename Shape_>
92 class MappWriteHelper<Shape_, 0>
93 {
94 public:
95 static void write_mapping(std::ostream& os, const TargetSetHolder<Shape_>& tsh, const String& sindent, bool skip_empty)
96 {
97 String sind(sindent);
98 if(!sind.empty())
99 sind.append(" ");
100
101 const auto& target_set = tsh.template get_target_set<0>();
102
103 // empty mapping?
104 if(skip_empty && (target_set.get_num_entities() == Index(0)))
105 return;
106
107 os << sindent << "<Mapping dim=\"0\">\n";
108 for(Index i(0); i < target_set.get_num_entities(); ++i)
109 os << sind << target_set[i] << '\n';
110 os << sindent << "</Mapping>\n";
111 }
112 };
113 } // namespace Intern
115
126 {
127 protected:
129 std::ostream& _os;
134
136 template<int shape_dim_>
137 static String aux_shape_string(const Shape::Hypercube<shape_dim_>&)
138 {
139 return "hypercube";
140 }
141
142 template<int shape_dim_>
143 static String aux_shape_string(const Shape::Simplex<shape_dim_>&)
144 {
145 return "simplex";
146 }
147
148 template<typename Shape_, int num_coords_, typename Coord_>
149 static String aux_meshtype_string(const ConformalMesh<Shape_, num_coords_, Coord_>&)
150 {
151 return String("conformal:") + aux_shape_string(Shape_()) + ":" + stringify(int(Shape_::dimension)) + ":" + stringify(num_coords_);
152 }
154
157 {
158 if(_indent)
159 _sindent.resize(_sindent.size()+2, ' ');
160 }
161
164 {
165 if(_indent)
166 _sindent.resize(_sindent.size()-2);
167 }
168
169 public:
180 explicit MeshFileWriter(std::ostream& os, bool indent = true) :
181 _os(os),
182 _indent(indent)
183 {
184 if(_indent)
185 _sindent.reserve(32);
186 }
187
190 {
191 }
192
202 template<typename RootMesh_>
203 void write_chart(const Atlas::ChartBase<RootMesh_>& chart, const String& name)
204 {
205 String sind(_sindent);
206 if(_indent)
207 sind.append(" ");
208
209 _os << _sindent << "<Chart name=\"" << name << "\">\n";
210 chart.write(_os, sind);
211 _os << _sindent << "</Chart>\n";
212 }
213
220 template<typename RootMesh_>
221 void write_atlas(const MeshAtlas<RootMesh_>& mesh_atlas)
222 {
223 // get all charts
224 std::deque<String> names = mesh_atlas.get_chart_names();
225
226 // loop over all charts
227 for(auto it = names.begin(); it != names.end(); ++it)
228 {
229 const Atlas::ChartBase<RootMesh_>* chart = mesh_atlas.find_mesh_chart(*it);
230 XASSERTM(chart != nullptr, String("Chart '") + (*it) + "' not found in atlas");
231
232 write_chart(*chart, *it);
233 }
234 }
235
242 template<typename Shape_, int num_coords_, typename Coord_>
244 {
246 _os << _sindent << "<Mesh type=\"" << aux_meshtype_string(mesh) << "\"";
247 _os << " size=\"" << mesh.get_num_entities(0);
248 for(int i(1); i <= MeshType::shape_dim; ++i)
249 _os << " " << mesh.get_num_entities(i);
250 _os << "\">\n";
251 _push_indent();
252
254 Intern::TopoWriteHelper<Shape_>::write_topology(_os, mesh.get_index_set_holder(), _sindent, false);
255
256 _pop_indent();
257 _os << _sindent << "</Mesh>\n";
258 }
259
275 template<typename Mesh_>
276 void write_meshpart(const MeshPart<Mesh_>& meshpart, const String& parent_name, const String& part_name, const String& chart_name)
277 {
278 typedef typename Mesh_::ShapeType ShapeType;
279
280 _os << _sindent << "<MeshPart";
281 _os << " name=\"" << part_name << "\"";
282 _os << " parent=\"" << parent_name << "\"";
283 if(!chart_name.empty())
284 _os << " chart=\"" << chart_name << "\"";
285 _os << " topology=\"" << (meshpart.has_topology() ? "full" : "none") << "\"";
286 _os << " size=\"" << meshpart.get_num_entities(0);
287 for(int i(1); i <= ShapeType::dimension; ++i)
288 _os << " " << meshpart.get_num_entities(i);
289 _os << "\">\n";
290 _push_indent();
291
292 // write mapping
293 Intern::MappWriteHelper<ShapeType>::write_mapping(_os, meshpart.get_target_set_holder(), _sindent, true);
294
295 // write topology
296 if(meshpart.has_topology())
297 Intern::TopoWriteHelper<ShapeType>::write_topology(_os, *meshpart.get_topology(), _sindent, true);
298
299 // write attributes
300 const auto& attrs = meshpart.get_mesh_attributes();
301 for(auto it = attrs.begin(); it != attrs.end(); ++it)
302 _write_attribute(*(it->second), it->first);
303
304 _pop_indent();
305 _os << _sindent << "</MeshPart>\n";
306 }
307
314 void write_partition(const Partition& partition)
315 {
316 _os << _sindent << "<Partition";
317 if(!partition.get_name().empty())
318 _os << " name=\"" << partition.get_name() << "\"";
319 _os << " priority=\"" << partition.get_priority() << "\"";
320 _os << " level=\"" << partition.get_level() << "\"";
321 _os << " size=\"" << partition.get_num_patches() << ' ' << partition.get_num_elements() << "\"";
322 _os << ">\n";
323 _push_indent();
324
325 // loop over all patches
326 const Adjacency::Graph& graph = partition.get_patches();
327 for(Index i(0); i < graph.get_num_nodes_domain(); ++i)
328 {
329 _os << _sindent << "<Patch rank=\"" << i << "\" size=\"" << graph.degree(i) << "\">\n";
330 _push_indent();
331 for(auto it = graph.image_begin(i); it != graph.image_end(i); ++it)
332 _os << _sindent << (*it) << '\n';
333 _pop_indent();
334 _os << _sindent << "</Patch>\n";
335 }
336
337 _pop_indent();
338 _os << _sindent << "</Partition>\n";
339 }
340
347 void write_partition_set(const PartitionSet& part_set)
348 {
349 for(const auto& p : part_set.get_partitions())
351 }
352
372 template<typename RootMesh_>
373 void write(
374 const RootMeshNode<RootMesh_>* mesh_node,
375 const MeshAtlas<RootMesh_>* mesh_atlas = nullptr,
376 const PartitionSet* part_set = nullptr,
377 bool skip_internal_meshparts = true)
378 {
379 const RootMesh_* root_mesh(nullptr);
380 if(mesh_node != nullptr)
381 root_mesh = mesh_node->get_mesh();
382
383 // print root markup
384 _os << "<FeatMeshFile version=\"1\"";
385 if(root_mesh != nullptr)
386 _os << " mesh=\"" << aux_meshtype_string(*root_mesh) << "\"";
387 _os << ">\n";
388
389 // increase indent
390 _push_indent();
391
392 // write mesh atlas
393 if(mesh_atlas != nullptr)
394 {
395 // write atlas
396 write_atlas(*mesh_atlas);
397 }
398
399 // write mesh node
400 if(mesh_node != nullptr)
401 {
402 // write mesh
403 if(root_mesh != nullptr)
404 write_mesh(*root_mesh);
405
406 // write meshparts
407 std::deque<String> part_names = mesh_node->get_mesh_part_names();
408 for(auto it = part_names.begin(); it != part_names.end(); ++it)
409 {
410 // skip mesh parts starting with an underscore;
411 // these are reserved for internal use and should not be exported
412 // unless explicitly specified by the caller
413 if(skip_internal_meshparts && it->starts_with('_'))
414 continue;
415
416 const MeshPart<RootMesh_>* meshpart = mesh_node->find_mesh_part(*it);
417 String chart_name = mesh_node->find_mesh_part_chart_name(*it);
418 write_meshpart(*meshpart, "root", *it, chart_name);
419 }
420 }
421
422 // write partitions
423 if(part_set != nullptr)
424 {
425 write_partition_set(*part_set);
426 }
427
428 _pop_indent();
429
430 // write terminator
431 _os << "</FeatMeshFile>\n";
432 }
433
434 void write_only(const PartitionSet& part_set)
435 {
436 _os << "<FeatMeshFile version=\"1\">\n";
437 _push_indent();
438 write_partition_set(part_set);
439 _pop_indent();
440 _os << "</FeatMeshFile>\n";
441 }
442
443 protected:
449 template<int num_coords_, typename Coord_>
451 {
452 _os << _sindent << "<Vertices>\n";
453 _push_indent();
454 for(Index i(0); i < vertex_set.get_num_vertices(); ++i)
455 {
456 const auto& v = vertex_set[i];
457 _os << _sindent << v[0];
458 for(int j(1); j < num_coords_; ++j)
459 _os << ' ' << v[j];
460 _os << '\n';
461 }
462 _pop_indent();
463 _os << _sindent << "</Vertices>\n";
464 }
465
475 template<typename Data_>
476 void _write_attribute(const AttributeSet<Data_>& attr, const String& name)
477 {
478 _os << _sindent << "<Attribute";
479 _os << " name=\"" << name << "\"";
480 _os << " dim=\"" << attr.get_dimension() << "\"";
481 _os << ">\n";
482 _push_indent();
483 for(Index i(0); i < attr.get_num_values(); ++i)
484 {
485 _os << _sindent << attr(i, 0);
486 for(int j(1); j < attr.get_dimension(); ++j)
487 _os << ' ' << attr(i, j);
488 _os << '\n';
489 }
490 _pop_indent();
491 _os << _sindent << "</Attribute>\n";
492 }
493 }; // class MeshFileWriter
494 } // namespace Geometry
495} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Adjacency Graph implementation.
Definition: graph.hpp:34
ImageIterator image_begin(Index domain_node) const
Returns an iterator for the first adjacent image node.
Definition: graph.hpp:958
ImageIterator image_end(Index domain_node) const
Returns an iterator for the first position past the last adjacent image node.
Definition: graph.hpp:966
Index degree(Index domain_node) const
Returns the degree of a domain node.
Definition: graph.hpp:333
Container for saving data related to mesh entities.
Index get_num_values() const
Returns the number of attribute values.
int get_dimension() const
Returns the number attribute dimension.
Conformal mesh class template.
Index get_num_entities(int dim) const
Returns the number of entities.
VertexSetType & get_vertex_set()
Returns a reference to the vertex set of the mesh.
Mesh Atlas class template.
Definition: mesh_atlas.hpp:32
MeshChartType * find_mesh_chart(const String &name)
Searches for a mesh chart.
Definition: mesh_atlas.hpp:162
std::deque< String > get_chart_names() const
Returns the names of all charts of this atlas.
Definition: mesh_atlas.hpp:131
void _write_vertex_set(const VertexSet< num_coords_, Coord_ > &vertex_set)
Writes a vertex-set of a mesh into the file.
void write_partition(const Partition &partition)
Writes a partition to the file.
void write_chart(const Atlas::ChartBase< RootMesh_ > &chart, const String &name)
Writes a chart into the file.
void _write_attribute(const AttributeSet< Data_ > &attr, const String &name)
Writes an attribute of a mesh part into the file.
virtual ~MeshFileWriter()
virtual destructor
String _sindent
the current indentation string
void _push_indent()
increases the current indent by two spaces
std::ostream & _os
the output stream to write to
void write_mesh(const ConformalMesh< Shape_, num_coords_, Coord_ > &mesh)
Writes a (root) mesh into the file.
bool _indent
specifies whether indentation is to be used
void write_meshpart(const MeshPart< Mesh_ > &meshpart, const String &parent_name, const String &part_name, const String &chart_name)
Writes a mesh-part into the file.
void write(const RootMeshNode< RootMesh_ > *mesh_node, const MeshAtlas< RootMesh_ > *mesh_atlas=nullptr, const PartitionSet *part_set=nullptr, bool skip_internal_meshparts=true)
Writes a full domain to the file.
void _pop_indent()
decreases the current indent by two spaces
MeshFileWriter(std::ostream &os, bool indent=true)
Creates a writer for a given output stream.
void write_partition_set(const PartitionSet &part_set)
Writes all partitions of a partition set to the file.
void write_atlas(const MeshAtlas< RootMesh_ > &mesh_atlas)
Writes all charts of an atlas into the file.
MeshPartType * find_mesh_part(const String &part_name)
Searches this container for a MeshPart.
Definition: mesh_node.hpp:398
String find_mesh_part_chart_name(const String &part_name) const
Searches for a chart name belonging to a MeshPart by name.
Definition: mesh_node.hpp:437
std::deque< String > get_mesh_part_names(bool no_internals=false) const
Returns the names of all mesh parts of this node.
Definition: mesh_node.hpp:251
MeshType * get_mesh()
Returns the mesh of this node.
Definition: mesh_node.hpp:225
Class template for partial meshes.
Definition: mesh_part.hpp:90
const AttributeSetContainer & get_mesh_attributes() const
Returns a const reference to the mesh attributes container.
Definition: mesh_part.hpp:346
bool has_topology() const
Checks if this MeshPart has a mesh topology.
Definition: mesh_part.hpp:297
Index get_num_entities(int dim) const
Returns the number of entities.
Definition: mesh_part.hpp:311
const Adjacency::Graph & get_patches() const
Root mesh node class template.
Definition: mesh_node.hpp:748
String class implementation.
Definition: string.hpp:46
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
std::uint64_t Index
Index data type.
Fixed-Sized Vertex Set class template.
Definition: vertex_set.hpp:37
Index get_num_vertices() const
Returns the number of vertices in the vertex set.
Definition: vertex_set.hpp:157
Hypercube shape tag struct template.
Definition: shape.hpp:64
Simplex shape tag struct template.
Definition: shape.hpp:44