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