OGS
FEFLOWMeshInterface.cpp
Go to the documentation of this file.
1 
9 #include "FEFLOWMeshInterface.h"
10 
11 #include <boost/algorithm/string/trim.hpp>
12 #include <cctype>
13 #include <memory>
14 
16 #include "BaseLib/FileTools.h"
17 #include "BaseLib/Logging.h"
18 #include "BaseLib/StringTools.h"
19 #include "GeoLib/Point.h"
20 #include "GeoLib/Polygon.h"
22 #include "MeshLib/Mesh.h"
23 #include "MeshLib/Node.h"
24 
25 namespace FileIO
26 {
28 {
29  std::ifstream in(filename.c_str());
30  if (!in)
31  {
32  ERR("FEFLOWMeshInterface::readFEFLOWFile(): Could not open file {:s}.",
33  filename);
34  return nullptr;
35  }
36 
37  FEM_CLASS fem_class;
38  FEM_DIM fem_dim;
39  std::vector<GeoLib::Point*>* points = nullptr;
40  std::vector<GeoLib::Polyline*>* lines = nullptr;
41 
42  bool isXZplane = false;
43 
44  std::vector<MeshLib::Node*> vec_nodes;
45  std::vector<MeshLib::Element*> vec_elements;
46 
47  std::vector<std::vector<std::size_t>> vec_elementsets;
48 
49  std::string line_string;
50  std::stringstream line_stream;
51  while (!in.eof())
52  {
53  std::getline(in, line_string);
54  boost::trim_right(line_string);
55  //....................................................................
56  // CLASS: the version number follows afterward, e.g. CLASS (v.5.313)
57  if (line_string.find("CLASS") != std::string::npos)
58  {
59  std::getline(in, line_string);
60  boost::trim_right(line_string);
61  line_stream.str(line_string);
62  // problem class, time mode, problem orientation, dimension, nr.
63  // layers for 3D, saturation switch, precision of results, precision
64  // of coordinates
65  line_stream >> fem_class.problem_class >> fem_class.time_mode >>
66  fem_class.orientation >> fem_class.dimension >>
67  fem_class.n_layers3d;
68  line_stream.clear();
69  }
70  //....................................................................
71  // DIMENS
72  else if (line_string == "DIMENS")
73  {
74  // DIMENS
75  std::getline(in, line_string);
76  line_stream.str(line_string);
77  line_stream >> fem_dim.n_nodes >> fem_dim.n_elements >>
78  fem_dim.n_nodes_of_element >> std::ws;
79  // create node pointers with dummy coordinates to create element
80  // objects.
81  // True coordinates are set later in COOR and ELEV_I.
82  vec_nodes.resize(fem_dim.n_nodes);
83  std::size_t count = 0;
84  double dummy_coords[3] = {};
85  std::generate(vec_nodes.begin(), vec_nodes.end(),
86  [&]()
87  { return new MeshLib::Node(dummy_coords, count++); });
88  line_stream.clear();
89  }
90  //....................................................................
91  // NODE (node index for elements)
92  else if (line_string == "NODE")
93  {
94  assert(!vec_nodes.empty());
95 
97  if (fem_dim.n_nodes_of_element == 2)
98  {
100  }
101  else if (fem_dim.n_nodes_of_element == 3)
102  {
104  }
105  else if (fem_dim.n_nodes_of_element == 4 &&
106  fem_class.dimension == 2)
107  {
108  eleType = MeshLib::MeshElemType::QUAD;
109  }
110  else if (fem_dim.n_nodes_of_element == 4 &&
111  fem_class.dimension == 3)
112  {
114  }
115  else if (fem_dim.n_nodes_of_element == 6 &&
116  fem_class.dimension == 3)
117  {
119  }
120  else if (fem_dim.n_nodes_of_element == 8 &&
121  fem_class.dimension == 3)
122  {
124  }
125 
126  if (eleType == MeshLib::MeshElemType::INVALID)
127  {
128  ERR("FEFLOWInterface::readFEFLOWFile(): Unsupported element "
129  "type with the number of node = {:d} and dim = {:d}",
130  fem_dim.n_nodes_of_element, fem_class.dimension);
131  std::for_each(vec_nodes.begin(), vec_nodes.end(),
132  [](MeshLib::Node* nod) { delete nod; });
133  vec_nodes.clear();
134  return nullptr;
135  }
136 
137  vec_elements.reserve(fem_dim.n_elements);
138  for (std::size_t i = 0; i < fem_dim.n_elements; i++)
139  {
140  std::getline(in, line_string);
141  vec_elements.push_back(
142  readElement(fem_dim, eleType, line_string, vec_nodes));
143  }
144  }
145  else if (line_string == "VARNODE")
146  {
147  assert(!vec_nodes.empty());
148 
149  vec_elements.reserve(fem_dim.n_elements);
150  if (fem_dim.n_nodes_of_element == 0)
151  { // mixed element case
152  if (!std::getline(in, line_string))
153  {
154  ERR("FEFLOWInterface::readFEFLOWFile(): read element "
155  "error");
156  std::for_each(vec_nodes.begin(), vec_nodes.end(),
157  [](MeshLib::Node* nod) { delete nod; });
158  vec_nodes.clear();
159  return nullptr;
160  }
161  }
162 
163  for (std::size_t i = 0; i < fem_dim.n_elements; i++)
164  {
165  std::getline(in, line_string);
166  vec_elements.push_back(readElement(line_string, vec_nodes));
167  }
168  }
169  //....................................................................
170  // COOR
171  else if (line_string == "COOR")
172  {
173  readNodeCoordinates(in, fem_class, fem_dim, vec_nodes);
174  }
175  else if (line_string == "XYZCOOR")
176  {
177  readNodeCoordinates(in, vec_nodes);
178  }
179  // ELEV_I
180  else if (line_string == "ELEV_I")
181  {
182  if (fem_class.dimension == 2)
183  {
184  continue;
185  }
186  readElevation(in, fem_class, fem_dim, vec_nodes);
187  }
188  //....................................................................
189  // GRAVITY
190  else if (line_string == "GRAVITY")
191  {
192  getline(in, line_string);
193  line_stream.str(line_string);
194  double vec[3] = {};
195  line_stream >> vec[0] >> vec[1] >> vec[2];
196  if (vec[0] == 0.0 && vec[1] == -1.0 && vec[2] == 0.0)
197  {
198  // x-z plane
199  isXZplane = true;
200  }
201  line_stream.clear();
202  }
203  //....................................................................
204  // ELEMENTALSETS
205  else if (line_string == "ELEMENTALSETS")
206  {
207  readELEMENTALSETS(in, vec_elementsets);
208  }
209  //....................................................................
210  // SUPERMESH
211  else if (line_string == "SUPERMESH")
212  {
214  points, lines);
215  }
216  //....................................................................
217  }
218  in.close();
219 
220  INFO("Create mesh");
221  std::string project_name(
223  auto mesh(
224  std::make_unique<MeshLib::Mesh>(project_name, vec_nodes, vec_elements));
225  INFO("Set values for material property.");
226  auto opt_material_ids(mesh->getProperties().createNewPropertyVector<int>(
227  "MaterialIDs", MeshLib::MeshItemType::Cell, 1));
228  if (!opt_material_ids)
229  {
230  WARN("Could not create PropertyVector for MaterialIDs in Mesh.");
231  }
232  else
233  {
234  opt_material_ids->resize(mesh->getNumberOfElements());
235  setMaterialIDs(fem_class, fem_dim, lines, vec_elementsets, vec_elements,
236  *opt_material_ids);
237  }
238 
239  if (isXZplane)
240  {
241  for (auto* nod : vec_nodes)
242  {
243  (*nod)[2] = (*nod)[1];
244  (*nod)[1] = 0.0;
245  }
246  if (points)
247  {
248  for (auto* pt : *points)
249  {
250  (*pt)[2] = (*pt)[1];
251  (*pt)[1] = .0;
252  }
253  }
254  }
255 
256  return mesh.release();
257 }
258 
260  std::ifstream& in, std::vector<MeshLib::Node*>& vec_nodes)
261 {
262  std::string line_string;
263  char dummy_char; // for comma(,)
264 
265  for (unsigned k = 0; k < vec_nodes.size(); ++k)
266  {
267  // read the line containing the coordinates as string
268  if (!std::getline(in, line_string))
269  {
270  ERR("Could not read the node '{:d}'.", k);
271  for (auto* n : vec_nodes)
272  {
273  delete n;
274  }
275  return;
276  }
277  std::stringstream line_stream;
278  line_stream.str(line_string);
279  // parse the particular coordinates from the string read above
280  for (std::size_t i(0); i < 3; ++i)
281  {
282  if (!(line_stream >> (*vec_nodes[k])[i]))
283  {
284  ERR("Could not parse coordinate {:d} of node '{:d}'.", i, k);
285  for (auto* n : vec_nodes)
286  {
287  delete n;
288  }
289  return;
290  }
291  if (!(line_stream >> dummy_char) && i < 2) // read comma
292  {
293  ERR("Could not parse node '{:d}'.", k);
294  for (auto* n : vec_nodes)
295  {
296  delete n;
297  }
298  return;
299  }
300  }
301  }
302 }
303 
305  std::ifstream& in, const FEM_CLASS& fem_class, const FEM_DIM& fem_dim,
306  std::vector<MeshLib::Node*> const& vec_nodes)
307 {
308  const std::size_t no_nodes_per_layer =
309  (fem_class.dimension == 2)
310  ? fem_dim.n_nodes
311  : fem_dim.n_nodes / (fem_class.n_layers3d + 1);
312  assert(no_nodes_per_layer > 0);
313  const std::size_t n_lines = (no_nodes_per_layer - 1) / 12 + 1;
314  const std::size_t n_layers =
315  (fem_class.dimension == 3) ? fem_class.n_layers3d + 1 : 1;
316  std::string line_string;
317  std::stringstream line_stream;
318  double x;
319  char dummy_char; // for comma(,)
320  // x, y
321  for (unsigned k = 0; k < 2; k++)
322  {
323  // each line
324  for (std::size_t i = 0; i < n_lines; i++)
325  {
326  getline(in, line_string);
327  line_stream.str(line_string);
328  for (unsigned j = 0; j < 12; j++)
329  {
330  if (i * 12 + j >= no_nodes_per_layer)
331  {
332  break;
333  }
334  line_stream >> x >> dummy_char;
335  for (std::size_t l = 0; l < n_layers; l++)
336  {
337  const std::size_t n = i * 12 + l * no_nodes_per_layer + j;
338  MeshLib::Node* m_nod = vec_nodes[n];
339  if (k == 0)
340  {
341  (*m_nod)[0] = x;
342  }
343  else
344  {
345  (*m_nod)[1] = x;
346  }
347  }
348  }
349  line_stream.clear();
350  }
351  }
352 }
353 
354 std::vector<std::size_t> FEFLOWMeshInterface::getIndexList(
355  const std::string& str_ranges)
356 {
357  std::vector<std::size_t> vec_node_IDs;
358 
359  // insert space before and after minus for splitting
360  std::string str_ranges2(BaseLib::replaceString("-", " # ", str_ranges));
361  BaseLib::trim(str_ranges2);
362  auto splitted_str = BaseLib::splitString(str_ranges2, ' ');
363  bool is_range = false;
364  for (auto str : splitted_str)
365  {
366  if (str.empty())
367  {
368  continue;
369  }
370  if (str[0] == '#')
371  {
372  is_range = true;
373  }
374  else if (is_range)
375  {
376  const std::size_t start = vec_node_IDs.back();
377  const auto end = BaseLib::str2number<std::size_t>(str);
378  for (std::size_t i = start + 1; i < end + 1; i++)
379  {
380  vec_node_IDs.push_back(i);
381  }
382  is_range = false;
383  }
384  else
385  {
386  BaseLib::trim(str);
387  vec_node_IDs.push_back(BaseLib::str2number<std::size_t>(str));
388  }
389  }
390 
391  return vec_node_IDs;
392 }
393 
394 void FEFLOWMeshInterface::readElevation(std::ifstream& in,
395  const FEM_CLASS& fem_class,
396  const FEM_DIM& fem_dim,
397  std::vector<MeshLib::Node*>& vec_nodes)
398 {
399  const std::size_t no_nodes_per_layer =
400  fem_dim.n_nodes / (fem_class.n_layers3d + 1);
401  double z = .0;
402  std::string str_nodeList;
403  std::string line_string;
404  std::stringstream line_stream;
405  std::size_t l = 0;
406  unsigned mode = 0; // 0: exit, 1: slice no, 2: elevation value, 3:
407  // continued line of mode 2
408  std::streamoff pos_prev_line = 0;
409  while (true)
410  {
411  pos_prev_line = in.tellg();
412  std::getline(in, line_string);
413  boost::trim_right(line_string);
414 
415  // check mode
416  auto columns = BaseLib::splitString(line_string, ' ');
417  if (!in || std::isalpha(line_string[0]))
418  {
419  mode = 0;
420  }
421  else if (line_string.empty())
422  {
423  continue;
424  }
425  else if (line_string[0] == '\t')
426  {
427  mode = 3;
428  }
429  else if (columns.size() == 1)
430  {
431  mode = 1;
432  }
433  else
434  { // columns.size()>1
435  mode = 2;
436  }
437 
438  // process stocked data
439  if (mode != 3 && !str_nodeList.empty())
440  {
441  // process previous lines
442  auto vec_nodeIDs = getIndexList(str_nodeList);
443  for (auto n0 : vec_nodeIDs)
444  {
445  const std::size_t n = n0 - 1 + l * no_nodes_per_layer;
446  (*vec_nodes[n])[2] = z;
447  }
448  str_nodeList.clear();
449  }
450 
451  if (mode == 0)
452  {
453  break;
454  }
455  if (mode == 1)
456  {
457  // slice number
458  l++;
459  assert(l + 1 == BaseLib::str2number<std::size_t>(columns.front()));
460  }
461  else if (mode == 2)
462  {
463  // parse current line
464  line_stream.str(line_string);
465  line_stream >> z;
466  std::getline(line_stream, str_nodeList);
467  boost::trim(str_nodeList);
468  line_stream.clear();
469  }
470  else if (mode == 3)
471  {
472  // continue reading node range
473  BaseLib::trim(line_string, '\t');
474  str_nodeList += " " + line_string;
475  }
476  }
477 
478  // move stream position to previous line
479  if (std::isalpha(line_string[0]))
480  {
481  in.seekg(pos_prev_line);
482  }
483 }
484 
486  std::string const& line, std::vector<MeshLib::Node*> const& nodes)
487 {
488  std::stringstream ss(line);
489 
490  int ele_type;
491  ss >> ele_type;
492 
493  MeshLib::MeshElemType elem_type;
494  std::size_t n_nodes_of_element;
495  switch (ele_type)
496  {
497  case 6:
499  n_nodes_of_element = 4;
500  break;
501  case 7:
502  elem_type = MeshLib::MeshElemType::PRISM;
503  n_nodes_of_element = 6;
504  break;
505  case 8:
507  n_nodes_of_element = 8;
508  break;
509  default:
510  WARN("Could not parse element type.");
511  return nullptr;
512  }
513 
514  unsigned idx[8];
515  for (std::size_t i = 0; i < n_nodes_of_element; ++i)
516  {
517  ss >> idx[i];
518  }
519  auto** ele_nodes = new MeshLib::Node*[n_nodes_of_element];
520 
521  switch (elem_type)
522  {
523  default:
524  for (std::size_t k(0); k < n_nodes_of_element; ++k)
525  {
526  ele_nodes[k] = nodes[idx[k] - 1];
527  }
528  break;
531  const unsigned n_half_nodes = n_nodes_of_element / 2;
532  for (unsigned k(0); k < n_half_nodes; ++k)
533  {
534  ele_nodes[k] = nodes[idx[k + n_half_nodes] - 1];
535  ele_nodes[k + n_half_nodes] = nodes[idx[k] - 1];
536  }
537  break;
538  }
539 
540  switch (elem_type)
541  {
543  return new MeshLib::Tet(ele_nodes);
545  return new MeshLib::Hex(ele_nodes);
547  return new MeshLib::Prism(ele_nodes);
548  default:
549  return nullptr;
550  }
551 }
552 
554  const FEM_DIM& fem_dim, const MeshLib::MeshElemType elem_type,
555  const std::string& line, const std::vector<MeshLib::Node*>& nodes)
556 {
557  std::stringstream ss(line);
558 
559  unsigned idx[8];
560  for (std::size_t i = 0; i < fem_dim.n_nodes_of_element; ++i)
561  {
562  ss >> idx[i];
563  }
564  auto** ele_nodes = new MeshLib::Node*[fem_dim.n_nodes_of_element];
565 
566  switch (elem_type)
567  {
568  default:
569  for (unsigned k(0); k < fem_dim.n_nodes_of_element; ++k)
570  {
571  ele_nodes[k] = nodes[idx[k] - 1];
572  }
573  break;
576  const unsigned n_half_nodes = fem_dim.n_nodes_of_element / 2;
577  for (unsigned k(0); k < n_half_nodes; ++k)
578  {
579  ele_nodes[k] = nodes[idx[k + n_half_nodes] - 1];
580  ele_nodes[k + n_half_nodes] = nodes[idx[k] - 1];
581  }
582  break;
583  }
584 
585  switch (elem_type)
586  {
588  return new MeshLib::Line(ele_nodes);
590  return new MeshLib::Tri(ele_nodes);
592  return new MeshLib::Quad(ele_nodes);
594  return new MeshLib::Tet(ele_nodes);
596  return new MeshLib::Hex(ele_nodes);
598  return new MeshLib::Prism(ele_nodes);
599  default:
600  assert(false);
601  return nullptr;
602  }
603 }
604 
606  std::ifstream& in, std::vector<std::vector<std::size_t>>& vec_elementsets)
607 {
608  auto compressSpaces = [](std::string const& str)
609  {
610  std::stringstream ss(str);
611  std::string new_str;
612  std::string word;
613  while (ss)
614  {
615  ss >> word;
616  new_str += " " + word;
617  }
618  return new_str;
619  };
620 
621  std::string line_string;
622  std::string str_idList;
623  std::streampos pos_prev_line = 0;
624  while (true)
625  {
626  pos_prev_line = in.tellg();
627  getline(in, line_string);
628 
629  unsigned mode = 0;
630  if (!in)
631  {
632  mode = 0; // reached the end of the file
633  }
634  else if (line_string.empty())
635  {
636  continue; // skip and see what comes next
637  }
638  else if (std::isalpha(line_string[0]))
639  {
640  mode = 0; // reached the next section
641  }
642  else if (line_string[0] == ' ')
643  {
644  mode = 1; // start of the element set definition
645  }
646  else if (line_string[0] == '\t')
647  {
648  mode = 2; // continue the definition
649  }
650  else
651  {
652  ERR("Failed during parsing of an ELEMENTALSETS section in a FEFLOW "
653  "file");
654  break;
655  }
656 
657  if (mode != 2 && !str_idList.empty())
658  {
659  vec_elementsets.push_back(getIndexList(str_idList));
660  str_idList.clear();
661  }
662 
663  if (mode == 0)
664  {
665  break;
666  }
667  if (mode == 1)
668  {
669  // starting a new set
670  std::string set_name;
671  std::string ids;
672  BaseLib::trim(line_string, ' ');
673  if (line_string[0] == '"')
674  { // multiple words
675  auto pos = line_string.find_last_of('"');
676  set_name = line_string.substr(1, pos - 1); // without quotation
677  ids = line_string.substr(pos + 1);
678  }
679  else
680  { // single word
681  auto pos = line_string.find_first_of(' ');
682  set_name = line_string.substr(0, pos);
683  ids = line_string.substr(pos + 1);
684  }
685  INFO("Found an element group - {:s}", set_name.data());
686  str_idList += compressSpaces(ids);
687  }
688  else
689  {
690  // continue reading a element ids
691  BaseLib::trim(line_string, '\t');
692  str_idList += compressSpaces(line_string);
693  }
694  }
695  // move stream position to previous line
696  if (std::isalpha(line_string[0]))
697  {
698  in.seekg(pos_prev_line);
699  }
700 }
701 
703  FEM_CLASS const& fem_class,
704  FEM_DIM const& fem_dim,
705  std::vector<GeoLib::Polyline*>* const& lines,
706  std::vector<std::vector<std::size_t>> const& vec_elementsets,
707  std::vector<MeshLib::Element*> const& vec_elements,
708  std::vector<int>& material_ids)
709 {
710  assert(material_ids.size() == vec_elements.size());
711  if (!vec_elementsets.empty())
712  {
713  for (std::size_t matid = 0; matid < vec_elementsets.size(); ++matid)
714  {
715  auto& eids = vec_elementsets[matid];
716  for (auto eid : eids)
717  {
718  material_ids[eid - 1] =
719  matid; // Element IDs given by FEFLOW starts from one!
720  }
721  }
722  }
723  else if (lines && !lines->empty())
724  {
725  for (std::size_t i = 0; i < vec_elements.size(); ++i)
726  {
727  MeshLib::Node const gpt =
728  MeshLib::getCenterOfGravity(*vec_elements[i]);
729  std::size_t matId = 0;
730  for (std::size_t j = 0; j < lines->size(); j++)
731  {
732  GeoLib::Polyline* poly = (*lines)[j];
733  if (!poly->isClosed())
734  {
735  continue;
736  }
737 
738  GeoLib::Polygon polygon(*poly, true);
739  if (polygon.isPntInPolygon(gpt))
740  {
741  matId = j;
742  break;
743  }
744  }
745  material_ids[i] = matId;
746  }
747  }
748  else if (fem_class.n_layers3d > 0)
749  {
750  const std::size_t no_nodes_per_layer =
751  fem_dim.n_nodes / (fem_class.n_layers3d + 1);
752  for (std::size_t i = 0; i < vec_elements.size(); i++)
753  {
754  MeshLib::Element* e = vec_elements[i];
755  std::size_t e_min_nodeID = std::numeric_limits<std::size_t>::max();
756  for (std::size_t j = 0; j < e->getNumberOfBaseNodes(); j++)
757  {
758  e_min_nodeID = std::min(e_min_nodeID, getNodeIndex(*e, j));
759  }
760  std::size_t layer_id = e_min_nodeID / no_nodes_per_layer;
761  material_ids[i] = layer_id;
762  }
763  }
764 }
765 
766 } // namespace FileIO
Filename manipulation routines.
Definition of the Point class.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
Definition of the Mesh class.
Definition of the Node class.
Definition of the Polygon class.
Definition of string helper functions.
static void readSuperMesh(std::ifstream &in, unsigned dimension, std::vector< GeoLib::Point * > *&points, std::vector< GeoLib::Polyline * > *&lines)
std::vector< std::size_t > getIndexList(const std::string &str_ranges)
void readNodeCoordinates(std::ifstream &in, std::vector< MeshLib::Node * > &nodes)
read node coordinates given in the XYZCOOR section
void readELEMENTALSETS(std::ifstream &in, std::vector< std::vector< std::size_t >> &vec_elementsets)
parse ELEMENTALSETS
MeshLib::Mesh * readFEFLOWFile(const std::string &filename)
void readElevation(std::ifstream &in, const FEM_CLASS &fem_class, const FEM_DIM &fem_dim, std::vector< MeshLib::Node * > &vec_nodes)
read elevation data
MeshLib::Element * readElement(std::string const &line, std::vector< MeshLib::Node * > const &nodes)
Read element type and node indices according to the element type.
void setMaterialIDs(FEM_CLASS const &fem_class, FEM_DIM const &fem_dim, std::vector< GeoLib::Polyline * > *const &lines, std::vector< std::vector< std::size_t >> const &vec_elementsets, std::vector< MeshLib::Element * > const &vec_elements, std::vector< int > &material_ids)
bool isPntInPolygon(const MathLib::Point3d &pnt) const
Definition: Polygon.cpp:71
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition: Polyline.h:51
bool isClosed() const
Definition: Polyline.cpp:109
virtual unsigned getNumberOfBaseNodes() const =0
std::string replaceString(const std::string &searchString, const std::string &replaceString, std::string stringToReplace)
Definition: StringTools.cpp:50
void trim(std::string &str, char ch)
Definition: StringTools.cpp:58
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
std::vector< std::string > splitString(std::string const &str)
Definition: StringTools.cpp:28
TemplateElement< MeshLib::TetRule4 > Tet
Definition: Tet.h:25
TemplateElement< MeshLib::LineRule2 > Line
Definition: Line.h:25
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition: Element.cpp:225
TemplateElement< MeshLib::TriRule3 > Tri
Definition: Tri.h:26
TemplateElement< MeshLib::PrismRule6 > Prism
Definition: Prism.h:25
MeshLib::Node getCenterOfGravity(Element const &element)
Calculates the center of gravity for the mesh element.
Definition: Element.cpp:126
MeshElemType
Types of mesh elements supported by OpenGeoSys. Values are from VTKCellType enum.
Definition: MeshEnums.h:27
TemplateElement< MeshLib::HexRule8 > Hex
Definition: Hex.h:25
TemplateElement< MeshLib::QuadRule4 > Quad
Definition: Quad.h:28