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