LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
gmsh_file_v4_text.cc
1
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]] > size_t_ >
147 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" > omit[size_t_[reserve(_val, _1), _a = _1]] >
165 repeat(_a)[periodic_link_] > "$EndPeriodic";
166 periodic_links_.name("periodic_links");
167
168 // ghost elements:
169 ghost_element_ %= size_t_ > int_ >
170 omit[size_t_[reserve(at_c<2>(_val), _1), _a = _1]] >
171 repeat(_a)[int_];
172 ghost_element_.name("ghost_element");
173
174 ghost_elements_ %= "$GhostElements" >
175 omit[size_t_[reserve(_val, _1), _a = _1]] >
176 repeat(_a)[ghost_element_] > "$EndGhostElements";
177 ghost_elements_.name("ghost_elements");
178
179 // The whole file
180 entry_ %= *comment_ >> -(physical_name_vector_ >> *comment_) >> entities_ >>
181 *comment_ >> -(partitioned_entities_ >> *comment_) >> nodes_ >>
182 *comment_ >> elements_ >> *comment_ >>
183 -(periodic_links_ >> *comment_) >>
184 -(ghost_elements_ >> *comment_);
185 entry_.name("entry");
186
187 qi::on_error<qi::fail>(entry_, error_handler_(_1, _2, _3, _4));
188 }
189
190 qi::rule<ITERATOR, std::string(), ascii::space_type> quoted_string_;
191 qi::rule<ITERATOR, std::string()> start_comment_;
192 qi::rule<ITERATOR, qi::locals<std::string>, ascii::space_type> comment_;
193 qi::rule<ITERATOR, Eigen::Vector3d(), ascii::space_type> vec3_;
194 qi::rule<ITERATOR, std::vector<int>, qi::locals<std::size_t>,
195 ascii::space_type>
196 int_vec_;
197
198 qi::rule<ITERATOR, GMshFileV4::PhysicalName(), ascii::space_type>
199 physical_name_;
200 qi::rule<ITERATOR, std::vector<GMshFileV4::PhysicalName>(),
201 qi::locals<std::size_t>, ascii::space_type>
202 physical_name_vector_;
203
204 qi::rule<ITERATOR, boost::fusion::adapted::MshFileV4Adapted(),
205 ascii::space_type>
206 entry_;
207
208 qi::rule<ITERATOR, GMshFileV4::PointEntity(), ascii::space_type>
209 point_entity_;
210
211 qi::rule<ITERATOR, GMshFileV4::Entity(), ascii::space_type> entity_;
212
213 qi::rule<
214 ITERATOR,
215 std::tuple<
216 std::vector<GMshFileV4::PointEntity>, std::vector<GMshFileV4::Entity>,
217 std::vector<GMshFileV4::Entity>, std::vector<GMshFileV4::Entity>>(),
218 qi::locals<std::size_t, std::size_t, std::size_t, std::size_t>,
219 ascii::space_type>
220 entities_;
221
222 qi::rule<ITERATOR, std::vector<GMshFileV4::GhostEntity>(),
223 qi::locals<std::size_t>, ascii::space_type>
224 ghost_entities_;
225
226 qi::rule<ITERATOR, GMshFileV4::PartitionedPointEntity(), ascii::space_type>
227 partitioned_point_entity_;
228
229 qi::rule<ITERATOR, GMshFileV4::PartitionedEntity(), ascii::space_type>
230 partitioned_entity_;
231
232 qi::rule<ITERATOR,
233 std::tuple<std::vector<GMshFileV4::PartitionedPointEntity>,
234 std::vector<GMshFileV4::PartitionedEntity>,
235 std::vector<GMshFileV4::PartitionedEntity>,
236 std::vector<GMshFileV4::PartitionedEntity>>(),
237 qi::locals<std::size_t, std::size_t, std::size_t, std::size_t>,
238 ascii::space_type>
239 partitioned_entities2_;
240
241 qi::rule<ITERATOR, GMshFileV4::PartitionedEntities(), ascii::space_type>
242 partitioned_entities_;
243
244 qi::rule<ITERATOR, GMshFileV4::NodeBlock(),
245 qi::locals<std::size_t, std::size_t>, ascii::space_type>
246 node_block_;
247
248 qi::rule<ITERATOR, GMshFileV4::Nodes(), qi::locals<std::size_t>,
249 ascii::space_type>
250 nodes_;
251
252 qi::rule<ITERATOR, GMshFileV4::ElementBlock(), qi::locals<std::size_t>,
253 ascii::space_type>
254 element_block_;
255
256 qi::rule<ITERATOR, GMshFileV4::Elements(), qi::locals<std::size_t>,
257 ascii::space_type>
258 elements_;
259
260 qi::rule<ITERATOR, Eigen::Matrix4d, ascii::space_type> matrix4d_;
261
262 qi::rule<ITERATOR, GMshFileV4::PeriodicLink(), qi::locals<std::size_t>,
263 ascii::space_type>
264 periodic_link_;
265
266 qi::rule<ITERATOR, std::vector<GMshFileV4::PeriodicLink>(),
267 qi::locals<std::size_t>, ascii::space_type>
268 periodic_links_;
269
270 qi::rule<ITERATOR, GMshFileV4::GhostElement(), qi::locals<std::size_t>,
271 ascii::space_type>
272 ghost_element_;
273
274 qi::rule<ITERATOR, std::vector<GMshFileV4::GhostElement>(),
275 qi::locals<std::size_t>, ascii::space_type>
276 ghost_elements_;
277
278 struct ErrorHandler {
279 template <class, class, class, class>
280 struct result {
281 using type = void;
282 };
283
284 template <class FIRST, class LAST, class ERROR_POS, class WHAT>
285 void operator()(FIRST first, LAST last, ERROR_POS /*errorPos*/,
286 WHAT what) const {
287 std::string input(first, last);
288 if (input.length() > 40) {
289 input = input.substr(0, 40);
290 }
291 std::cout << "Error in MshFileV4! Expecting " << what << " here: \""
292 << input << "\"" << std::endl;
293 }
294 };
295 phoenix::function<ErrorHandler> error_handler_;
296};
297
298} // namespace
299
300namespace detail {
301bool ParseGmshFileV4Text(std::string::const_iterator begin,
302 std::string::const_iterator end, GMshFileV4* result) {
303 // Text file
304 MshV4GrammarText<std::string::const_iterator> grammar;
305 return qi::phrase_parse(begin, end, grammar, ascii::space, *result);
306}
307
308} // namespace detail
309
310} // namespace lf::io
Mesh input (from file) and output (in various formats) facilities.
Definition: gmsh_file_v2.cc:35