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