Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
utilities/NekMesh/InputModules/InputNek5000.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: InputNek5000.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Nektar file format converter.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <map>
37 #include <vector>
38 #include <sstream>
39 #include <string>
40 
41 #include <boost/algorithm/string.hpp>
44 
45 #include "InputNek5000.h"
46 
47 using namespace std;
48 using namespace Nektar::NekMeshUtils;
49 
50 namespace Nektar
51 {
52 namespace Utilities
53 {
54 
55 ModuleKey InputNek5000::className = GetModuleFactory().RegisterCreatorFunction(
56  ModuleKey(eInputModule, "rea5000"),
57  InputNek5000::create, "Reads Nektar rea file.");
58 
59 InputNek5000::InputNek5000(MeshSharedPtr m) : InputModule(m)
60 {
61 }
62 
64 {
65 }
66 
67 /**
68  * @brief Processes Nek5000 file format.
69  *
70  * Nek5000 sessions are defined by rea files, and contain sections defining a
71  * DNS simulation in a specific order. The converter only reads mesh
72  * information, curve information if it exists and boundary information. The
73  * format is similar to the rea format supported by #InputNek, but the layout is
74  * sufficiently different that this module is separate.
75  */
77 {
78  // Open the file stream.
79  OpenStream();
80 
81  string line, word;
82  int nParam, nElements, nCurves;
83  int i, j, k, nodeCounter = 0;
84  int nComposite = 1;
86  double vertex[8][3];
87 
88  m_mesh->m_expDim = 0;
89  m_mesh->m_spaceDim = 0;
90 
91  if (m_mesh->m_verbose)
92  {
93  cout << "InputNek5000: Start reading file..." << endl;
94  }
95 
96  // -- Read in parameters.
97 
98  // Ignore first 3 lines. 4th line contains number of parameters.
99  for (i = 0; i < 4; ++i)
100  {
101  getline(m_mshFile, line);
102  }
103 
104  stringstream s(line);
105  s >> nParam;
106 
107  for (i = 0; i < nParam; ++i)
108  {
109  string tmp1, tmp2;
110  getline(m_mshFile, line);
111  s.str(line);
112  s >> tmp1 >> tmp2;
113  }
114 
115  // -- Read in passive scalars (ignore)
116  getline(m_mshFile, line);
117  s.clear();
118  s.str(line);
119  s >> j;
120  for (i = 0; i < j; ++i)
121  {
122  getline(m_mshFile, line);
123  }
124 
125  // -- Read in logical switches (ignore)
126  getline(m_mshFile, line);
127  s.clear();
128  s.str(line);
129  s >> j;
130  for (i = 0; i < j; ++i)
131  {
132  getline(m_mshFile, line);
133  }
134 
135  // -- Read in mesh data.
136 
137  // First hunt for MESH tag
138  bool foundMesh = false;
139  while (!m_mshFile.eof())
140  {
141  getline(m_mshFile, line);
142  if (line.find("MESH") != string::npos)
143  {
144  foundMesh = true;
145  break;
146  }
147  }
148 
149  if (!foundMesh)
150  {
151  cerr << "Couldn't find MESH tag inside file." << endl;
152  abort();
153  }
154 
155  // Now read in number of elements and space dimension.
156  getline(m_mshFile, line);
157  s.clear();
158  s.str(line);
159  s >> nElements >> m_mesh->m_expDim;
160  m_mesh->m_spaceDim = m_mesh->m_expDim;
161 
162  // Set up field names.
163  m_mesh->m_fields.push_back("u");
164  m_mesh->m_fields.push_back("v");
165  if (m_mesh->m_spaceDim > 2)
166  {
167  m_mesh->m_fields.push_back("w");
168  }
169  m_mesh->m_fields.push_back("p");
170 
171  // Loop over and create elements.
172  for (i = 0; i < nElements; ++i)
173  {
174  int nNodes;
175  getline(m_mshFile, line);
176 
177  if (m_mesh->m_expDim == 2)
178  {
179  // - quad: 2 lines with x-coords, y-coords
181  nNodes = 4;
182  for (j = 0; j < 2; ++j)
183  {
184  getline(m_mshFile, line);
185  s.clear();
186  s.str(line);
187  for (k = 0; k < 4; ++k)
188  {
189  s >> vertex[k][j];
190  }
191  }
192  }
193  else
194  {
195  // - hex: 3 lines with x/y/z-coords for base 4 nodes, then 3 more
196  // for upper 4 nodes
197  elType = LibUtilities::eHexahedron;
198  nNodes = 8;
199  for (j = 0; j < 6; ++j)
200  {
201  getline(m_mshFile, line);
202  s.clear();
203  s.str(line);
204  int offset = j > 2 ? 4 : 0;
205  for (k = 0; k < 4; ++k)
206  {
207  s >> vertex[offset + k][j % 3];
208  }
209  }
210  }
211 
212  // Nek5000 meshes do not contain a unique list of nodes, so this block
213  // constructs a unique set so that elements can be created with unique
214  // nodes.
215  vector<NodeSharedPtr> nodeList(nNodes);
216  for (k = 0; k < nNodes; ++k)
217  {
218  nodeList[k] = boost::shared_ptr<Node>(
219  new Node(
220  0, vertex[k][0], vertex[k][1], vertex[k][2]));
221  pair<NodeSet::iterator, bool> testIns =
222  m_mesh->m_vertexSet.insert(nodeList[k]);
223 
224  if (!testIns.second)
225  {
226  nodeList[k] = *(testIns.first);
227  }
228  else
229  {
230  nodeList[k]->m_id = nodeCounter++;
231  }
232  }
233 
234  vector<int> tags(1, 0);
235  ElmtConfig conf(elType, 1, false, false);
237  elType, conf, nodeList, tags);
238  m_mesh->m_element[E->GetDim()].push_back(E);
239  }
240 
241  // -- Read in curved data.
242  getline(m_mshFile, line);
243  if (line.find("CURVE") == string::npos)
244  {
245  cerr << "Cannot find curved side data." << endl;
246  abort();
247  }
248 
249  // Read number of curves.
250  getline(m_mshFile, line);
251  s.clear();
252  s.str(line);
253  s >> nCurves;
254 
256  int nq = 6;
258  LibUtilities::PointsManager()[curveType]->GetPoints(rp);
259 
260  // Map to reorder Nek5000 -> Nektar++ edge ordering. Nek5000 has the same
261  // counter-clockwise ordering of edges/vertices; however the vertical
262  // (i.e. t- or xi_3-direction) edges come last.
263  int nek2nekedge[12] = {
264  0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7
265  };
266 
267  // Map to reorder Nek5000 -> Nektar++ face ordering. Again we have the same
268  // counter-clockwise ordering; however the 4 vertical faces of the hex are
269  // first, followed by bottom face and then top face.
270  int nek2nekface[6] = {
271  1, 2, 3, 4, 0, 5
272  };
273 
274  if (nCurves > 0)
275  {
276  for (i = 0; i < nCurves; ++i)
277  {
278  getline(m_mshFile, line);
279 
280  int elmt, side;
281  NekDouble curveData[5];
282  char curveType;
283 
284  if (nElements < 1000)
285  {
286  // side in first 3 characters, elmt in next 3
287  s.str(line.substr(0, 3));
288  s >> side;
289  s.clear();
290  s.str(line.substr(3, 3));
291  s >> elmt;
292  line = line.substr(6);
293  }
294  else if (nElements < 1000000)
295  {
296  // side in first 2 characters, elmt in next 6
297  s.str(line.substr(0, 2));
298  s >> side;
299  s.clear();
300  s.str(line.substr(2, 6));
301  s >> elmt;
302  line = line.substr(8);
303  }
304  else
305  {
306  // side in first 2 characters, elmt in next 12
307  s.str(line.substr(0, 2));
308  s >> side;
309  s.clear();
310  s.str(line.substr(2, 12));
311  s >> elmt;
312  line = line.substr(14);
313  }
314 
315  s.clear();
316  s.str(line);
317 
318  for (j = 0; j < 5; ++j)
319  {
320  s >> curveData[j];
321  }
322  s >> curveType;
323 
324  elmt--;
325  side--;
326  side = nek2nekedge[side];
327 
328  switch (curveType)
329  {
330  case 'C':
331  {
332  // Apply circular curvature to edges. Nek5000 assumes that
333  // the curvature should be imposed in x-y planes and has no
334  // z-dependence. The following code is adapted from Semtex
335  // (src/mesh.C)
336  NekDouble radius = curveData[0];
337  int convexity = radius < 0 ? -1 : 1;
338  radius = fabs(radius);
339 
340  ElementSharedPtr el =
341  m_mesh->m_element[m_mesh->m_expDim][elmt];
342  EdgeSharedPtr edge = el->GetEdge(side);
343  edge->m_curveType = LibUtilities::eGaussLobattoLegendre;
344 
345  // Assume 2D projection
346  Node P1(*(edge->m_n1)), P2(*(edge->m_n2));
347 
348  if (fabs(P1.m_z - P2.m_z) > 1e-8)
349  {
350  cout << "warning: detected non x-y edge." << endl;
351  }
352  P1.m_z = P2.m_z = 0.0;
353 
354  Node unitNormal, link, centroid, centre;
355  Node midpoint = (P1 + P2)*0.5, dx = P2 - P1;
356  NekDouble l = sqrt(dx.abs2()), sign = 0.0, semiangle = 0.0;
357 
358  unitNormal.m_x = -dx.m_y / l;
359  unitNormal.m_y = dx.m_x / l;
360 
361  if (2.0 * radius < l)
362  {
363  cerr << "failure" << endl;
364  }
365  else
366  {
367  semiangle = asin (0.5 * l / radius);
368  }
369 
370  // Calculate element centroid
371  vector<NodeSharedPtr> elNodes = el->GetVertexList();
372  int nNodes = elNodes.size();
373 
374  for (int i = 0; i < nNodes; ++i)
375  {
376  // Assume 2D projection
377  Node tmp(*elNodes[i]);
378  tmp.m_z = 0.0;
379  centroid += tmp;
380  }
381 
382  centroid /= (NekDouble)nNodes;
383  link = centroid - midpoint;
384  sign = link.dot(unitNormal);
385  sign = convexity * sign / fabs(sign);
386  centre = midpoint + unitNormal * (sign * cos(semiangle) *
387  radius);
388 
389  NekDouble theta1, theta2, dtheta, phi;
390  theta1 = atan2 (P1.m_y - centre.m_y, P1.m_x - centre.m_x);
391  theta2 = atan2 (P2.m_y - centre.m_y, P2.m_x - centre.m_x);
392  dtheta = theta2 - theta1;
393 
394  if (fabs(dtheta) > 2.0*semiangle + 1e-15)
395  {
396  dtheta += (dtheta < 0.0) ? 2.0*M_PI : -2.0*M_PI;
397  }
398 
399  edge->m_edgeNodes.clear();
400 
401  for (j = 1; j < nq-1; ++j) {
402  phi = theta1 + dtheta * 0.5 * (rp[j] + 1.0);
403  NodeSharedPtr asd(new Node(
404  0,
405  centre.m_x + radius * cos(phi),
406  centre.m_y + radius * sin(phi),
407  edge->m_n1->m_z));
408  edge->m_edgeNodes.push_back(asd);
409  }
410  break;
411  }
412  case 's':
413  case 'S':
414  case 'm':
415  case 'M':
416  cerr << "Curve type '" << curveType << "' on side " << side
417  << " of element " << elmt << " is unsupported;"
418  << "will ignore." << endl;
419  break;
420  default:
421  cerr << "Unknown curve type '" << curveType << "' on side "
422  << side << " of element " << elmt << "; will ignore."
423  << endl;
424  break;
425  }
426  }
427  }
428 
429  // Read boundary conditions.
430  getline(m_mshFile, line);
431  getline(m_mshFile, line);
432  if (line.find("BOUNDARY") == string::npos)
433  {
434  cerr << "Cannot find boundary conditions." << endl;
435  abort();
436  }
437 
438  int nSurfaces = 0;
439  boost::unordered_set<pair<int, int> > periodicIn;
440  int periodicInId = -1, periodicOutId = -1;
441 
442  // Boundary conditions: should be precisely nElements * nFaces lines to
443  // read.
444  int lineCnt = 0;
445  int perIn = 0, perOut = 0;
446 
447  while (m_mshFile.good())
448  {
449  getline(m_mshFile, line);
450 
451  // Found a new section. We don't support anything in the rea file beyond
452  // this point so we'll just quit.
453  if (line.find("*") != string::npos)
454  {
455  break;
456  }
457 
459  char bcType;
460  int elmt, side;
461  NekDouble data[5];
462 
463  // type in chars 0-3
464  s.clear();
465  s.str(line.substr(0, 4));
466  s >> bcType;
467 
468  // Some lines have no boundary condition entries
469  if (s.fail())
470  {
471  lineCnt++;
472  continue;
473  }
474 
475  if (nElements < 1000)
476  {
477  // elmt in chars 4-6, side in next 3
478  s.clear();
479  s.str(line.substr(4, 3));
480  s >> elmt;
481  s.clear();
482  s.str(line.substr(7, 3));
483  s >> side;
484  line = line.substr(10);
485  }
486  else if (nElements < 100000)
487  {
488  // elmt in chars 4-8, side in next 1
489  s.clear();
490  s.str(line.substr(4, 5));
491  s >> elmt;
492  s.clear();
493  s.str(line.substr(9, 1));
494  s >> side;
495  line = line.substr(10);
496  }
497  else if (nElements < 1000000)
498  {
499  // elmt in chars 4-9, no side
500  s.clear();
501  s.str(line.substr(4, 6));
502  s >> elmt;
503  side = lineCnt % (2 * m_mesh->m_expDim);
504  line = line.substr(9);
505  }
506  else
507  {
508  // elmt in chars 4-15, no side
509  s.clear();
510  s.str(line.substr(4, 12));
511  s >> elmt;
512  side = lineCnt % (2 * m_mesh->m_expDim);
513  line = line.substr(15);
514  }
515 
516  s.clear();
517  s.str(line);
518 
519  for (i = 0; i < 5; ++i)
520  {
521  s >> data[i];
522  }
523 
524  // Our ordering starts from 0, not 1.
525  --elmt;
526  --side;
527 
528  // Increment lines read
529  lineCnt++;
530 
531  ElementSharedPtr el = m_mesh->m_element[m_mesh->m_spaceDim][elmt];
532 
533  std::string fields[] = { "u", "v", "w", "p" };
534 
535  switch (bcType)
536  {
537  case 'E':
538  // Edge/face connectivity; ignore since we already have this, at
539  // least for conformal meshes.
540  continue;
541 
542  case 'W':
543  {
544  for (i = 0; i < m_mesh->m_fields.size() - 1; ++i)
545  {
546  c->field.push_back(fields[i]);
547  c->value.push_back("0");
548  c->type.push_back(eDirichlet);
549  }
550 
551  // Set high-order boundary condition for wall.
552  c->field.push_back(fields[3]);
553  c->value.push_back("0");
554  c->type.push_back(eHOPCondition);
555  break;
556  }
557 
558  case 'P':
559  {
560  // Determine periodic element and face.
561  int perElmt = (int)(data[0] + 0.5) - 1;
562  int perFace = (int)(data[1] + 0.5) - 1;
563 
564  bool setup = false;
565  if (periodicInId == -1)
566  {
567  periodicInId = m_mesh->m_condition.size();
568  periodicOutId = m_mesh->m_condition.size()+1;
569  setup = true;
570  }
571 
572  bool hasIn = periodicIn.find(make_pair(perElmt, perFace)) !=
573  periodicIn.end();
574 
575  if (hasIn)
576  {
577  swap(periodicInId, periodicOutId);
578  perOut++;
579  }
580  else
581  {
582  periodicIn.insert(make_pair(elmt, side));
583  perIn++;
584  }
585 
586  std::string periodicInStr = "[" +
587  boost::lexical_cast<string>(periodicInId) + "]";
588  std::string periodicOutStr = "[" +
589  boost::lexical_cast<string>(periodicOutId) + "]";
590 
591  for (i = 0; i < m_mesh->m_fields.size() - 1; ++i)
592  {
593  c->field.push_back(fields[i]);
594  c->value.push_back(periodicOutStr);
595  c->type.push_back(ePeriodic);
596  }
597 
598  c->field.push_back(fields[3]);
599  c->value.push_back(periodicOutStr);
600  c->type.push_back(ePeriodic);
601 
602  if (setup)
603  {
606 
607  c->m_composite.push_back(nComposite++);
608  c2->m_composite.push_back(nComposite++);
609 
610  c2->field = c->field;
611  c2->type = c->type;
612  for (i = 0; i < c->type.size(); ++i)
613  {
614  c2->value.push_back(periodicInStr);
615  }
616 
617  m_mesh->m_condition[periodicInId] = c;
618  m_mesh->m_condition[periodicOutId] = c2;
619  }
620 
621  if (hasIn)
622  {
623  swap(periodicInId, periodicOutId);
624  }
625 
626  break;
627  }
628 
629  default:
630  continue;
631  }
632 
633  int compTag, conditionId;
634  ElementSharedPtr surfEl;
635 
636  // Create element for face (3D) or segment (2D).
637  if (el->GetDim() == 3)
638  {
639  FaceSharedPtr f = el->GetFace(nek2nekface[side]);
640  vector<NodeSharedPtr> nodeList;
641  nodeList.insert(nodeList.begin(),
642  f->m_vertexList.begin(),
643  f->m_vertexList.end());
644 
645  vector<int> tags;
646  ElmtConfig conf(
647  LibUtilities::eQuadrilateral, 1, true, true, false,
649  surfEl =
651  conf, nodeList, tags);
652 
653  // Copy high-order surface information from edges.
654  for (int i = 0; i < f->m_vertexList.size(); ++i)
655  {
656  surfEl->GetEdge(i)->m_edgeNodes = f->m_edgeList[i]->m_edgeNodes;
657  surfEl->GetEdge(i)->m_curveType = f->m_edgeList[i]->m_curveType;
658  }
659  }
660  else
661  {
662  EdgeSharedPtr f = el->GetEdge(side);
663 
664  vector<NodeSharedPtr> nodeList;
665  nodeList.push_back(f->m_n1);
666  nodeList.push_back(f->m_n2);
667 
668  vector<int> tags;
669 
670  ElmtConfig conf(
671  LibUtilities::eSegment, 1, true, true, false,
674  LibUtilities::eSegment, conf, nodeList, tags);
675  }
676 
677  // Now attempt to find this boundary condition inside
678  // m_mesh->condition. This is currently a linear search and should
679  // probably be made faster!
681  bool found = false;
682  for (it = m_mesh->m_condition.begin(); it != m_mesh->m_condition.end();
683  ++it)
684  {
685  if (c == it->second)
686  {
687  found = true;
688  c = it->second;
689  break;
690  }
691  }
692 
693  if (!found)
694  {
695  conditionId = m_mesh->m_condition.size();
696  compTag = nComposite;
697  c->m_composite.push_back(compTag);
698  m_mesh->m_condition[conditionId] = c;
699  }
700  else
701  {
702  compTag = c->m_composite[0];
703  }
704 
705  // Insert composite tag into element and insert element into
706  // mesh.
707  vector<int> existingTags = surfEl->GetTagList();
708 
709  existingTags.insert(existingTags.begin(), compTag);
710  surfEl->SetTagList(existingTags);
711  surfEl->SetId(nSurfaces);
712 
713  m_mesh->m_element[surfEl->GetDim()].push_back(surfEl);
714  nSurfaces++;
715  }
716 
717  if (lineCnt != nElements * (m_mesh->m_expDim * 2))
718  {
719  cerr << "Warning: boundary conditions may not have been correctly read "
720  << "from Nek5000 input file." << endl;
721  }
722 
723  if (perIn != perOut)
724  {
725  cerr << "Warning: number of periodic faces does not match." << endl;
726  }
727 
728  m_mshFile.reset();
729 
730  // -- Process rest of mesh.
731  ProcessEdges();
732  ProcessFaces();
733  ProcessElements();
735 
736  // -- Set periodic composites to not be reordered.
737  if (periodicInId != -1)
738  {
739  m_mesh->m_composite[m_mesh->m_condition[periodicInId]
740  ->m_composite[0]]->m_reorder = false;
741  m_mesh->m_composite[m_mesh->m_condition[periodicOutId]
742  ->m_composite[0]]->m_reorder = false;
743  }
744 }
745 
746 }
747 }
NEKMESHUTILS_EXPORT NekDouble dot(const Node &pSrc) const
Definition: Node.h:159
Basic information about an element.
Definition: ElementConfig.h:50
io::filtering_istream m_mshFile
Input stream.
tBaseSharedPtr CreateInstance(tKey idKey BOOST_PP_COMMA_IF(MAX_PARAM) BOOST_PP_ENUM_BINARY_PARAMS(MAX_PARAM, tParam, x))
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:162
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:27
STL namespace.
pair< ModuleType, string > ModuleKey
NekDouble m_y
Y-coordinate.
Definition: Node.h:401
ElementFactory & GetElementFactory()
Definition: Element.cpp:47
Represents a point in the domain.
Definition: Node.h:60
NEKMESHUTILS_EXPORT void OpenStream()
Open a file for input.
virtual NEKMESHUTILS_EXPORT void ProcessFaces(bool ReprocessFaces=true)
Extract element faces.
virtual NEKMESHUTILS_EXPORT void ProcessElements()
Generate element IDs.
boost::shared_ptr< Node > NodeSharedPtr
Definition: Node.h:50
PointsManagerT & PointsManager(void)
Defines a specification for a set of points.
Definition: Points.h:58
double NekDouble
boost::shared_ptr< Condition > ConditionSharedPtr
Definition: Mesh.h:82
boost::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
Abstract base class for input modules.
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
NekDouble m_x
X-coordinate.
Definition: Node.h:399
boost::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Definition: Mesh.h:147
virtual NEKMESHUTILS_EXPORT void ProcessEdges(bool ReprocessEdges=true)
Extract element edges.
boost::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
boost::shared_ptr< Face > FaceSharedPtr
Definition: Face.h:153
NekDouble m_z
Z-coordinate.
Definition: Node.h:403
std::pair< ModuleType, std::string > ModuleKey
virtual void Process()
Processes Nek5000 file format.
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites.
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:52
ModuleFactory & GetModuleFactory()
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215