8#include <kernel/geometry/conformal_mesh.hpp>
9#include <kernel/geometry/mesh_atlas.hpp>
10#include <kernel/geometry/mesh_part.hpp>
11#include <kernel/geometry/mesh_node.hpp>
12#include <kernel/geometry/atlas/bezier.hpp>
13#include <kernel/geometry/atlas/circle.hpp>
14#include <kernel/geometry/atlas/extrude.hpp>
15#include <kernel/geometry/atlas/surface_mesh.hpp>
16#include <kernel/geometry/atlas/sphere.hpp>
17#include <kernel/adjacency/dynamic_graph.hpp>
19#include <kernel/util/xml_scanner.hpp>
20#include <kernel/util/dist_file_io.hpp>
55 template<
typename RootMesh_>
65 std::deque<std::pair<String,String>> _meshpart_to_chart;
67 std::deque<String> _meshpart_deduct_topo;
96 _meshpart_to_chart.emplace_back(std::make_pair(meshpart, chart));
107 _meshpart_deduct_topo.emplace_back(meshpart);
118 while(!_meshpart_to_chart.empty())
120 String mpart_name = _meshpart_to_chart.front().first;
121 String chart_name = _meshpart_to_chart.front().second;
127 String msg =
String(
"Chart '") + chart_name +
"' not found for meshpart '" + mpart_name +
"'";
132 if(!
_mesh_node.set_mesh_part_chart(mpart_name, chart_name, chart))
134 String msg =
String(
"meshpart '" + mpart_name +
"' not found");
139 _meshpart_to_chart.pop_front();
143 const RootMesh_* root_mesh =
_mesh_node.get_mesh();
146 while(!_meshpart_deduct_topo.empty())
148 String mpart_name = _meshpart_deduct_topo.front();
151 if(mesh_part ==
nullptr)
153 String msg =
String(
"meshpart '" + mpart_name +
"' not found");
158 if(root_mesh ==
nullptr)
160 String msg =
String(
"Cannot deduct topology for meshpart '") + mpart_name +
"'; no root mesh found";
168 _meshpart_deduct_topo.pop_front();
177 template<
typename RootMesh_,
int world_dim>
178 struct DimensionalChartHelper;
180 template<
typename RootMesh_>
185 MeshAtlas<RootMesh_>& _atlas;
187 std::unique_ptr<Atlas::ChartBase<RootMesh_>> _chart;
190 explicit ChartParser(MeshAtlas<RootMesh_>& atlas) :
191 _atlas(atlas), _chart_name(), _chart()
195 virtual ~ChartParser()
199 virtual bool attribs(std::map<String,bool>& attrs)
const override
201 attrs.emplace(
"name",
true);
206 int iline,
const String& sline,
const String&,
207 const std::map<String, String>& attrs,
bool closed)
override
210 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
213 _chart_name = attrs.find(
"name")->second.
trim();
214 if(_chart_name.empty())
215 throw Xml::GrammarError(iline, sline,
"Empty chart name");
218 XASSERTM(_atlas.find_mesh_chart(_chart_name) ==
nullptr,
219 String(
"Chart '") + _chart_name +
"' already exists in atlas");
224 virtual void close(
int iline,
const String& sline)
override
228 throw Xml::GrammarError(iline, sline,
"Invalid empty chart");
231 _atlas.add_mesh_chart(_chart_name, std::move(_chart));
234 virtual bool content(
int,
const String&)
override
239 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String& name)
override
241 return DimensionalChartHelper<RootMesh_, RootMesh_::world_dim>::markup(name, _chart);
246 template<
int num_coords_,
typename Coord_>
247 class VerticesParser :
248 public Xml::MarkupParser
251 typedef VertexSet<num_coords_, Coord_> VertexSetType;
254 VertexSetType& _vertex_set;
258 explicit VerticesParser(VertexSetType& vertex_set) :
259 _vertex_set(vertex_set),
264 virtual bool attribs(std::map<String,bool>&)
const override
269 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>&,
bool closed)
override
272 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
275 virtual void close(
int iline,
const String& sline)
override
278 if(_read < _vertex_set.get_num_vertices())
279 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected point");
282 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
288 virtual bool content(
int iline,
const String& sline)
override
291 if(_read >= _vertex_set.get_num_vertices())
292 throw Xml::ContentError(iline, sline,
"Invalid content; expected terminator");
295 std::deque<String> scoords = sline.split_by_whitespaces();
298 if(scoords.size() != std::size_t(num_coords_))
299 throw Xml::ContentError(iline, sline,
"Invalid number of coordinates");
302 auto& vtx = _vertex_set[_read];
305 for(
int i(0); i < num_coords_; ++i)
307 if(!scoords.at(std::size_t(i)).parse(vtx[i]))
308 throw Xml::ContentError(iline, sline,
"Failed to parse vertex coordinate");
320 template<
typename Shape_,
int dim_ = Shape_::dimension>
321 struct TopoParseHelper
323 template<
typename TopoParser_>
324 static void init_topo(TopoParser_& tp, IndexSetHolder<Shape_>& ish,
int dim)
327 tp.init_idx_set(ish.template get_index_set<dim_, 0>(), dim_);
329 TopoParseHelper<Shape_, dim_-1>::init_topo(tp, ish, dim);
333 template<
typename Shape_>
334 struct TopoParseHelper<Shape_, 0>
336 template<
typename TopoParser_>
337 static void init_topo(TopoParser_&, IndexSetHolder<Shape_>&,
int)
339 XABORTM(
"Thou shall not arrive here");
343 template<
typename Shape_,
int dim_ = Shape_::dimension>
344 struct MappParseHelper
346 template<
typename MappParser_>
347 static void init_mapp(MappParser_& mp, TargetSetHolder<Shape_>& tsh,
int dim)
350 mp.init_trg_set(tsh.template get_target_set<dim_>(), dim_);
352 MappParseHelper<Shape_, dim_-1>::init_mapp(mp, tsh, dim);
356 template<
typename Shape_>
357 struct MappParseHelper<Shape_, 0>
359 template<
typename MappParser_>
360 static void init_mapp(MappParser_& mp, TargetSetHolder<Shape_>& tsh,
int)
362 mp.init_trg_set(tsh.template get_target_set<0>(), 0);
367 template<
typename Shape_>
368 class TopologyParser :
369 public Xml::MarkupParser
372 typedef IndexSetHolder<Shape_> TopologyType;
375 TopologyType& _topology;
376 std::deque<int>& _have_topology;
385 template<
int num_
idx_>
386 void init_idx_set(IndexSet<num_idx_>& idx_set,
int dim)
388 _indices =
reinterpret_cast<Index*
>(idx_set.get_indices());
389 _my_dim =
Index(dim);
390 _num_idx =
Index(num_idx_);
391 _bound = idx_set.get_index_bound();
392 _count = idx_set.get_num_entities();
397 explicit TopologyParser(TopologyType& topology, std::deque<int>& have_topology) :
399 _have_topology(have_topology),
409 virtual bool attribs(std::map<String,bool>& attrs)
const override
411 attrs.emplace(
"dim",
true);
415 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool closed)
override
418 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
421 if(!attrs.find(
"dim")->second.parse(_my_dim))
422 throw Xml::ContentError(iline, sline,
"Failed to parse 'dim' attribute");
425 if((_my_dim >
Index(_have_topology.size())) || (_my_dim ==
Index(0)))
426 throw Xml::ContentError(iline, sline,
"Invalid topology dimension");
429 if(_have_topology.at(_my_dim-1) != 0)
430 throw Xml::ContentError(iline, sline,
"Multiple topology for dimension " +
stringify(_my_dim));
431 _have_topology.at(_my_dim-1) = 1;
434 Intern::TopoParseHelper<Shape_>::init_topo(*
this, _topology,
int(_my_dim));
437 virtual void close(
int iline,
const String& sline)
override
441 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected index tuple");
444 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
450 virtual bool content(
int iline,
const String& sline)
override
454 throw Xml::ContentError(iline, sline,
"Invalid content; expected terminator");
457 std::deque<String> sidx = sline.split_by_whitespaces();
460 if(sidx.size() != std::size_t(_num_idx))
461 throw Xml::ContentError(iline, sline,
"Invalid number of indices");
464 for(Index i(0); i < _num_idx; ++i)
466 Index& idx = _indices[_read*_num_idx+i];
469 if(!sidx.at(i).parse(idx))
470 throw Xml::ContentError(iline, sline,
"Failed to parse index");
474 throw Xml::ContentError(iline, sline,
"Index out of bounds");
484 template<
typename Shape_>
485 class MappingParser :
486 public Xml::MarkupParser
489 typedef TargetSetHolder<Shape_> MappingType;
492 MappingType& _mapping;
493 std::deque<int>& _have_mapping;
500 void init_trg_set(TargetSet& trg_set,
int dim)
502 _indices = trg_set.get_indices();
503 _my_dim =
Index(dim);
504 _count = trg_set.get_num_entities();
508 explicit MappingParser(MappingType& mapping, std::deque<int>& have_mapping) :
510 _have_mapping(have_mapping),
518 virtual bool attribs(std::map<String,bool>& attrs)
const override
520 attrs.emplace(
"dim",
true);
524 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool closed)
override
527 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
530 if(!attrs.find(
"dim")->second.parse(_my_dim))
531 throw Xml::ContentError(iline, sline,
"Failed to parse 'dim' attribute");
534 if((_my_dim >
Index(_have_mapping.size())))
535 throw Xml::ContentError(iline, sline,
"Invalid mapping dimension");
538 if(_have_mapping.at(_my_dim) != 0)
539 throw Xml::ContentError(iline, sline,
"Multiple mapping for dimension " +
stringify(_my_dim));
540 _have_mapping.at(_my_dim) = 1;
543 Intern::MappParseHelper<Shape_>::init_mapp(*
this, _mapping,
int(_my_dim));
546 virtual void close(
int iline,
const String& sline)
override
550 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected index");
553 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
559 virtual bool content(
int iline,
const String& sline)
override
563 throw Xml::ContentError(iline, sline,
"Invalid content; expected terminator");
566 if(!sline.parse(_indices[_read]))
567 throw Xml::ContentError(iline, sline,
"Failed to parse index");
576 template<
typename MeshPart_,
typename DataType_ =
typename MeshPart_::AttributeDataType>
577 class AttributeParser :
578 public Xml::MarkupParser
581 typedef AttributeSet<DataType_> AttribType;
584 MeshPart_& _mesh_part;
585 std::unique_ptr<AttribType> _attrib;
592 explicit AttributeParser(MeshPart_& mesh_part) :
593 _mesh_part(mesh_part),
601 virtual ~AttributeParser()
605 virtual bool attribs(std::map<String,bool>& attrs)
const override
607 attrs.emplace(
"dim",
true);
608 attrs.emplace(
"name",
true);
612 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool closed)
override
615 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
618 if(!attrs.find(
"dim")->second.parse(_my_dim))
619 throw Xml::ContentError(iline, sline,
"Failed to parse 'dim' attribute");
622 if(_my_dim ==
Index(0))
623 throw Xml::ContentError(iline, sline,
"Invalid attribute dimension");
626 _my_name = attrs.find(
"name")->second;
629 _count = _mesh_part.get_num_entities(0);
630 _attrib.reset(
new AttribType(_count,
int(_my_dim)));
633 virtual void close(
int iline,
const String& sline)
override
637 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected index");
640 _mesh_part.add_attribute(std::move(_attrib), _my_name);
643 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
649 virtual bool content(
int iline,
const String& sline)
override
653 throw Xml::ContentError(iline, sline,
"Invalid content; expected terminator");
656 std::deque<String> svals = sline.split_by_whitespaces();
659 if(svals.size() != std::size_t(_my_dim))
660 throw Xml::ContentError(iline, sline,
"Invalid number of values");
663 for(
int i(0); i < int(_my_dim); ++i)
665 if(!svals.at(std::size_t(i)).parse(_attrib->operator()(_read,i)))
666 throw Xml::ContentError(iline, sline,
"Failed to parse value");
676 template<
typename Mesh_>
679 template<
typename Shape_,
int num_coords_,
typename Coord_>
680 class MeshParser<ConformalMesh<Shape_, num_coords_, Coord_>> :
681 public Xml::MarkupParser
684 typedef ConformalMesh<Shape_, num_coords_, Coord_> MeshType;
687 RootMeshNode<MeshType>& _root_node;
688 std::unique_ptr<MeshType> _mesh;
690 std::deque<int> _have_topology;
691 std::vector<Index> _sizes;
693 template<
int shape_dim_>
694 static String aux_shape_string(
const Shape::Hypercube<shape_dim_>&)
699 template<
int shape_dim_>
700 static String aux_shape_string(
const Shape::Simplex<shape_dim_>&)
706 explicit MeshParser(RootMeshNode<MeshType>& root_node) :
707 _root_node(root_node),
713 virtual ~MeshParser()
717 virtual bool attribs(std::map<String,bool>& attrs)
const override
719 attrs.emplace(
"type",
true);
720 attrs.emplace(
"size",
true);
724 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool closed)
override
727 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
730 std::deque<String> stype = attrs.find(
"type")->second.split_by_string(
":");
733 if(stype.size() != std::size_t(4))
734 throw Xml::ContentError(iline, sline,
"Invalid mesh type attribue");
735 if(stype.at(0) !=
"conformal")
736 throw Xml::ContentError(iline, sline,
"Invalid mesh type; expected 'conformal'");
737 String sshape = aux_shape_string(Shape_());
738 if(stype.at(1) != sshape)
739 throw Xml::ContentError(iline, sline,
"Invalid mesh shape type; expected '" + sshape +
"'");
740 int ishape_dim(0), iworld_dim(0);
741 if(!stype.at(2).parse(ishape_dim))
742 throw Xml::ContentError(iline, sline,
"Failed to parse mesh shape dimension");
743 if(ishape_dim != Shape_::dimension)
744 throw Xml::ContentError(iline, sline,
"Invalid mesh shape dimension");
745 if(!stype.at(3).parse(iworld_dim))
746 throw Xml::ContentError(iline, sline,
"Failed to parse mesh world dimension");
747 if(iworld_dim != num_coords_)
748 throw Xml::ContentError(iline, sline,
"Invalid mesh world dimension");
753 std::deque<String> ssize = attrs.find(
"size")->second.split_by_whitespaces();
754 if(ssize.size() != std::size_t(Shape_::dimension+1))
755 throw Xml::ContentError(iline, sline,
"Invalid mesh size count");
758 _sizes.resize(ssize.size());
759 for(std::size_t i(0); i <= std::size_t(Shape_::dimension); ++i)
761 if(!ssize.at(i).parse(_sizes.at(i)))
762 throw Xml::ContentError(iline, sline,
"Failed to parse mesh size");
766 _mesh.reset(
new MeshType(_sizes.data()));
770 _have_topology.resize(std::size_t(Shape_::dimension), 0);
773 virtual void close(
int iline,
const String& sline)
override
777 throw Xml::GrammarError(iline, sline,
"Mesh has no Vertices");
780 for(std::size_t i(0); i < _have_topology.size(); ++i)
782 if(_have_topology.at(i) == 0)
783 throw Xml::GrammarError(iline, sline,
"Missing topology for dimension " +
stringify(i+1));
789 RedundantIndexSetBuilder<Shape_>::compute(*_mesh->get_topology());
792 _root_node.set_mesh(std::move(_mesh));
795 virtual std::shared_ptr<Xml::MarkupParser> markup(
int iline,
const String& sline,
const String& name)
override
798 if(name ==
"Vertices")
801 throw Xml::GrammarError(iline, sline,
"More than one Vertices block in mesh");
805 return std::make_shared<VerticesParser<num_coords_, Coord_>>(_mesh->get_vertex_set());
809 if(name ==
"Topology")
812 return std::make_shared<TopologyParser<Shape_>>(*_mesh->get_topology(), _have_topology);
819 virtual bool content(
int,
const String&)
override
825 template<
typename Mesh_>
826 class MeshPartParser;
828 template<
typename Shape_,
int num_coords_,
typename Coord_>
829 class MeshPartParser<ConformalMesh<Shape_, num_coords_, Coord_>> :
830 public Xml::MarkupParser
833 typedef ConformalMesh<Shape_, num_coords_, Coord_> MeshType;
834 typedef MeshPart<MeshType> MeshPartType;
835 typedef Atlas::ChartBase<MeshType> ChartType;
844 RootMeshNode<MeshType>& _root_node;
845 MeshNodeLinker<MeshType>& _linker;
846 std::unique_ptr<MeshPartType> _mesh_part;
849 String _name, _parent, _chart_name;
850 std::deque<int> _have_topology;
851 std::deque<int> _have_mapping;
852 std::vector<Index> _sizes;
855 explicit MeshPartParser(RootMeshNode<MeshType>& root_node, MeshNodeLinker<MeshType>& linker) :
856 _root_node(root_node),
860 _topo_type(TopoType::none)
864 virtual ~MeshPartParser()
868 virtual bool attribs(std::map<String,bool>& attrs)
const override
870 attrs.emplace(
"name",
true);
871 attrs.emplace(
"parent",
true);
872 attrs.emplace(
"size",
true);
873 attrs.emplace(
"topology",
true);
874 attrs.emplace(
"chart",
false);
878 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool closed)
override
881 throw Xml::GrammarError(iline, sline,
"Invalid closed markup");
884 _name = attrs.find(
"name")->second;
885 _parent = attrs.find(
"parent")->second;
888 if(_root_node.find_mesh_part(_name) !=
nullptr)
889 throw Xml::ContentError(iline, sline, String(
"Mesh Part '") + _name +
"' already exists in mesh node");
893 auto it = attrs.find(
"chart");
894 if(it != attrs.end())
897 _chart_name = it->second;
898 _linker.meshpart_link_to_chart(_name, _chart_name);
903 if(_parent !=
"root")
904 throw Xml::ContentError(iline, sline,
"Invalid mesh part parent; only 'root' is accepted");
907 String stopo_type = attrs.find(
"topology")->second;
908 if(stopo_type ==
"none")
909 _topo_type = TopoType::none;
910 else if(stopo_type ==
"full")
911 _topo_type = TopoType::full;
912 else if(stopo_type ==
"parent")
914 _topo_type = TopoType::parent;
915 _linker.meshpart_deduct_topology(_name);
918 throw Xml::ContentError(iline, sline,
"Invalid topology attribute '" + stopo_type +
"'");
921 std::deque<String> ssize = attrs.find(
"size")->second.split_by_whitespaces();
922 if(ssize.size() > std::size_t(Shape_::dimension+1))
923 throw Xml::ContentError(iline, sline,
"Invalid mesh part size count");
926 _sizes.resize(std::size_t(Shape_::dimension+1),
Index(0));
927 for(std::size_t i(0); i < ssize.size(); ++i)
929 if(!ssize.at(i).parse(_sizes.at(i)))
930 throw Xml::ContentError(iline, sline,
"Failed to parse mesh part size");
934 _mesh_part.reset(
new MeshPartType(_sizes.data(), _topo_type != TopoType::none));
937 _have_topology.resize(std::size_t(Shape_::dimension), 0);
938 _have_mapping.resize(std::size_t(Shape_::dimension+1), 0);
941 virtual void close(
int iline,
const String& sline)
override
944 for(std::size_t i(0); i < _have_mapping.size(); ++i)
946 if((_have_mapping.at(i) == 0) && (_sizes.at(i) >
Index(0)))
947 throw Xml::GrammarError(iline, sline,
"Missing mapping for dimension " +
stringify(i));
950 if(_topo_type == TopoType::full)
954 for(std::size_t i(0); i < _have_topology.size(); ++i)
957 if(_sizes.at(i+1) > 0)
958 topo_all = topo_all && (_have_topology.at(i) != 0);
963 throw Xml::GrammarError(iline, sline,
"Incomplete topology");
967 RedundantIndexSetBuilder<Shape_>::compute(*_mesh_part->get_topology());
969 else if(_topo_type == TopoType::parent)
978 _root_node.add_mesh_part(_name, std::move(_mesh_part));
981 virtual std::shared_ptr<Xml::MarkupParser> markup(
int iline,
const String& sline,
const String& name)
override
984 if(name ==
"Mapping")
987 return std::make_shared<MappingParser<Shape_>>(_mesh_part->get_target_set_holder(), _have_mapping);
991 if(name ==
"Topology")
993 if(_topo_type == TopoType::none)
994 throw Xml::ContentError(iline, sline,
"Unexpected Topology found");
997 return std::make_shared<TopologyParser<Shape_>>(*_mesh_part->get_topology(), _have_topology);
1001 if(name ==
"Attribute")
1003 return std::make_shared<AttributeParser<MeshPartType>>(*_mesh_part);
1010 virtual bool content(
int,
const String&)
override
1017 public Xml::MarkupParser
1020 Adjacency::DynamicGraph& _patches;
1026 explicit PatchParser(Adjacency::DynamicGraph& patches) :
1034 virtual bool attribs(std::map<String,bool>& attrs)
const override
1036 attrs.emplace(
"rank",
true);
1037 attrs.emplace(
"size",
true);
1041 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool)
override
1044 if(!attrs.find(
"rank")->second.parse(_rank))
1045 throw Xml::ContentError(iline, sline,
"Cannot parse patch rank index");
1046 if(!attrs.find(
"size")->second.parse(_size))
1047 throw Xml::ContentError(iline, sline,
"Cannot parse patch size");
1050 if(_rank >= _patches.get_num_nodes_domain())
1051 throw Xml::ContentError(iline, sline,
"Patch rank index is out of bounds");
1054 virtual void close(
int iline,
const String& sline)
override
1057 throw Xml::GrammarError(iline, sline,
"Invalid terminator; expected index");
1060 virtual bool content(
int iline,
const String& sline)
override
1064 throw Xml::ContentError(iline, sline,
"Invalid content; expected terminator");
1068 if(!sline.parse(elem))
1069 throw Xml::ContentError(iline, sline,
"Failed to parse element index");
1071 if(elem >= _patches.get_num_nodes_image())
1072 throw Xml::ContentError(iline, sline,
"Patch element index is out of bounds");
1075 _patches.insert(_rank, elem);
1083 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String&)
override
1089 class PartitionParser :
1090 public Xml::MarkupParser
1093 PartitionSet& _part_set;
1097 int _num_ranks, _num_elems;
1098 Adjacency::DynamicGraph _patches;
1101 explicit PartitionParser(PartitionSet& part_set) :
1102 _part_set(part_set),
1112 virtual bool attribs(std::map<String,bool>& attrs)
const override
1114 attrs.emplace(
"size",
true);
1115 attrs.emplace(
"name",
false);
1116 attrs.emplace(
"priority",
false);
1117 attrs.emplace(
"level",
false);
1121 virtual void create(
int iline,
const String& sline,
const String&,
const std::map<String, String>& attrs,
bool)
override
1124 std::deque<String> ssize = attrs.find(
"size")->second.split_by_whitespaces();
1125 if(ssize.size() != std::size_t(2))
1126 throw Xml::ContentError(iline, sline,
"Invalid partition size");
1129 if(!ssize.front().parse(_num_ranks))
1130 throw Xml::ContentError(iline, sline,
"Failed to parse partition rank count");
1131 if(!ssize.back().parse(_num_elems))
1132 throw Xml::ContentError(iline, sline,
"Failed to parse partition element count");
1136 auto it = attrs.find(
"name");
1137 if(it != attrs.end())
1143 auto it = attrs.find(
"priority");
1144 if(it != attrs.end())
1146 if(!it->second.parse(_prio))
1147 throw Xml::ContentError(iline, sline,
"Cannot parse partition priority");
1153 auto it = attrs.find(
"level");
1154 if(it != attrs.end())
1156 if(!it->second.parse(_level))
1157 throw Xml::ContentError(iline, sline,
"Cannot parse partition level");
1159 throw Xml::ContentError(iline, sline,
"Invalid negative partition level");
1164 _patches = Adjacency::DynamicGraph(
Index(_num_ranks),
Index(_num_elems));
1167 virtual void close(
int,
const String&)
override
1170 _part_set.add_partition(Partition(_patches, _name, _prio, _level));
1173 virtual bool content(
int,
const String&)
override
1178 virtual std::shared_ptr<MarkupParser> markup(
int,
const String&,
const String& name)
override
1181 return std::make_shared<PatchParser>(_patches);
1187 template<
typename RootMesh_>
1188 class MeshNodeParser :
1189 public Xml::MarkupParser
1192 typedef RootMesh_ RootMeshType;
1193 typedef RootMeshNode<RootMesh_> RootMeshNodeType;
1194 typedef MeshAtlas<RootMesh_> MeshAtlasType;
1198 RootMeshNodeType& _root_node;
1200 MeshAtlasType& _mesh_atlas;
1202 PartitionSet* _part_set;
1204 MeshNodeLinker<RootMesh_>& _linker;
1209 explicit MeshNodeParser(RootMeshNodeType& root_node, MeshAtlasType& mesh_atlas, PartitionSet* part_set, MeshNodeLinker<RootMesh_>& linker) :
1210 _root_node(root_node),
1211 _mesh_atlas(mesh_atlas),
1212 _part_set(part_set),
1218 virtual bool attribs(std::map<String,bool>& attrs)
const override
1220 attrs.emplace(
"version",
true);
1221 attrs.emplace(
"mesh",
false);
1225 virtual void create(
int iline,
const String& sline,
const String& name,
const std::map<String, String>& attrs,
bool)
override
1228 if(name !=
"FeatMeshFile")
1229 throw Xml::GrammarError(iline, sline,
"Invalid root markup; expected '<FeatMeshFile ...>'");
1233 if(!attrs.find(
"version")->second.parse(version))
1234 throw Xml::ContentError(iline, sline,
"Cannot parse file version");
1236 throw Xml::ContentError(iline, sline,
"Invalid file version; expected 1");
1239 auto it = attrs.find(
"mesh");
1240 if(it != attrs.end())
1243 _mesh_decl = it->second;
1247 virtual void close(
int,
const String&)
override
1251 virtual bool content(
int,
const String&)
override
1256 virtual std::shared_ptr<MarkupParser> markup(
int iline,
const String& sline,
const String& name)
override
1262 return std::make_shared<Xml::DummyParser>();
1267 return std::make_shared<ChartParser<RootMeshType>>(_mesh_atlas);
1271 if(_root_node.get_mesh() !=
nullptr)
1274 throw Xml::GrammarError(iline, sline,
"Invalid second Mesh in file");
1278 return std::make_shared<MeshParser<RootMeshType>>(_root_node);
1280 if(name ==
"MeshPart")
1283 return std::make_shared<MeshPartParser<RootMeshType>>(_root_node, _linker);
1285 if(name ==
"Partition")
1288 if(_part_set !=
nullptr)
1289 return std::make_shared<PartitionParser>(*_part_set);
1293 return std::make_shared<Xml::DummyParser>();
1348 std::deque<std::shared_ptr<std::stringstream>>
_streams;
1392 _scanners.push_back(std::make_shared<Xml::Scanner>(is));
1416 _scanners.push_back(std::make_shared<Xml::Scanner>(is));
1435 if(filenames.empty())
1439 if(!dirpath.empty())
1443 if((dirpath.back() !=
'/') && (dirpath.back() !=
'\\'))
1444 dirpath.push_back(
'\\');
1446 if(dirpath.back() !=
'/')
1447 dirpath.push_back(
'/');
1452 for(std::size_t i(0); i < filenames.size(); ++i)
1455 String filepath = dirpath + filenames.at(i);
1458 auto stream = std::make_shared<std::stringstream>();
1497 std::deque<String> filenames;
1498 filenames.push_back(filename);
1613 auto it_v = attr.find(
"version");
1614 if(it_v == attr.end())
1615 scanner.
throw_grammar(
"Mesh file is missing mandatory attribute 'version'");
1617 if(!(it_v->second.parse(iversion)))
1618 scanner.
throw_grammar(
"Failed to parse mesh file version attribute");
1623 auto it_m = attr.find(
"mesh");
1624 if(it_m != attr.end())
1640 if(mts.size() != std::size_t(4))
1641 scanner.
throw_grammar(
"Mesh file root markup has invalid 'mesh' attribute");
1644 if(mts.at(0) ==
"conformal")
1647 scanner.
throw_grammar(
"Invalid 'mesh' attribute mesh type");
1650 if(mts.at(1) ==
"simplex")
1652 else if(mts.at(1) ==
"hypercube")
1655 scanner.
throw_grammar(
"Invalid 'mesh' attribute shape type");
1658 if(!mts.at(2).parse(_shape_dim) || (_shape_dim <= 0))
1659 scanner.
throw_content(
"Invalid 'mesh' attribute shape dimension");
1662 if(!mts.at(3).parse(_world_dim) || (_world_dim <= 0))
1663 scanner.
throw_content(
"Invalid 'mesh' attribute world dimension");
1691 template<
typename RootMesh_>
1706 (*it)->set_root_parser(std::make_shared<MeshNodeParser<RootMesh_>>(root_mesh_node, mesh_atlas, part_set, linker));
1725 template<
typename RootMesh_>
1735 parse(linker, root_mesh_node, mesh_atlas, part_set);
1756 template<
typename RootMesh_>
1757 std::unique_ptr<RootMeshNode<RootMesh_>>
parse(
1762 std::unique_ptr<RootMeshNode<RootMesh_>> root_mesh_node =
1766 this->
parse(*root_mesh_node, mesh_atlas, part_set);
1769 return root_mesh_node;
1787 template<
typename RootMesh_,
int world_dim>
1790 static_assert(RootMesh_::world_dim == world_dim,
"Nonmatching world_dim.");
1810 template<
typename RootMesh_>
1811 struct DimensionalChartHelper<RootMesh_,2>
1813 static std::shared_ptr<Xml::MarkupParser>
markup(
const String& name,
1814 std::unique_ptr<Atlas::ChartBase<RootMesh_>>& chart)
1816 if(name ==
"Circle")
1817 return std::make_shared<Atlas::CircleChartParser<RootMesh_>>(chart);
1818 if(name ==
"Bezier")
1819 return std::make_shared<Atlas::BezierChartParser<RootMesh_>>(chart);
1825 template<
typename RootMesh_>
1826 struct DimensionalChartHelper<RootMesh_,3>
1828 static std::shared_ptr<Xml::MarkupParser>
markup(
const String& name,
1829 std::unique_ptr<Atlas::ChartBase<RootMesh_>>& chart)
1831 if(name ==
"Sphere")
1832 return std::make_shared<Atlas::SphereChartParser<RootMesh_>>(chart);
1833 if(name ==
"SurfaceMesh")
1834 return std::make_shared<Atlas::SurfaceMeshChartParser<RootMesh_>>(chart);
1835 if(name ==
"Extrude")
1836 return std::make_shared<Atlas::ExtrudeChartParser<RootMesh_>>(chart);
1844 extern template class MeshNodeLinker<ConformalMesh<Shape::Simplex<2>, 2,
Real>>;
1845 extern template class MeshNodeLinker<ConformalMesh<Shape::Simplex<3>, 3,
Real>>;
1846 extern template class MeshNodeLinker<ConformalMesh<Shape::Hypercube<2>, 2,
Real>>;
1847 extern template class MeshNodeLinker<ConformalMesh<Shape::Hypercube<3>, 3,
Real>>;
1849 extern template void MeshFileReader::parse<ConformalMesh<Shape::Simplex<2>, 2,
Real>>(
1850 MeshNodeLinker<ConformalMesh<Shape::Simplex<2>, 2,
Real>>&,
1851 RootMeshNode<ConformalMesh<Shape::Simplex<2>, 2,
Real>>&,
1852 MeshAtlas<ConformalMesh<Shape::Simplex<2>, 2,
Real>>&,
1854 extern template void MeshFileReader::parse<ConformalMesh<Shape::Simplex<3>, 3,
Real>>(
1855 MeshNodeLinker<ConformalMesh<Shape::Simplex<3>, 3,
Real>>&,
1856 RootMeshNode<ConformalMesh<Shape::Simplex<3>, 3,
Real>>&,
1857 MeshAtlas<ConformalMesh<Shape::Simplex<3>, 3,
Real>>&,
1859 extern template void MeshFileReader::parse<ConformalMesh<Shape::Hypercube<2>, 2,
Real>>(
1860 MeshNodeLinker<ConformalMesh<Shape::Hypercube<2>, 2,
Real>>&,
1861 RootMeshNode<ConformalMesh<Shape::Hypercube<2>, 2,
Real>>&,
1862 MeshAtlas<ConformalMesh<Shape::Hypercube<2>, 2,
Real>>&,
1864 extern template void MeshFileReader::parse<ConformalMesh<Shape::Hypercube<3>, 3,
Real>>(
1865 MeshNodeLinker<ConformalMesh<Shape::Hypercube<3>, 3,
Real>>&,
1866 RootMeshNode<ConformalMesh<Shape::Hypercube<3>, 3,
Real>>&,
1867 MeshAtlas<ConformalMesh<Shape::Hypercube<3>, 3,
Real>>&,
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
static Comm world()
Returns a copy of the world communicator.
static void read_common(std::stringstream &stream, const String &filename, const Dist::Comm &comm, int root_rank=0)
Reads a common text file for all ranks.
Mesh Atlas class template.
MeshChartType * find_mesh_chart(const String &name)
Searches for a mesh chart.
void add_mesh_files(const Dist::Comm &comm, const std::deque< String > &filenames, String dirpath="")
Adds a list of mesh files to the list of streams to be parsed.
void add_mesh_file(const String &filename)
Adds a single mesh file to the list of streams to be parsed.
MeshFileReader(std::istream &is)
Input-Stream constructor.
const String & get_meshtype_string() const
Returns the mesh-type string from the root markup node.
ShapeType
shape type enumeration
@ simplex
simplex shape type
@ hypercube
hypercube shape type
int get_shape_dim() const
Returns the shape-dimension from the root markup node.
virtual ~MeshFileReader()
virtual destructor
MeshFileReader()
default constructor
void parse(MeshNodeLinker< RootMesh_ > &linker, RootMeshNode< RootMesh_ > &root_mesh_node, MeshAtlas< RootMesh_ > &mesh_atlas, PartitionSet *part_set=nullptr)
Parses the mesh file into a mesh node and a mesh atlas.
void parse(RootMeshNode< RootMesh_ > &root_mesh_node, MeshAtlas< RootMesh_ > &mesh_atlas, PartitionSet *part_set=nullptr)
Parses the mesh file into a mesh node and a mesh atlas.
ShapeType get_shape_type() const
Returns the shape-type from the root markup node.
void add_mesh_file(const Dist::Comm &comm, const String &filename)
Adds a single mesh file to the list of streams to be parsed.
MeshType
mesh type enumeration
@ unknown
unknown mesh type
@ conformal
conformal mesh type
String _mesh_type_string
The parsed mesh type.
std::deque< std::shared_ptr< std::stringstream > > _streams
Our internally managed streams.
MeshType get_mesh_type() const
Returns the mesh-type from the root markup node.
void add_mesh_files(const std::deque< String > &filenames, String dirpath="")
Adds a list of mesh files to the list of streams to be parsed.
void add_stream(std::istream &is)
Adds an input stream to the list of streams to be parsed.
int get_world_dim() const
Returns the world-dimension from the root markup node.
std::deque< std::shared_ptr< Xml::Scanner > > _scanners
Our Xml scanner objects.
std::unique_ptr< RootMeshNode< RootMesh_ > > parse(MeshAtlas< RootMesh_ > &mesh_atlas, PartitionSet *part_set=nullptr)
Parses the mesh file into a mesh node and a mesh atlas.
bool _have_root_markup
Did we read the root markup yet?
void read_root_markup()
Reads the root markup from the input stream and analyses it.
MeshNodeLinker Error class.
MeshNode liner class template.
void meshpart_deduct_topology(const String &meshpart)
Adds a task to deduct a meshpart topology from the root mesh.
MeshAtlas< RootMesh_ > & _atlas
our atlas
RootMeshNode< RootMesh_ > & _mesh_node
our mesh node
void meshpart_link_to_chart(const String &meshpart, const String &chart)
Adds a task to link a meshpart to a chart.
void execute()
Executes the linker.
MeshNodeLinker(RootMeshNode< RootMesh_ > &mesh_node, MeshAtlas< RootMesh_ > &atlas)
Constructor.
Class template for partial meshes.
void deduct_topology(const ParentIndexSetHolderType &parent_ish)
Fills the mesh topology from parent information.
Root mesh node class template.
static std::unique_ptr< RootMeshNode > make_unique(std::unique_ptr< MeshType > mesh, MeshAtlasType *atlas=nullptr)
Creates a new RootMeshNode on the heap and returns a unique pointer to it.
String class implementation.
std::deque< String > split_by_string(const String &delimiter) const
Splits the string by a delimiter substring.
String trim(const String &charset) const
Trims the string.
XML Markup Parser interface.
void read_root()
Tries to read the XML root markup.
void throw_content(const String &msg) const
Throws a ContentError for the current line.
void throw_grammar(const String &msg) const
Throws a GrammarError for the current line.
const std::map< String, String > & get_cur_attribs() const
const String & get_cur_name() const
@ parent
indicates that the level is a parent level
@ full
full Uzawa preconditioner
double Real
Real data type.
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.
World dimension dependent helper class for parsing charts.
static std::shared_ptr< Xml::MarkupParser > markup(const String &name, std::unique_ptr< Atlas::ChartBase< RootMesh_ > > &chart)
Creates a parser for a chart, its type identified by a name String.