Nektar++
MeshGraphXml.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: BoundaryConditions.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 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description:
32 //
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <iomanip>
37 
40 
45 
46 #include <boost/format.hpp>
47 
48 #include <tinyxml.h>
49 
50 using namespace std;
51 
52 namespace Nektar
53 {
54 namespace SpatialDomains
55 {
56 
57 std::string MeshGraphXml::className =
59  "Xml", MeshGraphXml::create, "IO with Xml geometry");
60 
61 void MeshGraphXml::PartitionMesh(
63 {
64  // Get row of comm, or the whole comm if not split
65  LibUtilities::CommSharedPtr comm = session->GetComm();
66  LibUtilities::CommSharedPtr commMesh = comm->GetRowComm();
67  const bool isRoot = comm->TreatAsRankZero();
68 
69  m_session = session;
70 
71  // Load file for root process only (since this is always needed)
72  // and determine if the provided geometry has already been
73  // partitioned. This will be the case if the user provides the
74  // directory of mesh partitions as an input. Partitioned geometries
75  // have the attribute
76  // PARTITION=X
77  // where X is the number of the partition (and should match the
78  // process rank). The result is shared with all other processes.
79  int isPartitioned = 0;
80  if (isRoot)
81  {
82  if (m_session->DefinesElement("Nektar/Geometry"))
83  {
84  if (m_session->GetElement("Nektar/Geometry")->Attribute("PARTITION"))
85  {
86  std::cout << "Using pre-partitioned mesh." << std::endl;
87  isPartitioned = 1;
88  }
89  }
90  }
91  comm->Bcast(isPartitioned, 0);
92 
93  // If the mesh is already partitioned, we are done. Remaining
94  // processes must load their partitions.
95  if (isPartitioned)
96  {
97  if (!isRoot)
98  {
99  m_session->InitSession();
100  }
101  }
102  else
103  {
104  // Default partitioner to use is Metis. Use Scotch as default if it is
105  // installed. Override default with command-line flags if they are set.
106  string partitionerName = "Metis";
107  if (GetMeshPartitionFactory().ModuleExists("Scotch"))
108  {
109  partitionerName = "Scotch";
110  }
111  if (session->DefinesCmdLineArgument("use-metis"))
112  {
113  partitionerName = "Metis";
114  }
115  if (session->DefinesCmdLineArgument("use-scotch"))
116  {
117  partitionerName = "Scotch";
118  }
119 
120  // Mesh has not been partitioned so do partitioning if required. Note
121  // in the serial case nothing is done as we have already loaded the
122  // mesh.
123  if (session->DefinesCmdLineArgument("part-only")||
124  session->DefinesCmdLineArgument("part-only-overlapping"))
125  {
126  // Perform partitioning of the mesh only. For this we insist the
127  // code is run in serial (parallel execution is pointless).
128  ASSERTL0(comm->GetSize() == 1,
129  "The 'part-only' option should be used in serial.");
130 
131  // Read 'lite' geometry information
132  ReadGeometry(NullDomainRangeShPtr, false);
133 
134  // Number of partitions is specified by the parameter.
135  int nParts;
136  auto comp = CreateCompositeDescriptor();
137 
138  MeshPartitionSharedPtr partitioner =
140  partitionerName, session, m_meshDimension,
141  CreateMeshEntities(), comp);
142 
143  if (session->DefinesCmdLineArgument("part-only"))
144  {
145  nParts = session->GetCmdLineArgument<int>("part-only");
146  partitioner->PartitionMesh(nParts, true);
147  }
148  else
149  {
150  nParts = session->GetCmdLineArgument<int>("part-only-overlapping");
151  partitioner->PartitionMesh(nParts, true, true);
152  }
153 
154  vector<set<unsigned int>> elmtIDs;
155  vector<unsigned int> parts(nParts);
156  for (int i = 0; i < nParts; ++i)
157  {
158  vector<unsigned int> elIDs;
159  set<unsigned int> tmp;
160  partitioner->GetElementIDs(i, elIDs);
161  tmp.insert(elIDs.begin(), elIDs.end());
162  elmtIDs.push_back(tmp);
163  parts[i] = i;
164  }
165 
166  this->WriteXMLGeometry(m_session->GetSessionName(), elmtIDs, parts);
167 
168  if (isRoot && session->DefinesCmdLineArgument("part-info"))
169  {
170  partitioner->PrintPartInfo(std::cout);
171  }
172 
173  session->Finalise();
174  exit(0);
175  }
176 
177  if (commMesh->GetSize() > 1)
178  {
179  int nParts = commMesh->GetSize();
180 
181  if (session->GetSharedFilesystem())
182  {
183  vector<unsigned int> keys, vals;
184  int i;
185 
186  if (isRoot)
187  {
188  // Read 'lite' geometry information
189  ReadGeometry(NullDomainRangeShPtr, false);
190 
191  // Store composite ordering and boundary information.
192  m_compOrder = CreateCompositeOrdering();
193  auto comp = CreateCompositeDescriptor();
194 
195  // Create mesh partitioner.
196  MeshPartitionSharedPtr partitioner =
198  partitionerName, session, m_meshDimension,
199  CreateMeshEntities(), comp);
200 
201  partitioner->PartitionMesh(nParts, true);
202 
203  vector<set<unsigned int>> elmtIDs;
204  vector<unsigned int> parts(nParts);
205  for (i = 0; i < nParts; ++i)
206  {
207  vector<unsigned int> elIDs;
208  set<unsigned int> tmp;
209  partitioner->GetElementIDs(i, elIDs);
210  tmp.insert(elIDs.begin(), elIDs.end());
211  elmtIDs.push_back(tmp);
212  parts[i] = i;
213  }
214 
215  // Call WriteGeometry to write out partition files. This
216  // will populate m_bndRegOrder.
217  this->WriteXMLGeometry(
218  m_session->GetSessionName(), elmtIDs, parts);
219 
220  // Communicate orderings to the other processors.
221 
222  // First send sizes of the orderings and boundary
223  // regions to allocate storage on the remote end.
224  keys.resize(2);
225  keys[0] = m_compOrder.size();
226  keys[1] = m_bndRegOrder.size();
227  comm->Bcast(keys, 0);
228 
229  // Construct the keys and sizes of values for composite
230  // ordering
231  keys.resize(m_compOrder.size());
232  vals.resize(m_compOrder.size());
233 
234  i = 0;
235  for (auto &cIt : m_compOrder)
236  {
237  keys[i ] = cIt.first;
238  vals[i++] = cIt.second.size();
239  }
240 
241  // Send across data.
242  comm->Bcast(keys, 0);
243  comm->Bcast(vals, 0);
244  for (auto &cIt : m_compOrder)
245  {
246  comm->Bcast(cIt.second, 0);
247  }
248 
249  // Construct the keys and sizes of values for composite
250  // ordering
251  keys.resize(m_bndRegOrder.size());
252  vals.resize(m_bndRegOrder.size());
253 
254  i = 0;
255  for (auto &bIt : m_bndRegOrder)
256  {
257  keys[i ] = bIt.first;
258  vals[i++] = bIt.second.size();
259  }
260 
261  // Send across data.
262  comm->Bcast(keys, 0);
263  comm->Bcast(vals, 0);
264  for (auto &bIt : m_bndRegOrder)
265  {
266  comm->Bcast(bIt.second, 0);
267  }
268 
269  if (session->DefinesCmdLineArgument("part-info"))
270  {
271  partitioner->PrintPartInfo(std::cout);
272  }
273  }
274  else
275  {
276  keys.resize(2);
277  comm->Bcast(keys, 0);
278 
279  int cmpSize = keys[0];
280  int bndSize = keys[1];
281 
282  keys.resize(cmpSize);
283  vals.resize(cmpSize);
284  comm->Bcast(keys, 0);
285  comm->Bcast(vals, 0);
286 
287  for (int i = 0; i < keys.size(); ++i)
288  {
289  vector<unsigned int> tmp(vals[i]);
290  comm->Bcast(tmp, 0);
291  m_compOrder[keys[i]] = tmp;
292  }
293 
294  keys.resize(bndSize);
295  vals.resize(bndSize);
296  comm->Bcast(keys, 0);
297  comm->Bcast(vals, 0);
298 
299  for (int i = 0; i < keys.size(); ++i)
300  {
301  vector<unsigned int> tmp(vals[i]);
302  comm->Bcast(tmp, 0);
303  m_bndRegOrder[keys[i]] = tmp;
304  }
305  }
306  }
307  else
308  {
309  m_session->InitSession();
310  ReadGeometry(NullDomainRangeShPtr, false);
311 
312  m_compOrder = CreateCompositeOrdering();
313  auto comp = CreateCompositeDescriptor();
314 
315  // Partitioner now operates in parallel. Each process receives
316  // partitioning over interconnect and writes its own session
317  // file to the working directory.
318  MeshPartitionSharedPtr partitioner =
320  partitionerName, session, m_meshDimension,
321  CreateMeshEntities(), comp);
322 
323  partitioner->PartitionMesh(nParts, false);
324 
325  vector<unsigned int> parts(1), tmp;
326  parts[0] = commMesh->GetRank();
327  vector<set<unsigned int>> elIDs(1);
328  partitioner->GetElementIDs(parts[0], tmp);
329  elIDs[0].insert(tmp.begin(), tmp.end());
330  this->WriteXMLGeometry(session->GetSessionName(), elIDs, parts);
331 
332  if (m_session->DefinesCmdLineArgument("part-info") && isRoot)
333  {
334  partitioner->PrintPartInfo(std::cout);
335  }
336  }
337 
338  // Wait for all processors to finish their writing activities.
339  comm->Block();
340 
341  std::string dirname = m_session->GetSessionName() + "_xml";
342  fs::path pdirname(dirname);
343  boost::format pad("P%1$07d.xml");
344  pad % comm->GetRowComm()->GetRank();
345  fs::path pFilename(pad.str());
346  fs::path fullpath = pdirname / pFilename;
347 
348  std::vector<std::string> filenames = {
349  LibUtilities::PortablePath(fullpath) };
350  m_session->InitSession(filenames);
351  }
352  else if (!isRoot)
353  {
354  // No partitioning, non-root processors need to read the session
355  // file -- handles case where --npz is the same as number of
356  // processors.
357  m_session->InitSession();
358  }
359  }
360 }
361 
362 void MeshGraphXml::ReadGeometry(
363  DomainRangeShPtr rng,
364  bool fillGraph)
365 {
366  // Reset member variables.
367  m_vertSet.clear();
368  m_curvedEdges.clear();
369  m_curvedFaces.clear();
370  m_segGeoms.clear();
371  m_triGeoms.clear();
372  m_quadGeoms.clear();
373  m_tetGeoms.clear();
374  m_pyrGeoms.clear();
375  m_prismGeoms.clear();
376  m_hexGeoms.clear();
377  m_meshComposites.clear();
378  m_compositesLabels.clear();
379  m_domain.clear();
380  m_expansionMapShPtrMap.clear();
381  m_geomInfo.clear();
382  m_faceToElMap.clear();
383 
384  m_domainRange = rng;
385  m_xmlGeom = m_session->GetElement("NEKTAR/GEOMETRY");
386 
387  int err; /// Error value returned by TinyXML.
388 
389  TiXmlAttribute *attr = m_xmlGeom->FirstAttribute();
390 
391  // Initialize the mesh and space dimensions to 3 dimensions.
392  // We want to do this each time we read a file, so it should
393  // be done here and not just during class initialization.
394  m_meshPartitioned = false;
395  m_meshDimension = 3;
396  m_spaceDimension = 3;
397 
398  while (attr)
399  {
400  std::string attrName(attr->Name());
401  if (attrName == "DIM")
402  {
403  err = attr->QueryIntValue(&m_meshDimension);
404  ASSERTL0(err == TIXML_SUCCESS, "Unable to read mesh dimension.");
405  }
406  else if (attrName == "SPACE")
407  {
408  err = attr->QueryIntValue(&m_spaceDimension);
409  ASSERTL0(err == TIXML_SUCCESS, "Unable to read space dimension.");
410  }
411  else if (attrName == "PARTITION")
412  {
413  err = attr->QueryIntValue(&m_partition);
414  ASSERTL0(err == TIXML_SUCCESS, "Unable to read partition.");
415  m_meshPartitioned = true;
416  }
417  else
418  {
419  std::string errstr("Unknown attribute: ");
420  errstr += attrName;
421  ASSERTL0(false, errstr.c_str());
422  }
423 
424  // Get the next attribute.
425  attr = attr->Next();
426  }
427 
428  ASSERTL0(m_meshDimension <= m_spaceDimension,
429  "Mesh dimension greater than space dimension");
430 
431  ReadVertices();
432  ReadCurves();
433  if (m_meshDimension >= 2)
434  {
435  ReadEdges();
436  if (m_meshDimension == 3)
437  {
438  ReadFaces();
439  }
440  }
441  ReadElements();
442  ReadComposites();
443  ReadDomain();
444 
445  if (fillGraph)
446  {
447  MeshGraph::FillGraph();
448  }
449 }
450 
451 void MeshGraphXml::ReadVertices()
452 {
453  // Now read the vertices
454  TiXmlElement *element = m_xmlGeom->FirstChildElement("VERTEX");
455  ASSERTL0(element, "Unable to find mesh VERTEX tag in file.");
456 
457  NekDouble xscale, yscale, zscale;
458 
459  // check to see if any scaling parameters are in
460  // attributes and determine these values
461  LibUtilities::Interpreter expEvaluator;
462  const char *xscal = element->Attribute("XSCALE");
463  if (!xscal)
464  {
465  xscale = 1.0;
466  }
467  else
468  {
469  std::string xscalstr = xscal;
470  int expr_id = expEvaluator.DefineFunction("", xscalstr);
471  xscale = expEvaluator.Evaluate(expr_id);
472  }
473 
474  const char *yscal = element->Attribute("YSCALE");
475  if (!yscal)
476  {
477  yscale = 1.0;
478  }
479  else
480  {
481  std::string yscalstr = yscal;
482  int expr_id = expEvaluator.DefineFunction("", yscalstr);
483  yscale = expEvaluator.Evaluate(expr_id);
484  }
485 
486  const char *zscal = element->Attribute("ZSCALE");
487  if (!zscal)
488  {
489  zscale = 1.0;
490  }
491  else
492  {
493  std::string zscalstr = zscal;
494  int expr_id = expEvaluator.DefineFunction("", zscalstr);
495  zscale = expEvaluator.Evaluate(expr_id);
496  }
497 
498  NekDouble xmove, ymove, zmove;
499 
500  // check to see if any moving parameters are in
501  // attributes and determine these values
502 
503  const char *xmov = element->Attribute("XMOVE");
504  if (!xmov)
505  {
506  xmove = 0.0;
507  }
508  else
509  {
510  std::string xmovstr = xmov;
511  int expr_id = expEvaluator.DefineFunction("", xmovstr);
512  xmove = expEvaluator.Evaluate(expr_id);
513  }
514 
515  const char *ymov = element->Attribute("YMOVE");
516  if (!ymov)
517  {
518  ymove = 0.0;
519  }
520  else
521  {
522  std::string ymovstr = ymov;
523  int expr_id = expEvaluator.DefineFunction("", ymovstr);
524  ymove = expEvaluator.Evaluate(expr_id);
525  }
526 
527  const char *zmov = element->Attribute("ZMOVE");
528  if (!zmov)
529  {
530  zmove = 0.0;
531  }
532  else
533  {
534  std::string zmovstr = zmov;
535  int expr_id = expEvaluator.DefineFunction("", zmovstr);
536  zmove = expEvaluator.Evaluate(expr_id);
537  }
538 
539  TiXmlElement *vertex = element->FirstChildElement("V");
540 
541  int indx;
542  int nextVertexNumber = -1;
543 
544  while (vertex)
545  {
546  nextVertexNumber++;
547 
548  TiXmlAttribute *vertexAttr = vertex->FirstAttribute();
549  std::string attrName(vertexAttr->Name());
550 
551  ASSERTL0(attrName == "ID",
552  (std::string("Unknown attribute name: ") + attrName).c_str());
553 
554  int err = vertexAttr->QueryIntValue(&indx);
555  ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
556 
557  // Now read body of vertex
558  std::string vertexBodyStr;
559 
560  TiXmlNode *vertexBody = vertex->FirstChild();
561 
562  while (vertexBody)
563  {
564  // Accumulate all non-comment body data.
565  if (vertexBody->Type() == TiXmlNode::TINYXML_TEXT)
566  {
567  vertexBodyStr += vertexBody->ToText()->Value();
568  vertexBodyStr += " ";
569  }
570 
571  vertexBody = vertexBody->NextSibling();
572  }
573 
574  ASSERTL0(!vertexBodyStr.empty(),
575  "Vertex definitions must contain vertex data.");
576 
577  // Get vertex data from the data string.
578  NekDouble xval, yval, zval;
579  std::istringstream vertexDataStrm(vertexBodyStr.c_str());
580 
581  try
582  {
583  while (!vertexDataStrm.fail())
584  {
585  vertexDataStrm >> xval >> yval >> zval;
586 
587  xval = xval * xscale + xmove;
588  yval = yval * yscale + ymove;
589  zval = zval * zscale + zmove;
590 
591  // Need to check it here because we may not be
592  // good after the read indicating that there
593  // was nothing to read.
594  if (!vertexDataStrm.fail())
595  {
596  PointGeomSharedPtr vert(
598  m_spaceDimension, indx, xval, yval, zval));
599  m_vertSet[indx] = vert;
600  }
601  }
602  }
603  catch (...)
604  {
605  ASSERTL0(false, "Unable to read VERTEX data.");
606  }
607 
608  vertex = vertex->NextSiblingElement("V");
609  }
610 }
611 
612 void MeshGraphXml::ReadCurves()
613 {
614  // check to see if any scaling parameters are in
615  // attributes and determine these values
616  TiXmlElement *element = m_xmlGeom->FirstChildElement("VERTEX");
617  ASSERTL0(element, "Unable to find mesh VERTEX tag in file.");
618 
619  NekDouble xscale, yscale, zscale;
620 
621  LibUtilities::Interpreter expEvaluator;
622  const char *xscal = element->Attribute("XSCALE");
623  if (!xscal)
624  {
625  xscale = 1.0;
626  }
627  else
628  {
629  std::string xscalstr = xscal;
630  int expr_id = expEvaluator.DefineFunction("", xscalstr);
631  xscale = expEvaluator.Evaluate(expr_id);
632  }
633 
634  const char *yscal = element->Attribute("YSCALE");
635  if (!yscal)
636  {
637  yscale = 1.0;
638  }
639  else
640  {
641  std::string yscalstr = yscal;
642  int expr_id = expEvaluator.DefineFunction("", yscalstr);
643  yscale = expEvaluator.Evaluate(expr_id);
644  }
645 
646  const char *zscal = element->Attribute("ZSCALE");
647  if (!zscal)
648  {
649  zscale = 1.0;
650  }
651  else
652  {
653  std::string zscalstr = zscal;
654  int expr_id = expEvaluator.DefineFunction("", zscalstr);
655  zscale = expEvaluator.Evaluate(expr_id);
656  }
657 
658  NekDouble xmove, ymove, zmove;
659 
660  // check to see if any moving parameters are in
661  // attributes and determine these values
662 
663  const char *xmov = element->Attribute("XMOVE");
664  if (!xmov)
665  {
666  xmove = 0.0;
667  }
668  else
669  {
670  std::string xmovstr = xmov;
671  int expr_id = expEvaluator.DefineFunction("", xmovstr);
672  xmove = expEvaluator.Evaluate(expr_id);
673  }
674 
675  const char *ymov = element->Attribute("YMOVE");
676  if (!ymov)
677  {
678  ymove = 0.0;
679  }
680  else
681  {
682  std::string ymovstr = ymov;
683  int expr_id = expEvaluator.DefineFunction("", ymovstr);
684  ymove = expEvaluator.Evaluate(expr_id);
685  }
686 
687  const char *zmov = element->Attribute("ZMOVE");
688  if (!zmov)
689  {
690  zmove = 0.0;
691  }
692  else
693  {
694  std::string zmovstr = zmov;
695  int expr_id = expEvaluator.DefineFunction("", zmovstr);
696  zmove = expEvaluator.Evaluate(expr_id);
697  }
698 
699  int err;
700 
701  /// Look for elements in CURVE block.
702  TiXmlElement *field = m_xmlGeom->FirstChildElement("CURVED");
703 
704  if (!field) // return if no curved entities
705  {
706  return;
707  }
708 
709  /// All curves are of the form: "<? ID="#" TYPE="GLL OR other
710  /// points type" NUMPOINTS="#"> ... </?>", with ? being an
711  /// element type (either E or F).
712 
713  TiXmlElement *edgelement = field->FirstChildElement("E");
714 
715  int edgeindx, edgeid;
716  int nextEdgeNumber = -1;
717 
718  while (edgelement)
719  {
720  /// These should be ordered.
721  nextEdgeNumber++;
722 
723  std::string edge(edgelement->ValueStr());
724  ASSERTL0(edge == "E",
725  (std::string("Unknown 3D curve type:") + edge).c_str());
726 
727  /// Read id attribute.
728  err = edgelement->QueryIntAttribute("ID", &edgeindx);
729  ASSERTL0(err == TIXML_SUCCESS, "Unable to read curve attribute ID.");
730 
731  /// Read edge id attribute.
732  err = edgelement->QueryIntAttribute("EDGEID", &edgeid);
733  ASSERTL0(err == TIXML_SUCCESS,
734  "Unable to read curve attribute EDGEID.");
735 
736  /// Read text edgelement description.
737  std::string elementStr;
738  TiXmlNode *elementChild = edgelement->FirstChild();
739 
740  while (elementChild)
741  {
742  // Accumulate all non-comment element data
743  if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
744  {
745  elementStr += elementChild->ToText()->ValueStr();
746  elementStr += " ";
747  }
748  elementChild = elementChild->NextSibling();
749  }
750 
751  ASSERTL0(!elementStr.empty(), "Unable to read curve description body.");
752 
753  /// Parse out the element components corresponding to type of
754  /// element.
755  if (edge == "E")
756  {
757  int numPts = 0;
758  // Determine the points type
759  std::string typeStr = edgelement->Attribute("TYPE");
760  ASSERTL0(!typeStr.empty(), "TYPE must be specified in "
761  "points definition");
762 
764  const std::string *begStr = LibUtilities::kPointsTypeStr;
765  const std::string *endStr =
767  const std::string *ptsStr = std::find(begStr, endStr, typeStr);
768 
769  ASSERTL0(ptsStr != endStr, "Invalid points type.");
770  type = (LibUtilities::PointsType)(ptsStr - begStr);
771 
772  // Determine the number of points
773  err = edgelement->QueryIntAttribute("NUMPOINTS", &numPts);
774  ASSERTL0(err == TIXML_SUCCESS,
775  "Unable to read curve attribute NUMPOINTS.");
776  CurveSharedPtr curve(
778 
779  // Read points (x, y, z)
780  NekDouble xval, yval, zval;
781  std::istringstream elementDataStrm(elementStr.c_str());
782  try
783  {
784  while (!elementDataStrm.fail())
785  {
786  elementDataStrm >> xval >> yval >> zval;
787 
788  xval = xval * xscale + xmove;
789  yval = yval * yscale + ymove;
790  zval = zval * zscale + zmove;
791 
792  // Need to check it here because we may not be
793  // good after the read indicating that there
794  // was nothing to read.
795  if (!elementDataStrm.fail())
796  {
797  PointGeomSharedPtr vert(
799  m_meshDimension, edgeindx, xval, yval, zval));
800 
801  curve->m_points.push_back(vert);
802  }
803  }
804  }
805  catch (...)
806  {
807  NEKERROR(ErrorUtil::efatal,
808  (std::string("Unable to read curve data for EDGE: ") +
809  elementStr)
810  .c_str());
811  }
812 
813  ASSERTL0(curve->m_points.size() == numPts,
814  "Number of points specificed by attribute "
815  "NUMPOINTS is different from number of points "
816  "in list (edgeid = " +
817  boost::lexical_cast<string>(edgeid));
818 
819  m_curvedEdges[edgeid] = curve;
820 
821  edgelement = edgelement->NextSiblingElement("E");
822 
823  } // end if-loop
824 
825  } // end while-loop
826 
827  TiXmlElement *facelement = field->FirstChildElement("F");
828  int faceindx, faceid;
829 
830  while (facelement)
831  {
832  std::string face(facelement->ValueStr());
833  ASSERTL0(face == "F",
834  (std::string("Unknown 3D curve type: ") + face).c_str());
835 
836  /// Read id attribute.
837  err = facelement->QueryIntAttribute("ID", &faceindx);
838  ASSERTL0(err == TIXML_SUCCESS, "Unable to read curve attribute ID.");
839 
840  /// Read face id attribute.
841  err = facelement->QueryIntAttribute("FACEID", &faceid);
842  ASSERTL0(err == TIXML_SUCCESS,
843  "Unable to read curve attribute FACEID.");
844 
845  /// Read text face element description.
846  std::string elementStr;
847  TiXmlNode *elementChild = facelement->FirstChild();
848 
849  while (elementChild)
850  {
851  // Accumulate all non-comment element data
852  if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
853  {
854  elementStr += elementChild->ToText()->ValueStr();
855  elementStr += " ";
856  }
857  elementChild = elementChild->NextSibling();
858  }
859 
860  ASSERTL0(!elementStr.empty(), "Unable to read curve description body.");
861 
862  /// Parse out the element components corresponding to type of
863  /// element.
864  if (face == "F")
865  {
866  std::string typeStr = facelement->Attribute("TYPE");
867  ASSERTL0(!typeStr.empty(), "TYPE must be specified in "
868  "points definition");
870  const std::string *begStr = LibUtilities::kPointsTypeStr;
871  const std::string *endStr =
873  const std::string *ptsStr = std::find(begStr, endStr, typeStr);
874 
875  ASSERTL0(ptsStr != endStr, "Invalid points type.");
876  type = (LibUtilities::PointsType)(ptsStr - begStr);
877 
878  std::string numptsStr = facelement->Attribute("NUMPOINTS");
879  ASSERTL0(!numptsStr.empty(),
880  "NUMPOINTS must be specified in points definition");
881  int numPts = 0;
882  std::stringstream s;
883  s << numptsStr;
884  s >> numPts;
885 
886  CurveSharedPtr curve(
888 
889  ASSERTL0(numPts >= 3, "NUMPOINTS for face must be greater than 2");
890 
891  if (numPts == 3)
892  {
893  ASSERTL0(ptsStr != endStr, "Invalid points type.");
894  }
895 
896  // Read points (x, y, z)
897  NekDouble xval, yval, zval;
898  std::istringstream elementDataStrm(elementStr.c_str());
899  try
900  {
901  while (!elementDataStrm.fail())
902  {
903  elementDataStrm >> xval >> yval >> zval;
904 
905  // Need to check it here because we
906  // may not be good after the read
907  // indicating that there was nothing
908  // to read.
909  if (!elementDataStrm.fail())
910  {
911  PointGeomSharedPtr vert(
913  m_meshDimension, faceindx, xval, yval, zval));
914  curve->m_points.push_back(vert);
915  }
916  }
917  }
918  catch (...)
919  {
920  NEKERROR(ErrorUtil::efatal,
921  (std::string("Unable to read curve data for FACE: ") +
922  elementStr)
923  .c_str());
924  }
925  m_curvedFaces[faceid] = curve;
926 
927  facelement = facelement->NextSiblingElement("F");
928  }
929  }
930 }
931 
932 void MeshGraphXml::ReadDomain()
933 {
934  TiXmlElement *domain = NULL;
935  /// Look for data in DOMAIN block.
936  domain = m_xmlGeom->FirstChildElement("DOMAIN");
937 
938  ASSERTL0(domain, "Unable to find DOMAIN tag in file.");
939 
940  /// Elements are of the form: "<D ID = "N"> ... </D>".
941  /// Read the ID field first.
942  TiXmlElement *multidomains = domain->FirstChildElement("D");
943 
944  if (multidomains)
945  {
946  int nextDomainNumber = 0;
947  while (multidomains)
948  {
949  int indx;
950  int err = multidomains->QueryIntAttribute("ID", &indx);
951  ASSERTL0(err == TIXML_SUCCESS,
952  "Unable to read attribute ID in Domain.");
953 
954  TiXmlNode *elementChild = multidomains->FirstChild();
955  while (elementChild &&
956  elementChild->Type() != TiXmlNode::TINYXML_TEXT)
957  {
958  elementChild = elementChild->NextSibling();
959  }
960 
961  ASSERTL0(elementChild, "Unable to read DOMAIN body.");
962  std::string elementStr = elementChild->ToText()->ValueStr();
963 
964  elementStr = elementStr.substr(elementStr.find_first_not_of(" "));
965 
966  std::string::size_type indxBeg = elementStr.find_first_of('[') + 1;
967  std::string::size_type indxEnd = elementStr.find_last_of(']') - 1;
968  std::string indxStr =
969  elementStr.substr(indxBeg, indxEnd - indxBeg + 1);
970 
971  ASSERTL0(
972  !indxStr.empty(),
973  "Unable to read domain's composite index (index missing?).");
974 
975  // Read the domain composites.
976  // Parse the composites into a list.
977  map<int, CompositeSharedPtr> unrollDomain;
978  GetCompositeList(indxStr, unrollDomain);
979  m_domain.push_back(unrollDomain);
980 
981  ASSERTL0(!m_domain[nextDomainNumber++].empty(),
982  (std::string(
983  "Unable to obtain domain's referenced composite: ") +
984  indxStr)
985  .c_str());
986 
987  /// Keep looking
988  multidomains = multidomains->NextSiblingElement("D");
989  }
990  }
991  else // previous definition of just one composite
992  {
993 
994  // find the non comment portion of the body.
995  TiXmlNode *elementChild = domain->FirstChild();
996  while (elementChild && elementChild->Type() != TiXmlNode::TINYXML_TEXT)
997  {
998  elementChild = elementChild->NextSibling();
999  }
1000 
1001  ASSERTL0(elementChild, "Unable to read DOMAIN body.");
1002  std::string elementStr = elementChild->ToText()->ValueStr();
1003 
1004  elementStr = elementStr.substr(elementStr.find_first_not_of(" "));
1005 
1006  std::string::size_type indxBeg = elementStr.find_first_of('[') + 1;
1007  std::string::size_type indxEnd = elementStr.find_last_of(']') - 1;
1008  std::string indxStr = elementStr.substr(indxBeg, indxEnd - indxBeg + 1);
1009 
1010  ASSERTL0(!indxStr.empty(),
1011  "Unable to read domain's composite index (index missing?).");
1012 
1013  // Read the domain composites.
1014  // Parse the composites into a list.
1015  map<int, CompositeSharedPtr> fullDomain;
1016  GetCompositeList(indxStr, fullDomain);
1017  m_domain.push_back(fullDomain);
1018 
1019  ASSERTL0(
1020  !m_domain[0].empty(),
1021  (std::string("Unable to obtain domain's referenced composite: ") +
1022  indxStr)
1023  .c_str());
1024  }
1025 }
1026 
1027 void MeshGraphXml::ReadEdges()
1028 {
1029  CurveMap::iterator it;
1030 
1031  /// Look for elements in ELEMENT block.
1032  TiXmlElement *field = m_xmlGeom->FirstChildElement("EDGE");
1033 
1034  ASSERTL0(field, "Unable to find EDGE tag in file.");
1035 
1036  /// All elements are of the form: "<E ID="#"> ... </E>", with
1037  /// ? being the element type.
1038  /// Read the ID field first.
1039  TiXmlElement *edge = field->FirstChildElement("E");
1040 
1041  /// Since all edge data is one big text block, we need to accumulate
1042  /// all TINYXML_TEXT data and then parse it. This approach effectively
1043  /// skips
1044  /// all comments or other node types since we only care about the
1045  /// edge list. We cannot handle missing edge numbers as we could
1046  /// with missing element numbers due to the text block format.
1047  std::string edgeStr;
1048  int indx;
1049 
1050  while (edge)
1051  {
1052  int err = edge->QueryIntAttribute("ID", &indx);
1053  ASSERTL0(err == TIXML_SUCCESS, "Unable to read edge attribute ID.");
1054 
1055  TiXmlNode *child = edge->FirstChild();
1056  edgeStr.clear();
1057  if (child->Type() == TiXmlNode::TINYXML_TEXT)
1058  {
1059  edgeStr += child->ToText()->ValueStr();
1060  }
1061 
1062  /// Now parse out the edges, three fields at a time.
1063  int vertex1, vertex2;
1064  std::istringstream edgeDataStrm(edgeStr.c_str());
1065 
1066  try
1067  {
1068  while (!edgeDataStrm.fail())
1069  {
1070  edgeDataStrm >> vertex1 >> vertex2;
1071 
1072  // Must check after the read because we
1073  // may be at the end and not know it. If
1074  // we are at the end we will add a
1075  // duplicate of the last entry if we don't
1076  // check here.
1077  if (!edgeDataStrm.fail())
1078  {
1079  PointGeomSharedPtr vertices[2] = {GetVertex(vertex1),
1080  GetVertex(vertex2)};
1081  SegGeomSharedPtr edge;
1082  it = m_curvedEdges.find(indx);
1083 
1084  if (it == m_curvedEdges.end())
1085  {
1087  indx, m_spaceDimension, vertices);
1088  }
1089  else
1090  {
1092  indx, m_spaceDimension, vertices, it->second);
1093  }
1094 
1095  m_segGeoms[indx] = edge;
1096  }
1097  }
1098  }
1099  catch (...)
1100  {
1101  NEKERROR(
1102  ErrorUtil::efatal,
1103  (std::string("Unable to read edge data: ") + edgeStr).c_str());
1104  }
1105 
1106  edge = edge->NextSiblingElement("E");
1107  }
1108 }
1109 
1110 void MeshGraphXml::ReadFaces()
1111 {
1112  /// Look for elements in FACE block.
1113  TiXmlElement *field = m_xmlGeom->FirstChildElement("FACE");
1114 
1115  ASSERTL0(field, "Unable to find FACE tag in file.");
1116 
1117  /// All faces are of the form: "<? ID="#"> ... </?>", with
1118  /// ? being an element type (either Q or T).
1119  /// They might be in compressed format and so then need upacking.
1120 
1121  TiXmlElement *element = field->FirstChildElement();
1122  CurveMap::iterator it;
1123 
1124  while (element)
1125  {
1126  std::string elementType(element->ValueStr());
1127 
1128  ASSERTL0(elementType == "Q" || elementType == "T",
1129  (std::string("Unknown 3D face type: ") + elementType).c_str());
1130 
1131  /// Read id attribute.
1132  int indx;
1133  int err = element->QueryIntAttribute("ID", &indx);
1134  ASSERTL0(err == TIXML_SUCCESS, "Unable to read face attribute ID.");
1135 
1136  /// See if this face has curves.
1137  it = m_curvedFaces.find(indx);
1138 
1139  /// Read text element description.
1140  TiXmlNode *elementChild = element->FirstChild();
1141  std::string elementStr;
1142  while (elementChild)
1143  {
1144  if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
1145  {
1146  elementStr += elementChild->ToText()->ValueStr();
1147  }
1148  elementChild = elementChild->NextSibling();
1149  }
1150 
1151  ASSERTL0(!elementStr.empty(), "Unable to read face description body.");
1152 
1153  /// Parse out the element components corresponding to type of
1154  /// element.
1155  if (elementType == "T")
1156  {
1157  // Read three edge numbers
1158  int edge1, edge2, edge3;
1159  std::istringstream elementDataStrm(elementStr.c_str());
1160 
1161  try
1162  {
1163  elementDataStrm >> edge1;
1164  elementDataStrm >> edge2;
1165  elementDataStrm >> edge3;
1166 
1167  ASSERTL0(
1168  !elementDataStrm.fail(),
1169  (std::string("Unable to read face data for TRIANGLE: ") +
1170  elementStr)
1171  .c_str());
1172 
1173  /// Create a TriGeom to hold the new definition.
1174  SegGeomSharedPtr edges[TriGeom::kNedges] = {
1175  GetSegGeom(edge1), GetSegGeom(edge2), GetSegGeom(edge3)};
1176 
1177  TriGeomSharedPtr trigeom;
1178 
1179  if (it == m_curvedFaces.end())
1180  {
1181  trigeom =
1183  }
1184  else
1185  {
1187  indx, edges, it->second);
1188  }
1189 
1190  trigeom->SetGlobalID(indx);
1191 
1192  m_triGeoms[indx] = trigeom;
1193  }
1194  catch (...)
1195  {
1196  NEKERROR(
1197  ErrorUtil::efatal,
1198  (std::string("Unable to read face data for TRIANGLE: ") +
1199  elementStr)
1200  .c_str());
1201  }
1202  }
1203  else if (elementType == "Q")
1204  {
1205  // Read four edge numbers
1206  int edge1, edge2, edge3, edge4;
1207  std::istringstream elementDataStrm(elementStr.c_str());
1208 
1209  try
1210  {
1211  elementDataStrm >> edge1;
1212  elementDataStrm >> edge2;
1213  elementDataStrm >> edge3;
1214  elementDataStrm >> edge4;
1215 
1216  ASSERTL0(!elementDataStrm.fail(),
1217  (std::string("Unable to read face data for QUAD: ") +
1218  elementStr)
1219  .c_str());
1220 
1221  /// Create a QuadGeom to hold the new definition.
1222  SegGeomSharedPtr edges[QuadGeom::kNedges] = {
1223  GetSegGeom(edge1), GetSegGeom(edge2), GetSegGeom(edge3),
1224  GetSegGeom(edge4)};
1225 
1226  QuadGeomSharedPtr quadgeom;
1227 
1228  if (it == m_curvedFaces.end())
1229  {
1230  quadgeom =
1232  }
1233  else
1234  {
1236  indx, edges, it->second);
1237  }
1238  quadgeom->SetGlobalID(indx);
1239 
1240  m_quadGeoms[indx] = quadgeom;
1241  }
1242  catch (...)
1243  {
1244  NEKERROR(ErrorUtil::efatal,
1245  (std::string("Unable to read face data for QUAD: ") +
1246  elementStr)
1247  .c_str());
1248  }
1249  }
1250  // Keep looking
1251  element = element->NextSiblingElement();
1252  }
1253 }
1254 
1255 void MeshGraphXml::ReadElements()
1256 {
1257  switch (m_meshDimension)
1258  {
1259  case 1:
1260  ReadElements1D();
1261  break;
1262  case 2:
1263  ReadElements2D();
1264  break;
1265  case 3:
1266  ReadElements3D();
1267  break;
1268  }
1269 }
1270 
1271 void MeshGraphXml::ReadElements1D()
1272 {
1273  TiXmlElement *field = NULL;
1274 
1275  /// Look for elements in ELEMENT block.
1276  field = m_xmlGeom->FirstChildElement("ELEMENT");
1277 
1278  ASSERTL0(field, "Unable to find ELEMENT tag in file.");
1279 
1280  /// All elements are of the form: "<S ID = n> ... </S>", with
1281  /// ? being the element type.
1282 
1283  TiXmlElement *segment = field->FirstChildElement("S");
1284  CurveMap::iterator it;
1285 
1286  while (segment)
1287  {
1288  int indx;
1289  int err = segment->QueryIntAttribute("ID", &indx);
1290  ASSERTL0(err == TIXML_SUCCESS, "Unable to read element attribute ID.");
1291 
1292  TiXmlNode *elementChild = segment->FirstChild();
1293  while (elementChild && elementChild->Type() != TiXmlNode::TINYXML_TEXT)
1294  {
1295  elementChild = elementChild->NextSibling();
1296  }
1297 
1298  ASSERTL0(elementChild, "Unable to read element description body.");
1299  std::string elementStr = elementChild->ToText()->ValueStr();
1300 
1301  /// Parse out the element components corresponding to type of
1302  /// element.
1303  /// Read two vertex numbers
1304  int vertex1, vertex2;
1305  std::istringstream elementDataStrm(elementStr.c_str());
1306 
1307  try
1308  {
1309  elementDataStrm >> vertex1;
1310  elementDataStrm >> vertex2;
1311 
1312  ASSERTL0(!elementDataStrm.fail(),
1313  (std::string("Unable to read element data for SEGMENT: ") +
1314  elementStr)
1315  .c_str());
1316 
1317  PointGeomSharedPtr vertices[2] = {GetVertex(vertex1),
1318  GetVertex(vertex2)};
1319  SegGeomSharedPtr seg;
1320  it = m_curvedEdges.find(indx);
1321 
1322  if (it == m_curvedEdges.end())
1323  {
1325  indx, m_spaceDimension, vertices);
1326  seg->SetGlobalID(indx); // Set global mesh id
1327  }
1328  else
1329  {
1331  indx, m_spaceDimension, vertices, it->second);
1332  seg->SetGlobalID(indx); // Set global mesh id
1333  }
1334  seg->SetGlobalID(indx);
1335  m_segGeoms[indx] = seg;
1336  }
1337  catch (...)
1338  {
1339  NEKERROR(ErrorUtil::efatal,
1340  (std::string("Unable to read element data for segment: ") +
1341  elementStr)
1342  .c_str());
1343  }
1344  /// Keep looking for additional segments
1345  segment = segment->NextSiblingElement("S");
1346  }
1347 }
1348 
1349 void MeshGraphXml::ReadElements2D()
1350 {
1351  /// Look for elements in ELEMENT block.
1352  TiXmlElement *field = m_xmlGeom->FirstChildElement("ELEMENT");
1353 
1354  ASSERTL0(field, "Unable to find ELEMENT tag in file.");
1355 
1356  // Set up curve map for curved elements on an embedded manifold.
1357  CurveMap::iterator it;
1358 
1359  /// All elements are of the form: "<? ID="#"> ... </?>", with
1360  /// ? being the element type.
1361 
1362  TiXmlElement *element = field->FirstChildElement();
1363 
1364  while (element)
1365  {
1366  std::string elementType(element->ValueStr());
1367 
1368  ASSERTL0(
1369  elementType == "Q" || elementType == "T",
1370  (std::string("Unknown 2D element type: ") + elementType).c_str());
1371 
1372  /// Read id attribute.
1373  int indx;
1374  int err = element->QueryIntAttribute("ID", &indx);
1375  ASSERTL0(err == TIXML_SUCCESS, "Unable to read element attribute ID.");
1376 
1377  it = m_curvedFaces.find(indx);
1378 
1379  /// Read text element description.
1380  TiXmlNode *elementChild = element->FirstChild();
1381  std::string elementStr;
1382  while (elementChild)
1383  {
1384  if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
1385  {
1386  elementStr += elementChild->ToText()->ValueStr();
1387  }
1388  elementChild = elementChild->NextSibling();
1389  }
1390 
1391  ASSERTL0(!elementStr.empty(),
1392  "Unable to read element description body.");
1393 
1394  /// Parse out the element components corresponding to type of
1395  /// element.
1396  if (elementType == "T")
1397  {
1398  // Read three edge numbers
1399  int edge1, edge2, edge3;
1400  std::istringstream elementDataStrm(elementStr.c_str());
1401 
1402  try
1403  {
1404  elementDataStrm >> edge1;
1405  elementDataStrm >> edge2;
1406  elementDataStrm >> edge3;
1407 
1408  ASSERTL0(
1409  !elementDataStrm.fail(),
1410  (std::string("Unable to read element data for TRIANGLE: ") +
1411  elementStr)
1412  .c_str());
1413 
1414  /// Create a TriGeom to hold the new definition.
1415  SegGeomSharedPtr edges[TriGeom::kNedges] = {
1416  GetSegGeom(edge1), GetSegGeom(edge2), GetSegGeom(edge3)};
1417 
1418  TriGeomSharedPtr trigeom;
1419  if (it == m_curvedFaces.end())
1420  {
1421  trigeom =
1423  }
1424  else
1425  {
1427  indx, edges, it->second);
1428  }
1429  trigeom->SetGlobalID(indx);
1430 
1431  m_triGeoms[indx] = trigeom;
1432  }
1433  catch (...)
1434  {
1435  NEKERROR(
1436  ErrorUtil::efatal,
1437  (std::string("Unable to read element data for TRIANGLE: ") +
1438  elementStr)
1439  .c_str());
1440  }
1441  }
1442  else if (elementType == "Q")
1443  {
1444  // Read four edge numbers
1445  int edge1, edge2, edge3, edge4;
1446  std::istringstream elementDataStrm(elementStr.c_str());
1447 
1448  try
1449  {
1450  elementDataStrm >> edge1;
1451  elementDataStrm >> edge2;
1452  elementDataStrm >> edge3;
1453  elementDataStrm >> edge4;
1454 
1455  ASSERTL0(
1456  !elementDataStrm.fail(),
1457  (std::string("Unable to read element data for QUAD: ") +
1458  elementStr)
1459  .c_str());
1460 
1461  /// Create a QuadGeom to hold the new definition.
1462  SegGeomSharedPtr edges[QuadGeom::kNedges] = {
1463  GetSegGeom(edge1), GetSegGeom(edge2), GetSegGeom(edge3),
1464  GetSegGeom(edge4)};
1465 
1466  QuadGeomSharedPtr quadgeom;
1467  if (it == m_curvedFaces.end())
1468  {
1469  quadgeom =
1471  }
1472  else
1473  {
1475  indx, edges, it->second);
1476  }
1477  quadgeom->SetGlobalID(indx);
1478 
1479  m_quadGeoms[indx] = quadgeom;
1480  }
1481  catch (...)
1482  {
1483  NEKERROR(
1484  ErrorUtil::efatal,
1485  (std::string("Unable to read element data for QUAD: ") +
1486  elementStr)
1487  .c_str());
1488  }
1489  }
1490  /// Keep looking
1491  element = element->NextSiblingElement();
1492  }
1493 }
1494 
1495 void MeshGraphXml::ReadElements3D()
1496 {
1497  /// Look for elements in ELEMENT block.
1498  TiXmlElement *field = m_xmlGeom->FirstChildElement("ELEMENT");
1499 
1500  ASSERTL0(field, "Unable to find ELEMENT tag in file.");
1501 
1502  /// All elements are of the form: "<? ID="#"> ... </?>", with
1503  /// ? being the element type.
1504 
1505  TiXmlElement *element = field->FirstChildElement();
1506 
1507  while (element)
1508  {
1509  std::string elementType(element->ValueStr());
1510 
1511  // A - tet, P - pyramid, R - prism, H - hex
1512  ASSERTL0(
1513  elementType == "A" || elementType == "P" || elementType == "R" ||
1514  elementType == "H",
1515  (std::string("Unknown 3D element type: ") + elementType).c_str());
1516 
1517  /// Read id attribute.
1518  int indx;
1519  int err = element->QueryIntAttribute("ID", &indx);
1520  ASSERTL0(err == TIXML_SUCCESS, "Unable to read element attribute ID.");
1521 
1522  /// Read text element description.
1523  TiXmlNode *elementChild = element->FirstChild();
1524  std::string elementStr;
1525  while (elementChild)
1526  {
1527  if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
1528  {
1529  elementStr += elementChild->ToText()->ValueStr();
1530  }
1531  elementChild = elementChild->NextSibling();
1532  }
1533 
1534  ASSERTL0(!elementStr.empty(),
1535  "Unable to read element description body.");
1536 
1537  std::istringstream elementDataStrm(elementStr.c_str());
1538 
1539  /// Parse out the element components corresponding to type of
1540  /// element.
1541 
1542  // Tetrahedral
1543  if (elementType == "A")
1544  {
1545  try
1546  {
1547  /// Create arrays for the tri and quad faces.
1548  const int kNfaces = TetGeom::kNfaces;
1549  const int kNtfaces = TetGeom::kNtfaces;
1550  const int kNqfaces = TetGeom::kNqfaces;
1551  TriGeomSharedPtr tfaces[kNtfaces];
1552  int Ntfaces = 0;
1553  int Nqfaces = 0;
1554 
1555  /// Fill the arrays and make sure there aren't too many
1556  /// faces.
1557  std::stringstream errorstring;
1558  errorstring << "Element " << indx << " must have " << kNtfaces
1559  << " triangle face(s), and " << kNqfaces
1560  << " quadrilateral face(s).";
1561  for (int i = 0; i < kNfaces; i++)
1562  {
1563  int faceID;
1564  elementDataStrm >> faceID;
1565  Geometry2DSharedPtr face = GetGeometry2D(faceID);
1566  if (face == Geometry2DSharedPtr() ||
1567  (face->GetShapeType() != LibUtilities::eTriangle &&
1568  face->GetShapeType() != LibUtilities::eQuadrilateral))
1569  {
1570  std::stringstream errorstring;
1571  errorstring << "Element " << indx
1572  << " has invalid face: " << faceID;
1573  ASSERTL0(false, errorstring.str().c_str());
1574  }
1575  else if (face->GetShapeType() == LibUtilities::eTriangle)
1576  {
1577  ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1578  tfaces[Ntfaces++] =
1579  static_pointer_cast<TriGeom>(face);
1580  }
1581  else if (face->GetShapeType() ==
1583  {
1584  ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1585  }
1586  }
1587 
1588  /// Make sure all of the face indicies could be read, and
1589  /// that there weren't too few.
1590  ASSERTL0(!elementDataStrm.fail(),
1591  (std::string(
1592  "Unable to read element data for TETRAHEDRON: ") +
1593  elementStr)
1594  .c_str());
1595  ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1596  ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1597 
1598  TetGeomSharedPtr tetgeom(
1600 
1601  m_tetGeoms[indx] = tetgeom;
1602  PopulateFaceToElMap(tetgeom, kNfaces);
1603  }
1604  catch (...)
1605  {
1606  NEKERROR(ErrorUtil::efatal,
1607  (std::string(
1608  "Unable to read element data for TETRAHEDRON: ") +
1609  elementStr)
1610  .c_str());
1611  }
1612  }
1613  // Pyramid
1614  else if (elementType == "P")
1615  {
1616  try
1617  {
1618  /// Create arrays for the tri and quad faces.
1619  const int kNfaces = PyrGeom::kNfaces;
1620  const int kNtfaces = PyrGeom::kNtfaces;
1621  const int kNqfaces = PyrGeom::kNqfaces;
1622  Geometry2DSharedPtr faces[kNfaces];
1623  int Nfaces = 0;
1624  int Ntfaces = 0;
1625  int Nqfaces = 0;
1626 
1627  /// Fill the arrays and make sure there aren't too many
1628  /// faces.
1629  std::stringstream errorstring;
1630  errorstring << "Element " << indx << " must have " << kNtfaces
1631  << " triangle face(s), and " << kNqfaces
1632  << " quadrilateral face(s).";
1633  for (int i = 0; i < kNfaces; i++)
1634  {
1635  int faceID;
1636  elementDataStrm >> faceID;
1637  Geometry2DSharedPtr face = GetGeometry2D(faceID);
1638  if (face == Geometry2DSharedPtr() ||
1639  (face->GetShapeType() != LibUtilities::eTriangle &&
1640  face->GetShapeType() != LibUtilities::eQuadrilateral))
1641  {
1642  std::stringstream errorstring;
1643  errorstring << "Element " << indx
1644  << " has invalid face: " << faceID;
1645  ASSERTL0(false, errorstring.str().c_str());
1646  }
1647  else if (face->GetShapeType() == LibUtilities::eTriangle)
1648  {
1649  ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1650  faces[Nfaces++] =
1651  static_pointer_cast<TriGeom>(face);
1652  Ntfaces++;
1653  }
1654  else if (face->GetShapeType() ==
1656  {
1657  ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1658  faces[Nfaces++] =
1659  static_pointer_cast<QuadGeom>(face);
1660  Nqfaces++;
1661  }
1662  }
1663 
1664  /// Make sure all of the face indicies could be read, and
1665  /// that there weren't too few.
1666  ASSERTL0(
1667  !elementDataStrm.fail(),
1668  (std::string("Unable to read element data for PYRAMID: ") +
1669  elementStr)
1670  .c_str());
1671  ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1672  ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1673 
1674  PyrGeomSharedPtr pyrgeom(
1676 
1677  m_pyrGeoms[indx] = pyrgeom;
1678  PopulateFaceToElMap(pyrgeom, kNfaces);
1679  }
1680  catch (...)
1681  {
1682  NEKERROR(
1683  ErrorUtil::efatal,
1684  (std::string("Unable to read element data for PYRAMID: ") +
1685  elementStr)
1686  .c_str());
1687  }
1688  }
1689  // Prism
1690  else if (elementType == "R")
1691  {
1692  try
1693  {
1694  /// Create arrays for the tri and quad faces.
1695  const int kNfaces = PrismGeom::kNfaces;
1696  const int kNtfaces = PrismGeom::kNtfaces;
1697  const int kNqfaces = PrismGeom::kNqfaces;
1698  Geometry2DSharedPtr faces[kNfaces];
1699  int Ntfaces = 0;
1700  int Nqfaces = 0;
1701  int Nfaces = 0;
1702 
1703  /// Fill the arrays and make sure there aren't too many
1704  /// faces.
1705  std::stringstream errorstring;
1706  errorstring << "Element " << indx << " must have " << kNtfaces
1707  << " triangle face(s), and " << kNqfaces
1708  << " quadrilateral face(s).";
1709 
1710  for (int i = 0; i < kNfaces; i++)
1711  {
1712  int faceID;
1713  elementDataStrm >> faceID;
1714  Geometry2DSharedPtr face = GetGeometry2D(faceID);
1715  if (face == Geometry2DSharedPtr() ||
1716  (face->GetShapeType() != LibUtilities::eTriangle &&
1717  face->GetShapeType() != LibUtilities::eQuadrilateral))
1718  {
1719  std::stringstream errorstring;
1720  errorstring << "Element " << indx
1721  << " has invalid face: " << faceID;
1722  ASSERTL0(false, errorstring.str().c_str());
1723  }
1724  else if (face->GetShapeType() == LibUtilities::eTriangle)
1725  {
1726  ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1727  faces[Nfaces++] =
1728  std::static_pointer_cast<TriGeom>(face);
1729  Ntfaces++;
1730  }
1731  else if (face->GetShapeType() ==
1733  {
1734  ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1735  faces[Nfaces++] =
1736  std::static_pointer_cast<QuadGeom>(face);
1737  Nqfaces++;
1738  }
1739  }
1740 
1741  /// Make sure all of the face indicies could be read, and
1742  /// that there weren't too few.
1743  ASSERTL0(
1744  !elementDataStrm.fail(),
1745  (std::string("Unable to read element data for PRISM: ") +
1746  elementStr)
1747  .c_str());
1748  ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1749  ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1750 
1751  PrismGeomSharedPtr prismgeom(
1753 
1754  m_prismGeoms[indx] = prismgeom;
1755  PopulateFaceToElMap(prismgeom, kNfaces);
1756  }
1757  catch (...)
1758  {
1759  NEKERROR(
1760  ErrorUtil::efatal,
1761  (std::string("Unable to read element data for PRISM: ") +
1762  elementStr)
1763  .c_str());
1764  }
1765  }
1766  // Hexahedral
1767  else if (elementType == "H")
1768  {
1769  try
1770  {
1771  /// Create arrays for the tri and quad faces.
1772  const int kNfaces = HexGeom::kNfaces;
1773  const int kNtfaces = HexGeom::kNtfaces;
1774  const int kNqfaces = HexGeom::kNqfaces;
1775  // TriGeomSharedPtr tfaces[kNtfaces];
1776  QuadGeomSharedPtr qfaces[kNqfaces];
1777  int Ntfaces = 0;
1778  int Nqfaces = 0;
1779 
1780  /// Fill the arrays and make sure there aren't too many
1781  /// faces.
1782  std::stringstream errorstring;
1783  errorstring << "Element " << indx << " must have " << kNtfaces
1784  << " triangle face(s), and " << kNqfaces
1785  << " quadrilateral face(s).";
1786  for (int i = 0; i < kNfaces; i++)
1787  {
1788  int faceID;
1789  elementDataStrm >> faceID;
1790  Geometry2DSharedPtr face = GetGeometry2D(faceID);
1791  if (face == Geometry2DSharedPtr() ||
1792  (face->GetShapeType() != LibUtilities::eTriangle &&
1793  face->GetShapeType() != LibUtilities::eQuadrilateral))
1794  {
1795  std::stringstream errorstring;
1796  errorstring << "Element " << indx
1797  << " has invalid face: " << faceID;
1798  ASSERTL0(false, errorstring.str().c_str());
1799  }
1800  else if (face->GetShapeType() == LibUtilities::eTriangle)
1801  {
1802  ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1803  // tfaces[Ntfaces++] =
1804  // boost::static_pointer_cast<TriGeom>(face);
1805  }
1806  else if (face->GetShapeType() ==
1808  {
1809  ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1810  qfaces[Nqfaces++] =
1811  std::static_pointer_cast<QuadGeom>(face);
1812  }
1813  }
1814 
1815  /// Make sure all of the face indicies could be read, and
1816  /// that there weren't too few.
1817  ASSERTL0(!elementDataStrm.fail(),
1818  (std::string(
1819  "Unable to read element data for HEXAHEDRAL: ") +
1820  elementStr)
1821  .c_str());
1822  ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1823  ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1824 
1825  HexGeomSharedPtr hexgeom(
1827 
1828  m_hexGeoms[indx] = hexgeom;
1829  PopulateFaceToElMap(hexgeom, kNfaces);
1830  }
1831  catch (...)
1832  {
1833  NEKERROR(ErrorUtil::efatal,
1834  (std::string(
1835  "Unable to read element data for HEXAHEDRAL: ") +
1836  elementStr)
1837  .c_str());
1838  }
1839  }
1840  /// Keep looking
1841  element = element->NextSiblingElement();
1842  }
1843 }
1844 
1845 void MeshGraphXml::ReadComposites()
1846 {
1847  TiXmlElement *field = NULL;
1848 
1849  /// Look for elements in ELEMENT block.
1850  field = m_xmlGeom->FirstChildElement("COMPOSITE");
1851 
1852  ASSERTL0(field, "Unable to find COMPOSITE tag in file.");
1853 
1854  TiXmlElement *node = field->FirstChildElement("C");
1855 
1856  // Sequential counter for the composite numbers.
1857  int nextCompositeNumber = -1;
1858 
1859  while (node)
1860  {
1861  /// All elements are of the form: "<? ID="#"> ... </?>", with
1862  /// ? being the element type.
1863 
1864  nextCompositeNumber++;
1865 
1866  int indx;
1867  int err = node->QueryIntAttribute("ID", &indx);
1868  ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
1869  // ASSERTL0(indx == nextCompositeNumber, "Composite IDs must begin with
1870  // zero and be sequential.");
1871 
1872  TiXmlNode *compositeChild = node->FirstChild();
1873  // This is primarily to skip comments that may be present.
1874  // Comments appear as nodes just like elements.
1875  // We are specifically looking for text in the body
1876  // of the definition.
1877  while (compositeChild &&
1878  compositeChild->Type() != TiXmlNode::TINYXML_TEXT)
1879  {
1880  compositeChild = compositeChild->NextSibling();
1881  }
1882 
1883  ASSERTL0(compositeChild, "Unable to read composite definition body.");
1884  std::string compositeStr = compositeChild->ToText()->ValueStr();
1885 
1886  /// Parse out the element components corresponding to type of element.
1887 
1888  std::istringstream compositeDataStrm(compositeStr.c_str());
1889 
1890  try
1891  {
1892  bool first = true;
1893  std::string prevCompositeElementStr;
1894 
1895  while (!compositeDataStrm.fail())
1896  {
1897  std::string compositeElementStr;
1898  compositeDataStrm >> compositeElementStr;
1899 
1900  if (!compositeDataStrm.fail())
1901  {
1902  if (first)
1903  {
1904  first = false;
1905 
1906  CompositeSharedPtr curVector =
1908  m_meshComposites[indx] = curVector;
1909  }
1910 
1911  if (compositeElementStr.length() > 0)
1912  {
1913  ResolveGeomRef(prevCompositeElementStr,
1914  compositeElementStr,
1915  m_meshComposites[indx]);
1916  }
1917  prevCompositeElementStr = compositeElementStr;
1918  }
1919  }
1920  }
1921  catch (...)
1922  {
1923  NEKERROR(
1924  ErrorUtil::efatal,
1925  (std::string("Unable to read COMPOSITE data for composite: ") +
1926  compositeStr)
1927  .c_str());
1928  }
1929 
1930  /// Keep looking for additional composite definitions.
1931  node = node->NextSiblingElement("C");
1932  }
1933 
1934  ASSERTL0(nextCompositeNumber >= 0,
1935  "At least one composite must be specified.");
1936 }
1937 
1938 void MeshGraphXml::ResolveGeomRef(const std::string &prevToken,
1939  const std::string &token,
1940  CompositeSharedPtr &composite)
1941 {
1942  switch (m_meshDimension)
1943  {
1944  case 1:
1945  ResolveGeomRef1D(prevToken, token, composite);
1946  break;
1947  case 2:
1948  ResolveGeomRef2D(prevToken, token, composite);
1949  break;
1950  case 3:
1951  ResolveGeomRef3D(prevToken, token, composite);
1952  break;
1953  }
1954 }
1955 
1956 void MeshGraphXml::ResolveGeomRef1D(const std::string &prevToken,
1957  const std::string &token,
1958  CompositeSharedPtr &composite)
1959 {
1960  try
1961  {
1962  std::istringstream tokenStream(token);
1963  std::istringstream prevTokenStream(prevToken);
1964 
1965  char type;
1966  char prevType;
1967 
1968  tokenStream >> type;
1969 
1970  std::string::size_type indxBeg = token.find_first_of('[') + 1;
1971  std::string::size_type indxEnd = token.find_last_of(']') - 1;
1972 
1973  ASSERTL0(
1974  indxBeg <= indxEnd,
1975  (std::string("Error reading index definition:") + token).c_str());
1976 
1977  std::string indxStr = token.substr(indxBeg, indxEnd - indxBeg + 1);
1978 
1979  typedef vector<unsigned int> SeqVectorType;
1980  SeqVectorType seqVector;
1981 
1982  if (!ParseUtils::GenerateSeqVector(indxStr.c_str(), seqVector))
1983  {
1984  NEKERROR(ErrorUtil::efatal,
1985  (std::string("Ill-formed sequence definition: ") + indxStr)
1986  .c_str());
1987  }
1988 
1989  prevTokenStream >> prevType;
1990 
1991  // All composites must be of the same dimension.
1992  bool validSequence =
1993  (prevToken.empty() || // No previous, then current is just fine.
1994  (type == 'V' && prevType == 'V') ||
1995  (type == 'S' && prevType == 'S'));
1996 
1997  ASSERTL0(validSequence,
1998  (std::string("Invalid combination of composite items: ") +
1999  type + " and " + prevType + ".")
2000  .c_str());
2001 
2002  switch (type)
2003  {
2004  case 'V': // Vertex
2005  for (SeqVectorType::iterator iter = seqVector.begin();
2006  iter != seqVector.end(); ++iter)
2007  {
2008  if (m_vertSet.find(*iter) == m_vertSet.end())
2009  {
2010  char errStr[16] = "";
2011  ::sprintf(errStr, "%d", *iter);
2012  NEKERROR(
2013  ErrorUtil::ewarning,
2014  (std::string("Unknown vertex index: ") + errStr)
2015  .c_str());
2016  }
2017  else
2018  {
2019  composite->m_geomVec.push_back(m_vertSet[*iter]);
2020  }
2021  }
2022  break;
2023 
2024  case 'S': // Segment
2025  for (SeqVectorType::iterator iter = seqVector.begin();
2026  iter != seqVector.end(); ++iter)
2027  {
2028  if (m_segGeoms.find(*iter) == m_segGeoms.end())
2029  {
2030  char errStr[16] = "";
2031  ::sprintf(errStr, "%d", *iter);
2032  NEKERROR(
2033  ErrorUtil::ewarning,
2034  (std::string("Unknown segment index: ") + errStr)
2035  .c_str());
2036  }
2037  else
2038  {
2039  composite->m_geomVec.push_back(m_segGeoms[*iter]);
2040  }
2041  }
2042  break;
2043 
2044  default:
2045  NEKERROR(ErrorUtil::efatal,
2046  (std::string("Unrecognized composite token: ") + token)
2047  .c_str());
2048  }
2049  }
2050  catch (...)
2051  {
2052  NEKERROR(ErrorUtil::efatal,
2053  (std::string("Problem processing composite token: ") + token)
2054  .c_str());
2055  }
2056 
2057  return;
2058 }
2059 
2060 void MeshGraphXml::ResolveGeomRef2D(const std::string &prevToken,
2061  const std::string &token,
2062  CompositeSharedPtr &composite)
2063 {
2064  try
2065  {
2066  std::istringstream tokenStream(token);
2067  std::istringstream prevTokenStream(prevToken);
2068 
2069  char type;
2070  char prevType;
2071 
2072  tokenStream >> type;
2073 
2074  std::string::size_type indxBeg = token.find_first_of('[') + 1;
2075  std::string::size_type indxEnd = token.find_last_of(']') - 1;
2076 
2077  ASSERTL0(
2078  indxBeg <= indxEnd,
2079  (std::string("Error reading index definition:") + token).c_str());
2080 
2081  std::string indxStr = token.substr(indxBeg, indxEnd - indxBeg + 1);
2082  std::vector<unsigned int> seqVector;
2083  std::vector<unsigned int>::iterator seqIter;
2084 
2085  bool err = ParseUtils::GenerateSeqVector(indxStr.c_str(), seqVector);
2086 
2087  ASSERTL0(err,
2088  (std::string("Error reading composite elements: ") + indxStr)
2089  .c_str());
2090 
2091  prevTokenStream >> prevType;
2092 
2093  // All composites must be of the same dimension.
2094  bool validSequence =
2095  (prevToken.empty() || // No previous, then current is just fine.
2096  (type == 'V' && prevType == 'V') ||
2097  (type == 'E' && prevType == 'E') ||
2098  ((type == 'T' || type == 'Q') &&
2099  (prevType == 'T' || prevType == 'Q')));
2100 
2101  ASSERTL0(validSequence,
2102  (std::string("Invalid combination of composite items: ") +
2103  type + " and " + prevType + ".")
2104  .c_str());
2105 
2106  switch (type)
2107  {
2108  case 'E': // Edge
2109  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2110  ++seqIter)
2111  {
2112  if (m_segGeoms.find(*seqIter) == m_segGeoms.end())
2113  {
2114  char errStr[16] = "";
2115  ::sprintf(errStr, "%d", *seqIter);
2116  NEKERROR(ErrorUtil::ewarning,
2117  (std::string("Unknown edge index: ") + errStr)
2118  .c_str());
2119  }
2120  else
2121  {
2122  composite->m_geomVec.push_back(m_segGeoms[*seqIter]);
2123  }
2124  }
2125  break;
2126 
2127  case 'T': // Triangle
2128  {
2129  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2130  ++seqIter)
2131  {
2132  if (m_triGeoms.count(*seqIter) == 0)
2133  {
2134  char errStr[16] = "";
2135  ::sprintf(errStr, "%d", *seqIter);
2136  NEKERROR(
2137  ErrorUtil::ewarning,
2138  (std::string("Unknown triangle index: ") + errStr)
2139  .c_str());
2140  }
2141  else
2142  {
2143  if (CheckRange(*m_triGeoms[*seqIter]))
2144  {
2145  composite->m_geomVec.push_back(
2146  m_triGeoms[*seqIter]);
2147  }
2148  }
2149  }
2150  }
2151  break;
2152 
2153  case 'Q': // Quad
2154  {
2155  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2156  ++seqIter)
2157  {
2158  if (m_quadGeoms.count(*seqIter) == 0)
2159  {
2160  char errStr[16] = "";
2161  ::sprintf(errStr, "%d", *seqIter);
2162  NEKERROR(ErrorUtil::ewarning,
2163  (std::string("Unknown quad index: ") + errStr +
2164  std::string(" in Composite section"))
2165  .c_str());
2166  }
2167  else
2168  {
2169  if (CheckRange(*m_quadGeoms[*seqIter]))
2170  {
2171  composite->m_geomVec.push_back(
2172  m_quadGeoms[*seqIter]);
2173  }
2174  }
2175  }
2176  }
2177  break;
2178 
2179  case 'V': // Vertex
2180  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2181  ++seqIter)
2182  {
2183  if (*seqIter >= m_vertSet.size())
2184  {
2185  char errStr[16] = "";
2186  ::sprintf(errStr, "%d", *seqIter);
2187  NEKERROR(
2188  ErrorUtil::ewarning,
2189  (std::string("Unknown vertex index: ") + errStr)
2190  .c_str());
2191  }
2192  else
2193  {
2194  composite->m_geomVec.push_back(m_vertSet[*seqIter]);
2195  }
2196  }
2197  break;
2198 
2199  default:
2200  NEKERROR(ErrorUtil::efatal,
2201  (std::string("Unrecognized composite token: ") + token)
2202  .c_str());
2203  }
2204  }
2205  catch (...)
2206  {
2207  NEKERROR(ErrorUtil::efatal,
2208  (std::string("Problem processing composite token: ") + token)
2209  .c_str());
2210  }
2211 
2212  return;
2213 }
2214 
2215 void MeshGraphXml::ResolveGeomRef3D(const std::string &prevToken,
2216  const std::string &token,
2217  CompositeSharedPtr &composite)
2218 {
2219  try
2220  {
2221  std::istringstream tokenStream(token);
2222  std::istringstream prevTokenStream(prevToken);
2223 
2224  char type;
2225  char prevType;
2226 
2227  tokenStream >> type;
2228 
2229  std::string::size_type indxBeg = token.find_first_of('[') + 1;
2230  std::string::size_type indxEnd = token.find_last_of(']') - 1;
2231 
2232  ASSERTL0(
2233  indxBeg <= indxEnd,
2234  (std::string("Error reading index definition:") + token).c_str());
2235 
2236  std::string indxStr = token.substr(indxBeg, indxEnd - indxBeg + 1);
2237 
2238  std::vector<unsigned int> seqVector;
2239  std::vector<unsigned int>::iterator seqIter;
2240 
2241  bool err = ParseUtils::GenerateSeqVector(indxStr.c_str(), seqVector);
2242 
2243  ASSERTL0(err,
2244  (std::string("Error reading composite elements: ") + indxStr)
2245  .c_str());
2246 
2247  prevTokenStream >> prevType;
2248 
2249  // All composites must be of the same dimension. This map makes things
2250  // clean to compare.
2251  map<char, int> typeMap;
2252  typeMap['V'] = 1; // Vertex
2253  typeMap['E'] = 1; // Edge
2254  typeMap['T'] = 2; // Triangle
2255  typeMap['Q'] = 2; // Quad
2256  typeMap['A'] = 3; // Tet
2257  typeMap['P'] = 3; // Pyramid
2258  typeMap['R'] = 3; // Prism
2259  typeMap['H'] = 3; // Hex
2260 
2261  // Make sure only geoms of the same dimension are combined.
2262  bool validSequence =
2263  (prevToken.empty() || (typeMap[type] == typeMap[prevType]));
2264 
2265  ASSERTL0(validSequence,
2266  (std::string("Invalid combination of composite items: ") +
2267  type + " and " + prevType + ".")
2268  .c_str());
2269 
2270  switch (type)
2271  {
2272  case 'V': // Vertex
2273  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2274  ++seqIter)
2275  {
2276  if (m_vertSet.find(*seqIter) == m_vertSet.end())
2277  {
2278  char errStr[16] = "";
2279  ::sprintf(errStr, "%d", *seqIter);
2280  NEKERROR(
2281  ErrorUtil::ewarning,
2282  (std::string("Unknown vertex index: ") + errStr)
2283  .c_str());
2284  }
2285  else
2286  {
2287  composite->m_geomVec.push_back(m_vertSet[*seqIter]);
2288  }
2289  }
2290  break;
2291 
2292  case 'E': // Edge
2293  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2294  ++seqIter)
2295  {
2296  if (m_segGeoms.find(*seqIter) == m_segGeoms.end())
2297  {
2298  char errStr[16] = "";
2299  ::sprintf(errStr, "%d", *seqIter);
2300  NEKERROR(ErrorUtil::ewarning,
2301  (std::string("Unknown edge index: ") + errStr)
2302  .c_str());
2303  }
2304  else
2305  {
2306  composite->m_geomVec.push_back(m_segGeoms[*seqIter]);
2307  }
2308  }
2309  break;
2310 
2311  case 'F': // Face
2312  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2313  ++seqIter)
2314  {
2315  Geometry2DSharedPtr face = GetGeometry2D(*seqIter);
2316  if (face == Geometry2DSharedPtr())
2317  {
2318  char errStr[16] = "";
2319  ::sprintf(errStr, "%d", *seqIter);
2320  NEKERROR(ErrorUtil::ewarning,
2321  (std::string("Unknown face index: ") + errStr)
2322  .c_str());
2323  }
2324  else
2325  {
2326  if (CheckRange(*face))
2327  {
2328  composite->m_geomVec.push_back(face);
2329  }
2330  }
2331  }
2332  break;
2333 
2334  case 'T': // Triangle
2335  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2336  ++seqIter)
2337  {
2338  if (m_triGeoms.find(*seqIter) == m_triGeoms.end())
2339  {
2340  char errStr[16] = "";
2341  ::sprintf(errStr, "%d", *seqIter);
2342  NEKERROR(
2343  ErrorUtil::ewarning,
2344  (std::string("Unknown triangle index: ") + errStr)
2345  .c_str());
2346  }
2347  else
2348  {
2349  if (CheckRange(*m_triGeoms[*seqIter]))
2350  {
2351  composite->m_geomVec.push_back(
2352  m_triGeoms[*seqIter]);
2353  }
2354  }
2355  }
2356  break;
2357 
2358  case 'Q': // Quad
2359  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2360  ++seqIter)
2361  {
2362  if (m_quadGeoms.find(*seqIter) == m_quadGeoms.end())
2363  {
2364  char errStr[16] = "";
2365  ::sprintf(errStr, "%d", *seqIter);
2366  NEKERROR(ErrorUtil::ewarning,
2367  (std::string("Unknown quad index: ") + errStr)
2368  .c_str());
2369  }
2370  else
2371  {
2372  if (CheckRange(*m_quadGeoms[*seqIter]))
2373  {
2374  composite->m_geomVec.push_back(
2375  m_quadGeoms[*seqIter]);
2376  }
2377  }
2378  }
2379  break;
2380 
2381  // Tetrahedron
2382  case 'A':
2383  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2384  ++seqIter)
2385  {
2386  if (m_tetGeoms.find(*seqIter) == m_tetGeoms.end())
2387  {
2388  char errStr[16] = "";
2389  ::sprintf(errStr, "%d", *seqIter);
2390  NEKERROR(ErrorUtil::ewarning,
2391  (std::string("Unknown tet index: ") + errStr)
2392  .c_str());
2393  }
2394  else
2395  {
2396  if (CheckRange(*m_tetGeoms[*seqIter]))
2397  {
2398  composite->m_geomVec.push_back(
2399  m_tetGeoms[*seqIter]);
2400  }
2401  }
2402  }
2403  break;
2404 
2405  // Pyramid
2406  case 'P':
2407  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2408  ++seqIter)
2409  {
2410  if (m_pyrGeoms.find(*seqIter) == m_pyrGeoms.end())
2411  {
2412  char errStr[16] = "";
2413  ::sprintf(errStr, "%d", *seqIter);
2414  NEKERROR(
2415  ErrorUtil::ewarning,
2416  (std::string("Unknown pyramid index: ") + errStr)
2417  .c_str());
2418  }
2419  else
2420  {
2421  if (CheckRange(*m_pyrGeoms[*seqIter]))
2422  {
2423  composite->m_geomVec.push_back(
2424  m_pyrGeoms[*seqIter]);
2425  }
2426  }
2427  }
2428  break;
2429 
2430  // Prism
2431  case 'R':
2432  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2433  ++seqIter)
2434  {
2435  if (m_prismGeoms.find(*seqIter) == m_prismGeoms.end())
2436  {
2437  char errStr[16] = "";
2438  ::sprintf(errStr, "%d", *seqIter);
2439  NEKERROR(ErrorUtil::ewarning,
2440  (std::string("Unknown prism index: ") + errStr)
2441  .c_str());
2442  }
2443  else
2444  {
2445  if (CheckRange(*m_prismGeoms[*seqIter]))
2446  {
2447  composite->m_geomVec.push_back(
2448  m_prismGeoms[*seqIter]);
2449  }
2450  }
2451  }
2452  break;
2453 
2454  // Hex
2455  case 'H':
2456  for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2457  ++seqIter)
2458  {
2459  if (m_hexGeoms.find(*seqIter) == m_hexGeoms.end())
2460  {
2461  char errStr[16] = "";
2462  ::sprintf(errStr, "%d", *seqIter);
2463  NEKERROR(ErrorUtil::ewarning,
2464  (std::string("Unknown hex index: ") + errStr)
2465  .c_str());
2466  }
2467  else
2468  {
2469  if (CheckRange(*m_hexGeoms[*seqIter]))
2470  {
2471  composite->m_geomVec.push_back(
2472  m_hexGeoms[*seqIter]);
2473  }
2474  }
2475  }
2476  break;
2477 
2478  default:
2479  NEKERROR(ErrorUtil::efatal,
2480  (std::string("Unrecognized composite token: ") + token)
2481  .c_str());
2482  }
2483  }
2484  catch (...)
2485  {
2486  NEKERROR(ErrorUtil::efatal,
2487  (std::string("Problem processing composite token: ") + token)
2488  .c_str());
2489  }
2490 
2491  return;
2492 }
2493 
2494 void MeshGraphXml::WriteVertices(TiXmlElement *geomTag, PointGeomMap &verts)
2495 {
2496  TiXmlElement *vertTag = new TiXmlElement("VERTEX");
2497 
2498  for (auto &i : verts)
2499  {
2500  stringstream s;
2501  s << scientific << setprecision(8) << (*i.second)(0) << " "
2502  << (*i.second)(1) << " " << (*i.second)(2);
2503  TiXmlElement *v = new TiXmlElement("V");
2504  v->SetAttribute("ID", i.second->GetGlobalID());
2505  v->LinkEndChild(new TiXmlText(s.str()));
2506  vertTag->LinkEndChild(v);
2507  }
2508 
2509  geomTag->LinkEndChild(vertTag);
2510 }
2511 
2512 void MeshGraphXml::WriteEdges(TiXmlElement *geomTag, SegGeomMap &edges)
2513 {
2514  TiXmlElement *edgeTag =
2515  new TiXmlElement(m_meshDimension == 1 ? "ELEMENT" : "EDGE");
2516  string tag = m_meshDimension == 1 ? "S" : "E";
2517 
2518  for (auto &i : edges)
2519  {
2520  stringstream s;
2521  SegGeomSharedPtr seg = i.second;
2522  s << seg->GetVid(0) << " " << seg->GetVid(1);
2523  TiXmlElement *e = new TiXmlElement(tag);
2524  e->SetAttribute("ID", i.first);
2525  e->LinkEndChild(new TiXmlText(s.str()));
2526  edgeTag->LinkEndChild(e);
2527  }
2528 
2529  geomTag->LinkEndChild(edgeTag);
2530 }
2531 
2532 void MeshGraphXml::WriteTris(TiXmlElement *faceTag, TriGeomMap &tris)
2533 {
2534  string tag = "T";
2535 
2536  for (auto &i : tris)
2537  {
2538  stringstream s;
2539  TriGeomSharedPtr tri = i.second;
2540  s << tri->GetEid(0) << " " << tri->GetEid(1) << " " << tri->GetEid(2);
2541  TiXmlElement *t = new TiXmlElement(tag);
2542  t->SetAttribute("ID", i.first);
2543  t->LinkEndChild(new TiXmlText(s.str()));
2544  faceTag->LinkEndChild(t);
2545  }
2546 }
2547 
2548 void MeshGraphXml::WriteQuads(TiXmlElement *faceTag, QuadGeomMap &quads)
2549 {
2550  string tag = "Q";
2551 
2552  for (auto &i : quads)
2553  {
2554  stringstream s;
2555  QuadGeomSharedPtr quad = i.second;
2556  s << quad->GetEid(0) << " " << quad->GetEid(1) << " " << quad->GetEid(2)
2557  << " " << quad->GetEid(3);
2558  TiXmlElement *q = new TiXmlElement(tag);
2559  q->SetAttribute("ID", i.first);
2560  q->LinkEndChild(new TiXmlText(s.str()));
2561  faceTag->LinkEndChild(q);
2562  }
2563 }
2564 
2565 void MeshGraphXml::WriteHexs(TiXmlElement *elmtTag, HexGeomMap &hexs)
2566 {
2567  string tag = "H";
2568 
2569  for (auto &i : hexs)
2570  {
2571  stringstream s;
2572  HexGeomSharedPtr hex = i.second;
2573  s << hex->GetFid(0) << " " << hex->GetFid(1) << " " << hex->GetFid(2)
2574  << " " << hex->GetFid(3) << " " << hex->GetFid(4) << " "
2575  << hex->GetFid(5) << " ";
2576  TiXmlElement *h = new TiXmlElement(tag);
2577  h->SetAttribute("ID", i.first);
2578  h->LinkEndChild(new TiXmlText(s.str()));
2579  elmtTag->LinkEndChild(h);
2580  }
2581 }
2582 
2583 void MeshGraphXml::WritePrisms(TiXmlElement *elmtTag, PrismGeomMap &pris)
2584 {
2585  string tag = "R";
2586 
2587  for (auto &i : pris)
2588  {
2589  stringstream s;
2590  PrismGeomSharedPtr prism = i.second;
2591  s << prism->GetFid(0) << " " << prism->GetFid(1) << " "
2592  << prism->GetFid(2) << " " << prism->GetFid(3) << " "
2593  << prism->GetFid(4) << " ";
2594  TiXmlElement *p = new TiXmlElement(tag);
2595  p->SetAttribute("ID", i.first);
2596  p->LinkEndChild(new TiXmlText(s.str()));
2597  elmtTag->LinkEndChild(p);
2598  }
2599 }
2600 
2601 void MeshGraphXml::WritePyrs(TiXmlElement *elmtTag, PyrGeomMap &pyrs)
2602 {
2603  string tag = "P";
2604 
2605  for (auto &i : pyrs)
2606  {
2607  stringstream s;
2608  PyrGeomSharedPtr pyr = i.second;
2609  s << pyr->GetFid(0) << " " << pyr->GetFid(1) << " " << pyr->GetFid(2)
2610  << " " << pyr->GetFid(3) << " " << pyr->GetFid(4) << " ";
2611  TiXmlElement *p = new TiXmlElement(tag);
2612  p->SetAttribute("ID", i.first);
2613  p->LinkEndChild(new TiXmlText(s.str()));
2614  elmtTag->LinkEndChild(p);
2615  }
2616 }
2617 
2618 void MeshGraphXml::WriteTets(TiXmlElement *elmtTag, TetGeomMap &tets)
2619 {
2620  string tag = "A";
2621 
2622  for (auto &i : tets)
2623  {
2624  stringstream s;
2625  TetGeomSharedPtr tet = i.second;
2626  s << tet->GetFid(0) << " " << tet->GetFid(1) << " " << tet->GetFid(2)
2627  << " " << tet->GetFid(3) << " ";
2628  TiXmlElement *t = new TiXmlElement(tag);
2629  t->SetAttribute("ID", i.first);
2630  t->LinkEndChild(new TiXmlText(s.str()));
2631  elmtTag->LinkEndChild(t);
2632  }
2633 }
2634 
2635 void MeshGraphXml::WriteCurves(TiXmlElement *geomTag, CurveMap &edges,
2636  CurveMap &faces)
2637 {
2638  TiXmlElement *curveTag = new TiXmlElement("CURVED");
2639  CurveMap::iterator curveIt;
2640  int curveId = 0;
2641 
2642  for (curveIt = edges.begin(); curveIt != edges.end(); ++curveIt)
2643  {
2644  CurveSharedPtr curve = curveIt->second;
2645  TiXmlElement *c = new TiXmlElement("E");
2646  stringstream s;
2647  s.precision(8);
2648 
2649  for (int j = 0; j < curve->m_points.size(); ++j)
2650  {
2651  SpatialDomains::PointGeomSharedPtr p = curve->m_points[j];
2652  s << scientific << (*p)(0) << " " << (*p)(1) << " " << (*p)(2)
2653  << " ";
2654  }
2655 
2656  c->SetAttribute("ID", curveId++);
2657  c->SetAttribute("EDGEID", curve->m_curveID);
2658  c->SetAttribute("NUMPOINTS", curve->m_points.size());
2659  c->SetAttribute("TYPE", LibUtilities::kPointsTypeStr[curve->m_ptype]);
2660  c->LinkEndChild(new TiXmlText(s.str()));
2661  curveTag->LinkEndChild(c);
2662  }
2663 
2664  for (curveIt = faces.begin(); curveIt != faces.end(); ++curveIt)
2665  {
2666  CurveSharedPtr curve = curveIt->second;
2667  TiXmlElement *c = new TiXmlElement("F");
2668  stringstream s;
2669  s.precision(8);
2670 
2671  for (int j = 0; j < curve->m_points.size(); ++j)
2672  {
2673  SpatialDomains::PointGeomSharedPtr p = curve->m_points[j];
2674  s << scientific << (*p)(0) << " " << (*p)(1) << " " << (*p)(2)
2675  << " ";
2676  }
2677 
2678  c->SetAttribute("ID", curveId++);
2679  c->SetAttribute("FACEID", curve->m_curveID);
2680  c->SetAttribute("NUMPOINTS", curve->m_points.size());
2681  c->SetAttribute("TYPE", LibUtilities::kPointsTypeStr[curve->m_ptype]);
2682  c->LinkEndChild(new TiXmlText(s.str()));
2683  curveTag->LinkEndChild(c);
2684  }
2685 
2686  geomTag->LinkEndChild(curveTag);
2687 }
2688 
2689 void MeshGraphXml::WriteComposites(TiXmlElement *geomTag, CompositeMap &comps)
2690 {
2691  TiXmlElement *compTag = new TiXmlElement("COMPOSITE");
2692 
2693  for (auto &cIt : comps)
2694  {
2695  if (cIt.second->m_geomVec.size() == 0)
2696  {
2697  continue;
2698  }
2699 
2700  TiXmlElement *c = new TiXmlElement("C");
2701  c->SetAttribute("ID", cIt.first);
2702  c->LinkEndChild(new TiXmlText(GetCompositeString(cIt.second)));
2703  compTag->LinkEndChild(c);
2704  }
2705 
2706  geomTag->LinkEndChild(compTag);
2707 }
2708 
2709 void MeshGraphXml::WriteDomain(TiXmlElement *geomTag,
2710  vector<CompositeMap> &domain)
2711 {
2712  TiXmlElement *domTag = new TiXmlElement("DOMAIN");
2713  stringstream domString;
2714 
2715  // @todo Fix this to accomodate multi domain output
2716  vector<unsigned int> idxList;
2717  for (auto cIt = domain[0].begin(); cIt != domain[0].end(); ++cIt)
2718  {
2719  idxList.push_back(cIt->first);
2720  }
2721 
2722  domString << " C[" << ParseUtils::GenerateSeqString(idxList) << "] ";
2723  domTag->LinkEndChild(new TiXmlText(domString.str()));
2724  geomTag->LinkEndChild(domTag);
2725 }
2726 
2727 void MeshGraphXml::WriteDefaultExpansion(TiXmlElement *root)
2728 {
2729  TiXmlElement *expTag = new TiXmlElement("EXPANSIONS");
2730 
2731  for (auto it = m_meshComposites.begin(); it != m_meshComposites.end(); it++)
2732  {
2733  if (it->second->m_geomVec[0]->GetShapeDim() == m_meshDimension)
2734  {
2735  TiXmlElement *exp = new TiXmlElement("E");
2736  exp->SetAttribute("COMPOSITE",
2737  "C[" + boost::lexical_cast<string>(it->first) +
2738  "]");
2739  exp->SetAttribute("NUMMODES", 4);
2740  exp->SetAttribute("TYPE", "MODIFIED");
2741  exp->SetAttribute("FIELDS", "u");
2742 
2743  expTag->LinkEndChild(exp);
2744  }
2745  }
2746  root->LinkEndChild(expTag);
2747 }
2748 
2749 /**
2750  * @brief Write out an XML file containing the GEOMETRY block
2751  * representing this MeshGraph instance inside a NEKTAR tag.
2752  */
2753 void MeshGraphXml::WriteGeometry(
2754  std::string &outfilename,
2755  bool defaultExp,
2756  const LibUtilities::FieldMetaDataMap &metadata)
2757 {
2758  // Create empty TinyXML document.
2759  TiXmlDocument doc;
2760  TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
2761  doc.LinkEndChild(decl);
2762 
2763  TiXmlElement *root = new TiXmlElement("NEKTAR");
2764  doc.LinkEndChild(root);
2765  TiXmlElement *geomTag = new TiXmlElement("GEOMETRY");
2766  root->LinkEndChild(geomTag);
2767 
2768  // Add provenance information using FieldIO library.
2769  LibUtilities::FieldIO::AddInfoTag(
2771  new LibUtilities::XmlTagWriter(root)),
2772  metadata);
2773 
2774  // Update attributes with dimensions.
2775  geomTag->SetAttribute("DIM", m_meshDimension);
2776  geomTag->SetAttribute("SPACE", m_spaceDimension);
2777 
2778  // Clear existing elements.
2779  geomTag->Clear();
2780 
2781  // Write out informatio
2782  WriteVertices(geomTag, m_vertSet);
2783  WriteEdges(geomTag, m_segGeoms);
2784  if (m_meshDimension > 1)
2785  {
2786  TiXmlElement *faceTag =
2787  new TiXmlElement(m_meshDimension == 2 ? "ELEMENT" : "FACE");
2788 
2789  WriteTris(faceTag, m_triGeoms);
2790  WriteQuads(faceTag, m_quadGeoms);
2791  geomTag->LinkEndChild(faceTag);
2792  }
2793  if (m_meshDimension > 2)
2794  {
2795  TiXmlElement *elmtTag = new TiXmlElement("ELEMENT");
2796 
2797  WriteHexs(elmtTag, m_hexGeoms);
2798  WritePyrs(elmtTag, m_pyrGeoms);
2799  WritePrisms(elmtTag, m_prismGeoms);
2800  WriteTets(elmtTag, m_tetGeoms);
2801 
2802  geomTag->LinkEndChild(elmtTag);
2803  }
2804  WriteCurves(geomTag, m_curvedEdges, m_curvedFaces);
2805  WriteComposites(geomTag, m_meshComposites);
2806  WriteDomain(geomTag, m_domain);
2807 
2808  if (defaultExp)
2809  {
2810  WriteDefaultExpansion(root);
2811  }
2812 
2813  // Save file.
2814  doc.SaveFile(outfilename);
2815 }
2816 
2817 void MeshGraphXml::WriteXMLGeometry(std::string outname,
2818  vector<set<unsigned int>> elements,
2819  vector<unsigned int> partitions)
2820 {
2821  // so in theory this function is used by the mesh partitioner
2822  // giving instructions on how to write out a paritioned mesh.
2823  // the theory goes that the elements stored in the meshgraph are the
2824  // "whole" mesh so based on the information from the elmements list
2825  // we can filter the mesh entities and write some individual files
2826  // hopefully
2827 
2828  // this is xml so we are going to write a directory with lots of
2829  // xml files
2830  string dirname = outname + "_xml";
2831  boost::filesystem::path pdirname(dirname);
2832 
2833  if (!boost::filesystem::is_directory(dirname))
2834  {
2835  boost::filesystem::create_directory(dirname);
2836  }
2837 
2838  ASSERTL0(elements.size() == partitions.size(),
2839  "error in partitioned information");
2840 
2841  for (int i = 0; i < partitions.size(); i++)
2842  {
2843  TiXmlDocument doc;
2844  TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
2845  doc.LinkEndChild(decl);
2846 
2847  TiXmlElement *root = doc.FirstChildElement("NEKTAR");
2848  TiXmlElement *geomTag;
2849 
2850  // Try to find existing NEKTAR tag.
2851  if (!root)
2852  {
2853  root = new TiXmlElement("NEKTAR");
2854  doc.LinkEndChild(root);
2855 
2856  geomTag = new TiXmlElement("GEOMETRY");
2857  root->LinkEndChild(geomTag);
2858  }
2859  else
2860  {
2861  // Try to find existing GEOMETRY tag.
2862  geomTag = root->FirstChildElement("GEOMETRY");
2863 
2864  if (!geomTag)
2865  {
2866  geomTag = new TiXmlElement("GEOMETRY");
2867  root->LinkEndChild(geomTag);
2868  }
2869  }
2870 
2871  geomTag->SetAttribute("DIM", m_meshDimension);
2872  geomTag->SetAttribute("SPACE", m_spaceDimension);
2873  geomTag->SetAttribute("PARTITION", partitions[i]);
2874 
2875  // Add Mesh //
2876  // Get the elements
2877  HexGeomMap localHex;
2878  PyrGeomMap localPyr;
2879  PrismGeomMap localPrism;
2880  TetGeomMap localTet;
2881  TriGeomMap localTri;
2882  QuadGeomMap localQuad;
2883  SegGeomMap localEdge;
2884  PointGeomMap localVert;
2885  CurveMap localCurveEdge;
2886  CurveMap localCurveFace;
2887 
2888  vector<set<unsigned int>> entityIds(4);
2889  entityIds[m_meshDimension] = elements[i];
2890 
2891  switch (m_meshDimension)
2892  {
2893  case 3:
2894  {
2895  for (auto &j : entityIds[3])
2896  {
2898  if (m_hexGeoms.count(j))
2899  {
2900  g = m_hexGeoms[j];
2901  localHex[j] = m_hexGeoms[j];
2902  }
2903  else if (m_pyrGeoms.count(j))
2904  {
2905  g = m_pyrGeoms[j];
2906  localPyr[j] = m_pyrGeoms[j];
2907  }
2908  else if (m_prismGeoms.count(j))
2909  {
2910  g = m_prismGeoms[j];
2911  localPrism[j] = m_prismGeoms[j];
2912  }
2913  else if (m_tetGeoms.count(j))
2914  {
2915  g = m_tetGeoms[j];
2916  localTet[j] = m_tetGeoms[j];
2917  }
2918  else
2919  {
2920  ASSERTL0(false, "element in partition not found");
2921  }
2922 
2923  for (int k = 0; k < g->GetNumFaces(); k++)
2924  {
2925  entityIds[2].insert(g->GetFid(k));
2926  }
2927  for (int k = 0; k < g->GetNumEdges(); k++)
2928  {
2929  entityIds[1].insert(g->GetEid(k));
2930  }
2931  for (int k = 0; k < g->GetNumVerts(); k++)
2932  {
2933  entityIds[0].insert(g->GetVid(k));
2934  }
2935  }
2936  }
2937  break;
2938  case 2:
2939  {
2940  for (auto &j : entityIds[2])
2941  {
2943  if (m_triGeoms.count(j))
2944  {
2945  g = m_triGeoms[j];
2946  localTri[j] = m_triGeoms[j];
2947  }
2948  else if (m_quadGeoms.count(j))
2949  {
2950  g = m_quadGeoms[j];
2951  localQuad[j] = m_quadGeoms[j];
2952  }
2953  else
2954  {
2955  ASSERTL0(false, "element in partition not found");
2956  }
2957 
2958  for (int k = 0; k < g->GetNumEdges(); k++)
2959  {
2960  entityIds[1].insert(g->GetEid(k));
2961  }
2962  for (int k = 0; k < g->GetNumVerts(); k++)
2963  {
2964  entityIds[0].insert(g->GetVid(k));
2965  }
2966  }
2967  }
2968  break;
2969  case 1:
2970  {
2971  for (auto &j : entityIds[1])
2972  {
2974  if (m_segGeoms.count(j))
2975  {
2976  g = m_segGeoms[j];
2977  localEdge[j] = m_segGeoms[j];
2978  }
2979  else
2980  {
2981  ASSERTL0(false, "element in partition not found");
2982  }
2983 
2984  for (int k = 0; k < g->GetNumVerts(); k++)
2985  {
2986  entityIds[0].insert(g->GetVid(k));
2987  }
2988  }
2989  }
2990  }
2991 
2992  if (m_meshDimension > 2)
2993  {
2994  for (auto &j : entityIds[2])
2995  {
2996  if (m_triGeoms.count(j))
2997  {
2998  localTri[j] = m_triGeoms[j];
2999  }
3000  else if (m_quadGeoms.count(j))
3001  {
3002  localQuad[j] = m_quadGeoms[j];
3003  }
3004  else
3005  {
3006  ASSERTL0(false, "face not found");
3007  }
3008  }
3009  }
3010 
3011  if (m_meshDimension > 1)
3012  {
3013  for (auto &j : entityIds[1])
3014  {
3015  if (m_segGeoms.count(j))
3016  {
3017  localEdge[j] = m_segGeoms[j];
3018  }
3019  else
3020  {
3021  ASSERTL0(false, "edge not found");
3022  }
3023  }
3024  }
3025 
3026  for (auto &j : entityIds[0])
3027  {
3028  if (m_vertSet.count(j))
3029  {
3030  localVert[j] = m_vertSet[j];
3031  }
3032  else
3033  {
3034  ASSERTL0(false, "vert not found");
3035  }
3036  }
3037 
3038  WriteVertices(geomTag, localVert);
3039  WriteEdges(geomTag, localEdge);
3040  if (m_meshDimension > 1)
3041  {
3042  TiXmlElement *faceTag =
3043  new TiXmlElement(m_meshDimension == 2 ? "ELEMENT" : "FACE");
3044 
3045  WriteTris(faceTag, localTri);
3046  WriteQuads(faceTag, localQuad);
3047  geomTag->LinkEndChild(faceTag);
3048  }
3049  if (m_meshDimension > 2)
3050  {
3051  TiXmlElement *elmtTag = new TiXmlElement("ELEMENT");
3052 
3053  WriteHexs(elmtTag, localHex);
3054  WritePyrs(elmtTag, localPyr);
3055  WritePrisms(elmtTag, localPrism);
3056  WriteTets(elmtTag, localTet);
3057 
3058  geomTag->LinkEndChild(elmtTag);
3059  }
3060 
3061  for (auto &j : localTri)
3062  {
3063  if (m_curvedFaces.count(j.first))
3064  {
3065  localCurveFace[j.first] = m_curvedFaces[j.first];
3066  }
3067  }
3068  for (auto &j : localQuad)
3069  {
3070  if (m_curvedFaces.count(j.first))
3071  {
3072  localCurveFace[j.first] = m_curvedFaces[j.first];
3073  }
3074  }
3075  for (auto &j : localEdge)
3076  {
3077  if (m_curvedEdges.count(j.first))
3078  {
3079  localCurveEdge[j.first] = m_curvedEdges[j.first];
3080  }
3081  }
3082 
3083  WriteCurves(geomTag, localCurveEdge, localCurveFace);
3084 
3085  CompositeMap localComp;
3086 
3087  for (auto &j : m_meshComposites)
3088  {
3090  int dim = j.second->m_geomVec[0]->GetShapeDim();
3091 
3092  for (int k = 0; k < j.second->m_geomVec.size(); k++)
3093  {
3094  if (entityIds[dim].count(j.second->m_geomVec[k]->GetGlobalID()))
3095  {
3096  comp->m_geomVec.push_back(j.second->m_geomVec[k]);
3097  }
3098  }
3099 
3100  if (comp->m_geomVec.size())
3101  {
3102  localComp[j.first] = comp;
3103  }
3104  }
3105 
3106  WriteComposites(geomTag, localComp);
3107 
3108  vector<CompositeMap> domain;
3109  CompositeMap domMap;
3110  for (auto &j : localComp)
3111  {
3112  if (j.second->m_geomVec[0]->GetShapeDim() == m_meshDimension)
3113  {
3114  domMap[j.first] = j.second;
3115  }
3116  }
3117  domain.push_back(domMap);
3118 
3119  WriteDomain(geomTag, domain);
3120 
3121  if (m_session->DefinesElement("NEKTAR/CONDITIONS"))
3122  {
3123  std::set<int> vBndRegionIdList;
3124  TiXmlElement *vConditions =
3125  new TiXmlElement(*m_session->GetElement("Nektar/Conditions"));
3126  TiXmlElement *vBndRegions =
3127  vConditions->FirstChildElement("BOUNDARYREGIONS");
3128  TiXmlElement *vBndConditions =
3129  vConditions->FirstChildElement("BOUNDARYCONDITIONS");
3130  TiXmlElement *vItem;
3131 
3132  if (vBndRegions)
3133  {
3134  TiXmlElement *vNewBndRegions =
3135  new TiXmlElement("BOUNDARYREGIONS");
3136  vItem = vBndRegions->FirstChildElement();
3137  while (vItem)
3138  {
3139  std::string vSeqStr =
3140  vItem->FirstChild()->ToText()->Value();
3141  std::string::size_type indxBeg =
3142  vSeqStr.find_first_of('[') + 1;
3143  std::string::size_type indxEnd =
3144  vSeqStr.find_last_of(']') - 1;
3145  vSeqStr = vSeqStr.substr(indxBeg, indxEnd - indxBeg + 1);
3146  std::vector<unsigned int> vSeq;
3147  ParseUtils::GenerateSeqVector(vSeqStr.c_str(), vSeq);
3148 
3149  vector<unsigned int> idxList;
3150 
3151  for (unsigned int i = 0; i < vSeq.size(); ++i)
3152  {
3153  if (localComp.find(vSeq[i]) != localComp.end())
3154  {
3155  idxList.push_back(vSeq[i]);
3156  }
3157  }
3158  int p = atoi(vItem->Attribute("ID"));
3159 
3160  std::string vListStr =
3161  ParseUtils::GenerateSeqString(idxList);
3162 
3163  if (vListStr.length() == 0)
3164  {
3165  TiXmlElement *tmp = vItem;
3166  vItem = vItem->NextSiblingElement();
3167  vBndRegions->RemoveChild(tmp);
3168  }
3169  else
3170  {
3171  vListStr = "C[" + vListStr + "]";
3172  TiXmlText *vList = new TiXmlText(vListStr);
3173  TiXmlElement *vNewElement = new TiXmlElement("B");
3174  vNewElement->SetAttribute("ID", p);
3175  vNewElement->LinkEndChild(vList);
3176  vNewBndRegions->LinkEndChild(vNewElement);
3177  vBndRegionIdList.insert(p);
3178  vItem = vItem->NextSiblingElement();
3179  }
3180 
3181  // store original bnd region order
3182  m_bndRegOrder[p] = vSeq;
3183  }
3184  vConditions->ReplaceChild(vBndRegions, *vNewBndRegions);
3185  }
3186 
3187  if (vBndConditions)
3188  {
3189  vItem = vBndConditions->FirstChildElement();
3190  while (vItem)
3191  {
3192  std::set<int>::iterator x;
3193  if ((x = vBndRegionIdList.find(atoi(vItem->Attribute(
3194  "REF")))) != vBndRegionIdList.end())
3195  {
3196  vItem->SetAttribute("REF", *x);
3197  vItem = vItem->NextSiblingElement();
3198  }
3199  else
3200  {
3201  TiXmlElement *tmp = vItem;
3202  vItem = vItem->NextSiblingElement();
3203  vBndConditions->RemoveChild(tmp);
3204  }
3205  }
3206  }
3207  root->LinkEndChild(vConditions);
3208  }
3209 
3210  // Distribute other sections of the XML to each process as is.
3211  TiXmlElement *vSrc =
3212  m_session->GetElement("Nektar")->FirstChildElement();
3213  while (vSrc)
3214  {
3215  std::string vName = boost::to_upper_copy(vSrc->ValueStr());
3216  if (vName != "GEOMETRY" && vName != "CONDITIONS")
3217  {
3218  root->LinkEndChild(new TiXmlElement(*vSrc));
3219  }
3220  vSrc = vSrc->NextSiblingElement();
3221  }
3222 
3223  // Save Mesh
3224 
3225  boost::format pad("P%1$07d.xml");
3226  pad % partitions[i];
3227  boost::filesystem::path pFilename(pad.str());
3228 
3229  boost::filesystem::path fullpath = pdirname / pFilename;
3230  doc.SaveFile(LibUtilities::PortablePath(fullpath));
3231  }
3232 }
3233 
3234 CompositeOrdering MeshGraphXml::CreateCompositeOrdering()
3235 {
3236  CompositeOrdering ret;
3237 
3238  for (auto &c : m_meshComposites)
3239  {
3240  std::vector<unsigned int> ids;
3241  for (auto &elmt : c.second->m_geomVec)
3242  {
3243  ids.push_back(elmt->GetGlobalID());
3244  }
3245  ret[c.first] = ids;
3246  }
3247 
3248  return ret;
3249 }
3250 
3251 }
3252 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation.
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
std::shared_ptr< MeshPartition > MeshPartitionSharedPtr
std::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:88
std::unordered_map< int, CurveSharedPtr > CurveMap
Definition: Curve.hpp:62
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
const std::string kPointsTypeStr[]
Definition: Foundations.hpp:70
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
std::shared_ptr< QuadGeom > QuadGeomSharedPtr
Definition: HexGeom.h:46
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
STL namespace.
std::map< int, CompositeSharedPtr > CompositeMap
Definition: MeshGraph.h:137
std::map< int, PrismGeomSharedPtr > PrismGeomMap
Definition: PrismGeom.h:89
std::shared_ptr< Composite > CompositeSharedPtr
Definition: MeshGraph.h:136
std::map< int, PyrGeomSharedPtr > PyrGeomMap
Definition: PyrGeom.h:81
std::shared_ptr< DomainRange > DomainRangeShPtr
Definition: MeshGraph.h:128
std::map< std::string, std::string > FieldMetaDataMap
Definition: FieldIO.h:52
std::map< int, TetGeomSharedPtr > TetGeomMap
Definition: TetGeom.h:90
std::map< int, TriGeomSharedPtr > TriGeomMap
Definition: TriGeom.h:59
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
std::shared_ptr< TriGeom > TriGeomSharedPtr
Definition: TriGeom.h:58
MeshGraphFactory & GetMeshGraphFactory()
Definition: MeshGraph.cpp:76
std::map< int, std::vector< unsigned int > > CompositeOrdering
Definition: MeshGraph.h:108
std::map< int, SegGeomSharedPtr > SegGeomMap
Definition: SegGeom.h:52
std::shared_ptr< Geometry > GeometrySharedPtr
Definition: Geometry.h:53
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:41
double NekDouble
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:59
Interpreter class for the evaluation of mathematical expressions.
Definition: Interpreter.h:77
std::shared_ptr< PyrGeom > PyrGeomSharedPtr
Definition: PyrGeom.h:80
std::shared_ptr< XmlTagWriter > XmlTagWriterSharedPtr
Definition: FieldIOXml.h:163
std::map< int, QuadGeomSharedPtr > QuadGeomMap
Definition: QuadGeom.h:54
static DomainRangeShPtr NullDomainRangeShPtr
Definition: MeshGraph.h:129
std::shared_ptr< HexGeom > HexGeomSharedPtr
Definition: HexGeom.h:90
std::shared_ptr< Curve > CurveSharedPtr
Definition: Curve.hpp:61
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:358
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
std::shared_ptr< PrismGeom > PrismGeomSharedPtr
Definition: PrismGeom.h:88
std::map< int, PointGeomSharedPtr > PointGeomMap
Definition: PointGeom.h:54
MeshPartitionFactory & GetMeshPartitionFactory()
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62
std::map< int, HexGeomSharedPtr > HexGeomMap
Definition: HexGeom.h:91
std::shared_ptr< SessionReader > SessionReaderSharedPtr