LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
gmsh_file_v4_text.cc
1
10
11#include "gmsh_file_v4_detail.h"
12
13namespace lf::io {
14
15namespace /*anonymous*/ {
16namespace qi = boost::spirit::qi;
17namespace ascii = boost::spirit::ascii;
18namespace phoenix = boost::phoenix;
19
20template <class ITERATOR>
21struct MshV4GrammarText
22 : qi::grammar<ITERATOR, boost::fusion::adapted::MshFileV4Adapted(),
23 ascii::space_type> {
24 MshV4GrammarText() : MshV4GrammarText::base_type(entry_, "Msh File") {
25 using phoenix::at_c;
26 using phoenix::push_back;
27 using phoenix::reserve;
28 using phoenix::val;
29 using qi::_val;
30 using qi::attr;
31 using qi::char_;
32 using qi::double_;
33 using qi::eps;
34 using qi::int_;
35 using qi::lexeme;
36 using qi::lit;
37 using qi::omit;
38 using qi::repeat;
39 using qi::labels::_1;
40 using qi::labels::_2;
41 using qi::labels::_3;
42 using qi::labels::_4;
43 using qi::labels::_a;
44 using qi::labels::_b;
45 using qi::labels::_c;
46 using qi::labels::_d;
47
48 auto size_t_ = qi::ulong_long;
49
50 // General Parsers:
51 quoted_string_ %= lexeme['"' >> +(char_ - '"') >> '"'];
52 quoted_string_.name("string");
53 vec3_ %= double_ > double_ > double_; // NOLINT(misc-redundant-expression)
54 int_vec_ %= omit[size_t_[(reserve(_val, _1), _a = _1)]] > repeat(_a)[int_];
55 start_comment_ %= !lit("$PhysicalNames") >> !lit("$Entities") >>
56 !lit("$PartitionedEntities") >> !lit("$Nodes") >>
57 !lit("$Elements") >> !lit("$Periodic") >>
58 !lit("$GhostElements") >>
59 (lit('$') >> (+(char_ - qi::eol)));
60 start_comment_.name("Start of Comment");
61 comment_ %= start_comment_[_a = qi::_1] > *(char_ - '$') >> "$End" >>
62 qi::string(_a);
63 comment_.name("comment");
64 qi::on_error<qi::fail>(comment_, error_handler_(_1, _2, _3, _4));
65
66 // Physical names
67 // NOLINTNEXTLINE(misc-redundant-expression)
68 physical_name_ %= int_ > int_ > quoted_string_;
69 physical_name_.name("Physical Name");
70 qi::on_error<qi::fail>(physical_name_, error_handler_(_1, _2, _3, _4));
71 physical_name_vector_ %= "$PhysicalNames" >
72 omit[size_t_[(reserve(_val, _1), _a = _1)]] >
73 repeat(_a)[physical_name_] > "$EndPhysicalNames";
74 physical_name_vector_.name("$PhyiscalNames");
75 /*qi::on_error<qi::fail>(physical_name_vector_,
76 error_handler_(_1, _2, _3, _4));*/
77
78 // entities:
79 point_entity_ %= int_ > vec3_ > int_vec_;
80 point_entity_.name("Point entity");
81
82 entity_ %= int_ > vec3_ > vec3_ > int_vec_ > int_vec_;
83 entity_.name("entity");
84
85 entities_ %= "$Entities" >
86 omit[size_t_[(reserve(phoenix::at_c<0>(_val), _1), _a = _1)]] >
87 omit[size_t_[(reserve(phoenix::at_c<1>(_val), _1), _b = _1)]] >
88 omit[size_t_[(reserve(phoenix::at_c<2>(_val), _1), _c = _1)]] >
89 omit[size_t_[(reserve(phoenix::at_c<3>(_val), _1), _d = _1)]] >
90 repeat(_a)[point_entity_] > repeat(_b)[entity_] >
91 repeat(_c)[entity_] > repeat(_d)[entity_] > "$EndEntities";
92 entities_.name("$Entities");
93 qi::on_error<qi::fail>(entities_, error_handler_(_1, _2, _3, _4));
94
95 // PartitionedEntities
96 ghost_entities_ %=
97 omit[size_t_[(reserve(_val, _1), _a = _1)]] >
98 repeat(_a)[int_ > int_]; // NOLINT(misc-redundant-expression)
99 ghost_entities_.name("ghost_entities");
100 partitioned_point_entity_ %=
101 int_ > int_ > int_ > int_vec_ > vec3_ > int_vec_; // NOLINT
102 partitioned_point_entity_.name("partitioned_point_entity");
103
104 // NOLINTNEXTLINE
105 partitioned_entity_ %= int_ > int_ > int_ > int_vec_ > vec3_ > vec3_ >
106 int_vec_ > int_vec_; // NOLINT
107 partitioned_entity_.name("partitioned_entity");
108
109 partitioned_entities2_ %=
110 omit[size_t_[(reserve(at_c<0>(_val), _1), _a = _1)]] >
111 omit[size_t_[(reserve(at_c<1>(_val), _1), _b = _1)]] >
112 omit[size_t_[(reserve(at_c<2>(_val), _1), _c = _1)]] >
113 omit[size_t_[(reserve(at_c<3>(_val), _1), _d = _1)]] >
114 repeat(_a)[partitioned_point_entity_] >
115 repeat(_b)[partitioned_entity_] > repeat(_c)[partitioned_entity_] >
116 repeat(_d)[partitioned_entity_];
117 partitioned_entities2_.name("partitioned_entities2");
118
119 partitioned_entities_ %= "$PartitionedEntities" > size_t_ >
120 ghost_entities_ > partitioned_entities2_ >
121 "$EndPartitionedEntities";
122 partitioned_entities_.name("partitioned_entities");
123
124 // nodes:
125 node_block_ %=
126 int_ > int_ > int_ > // NOLINT
127 omit[size_t_[(phoenix::resize(at_c<3>(_val), _1), _a = _1, _b = 0)]] >
128 omit[repeat(_a)[size_t_[at_c<0>(at_c<3>(_val)[_b++]) = _1]]] >
129 eps[_b = 0] >
130 omit[repeat(_a)[vec3_[at_c<1>(at_c<3>(_val)[_b++]) = _1]]];
131 node_block_.name("node_block");
132
133 nodes_ %= "$Nodes" > omit[size_t_[(reserve(at_c<3>(_val), _1), _a = _1)]] >
134 size_t_ > size_t_ > size_t_ > repeat(_a)[node_block_] >
135 "$EndNodes";
136 nodes_.name("nodes");
137
138 // elements:
139 element_block_ %=
140 int_ > int_ > int_ > // NOLINT
141 omit[size_t_[(reserve(at_c<3>(_val), _1), _a = _1)]] >
142 repeat(_a)[size_t_ > repeat(numNodesAdapted(at_c<2>(_val)))[size_t_]];
143 element_block_.name("element_block");
144
145 elements_ %= "$Elements" >
146 omit[size_t_[(reserve(at_c<3>(_val), _1), _a = _1)]] >
147 size_t_ > size_t_ > size_t_ > repeat(_a)[element_block_] >
148 "$EndElements";
149 elements_.name("elements");
150
151 // periodic link
152 // NOLINTNEXTLINE
153 matrix4d_ %= double_ > double_ > double_ > double_ > double_ > double_ >
154 double_ > double_ > double_ > double_ > double_ > double_ >
155 double_ > double_ > double_ > double_;
156 matrix4d_.name("matrix4d");
157
158 // NOLINTNEXTLINE
159 periodic_link_ %= int_ > int_ > int_ > ('0' | ("16" > matrix4d_)) >
160 omit[size_t_[(reserve(at_c<4>(_val), _1), _a = _1)]] >
161 repeat(_a)[size_t_ > size_t_];
162 periodic_link_.name("periodic_link");
163
164 periodic_links_ %= "$Periodic" >
165 omit[size_t_[(reserve(_val, _1), _a = _1)]] >
166 repeat(_a)[periodic_link_] > "$EndPeriodic";
167 periodic_links_.name("periodic_links");
168
169 // ghost elements:
170 ghost_element_ %= size_t_ > int_ >
171 omit[size_t_[(reserve(at_c<2>(_val), _1), _a = _1)]] >
172 repeat(_a)[int_];
173 ghost_element_.name("ghost_element");
174
175 ghost_elements_ %= "$GhostElements" >
176 omit[size_t_[(reserve(_val, _1), _a = _1)]] >
177 repeat(_a)[ghost_element_] > "$EndGhostElements";
178 ghost_elements_.name("ghost_elements");
179
180 // The whole file
181 entry_ %= *comment_ >> -(physical_name_vector_ >> *comment_) >> entities_ >>
182 *comment_ >> -(partitioned_entities_ >> *comment_) >> nodes_ >>
183 *comment_ >> elements_ >> *comment_ >>
184 -(periodic_links_ >> *comment_) >>
185 -(ghost_elements_ >> *comment_);
186 entry_.name("entry");
187
188 qi::on_error<qi::fail>(entry_, error_handler_(_1, _2, _3, _4));
189 }
190
191 qi::rule<ITERATOR, std::string(), ascii::space_type> quoted_string_;
192 qi::rule<ITERATOR, std::string()> start_comment_;
193 qi::rule<ITERATOR, qi::locals<std::string>, ascii::space_type> comment_;
194 qi::rule<ITERATOR, Eigen::Vector3d(), ascii::space_type> vec3_;
195 qi::rule<ITERATOR, std::vector<int>, qi::locals<std::size_t>,
196 ascii::space_type>
197 int_vec_;
198
199 qi::rule<ITERATOR, GMshFileV4::PhysicalName(), ascii::space_type>
200 physical_name_;
201 qi::rule<ITERATOR, std::vector<GMshFileV4::PhysicalName>(),
202 qi::locals<std::size_t>, ascii::space_type>
203 physical_name_vector_;
204
205 qi::rule<ITERATOR, boost::fusion::adapted::MshFileV4Adapted(),
206 ascii::space_type>
207 entry_;
208
209 qi::rule<ITERATOR, GMshFileV4::PointEntity(), ascii::space_type>
210 point_entity_;
211
212 qi::rule<ITERATOR, GMshFileV4::Entity(), ascii::space_type> entity_;
213
214 qi::rule<
215 ITERATOR,
216 std::tuple<
217 std::vector<GMshFileV4::PointEntity>, std::vector<GMshFileV4::Entity>,
218 std::vector<GMshFileV4::Entity>, std::vector<GMshFileV4::Entity>>(),
219 qi::locals<std::size_t, std::size_t, std::size_t, std::size_t>,
220 ascii::space_type>
221 entities_;
222
223 qi::rule<ITERATOR, std::vector<GMshFileV4::GhostEntity>(),
224 qi::locals<std::size_t>, ascii::space_type>
225 ghost_entities_;
226
227 qi::rule<ITERATOR, GMshFileV4::PartitionedPointEntity(), ascii::space_type>
228 partitioned_point_entity_;
229
230 qi::rule<ITERATOR, GMshFileV4::PartitionedEntity(), ascii::space_type>
231 partitioned_entity_;
232
233 qi::rule<ITERATOR,
234 std::tuple<std::vector<GMshFileV4::PartitionedPointEntity>,
235 std::vector<GMshFileV4::PartitionedEntity>,
236 std::vector<GMshFileV4::PartitionedEntity>,
237 std::vector<GMshFileV4::PartitionedEntity>>(),
238 qi::locals<std::size_t, std::size_t, std::size_t, std::size_t>,
239 ascii::space_type>
240 partitioned_entities2_;
241
242 qi::rule<ITERATOR, GMshFileV4::PartitionedEntities(), ascii::space_type>
243 partitioned_entities_;
244
245 qi::rule<ITERATOR, GMshFileV4::NodeBlock(),
246 qi::locals<std::size_t, std::size_t>, ascii::space_type>
247 node_block_;
248
249 qi::rule<ITERATOR, GMshFileV4::Nodes(), qi::locals<std::size_t>,
250 ascii::space_type>
251 nodes_;
252
253 qi::rule<ITERATOR, GMshFileV4::ElementBlock(), qi::locals<std::size_t>,
254 ascii::space_type>
255 element_block_;
256
257 qi::rule<ITERATOR, GMshFileV4::Elements(), qi::locals<std::size_t>,
258 ascii::space_type>
259 elements_;
260
261 qi::rule<ITERATOR, Eigen::Matrix4d, ascii::space_type> matrix4d_;
262
263 qi::rule<ITERATOR, GMshFileV4::PeriodicLink(), qi::locals<std::size_t>,
264 ascii::space_type>
265 periodic_link_;
266
267 qi::rule<ITERATOR, std::vector<GMshFileV4::PeriodicLink>(),
268 qi::locals<std::size_t>, ascii::space_type>
269 periodic_links_;
270
271 qi::rule<ITERATOR, GMshFileV4::GhostElement(), qi::locals<std::size_t>,
272 ascii::space_type>
273 ghost_element_;
274
275 qi::rule<ITERATOR, std::vector<GMshFileV4::GhostElement>(),
276 qi::locals<std::size_t>, ascii::space_type>
277 ghost_elements_;
278
279 struct ErrorHandler {
280 template <class, class, class, class>
281 struct result {
282 using type = void;
283 };
284
285 template <class FIRST, class LAST, class ERROR_POS, class WHAT>
286 void operator()(FIRST first, LAST last, ERROR_POS /*errorPos*/,
287 WHAT what) const {
288 std::string input(first, last);
289 if (input.length() > 40) {
290 input = input.substr(0, 40);
291 }
292 std::cout << "Error in MshFileV4! Expecting " << what << " here: \""
293 << input << "\"" << std::endl;
294 }
295 };
296 phoenix::function<ErrorHandler> error_handler_;
297};
298
299} // namespace
300
301namespace detail {
302bool ParseGmshFileV4Text(std::string::const_iterator begin,
303 std::string::const_iterator end, GMshFileV4* result) {
304 // Text file
305 const MshV4GrammarText<std::string::const_iterator> grammar;
306 return qi::phrase_parse(begin, end, grammar, ascii::space, *result);
307}
308
309} // namespace detail
310
311} // namespace lf::io
Mesh input (from file) and output (in various formats) facilities.