OGS
GocadSGridReader.cpp
Go to the documentation of this file.
1
10#include "GocadSGridReader.h"
11
12#include <algorithm>
13#include <boost/tokenizer.hpp>
14#include <cstddef>
15#include <fstream>
16#include <iostream>
17#include <sstream>
18
19#include "BaseLib/FileTools.h"
22#include "MeshLib/Mesh.h"
24
25namespace FileIO
26{
27namespace Gocad
28{
29using Bitset = boost::dynamic_bitset<>;
30
31GocadSGridReader::GocadSGridReader(std::string const& fname)
32 : _fname(fname),
33 _path(BaseLib::extractPath(fname)),
34 _n_face_sets(0),
35 _double_precision_binary(false),
36 _bin_pnts_in_double_precision(false)
37{
38 // check if file exists
39 std::ifstream in(_fname.c_str());
40 if (!in)
41 {
42 ERR("Could not open '{:s}'.", _fname);
43 in.close();
44 return;
45 }
46
47 bool pnts_read(false);
48
49 // read information in the stratigraphic grid file
50 std::string line;
51 while (std::getline(in, line))
52 {
53 if (line.empty()) // skip empty lines
54 {
55 continue;
56 }
57 if (line.back() == '\r') // check dos line ending
58 {
59 line.pop_back();
60 }
61 if (line.substr(0, 8) == "HEADER {")
62 {
63 parseHeader(in);
64 }
65 if (line.substr(0, 32) == "GOCAD_ORIGINAL_COORDINATE_SYSTEM")
66 {
68 continue;
69 }
70 if (line.substr(0, 7) == "AXIS_N ")
71 {
72 parseDims(line);
73 }
74 else if (line.substr(0, 12) == "POINTS_FILE ")
75 {
77 }
78 else if (line.substr(0, 9) == "PROPERTY ")
79 {
82 }
83 else if (line.substr(0, 35) == "BINARY_POINTS_IN_DOUBLE_PRECISION 1")
84 {
86 }
87 else if (line.substr(0, 11) == "FLAGS_FILE ")
88 {
90 }
91 else if (line.substr(0, 18) == "REGION_FLAGS_FILE ")
92 {
94 }
95 else if (line.substr(0, 7) == "REGION " ||
96 line.substr(0, 13) == "MODEL_REGION ")
97 {
98 regions.push_back(Gocad::parseRegion(line));
99 }
100 else if (line.substr(0, 12) == "MODEL_LAYER ")
101 {
102 layers.push_back(Gocad::parseLayer(line, regions));
103 }
104 else if (line.substr(0, 24) == "REGION_FLAGS_BIT_LENGTH ")
105 {
106 std::istringstream iss(line);
107 std::istream_iterator<std::string> it(iss);
108 it++;
109 std::size_t bit_length = std::atoi(it->c_str());
110 if (regions.size() != bit_length)
111 {
112 ERR("{:d} regions read but {:d} expected.\n", regions.size(),
113 bit_length);
114 throw std::runtime_error(
115 "Number of read regions differs from expected.\n");
116 }
117 }
118 else if (line.substr(0, 9) == "FACE_SET ")
119 {
120 // first read the points
121 if (!pnts_read)
122 {
124 pnts_read = true;
125 }
126 parseFaceSet(line, in);
127 }
128 }
129
130#ifndef NDEBUG
131 std::stringstream regions_ss;
132 regions_ss << regions.size() << " regions read:\n";
133 std::copy(regions.begin(), regions.end(),
134 std::ostream_iterator<Gocad::Region>(regions_ss, "\t"));
135 DBUG("{:s}", regions_ss.str());
136
137 std::stringstream layers_ss;
138 layers_ss << layers.size() << " layers read:\n";
139 std::copy(layers.begin(), layers.end(),
140 std::ostream_iterator<Gocad::Layer>(layers_ss, "\n"));
141 DBUG("{:s}", layers_ss.str());
142
143 std::stringstream properties_ss;
144 properties_ss << "meta data for " << _property_meta_data_vecs.size()
145 << " properties read:\n";
146 std::copy(_property_meta_data_vecs.begin(), _property_meta_data_vecs.end(),
147 std::ostream_iterator<Gocad::Property>(properties_ss, "\n"));
148 DBUG("{:s}", properties_ss.str());
149#endif
150
151 // if not done already read the points
152 if (!pnts_read)
153 {
155 }
157 std::vector<Bitset> region_flags = readRegionFlagsBinary();
158 mapRegionFlagsToCellProperties(region_flags);
159
161
162 in.close();
163}
164
166{
167 for (auto node : _nodes)
168 {
169 delete node;
170 }
171 for (auto node : _split_nodes)
172 {
173 delete node;
174 }
175}
176
177std::unique_ptr<MeshLib::Mesh> GocadSGridReader::getMesh() const
178{
179 std::vector<MeshLib::Node*> nodes;
180 std::transform(_nodes.cbegin(), _nodes.cend(), std::back_inserter(nodes),
181 [](MeshLib::Node const* const node)
182 { return new MeshLib::Node(*node); });
183
184 std::vector<MeshLib::Element*> elements(createElements(nodes));
185 applySplitInformation(nodes, elements);
186
187 DBUG("Creating mesh from Gocad SGrid.");
188 std::unique_ptr<MeshLib::Mesh> mesh(new MeshLib::Mesh(
190 true /* compute_element_neighbors */));
192 DBUG("Mesh created.");
193
194 return mesh;
195}
196
198{
199 std::vector<std::string> const& prop_names(getPropertyNames());
200 for (auto const& name : prop_names)
201 {
202 auto prop = getProperty(name);
203 if (!prop)
204 {
205 continue;
206 }
207
208 DBUG("Adding Gocad property '{:s}' with {:d} values.", name,
209 prop->_property_data.size());
210
211 auto pv = MeshLib::getOrCreateMeshProperty<double>(
212 mesh, name, MeshLib::MeshItemType::Cell, 1);
213 if (pv == nullptr)
214 {
215 ERR("Could not create mesh property '{:s}'.", name);
216 continue;
217 }
218
219 pv->resize(prop->_property_data.size());
220 std::copy(prop->_property_data.cbegin(), prop->_property_data.cend(),
221 pv->begin());
222 }
223}
224
225void GocadSGridReader::parseHeader(std::istream& in)
226{
227 std::string line;
228 while (std::getline(in, line))
229 {
230 if (line.front() == '}')
231 {
232 return;
233 }
234 if (line.substr(0, 27) == "double_precision_binary: on")
235 {
237 }
238 }
240 {
241 DBUG(
242 "GocadSGridReader::parseHeader(): _double_precision_binary == "
243 "true.");
244 }
245}
246
247void GocadSGridReader::parseDims(std::string const& line)
248{
249 std::size_t x_dim(0);
250 std::size_t y_dim(0);
251 std::size_t z_dim(0);
252 boost::tokenizer<> tok(line);
253 auto it(tok.begin());
254 it++; // overread token "AXIS"
255 it++; // overread "N"
256 std::stringstream ssx(*(it),
257 std::stringstream::in | std::stringstream::out);
258 ssx >> x_dim;
259 it++;
260 std::stringstream ssy(*it, std::stringstream::in | std::stringstream::out);
261 ssy >> y_dim;
262 it++;
263 std::stringstream ssz(*it, std::stringstream::in | std::stringstream::out);
264 ssz >> z_dim;
265 _index_calculator = Gocad::IndexCalculator(x_dim, y_dim, z_dim);
266 DBUG(
267 "x_dim = {:d}, y_dim = {:d}, z_dim = {:d} => #nodes = {:d}, #cells = "
268 "{:d}",
269 x_dim, y_dim, z_dim, _index_calculator._n_nodes,
271}
272
273void GocadSGridReader::parseFileName(std::string const& line,
274 std::string& result_string) const
275{
276 boost::char_separator<char> sep(" \r");
277 boost::tokenizer<boost::char_separator<char>> tok(line, sep);
278 auto it(tok.begin());
279 ++it; // overread POINTS_FILE or FLAGS_FILE or REGION_FLAGS_FILE
280 result_string = _path + *it;
281}
282
287void GocadSGridReader::parseFaceSet(std::string& line, std::istream& in)
288{
289 // create and initialize a Gocad::Property object for storing face set data
290 Gocad::Property face_set_property;
291 face_set_property._property_id = _n_face_sets;
292 face_set_property._property_name = "FaceSet";
293 face_set_property._property_class_name = "FaceSetData";
294 face_set_property._property_unit = "unitless";
295 face_set_property._property_data_type = "double";
296 face_set_property._property_data_fname = "";
297 face_set_property._property_no_data_value = -1.0;
298 face_set_property._property_data.resize(_index_calculator._n_cells);
299 std::fill(face_set_property._property_data.begin(),
300 face_set_property._property_data.end(),
301 face_set_property._property_no_data_value);
302
303 std::istringstream iss(line);
304 std::istream_iterator<std::string> it(iss);
305 // Check first word is FACE_SET
306 if (*it != std::string("FACE_SET"))
307 {
308 ERR("Expected FACE_SET keyword but '{:s}' found.", it->c_str());
309 throw std::runtime_error(
310 "In GocadSGridReader::parseFaceSet() expected FACE_SET keyword not "
311 "found.");
312 }
313 ++it;
314 face_set_property._property_name += *it;
315 ++it;
316 auto const n_of_face_set_ids(
317 static_cast<std::size_t>(std::atoi(it->c_str())));
318 std::size_t face_set_id_cnt(0);
319
320 while (std::getline(in, line) && face_set_id_cnt < n_of_face_set_ids)
321 {
322 if (line.back() == '\r')
323 {
324 line.pop_back();
325 }
326 boost::char_separator<char> sep("\t ");
327 boost::tokenizer<boost::char_separator<char>> tokens(line, sep);
328
329 for (auto tok_it = tokens.begin(); tok_it != tokens.end();)
330 {
331 auto const id(static_cast<std::size_t>(std::atoi(tok_it->c_str())));
332 tok_it++;
333 auto const face_indicator(
334 static_cast<std::size_t>(std::atoi(tok_it->c_str())));
335 tok_it++;
336
337 if (id >= _index_calculator._n_nodes)
338 {
339 ERR("Face set id {:d} is greater than the number of nodes "
340 "({:d}).",
342 }
343 else
344 {
345 static_cast<GocadNode*>(_nodes[id])
346 ->setFaceSet(_n_face_sets, face_indicator);
347 std::array<std::size_t, 3> const c(
349 if (c[0] >= _index_calculator._x_dim - 1)
350 {
351 ERR("****** i coord {:d} to big for id {:d}.", c[0], id);
352 }
353 if (c[1] >= _index_calculator._y_dim - 1)
354 {
355 ERR("****** j coord {:d} to big for id {:d}.", c[1], id);
356 }
357 if (c[2] >= _index_calculator._z_dim - 1)
358 {
359 ERR("****** k coord {:d} to big for id {:d}.", c[2], id);
360 }
361 std::size_t const cell_id(
362 _index_calculator.getCellIdx(c[0], c[1], c[2]));
363 face_set_property._property_data[cell_id] =
364 static_cast<double>(face_indicator);
365 }
366 face_set_id_cnt++;
367 }
368 }
369
370 if (face_set_id_cnt != n_of_face_set_ids)
371 {
372 ERR("Expected {:d} number of face set ids, read {:d}.",
373 n_of_face_set_ids, face_set_id_cnt);
374 throw std::runtime_error(
375 "Expected number of face set points does not match number of read "
376 "points.");
377 }
378 _n_face_sets++;
379
380 // pre condition: split nodes are read already
381 for (auto split_node : _split_nodes)
382 {
383 std::size_t const id(_index_calculator(split_node->getGridCoords()));
384 split_node->transmitFaceDirections(*_nodes[id]);
385 }
386
387 _property_meta_data_vecs.push_back(face_set_property);
388}
389
390// Reads given number of bits (rounded up to next byte) into a bitset.
391// Used for reading region information which can be represented by some
392// number of bits.
393Bitset readBits(std::ifstream& in, const std::size_t bits)
394{
395 using block_t = Bitset::block_type;
396 auto const bytes = static_cast<std::size_t>(std::ceil(bits / 8.));
397 std::size_t const blocks =
398 bytes + 1 < sizeof(block_t) ? 1 : (bytes + 1) / sizeof(block_t);
399
400 std::vector<block_t> data;
401 data.resize(blocks);
402 std::fill_n(data.data(), blocks, 0);
403 in.read(reinterpret_cast<char*>(data.data()), bytes);
404
405 return Bitset(data.begin(), data.end());
406}
407
409{
410 std::ifstream in(_pnts_fname.c_str(), std::ios::binary);
411 if (!in)
412 {
413 ERR("Could not open points file '{:s}'.", _pnts_fname);
414 throw std::runtime_error("Could not open points file.");
415 }
416
417 std::size_t const n = _index_calculator._n_nodes;
418 _nodes.resize(n);
419
420 double coords[3];
421
422 std::size_t k = 0;
423 while (in && k < n * 3)
424 {
426 {
427 coords[k % 3] =
429 }
430 else
431 {
432 coords[k % 3] =
434 }
435 if ((k + 1) % 3 == 0)
436 {
437 const std::size_t layer_transition_idx(
439 _nodes[k / 3] = new GocadNode(coords, k / 3, layer_transition_idx);
440 }
441 k++;
442 }
443 if (k != n * 3 && !in.eof())
444 {
445 ERR("Read different number of points. Expected {:d} floats, got "
446 "{:d}.\n",
447 n * 3, k);
448 }
449}
450
452 std::vector<Bitset> const& rf)
453{
454 DBUG(
455 "GocadSGridReader::mapRegionFlagsToCellProperties region_flags.size: "
456 "{:d}",
457 rf.size());
458
459 Gocad::Property region_flags;
460 region_flags._property_id = 0;
461 region_flags._property_name = "RegionFlags";
462 region_flags._property_class_name = "RegionFlags";
463 region_flags._property_unit = "unitless";
464 region_flags._property_data_type = "int";
465 region_flags._property_data_fname = "";
466 region_flags._property_no_data_value = -1;
467 std::size_t const n = _index_calculator._n_cells;
468 region_flags._property_data.resize(n);
469 std::fill(region_flags._property_data.begin(),
470 region_flags._property_data.end(), -1);
471
472 // region flags are stored in each node ijk and give the region index for
473 // the ijk-th cell.
474 for (std::size_t i(0); i < _index_calculator._x_dim - 1; i++)
475 {
476 for (std::size_t j(0); j < _index_calculator._y_dim - 1; j++)
477 {
478 for (std::size_t k(0); k < _index_calculator._z_dim - 1; k++)
479 {
480 std::size_t const cell_id(
482 std::size_t const node_id(_index_calculator({i, j, k}));
483 for (auto& region : regions)
484 {
485 if (rf[node_id].test(region.bit))
486 {
487 region_flags._property_data[cell_id] += region.bit + 1;
488 }
489 }
490 }
491 }
492 }
493
494 _property_meta_data_vecs.push_back(region_flags);
495}
496
498{
499 for (auto& property : _property_meta_data_vecs)
500 {
501 std::string const& fname(property._property_data_fname);
502 if (property._property_data_fname.empty())
503 {
504 WARN("Empty filename for property {:s}.", property._property_name);
505 continue;
506 }
507 std::vector<float> float_properties =
509 DBUG(
510 "GocadSGridReader::readElementPropertiesBinary(): Read {:d} float "
511 "properties from binary file.",
513
514 std::transform(float_properties.cbegin(), float_properties.cend(),
515 float_properties.begin(),
516 [](float const& val)
517 { return BaseLib::swapEndianness(val); });
518
519 property._property_data.resize(float_properties.size());
520 std::copy(float_properties.begin(), float_properties.end(),
521 property._property_data.begin());
522 if (property._property_data.empty())
523 {
524 ERR("Reading of element properties file '{:s}' failed.", fname);
525 }
526 }
527}
528
530{
531 std::vector<Bitset> result;
532
533 std::ifstream in(_region_flags_fname.c_str());
534 if (!in)
535 {
536 ERR("readRegionFlagsBinary(): Could not open file '{:s}' for input.\n",
538 in.close();
539 return result;
540 }
541
542 std::size_t const n = _index_calculator._n_nodes;
543 result.resize(n);
544
545 std::size_t k = 0;
546 while (in && k < n)
547 {
548 result[k++] = readBits(in, regions.size());
549 }
550 if (k != n && !in.eof())
551 {
552 ERR("Read different number of values. Expected {:d}, got {:d}.\n", n,
553 k);
554 }
555 return result;
556}
557std::vector<MeshLib::Element*> GocadSGridReader::createElements(
558 std::vector<MeshLib::Node*> const& nodes) const
559{
560 std::vector<MeshLib::Element*> elements;
561 elements.resize(_index_calculator._n_cells);
562 std::array<MeshLib::Node*, 8> element_nodes{};
563 std::size_t cnt(0);
564 for (std::size_t k(0); k < _index_calculator._z_dim - 1; k++)
565 {
566 for (std::size_t j(0); j < _index_calculator._y_dim - 1; j++)
567 {
568 for (std::size_t i(0); i < _index_calculator._x_dim - 1; i++)
569 {
570 element_nodes[0] = nodes[_index_calculator({i, j, k})];
571 element_nodes[1] = nodes[_index_calculator({i + 1, j, k})];
572 element_nodes[2] = nodes[_index_calculator({i + 1, j + 1, k})];
573 element_nodes[3] = nodes[_index_calculator({i, j + 1, k})];
574 element_nodes[4] = nodes[_index_calculator({i, j, k + 1})];
575 element_nodes[5] = nodes[_index_calculator({i + 1, j, k + 1})];
576 element_nodes[6] =
577 nodes[_index_calculator({i + 1, j + 1, k + 1})];
578 element_nodes[7] = nodes[_index_calculator({i, j + 1, k + 1})];
579 elements[cnt] = new MeshLib::Hex(
580 element_nodes, _index_calculator.getCellIdx(i, j, k));
581 cnt++;
582 }
583 }
584 }
585 return elements;
586}
587
589{
590 std::ifstream in(_fname.c_str());
591 if (!in)
592 {
593 ERR("Could not open '{:s}'.", _fname);
594 in.close();
595 return;
596 }
597
598 // read split information from the stratigraphic grid file
599 std::string line;
600 std::stringstream ss;
601 while (std::getline(in, line))
602 {
603 std::size_t pos(line.find("SPLIT "));
604 if (pos != std::string::npos)
605 {
606 ss << line.substr(pos + 6, line.size() - (pos + 6));
607 // read position in grid
608 std::array<std::size_t, 3> grid_coords{};
609 ss >> grid_coords[0];
610 ss >> grid_coords[1];
611 ss >> grid_coords[2];
612 // read coordinates for the split node
613 double coords[3];
614 ss >> coords[0];
615 ss >> coords[1];
616 ss >> coords[2];
617 // read the id
618 std::size_t id;
619 ss >> id;
620 // read the affected cells
621 std::bitset<8> affected_cells{};
622 for (std::size_t ac = 0; ac < 8; ++ac)
623 {
624 char bit;
625 ss >> bit;
626 affected_cells[ac] = bit != '0';
627 }
628 const std::size_t layer_transition_index(
629 _nodes[id]->getLayerTransitionIndex());
630 _split_nodes.push_back(new GocadSplitNode(coords, id, grid_coords,
631 affected_cells,
632 layer_transition_index));
633 }
634 }
635}
636
638 std::vector<MeshLib::Node*>& nodes,
639 std::vector<MeshLib::Element*> const& elements) const
640{
641 for (auto split_node : _split_nodes)
642 {
643 std::size_t const new_node_pos(nodes.size());
644 nodes.push_back(new MeshLib::Node(split_node->data(), new_node_pos));
645
646 // get grid coordinates
647 std::array<std::size_t, 3> const& gc(split_node->getGridCoords());
648 // get affected cells
649 auto const& affected_cells(split_node->getAffectedCells());
650 // get mesh node to substitute in elements
651 MeshLib::Node const* const node2sub(nodes[_index_calculator(gc)]);
652
653 if (affected_cells[0] && gc[0] < _index_calculator._x_dim - 1 &&
654 gc[1] < _index_calculator._y_dim - 1 &&
655 gc[2] < _index_calculator._z_dim - 1)
656 {
657 const std::size_t idx(
658 _index_calculator.getCellIdx(gc[0], gc[1], gc[2]));
659 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
660 }
661 if (affected_cells[1] && gc[0] > 0 &&
662 gc[1] < _index_calculator._y_dim - 1 &&
663 gc[2] < _index_calculator._z_dim - 1)
664 {
665 const std::size_t idx(
666 _index_calculator.getCellIdx(gc[0] - 1, gc[1], gc[2]));
667 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
668 }
669 if (affected_cells[2] && gc[1] > 0 &&
670 gc[0] < _index_calculator._x_dim - 1 &&
671 gc[2] < _index_calculator._z_dim - 1)
672 {
673 const std::size_t idx(
674 _index_calculator.getCellIdx(gc[0], gc[1] - 1, gc[2]));
675 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
676 }
677 if (affected_cells[3] && gc[0] > 0 && gc[1] > 0 &&
678 gc[2] < _index_calculator._z_dim - 1)
679 {
680 const std::size_t idx(
681 _index_calculator.getCellIdx(gc[0] - 1, gc[1] - 1, gc[2]));
682 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
683 }
684 if (affected_cells[4] && gc[2] > 0 &&
685 gc[0] < _index_calculator._x_dim - 1 &&
686 gc[1] < _index_calculator._y_dim - 1)
687 {
688 const std::size_t idx(
689 _index_calculator.getCellIdx(gc[0], gc[1], gc[2] - 1));
690 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
691 }
692 if (affected_cells[5] && gc[0] > 0 && gc[2] > 0 &&
693 gc[1] < _index_calculator._y_dim - 1)
694 {
695 const std::size_t idx(
696 _index_calculator.getCellIdx(gc[0] - 1, gc[1], gc[2] - 1));
697 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
698 }
699 if (affected_cells[6] && gc[1] > 0 && gc[2] > 0 &&
700 gc[0] < _index_calculator._x_dim - 1)
701 {
702 const std::size_t idx(
703 _index_calculator.getCellIdx(gc[0], gc[1] - 1, gc[2] - 1));
704 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
705 }
706 if (affected_cells[7] && gc[0] > 0 && gc[1] > 0 && gc[2] > 0)
707 {
708 const std::size_t idx(
709 _index_calculator.getCellIdx(gc[0] - 1, gc[1] - 1, gc[2] - 1));
710 modifyElement(elements[idx], node2sub, nodes[new_node_pos]);
711 }
712 }
713}
714
716 MeshLib::Node const* const node2sub,
717 MeshLib::Node* const substitute_node)
718{
719 // get the node pointers of the cell
720 MeshLib::Node* const* hex_nodes(hex->getNodes());
721 // search for the position the split node will be set to
722 MeshLib::Node* const* node_pos(
723 std::find(hex_nodes, hex_nodes + 8, node2sub));
724 // set the split node instead of the node2sub
725 if (node_pos != hex_nodes + 8)
726 {
727 const_cast<MeshLib::Node**>(
728 hex_nodes)[std::distance(hex_nodes, node_pos)] = substitute_node;
729 }
730}
731
733 std::string const& name) const
734{
735 auto const it(std::find_if(_property_meta_data_vecs.begin(),
737 [&name](Gocad::Property const& p)
738 { return p._property_name == name; }));
739 if (it == _property_meta_data_vecs.end())
740 {
741 return nullptr;
742 }
743 return &*it;
744}
745
746std::vector<std::string> GocadSGridReader::getPropertyNames() const
747{
748 std::vector<std::string> names;
749 std::transform(_property_meta_data_vecs.begin(),
751 std::back_inserter(names),
752 [](Gocad::Property const& p) { return p._property_name; });
753 return names;
754}
755
756std::unique_ptr<MeshLib::Mesh> GocadSGridReader::getFaceSetMesh(
757 std::size_t const face_set_number) const
758{
759 std::vector<MeshLib::Node*> face_set_nodes;
760 std::vector<MeshLib::Element*> face_set_elements;
761
762 for (auto const node : _nodes)
763 {
764 if (node->isMemberOfFaceSet(face_set_number))
765 {
766 addFaceSetQuad(node, face_set_number, face_set_nodes,
767 face_set_elements);
768 }
769 }
770
771 if (face_set_nodes.empty())
772 {
773 return nullptr;
774 }
775
776 for (auto const node : _split_nodes)
777 {
778 if (node->isMemberOfFaceSet(face_set_number))
779 {
780 if (node->getAffectedCells()[0])
781 {
782 addFaceSetQuad(node, face_set_number, face_set_nodes,
783 face_set_elements);
784 }
785 }
786 }
787
788 std::string const mesh_name("FaceSet-" + std::to_string(face_set_number));
789 return std::make_unique<MeshLib::Mesh>(
790 mesh_name, face_set_nodes, face_set_elements,
791 true /* compute_element_neighbors */);
792}
793
795 GocadNode* face_set_node, std::size_t face_set_number,
796 std::vector<MeshLib::Node*>& face_set_nodes,
797 std::vector<MeshLib::Element*>& face_set_elements) const
798{
799 std::array<MeshLib::Node*, 4> quad_nodes{};
800 quad_nodes[0] = new GocadNode(*face_set_node);
801 const std::size_t id(face_set_node->getID());
802 std::array<std::size_t, 3> const c(_index_calculator.getCoordsForID(id));
803
804 const FaceDirection dir(face_set_node->getFaceDirection(face_set_number));
805 switch (dir)
806 {
807 case FaceDirection::U:
808 quad_nodes[1] = new GocadNode(
809 *_nodes[_index_calculator({c[0], c[1] + 1, c[2]})]);
810 quad_nodes[2] = new GocadNode(
811 *_nodes[_index_calculator({c[0], c[1] + 1, c[2] + 1})]);
812 quad_nodes[3] = new GocadNode(
813 *_nodes[_index_calculator({c[0], c[1], c[2] + 1})]);
814 break;
815 case FaceDirection::V:
816 quad_nodes[1] = new GocadNode(
817 *_nodes[_index_calculator({c[0] + 1, c[1], c[2]})]);
818 quad_nodes[2] = new GocadNode(
819 *_nodes[_index_calculator({c[0] + 1, c[1], c[2] + 1})]);
820 quad_nodes[3] = new GocadNode(
821 *_nodes[_index_calculator({c[0], c[1], c[2] + 1})]);
822 break;
823 case FaceDirection::W:
824 quad_nodes[1] = new GocadNode(
825 *_nodes[_index_calculator({c[0] + 1, c[1], c[2]})]);
826 quad_nodes[2] = new GocadNode(
827 *_nodes[_index_calculator({c[0] + 1, c[1] + 1, c[2]})]);
828 quad_nodes[3] = new GocadNode(
829 *_nodes[_index_calculator({c[0], c[1] + 1, c[2]})]);
830 break;
831 default:
832 ERR("Could not create face for node with id {:d}.", id);
833 }
834 std::copy(begin(quad_nodes), end(quad_nodes),
835 back_inserter(face_set_nodes));
836 face_set_elements.push_back(new MeshLib::Quad(quad_nodes));
837}
838
839} // end namespace Gocad
840} // end namespace FileIO
Filename manipulation routines.
Definition of the Hex class.
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Definition of the Mesh class.
Definition of the Quad class.
FaceDirection getFaceDirection(std::size_t const face_set_number) const
Definition GocadNode.h:90
Gocad::Property const * getProperty(std::string const &name) const
std::vector< Gocad::Property > _property_meta_data_vecs
std::vector< MeshLib::Element * > createElements(std::vector< MeshLib::Node * > const &nodes) const
std::unique_ptr< MeshLib::Mesh > getFaceSetMesh(std::size_t const face_set_number) const
std::vector< GocadNode * > _nodes
std::vector< Gocad::Region > regions
std::unique_ptr< MeshLib::Mesh > getMesh() const
std::vector< Bitset > readRegionFlagsBinary() const
void addGocadPropertiesToMesh(MeshLib::Mesh &mesh) const
void applySplitInformation(std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > const &elements) const
void mapRegionFlagsToCellProperties(std::vector< Bitset > const &rf)
Gocad::CoordinateSystem _coordinate_system
static void modifyElement(MeshLib::Element const *hex, MeshLib::Node const *node2sub, MeshLib::Node *substitute_node)
void parseFaceSet(std::string &line, std::istream &in)
void parseFileName(std::string const &line, std::string &result_string) const
Gocad::IndexCalculator _index_calculator
std::vector< GocadSplitNode * > _split_nodes
void parseDims(std::string const &line)
std::vector< std::string > getPropertyNames() const
void addFaceSetQuad(GocadNode *face_set_node, std::size_t face_set_number, std::vector< MeshLib::Node * > &face_set_nodes, std::vector< MeshLib::Element * > &face_set_elements) const
std::vector< Gocad::Layer > layers
std::size_t getCellIdx(std::size_t u, std::size_t v, std::size_t w) const
std::array< std::size_t, 3 > getCoordsForID(std::size_t id) const
std::size_t getID() const
virtual Node *const * getNodes() const =0
Get array of element nodes.
template float readBinaryValue< float >(std::istream &)
std::string extractBaseNameWithoutExtension(std::string const &pathname)
template double readBinaryValue< double >(std::istream &)
double swapEndianness(double const &v)
template std::vector< float > readBinaryArray< float >(std::string const &, std::size_t const)
boost::dynamic_bitset<> Bitset
Property parseGocadPropertyMetaData(std::string &line, std::istream &in, std::string const &path)
Definition Property.cpp:30
Bitset readBits(std::ifstream &in, const std::size_t bits)
Layer parseLayer(std::string const &line, std::vector< Region > const &regions)
Definition Layer.cpp:29
Region parseRegion(std::string const &line)
Definition Region.cpp:26
TemplateElement< MeshLib::HexRule8 > Hex
Definition Hex.h:25
double _property_no_data_value
Definition Property.h:29
std::string _property_data_fname
Definition Property.h:28
std::string _property_class_name
Definition Property.h:25
std::string _property_unit
Definition Property.h:26
std::string _property_name
Definition Property.h:24
std::size_t _property_id
Definition Property.h:23
std::string _property_data_type
Definition Property.h:27
std::vector< double > _property_data
Definition Property.h:43