Nektar++
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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
40
45
46#include <boost/format.hpp>
47
48#include <tinyxml.h>
49
50using namespace std;
51
52namespace Nektar
53{
54namespace SpatialDomains
55{
56
57std::string MeshGraphXml::className =
59 "IO with Xml geometry");
60
63{
64 // Get row of comm, or the whole comm if not split
65 LibUtilities::CommSharedPtr comm = session->GetComm();
66 LibUtilities::CommSharedPtr commMesh = comm->GetRowComm();
67 const bool isRoot = comm->TreatAsRankZero();
68
69 m_session = session;
70
71 // Load file for root process only (since this is always needed)
72 // and determine if the provided geometry has already been
73 // partitioned. This will be the case if the user provides the
74 // directory of mesh partitions as an input. Partitioned geometries
75 // have the attribute
76 // PARTITION=X
77 // where X is the number of the partition (and should match the
78 // process rank). The result is shared with all other processes.
79 int isPartitioned = 0;
80 if (isRoot)
81 {
82 if (m_session->DefinesElement("Nektar/Geometry"))
83 {
84 if (m_session->GetElement("Nektar/Geometry")
85 ->Attribute("PARTITION"))
86 {
87 std::cout << "Using pre-partitioned mesh." << std::endl;
88 isPartitioned = 1;
89 }
90 }
91 }
92 comm->Bcast(isPartitioned, 0);
93
94 // If the mesh is already partitioned, we are done. Remaining
95 // processes must load their partitions.
96 if (isPartitioned)
97 {
98 if (!isRoot)
99 {
100 m_session->InitSession();
101 }
102 }
103 else
104 {
105 // Default partitioner to use is Metis. Use Scotch as default if it is
106 // installed. Override default with command-line flags if they are set.
107 string partitionerName = "Metis";
108 if (GetMeshPartitionFactory().ModuleExists("Scotch"))
109 {
110 partitionerName = "Scotch";
111 }
112 if (session->DefinesCmdLineArgument("use-metis"))
113 {
114 partitionerName = "Metis";
115 }
116 if (session->DefinesCmdLineArgument("use-scotch"))
117 {
118 partitionerName = "Scotch";
119 }
120
121 // Mesh has not been partitioned so do partitioning if required. Note
122 // in the serial case nothing is done as we have already loaded the
123 // mesh.
124 if (session->DefinesCmdLineArgument("part-only") ||
125 session->DefinesCmdLineArgument("part-only-overlapping"))
126 {
127 // Perform partitioning of the mesh only. For this we insist the
128 // code is run in serial (parallel execution is pointless).
129 ASSERTL0(comm->GetSize() == 1,
130 "The 'part-only' option should be used in serial.");
131
132 // Read 'lite' geometry information
134
135 // Number of partitions is specified by the parameter.
136 int nParts;
137 auto comp = CreateCompositeDescriptor();
138
139 MeshPartitionSharedPtr partitioner =
141 partitionerName, session, session->GetComm(),
143
144 if (session->DefinesCmdLineArgument("part-only"))
145 {
146 nParts = session->GetCmdLineArgument<int>("part-only");
147 partitioner->PartitionMesh(nParts, true);
148 }
149 else
150 {
151 nParts =
152 session->GetCmdLineArgument<int>("part-only-overlapping");
153 partitioner->PartitionMesh(nParts, true, true);
154 }
155
156 vector<set<unsigned int>> elmtIDs;
157 vector<unsigned int> parts(nParts);
158 for (int i = 0; i < nParts; ++i)
159 {
160 vector<unsigned int> elIDs;
161 set<unsigned int> tmp;
162 partitioner->GetElementIDs(i, elIDs);
163 tmp.insert(elIDs.begin(), elIDs.end());
164 elmtIDs.push_back(tmp);
165 parts[i] = i;
166 }
167
168 this->WriteXMLGeometry(m_session->GetSessionName(), elmtIDs, parts);
169
170 if (isRoot && session->DefinesCmdLineArgument("part-info"))
171 {
172 partitioner->PrintPartInfo(std::cout);
173 }
174
175 session->Finalise();
176 exit(0);
177 }
178
179 if (commMesh->GetSize() > 1)
180 {
181 int nParts = commMesh->GetSize();
182
183 if (session->GetSharedFilesystem())
184 {
185 vector<unsigned int> keys, vals;
186 int i;
187
188 if (isRoot)
189 {
190 // Read 'lite' geometry information
192
193 // Store composite ordering and boundary information.
195 auto comp = CreateCompositeDescriptor();
196
197 // Create mesh partitioner.
198 MeshPartitionSharedPtr partitioner =
200 partitionerName, session, session->GetComm(),
202
203 partitioner->PartitionMesh(nParts, true);
204
205 vector<set<unsigned int>> elmtIDs;
206 vector<unsigned int> parts(nParts);
207 for (i = 0; i < nParts; ++i)
208 {
209 vector<unsigned int> elIDs;
210 set<unsigned int> tmp;
211 partitioner->GetElementIDs(i, elIDs);
212 tmp.insert(elIDs.begin(), elIDs.end());
213 elmtIDs.push_back(tmp);
214 parts[i] = i;
215 }
216
217 // Call WriteGeometry to write out partition files. This
218 // will populate m_bndRegOrder.
219 this->WriteXMLGeometry(m_session->GetSessionName(), elmtIDs,
220 parts);
221
222 // Communicate orderings to the other processors.
223
224 // First send sizes of the orderings and boundary
225 // regions to allocate storage on the remote end.
226 keys.resize(2);
227 keys[0] = m_compOrder.size();
228 keys[1] = m_bndRegOrder.size();
229 comm->Bcast(keys, 0);
230
231 // Construct the keys and sizes of values for composite
232 // ordering
233 keys.resize(m_compOrder.size());
234 vals.resize(m_compOrder.size());
235
236 i = 0;
237 for (auto &cIt : m_compOrder)
238 {
239 keys[i] = cIt.first;
240 vals[i++] = cIt.second.size();
241 }
242
243 // Send across data.
244 comm->Bcast(keys, 0);
245 comm->Bcast(vals, 0);
246 for (auto &cIt : m_compOrder)
247 {
248 comm->Bcast(cIt.second, 0);
249 }
250
251 // Construct the keys and sizes of values for composite
252 // ordering
253 keys.resize(m_bndRegOrder.size());
254 vals.resize(m_bndRegOrder.size());
255
256 i = 0;
257 for (auto &bIt : m_bndRegOrder)
258 {
259 keys[i] = bIt.first;
260 vals[i++] = bIt.second.size();
261 }
262
263 // Send across data.
264 if (!keys.empty())
265 {
266 comm->Bcast(keys, 0);
267 }
268 if (!vals.empty())
269 {
270 comm->Bcast(vals, 0);
271 }
272 for (auto &bIt : m_bndRegOrder)
273 {
274 comm->Bcast(bIt.second, 0);
275 }
276
277 if (session->DefinesCmdLineArgument("part-info"))
278 {
279 partitioner->PrintPartInfo(std::cout);
280 }
281 }
282 else
283 {
284 keys.resize(2);
285 comm->Bcast(keys, 0);
286
287 int cmpSize = keys[0];
288 int bndSize = keys[1];
289
290 keys.resize(cmpSize);
291 vals.resize(cmpSize);
292 comm->Bcast(keys, 0);
293 comm->Bcast(vals, 0);
294
295 for (int i = 0; i < keys.size(); ++i)
296 {
297 vector<unsigned int> tmp(vals[i]);
298 comm->Bcast(tmp, 0);
299 m_compOrder[keys[i]] = tmp;
300 }
301
302 keys.resize(bndSize);
303 vals.resize(bndSize);
304 if (!keys.empty())
305 {
306 comm->Bcast(keys, 0);
307 }
308 if (!vals.empty())
309 {
310 comm->Bcast(vals, 0);
311 }
312 for (int i = 0; i < keys.size(); ++i)
313 {
314 vector<unsigned int> tmp(vals[i]);
315 comm->Bcast(tmp, 0);
316 m_bndRegOrder[keys[i]] = tmp;
317 }
318 }
319 }
320 else
321 {
322 m_session->InitSession();
324
326 auto comp = CreateCompositeDescriptor();
327
328 // Partitioner now operates in parallel. Each process receives
329 // partitioning over interconnect and writes its own session
330 // file to the working directory.
331 MeshPartitionSharedPtr partitioner =
333 partitionerName, session, session->GetComm(),
335
336 partitioner->PartitionMesh(nParts, false);
337
338 vector<unsigned int> parts(1), tmp;
339 parts[0] = commMesh->GetRank();
340 vector<set<unsigned int>> elIDs(1);
341 partitioner->GetElementIDs(parts[0], tmp);
342 elIDs[0].insert(tmp.begin(), tmp.end());
343
344 // if (comm->GetTimeComm()->GetRank() == 0) // FIXME
345 // (OpenMPI 3.1.3)
346 {
347 this->WriteXMLGeometry(session->GetSessionName(), elIDs,
348 parts);
349 }
350
351 if (m_session->DefinesCmdLineArgument("part-info") && isRoot)
352 {
353 partitioner->PrintPartInfo(std::cout);
354 }
355 }
356
357 // Wait for all processors to finish their writing activities.
358 comm->Block();
359
360 std::string dirname = m_session->GetSessionName() + "_xml";
361 fs::path pdirname(dirname);
362 boost::format pad("P%1$07d.xml");
363 pad % comm->GetRowComm()->GetRank();
364 fs::path pFilename(pad.str());
365 fs::path fullpath = pdirname / pFilename;
366
367 std::vector<std::string> filenames = {
369 m_session->InitSession(filenames);
370 }
371 else if (!isRoot)
372 {
373 // No partitioning, non-root processors need to read the session
374 // file -- handles case where --npz is the same as number of
375 // processors.
376 m_session->InitSession();
377 }
378 }
379}
380
382 bool fillGraph)
383{
384 // Reset member variables.
385 m_vertSet.clear();
386 m_curvedEdges.clear();
387 m_curvedFaces.clear();
388 m_segGeoms.clear();
389 m_triGeoms.clear();
390 m_quadGeoms.clear();
391 m_tetGeoms.clear();
392 m_pyrGeoms.clear();
393 m_prismGeoms.clear();
394 m_hexGeoms.clear();
395 m_meshComposites.clear();
396 m_compositesLabels.clear();
397 m_domain.clear();
399 m_faceToElMap.clear();
400
401 m_domainRange = rng;
402 m_xmlGeom = m_session->GetElement("NEKTAR/GEOMETRY");
403
404 int err; /// Error value returned by TinyXML.
405
406 TiXmlAttribute *attr = m_xmlGeom->FirstAttribute();
407
408 // Initialize the mesh and space dimensions to 3 dimensions.
409 // We want to do this each time we read a file, so it should
410 // be done here and not just during class initialization.
411 m_meshPartitioned = false;
412 m_meshDimension = 3;
414
415 while (attr)
416 {
417 std::string attrName(attr->Name());
418 if (attrName == "DIM")
419 {
420 err = attr->QueryIntValue(&m_meshDimension);
421 ASSERTL0(err == TIXML_SUCCESS, "Unable to read mesh dimension.");
422 }
423 else if (attrName == "SPACE")
424 {
425 err = attr->QueryIntValue(&m_spaceDimension);
426 ASSERTL0(err == TIXML_SUCCESS, "Unable to read space dimension.");
427 }
428 else if (attrName == "PARTITION")
429 {
430 err = attr->QueryIntValue(&m_partition);
431 ASSERTL0(err == TIXML_SUCCESS, "Unable to read partition.");
432 m_meshPartitioned = true;
433 }
434 else
435 {
436 std::string errstr("Unknown attribute: ");
437 errstr += attrName;
438 ASSERTL0(false, errstr.c_str());
439 }
440
441 // Get the next attribute.
442 attr = attr->Next();
443 }
444
446 "Mesh dimension greater than space dimension");
447
449 v_ReadCurves();
450 if (m_meshDimension >= 2)
451 {
452 v_ReadEdges();
453 if (m_meshDimension == 3)
454 {
455 v_ReadFaces();
456 }
457 }
458 ReadElements();
460 ReadDomain();
461
462 if (fillGraph)
463 {
465 }
466}
467
469{
470 // Now read the vertices
471 TiXmlElement *element = m_xmlGeom->FirstChildElement("VERTEX");
472 ASSERTL0(element, "Unable to find mesh VERTEX tag in file.");
473
474 NekDouble xscale, yscale, zscale;
475
476 // check to see if any scaling parameters are in
477 // attributes and determine these values
478 LibUtilities::Interpreter expEvaluator;
479 const char *xscal = element->Attribute("XSCALE");
480 if (!xscal)
481 {
482 xscale = 1.0;
483 }
484 else
485 {
486 std::string xscalstr = xscal;
487 int expr_id = expEvaluator.DefineFunction("", xscalstr);
488 xscale = expEvaluator.Evaluate(expr_id);
489 }
490
491 const char *yscal = element->Attribute("YSCALE");
492 if (!yscal)
493 {
494 yscale = 1.0;
495 }
496 else
497 {
498 std::string yscalstr = yscal;
499 int expr_id = expEvaluator.DefineFunction("", yscalstr);
500 yscale = expEvaluator.Evaluate(expr_id);
501 }
502
503 const char *zscal = element->Attribute("ZSCALE");
504 if (!zscal)
505 {
506 zscale = 1.0;
507 }
508 else
509 {
510 std::string zscalstr = zscal;
511 int expr_id = expEvaluator.DefineFunction("", zscalstr);
512 zscale = expEvaluator.Evaluate(expr_id);
513 }
514
515 NekDouble xmove, ymove, zmove;
516
517 // check to see if any moving parameters are in
518 // attributes and determine these values
519
520 const char *xmov = element->Attribute("XMOVE");
521 if (!xmov)
522 {
523 xmove = 0.0;
524 }
525 else
526 {
527 std::string xmovstr = xmov;
528 int expr_id = expEvaluator.DefineFunction("", xmovstr);
529 xmove = expEvaluator.Evaluate(expr_id);
530 }
531
532 const char *ymov = element->Attribute("YMOVE");
533 if (!ymov)
534 {
535 ymove = 0.0;
536 }
537 else
538 {
539 std::string ymovstr = ymov;
540 int expr_id = expEvaluator.DefineFunction("", ymovstr);
541 ymove = expEvaluator.Evaluate(expr_id);
542 }
543
544 const char *zmov = element->Attribute("ZMOVE");
545 if (!zmov)
546 {
547 zmove = 0.0;
548 }
549 else
550 {
551 std::string zmovstr = zmov;
552 int expr_id = expEvaluator.DefineFunction("", zmovstr);
553 zmove = expEvaluator.Evaluate(expr_id);
554 }
555
556 TiXmlElement *vertex = element->FirstChildElement("V");
557
558 int indx;
559 int nextVertexNumber = -1;
560
561 while (vertex)
562 {
563 nextVertexNumber++;
564
565 TiXmlAttribute *vertexAttr = vertex->FirstAttribute();
566 std::string attrName(vertexAttr->Name());
567
568 ASSERTL0(attrName == "ID",
569 (std::string("Unknown attribute name: ") + attrName).c_str());
570
571 int err = vertexAttr->QueryIntValue(&indx);
572 ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
573
574 // Now read body of vertex
575 std::string vertexBodyStr;
576
577 TiXmlNode *vertexBody = vertex->FirstChild();
578
579 while (vertexBody)
580 {
581 // Accumulate all non-comment body data.
582 if (vertexBody->Type() == TiXmlNode::TINYXML_TEXT)
583 {
584 vertexBodyStr += vertexBody->ToText()->Value();
585 vertexBodyStr += " ";
586 }
587
588 vertexBody = vertexBody->NextSibling();
589 }
590
591 ASSERTL0(!vertexBodyStr.empty(),
592 "Vertex definitions must contain vertex data.");
593
594 // Get vertex data from the data string.
595 NekDouble xval, yval, zval;
596 std::istringstream vertexDataStrm(vertexBodyStr.c_str());
597
598 try
599 {
600 while (!vertexDataStrm.fail())
601 {
602 vertexDataStrm >> xval >> yval >> zval;
603
604 xval = xval * xscale + xmove;
605 yval = yval * yscale + ymove;
606 zval = zval * zscale + zmove;
607
608 // Need to check it here because we may not be
609 // good after the read indicating that there
610 // was nothing to read.
611 if (!vertexDataStrm.fail())
612 {
615 m_spaceDimension, indx, xval, yval, zval));
616 m_vertSet[indx] = vert;
617 }
618 }
619 }
620 catch (...)
621 {
622 ASSERTL0(false, "Unable to read VERTEX data.");
623 }
624
625 vertex = vertex->NextSiblingElement("V");
626 }
627}
628
630{
631 // check to see if any scaling parameters are in
632 // attributes and determine these values
633 TiXmlElement *element = m_xmlGeom->FirstChildElement("VERTEX");
634 ASSERTL0(element, "Unable to find mesh VERTEX tag in file.");
635
636 NekDouble xscale, yscale, zscale;
637
638 LibUtilities::Interpreter expEvaluator;
639 const char *xscal = element->Attribute("XSCALE");
640 if (!xscal)
641 {
642 xscale = 1.0;
643 }
644 else
645 {
646 std::string xscalstr = xscal;
647 int expr_id = expEvaluator.DefineFunction("", xscalstr);
648 xscale = expEvaluator.Evaluate(expr_id);
649 }
650
651 const char *yscal = element->Attribute("YSCALE");
652 if (!yscal)
653 {
654 yscale = 1.0;
655 }
656 else
657 {
658 std::string yscalstr = yscal;
659 int expr_id = expEvaluator.DefineFunction("", yscalstr);
660 yscale = expEvaluator.Evaluate(expr_id);
661 }
662
663 const char *zscal = element->Attribute("ZSCALE");
664 if (!zscal)
665 {
666 zscale = 1.0;
667 }
668 else
669 {
670 std::string zscalstr = zscal;
671 int expr_id = expEvaluator.DefineFunction("", zscalstr);
672 zscale = expEvaluator.Evaluate(expr_id);
673 }
674
675 NekDouble xmove, ymove, zmove;
676
677 // check to see if any moving parameters are in
678 // attributes and determine these values
679
680 const char *xmov = element->Attribute("XMOVE");
681 if (!xmov)
682 {
683 xmove = 0.0;
684 }
685 else
686 {
687 std::string xmovstr = xmov;
688 int expr_id = expEvaluator.DefineFunction("", xmovstr);
689 xmove = expEvaluator.Evaluate(expr_id);
690 }
691
692 const char *ymov = element->Attribute("YMOVE");
693 if (!ymov)
694 {
695 ymove = 0.0;
696 }
697 else
698 {
699 std::string ymovstr = ymov;
700 int expr_id = expEvaluator.DefineFunction("", ymovstr);
701 ymove = expEvaluator.Evaluate(expr_id);
702 }
703
704 const char *zmov = element->Attribute("ZMOVE");
705 if (!zmov)
706 {
707 zmove = 0.0;
708 }
709 else
710 {
711 std::string zmovstr = zmov;
712 int expr_id = expEvaluator.DefineFunction("", zmovstr);
713 zmove = expEvaluator.Evaluate(expr_id);
714 }
715
716 int err;
717
718 /// Look for elements in CURVE block.
719 TiXmlElement *field = m_xmlGeom->FirstChildElement("CURVED");
720
721 if (!field) // return if no curved entities
722 {
723 return;
724 }
725
726 /// All curves are of the form: "<? ID="#" TYPE="GLL OR other
727 /// points type" NUMPOINTS="#"> ... </?>", with ? being an
728 /// element type (either E or F).
729
730 TiXmlElement *edgelement = field->FirstChildElement("E");
731
732 int edgeindx, edgeid;
733 int nextEdgeNumber = -1;
734
735 while (edgelement)
736 {
737 /// These should be ordered.
738 nextEdgeNumber++;
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 = NULL;
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 = NULL;
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 = NULL;
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 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 // Save file.
2805 doc.SaveFile(outfilename);
2806}
2807
2808void MeshGraphXml::WriteXMLGeometry(std::string outname,
2809 vector<set<unsigned int>> elements,
2810 vector<unsigned int> partitions)
2811{
2812 // so in theory this function is used by the mesh partitioner
2813 // giving instructions on how to write out a paritioned mesh.
2814 // the theory goes that the elements stored in the meshgraph are the
2815 // "whole" mesh so based on the information from the elmements list
2816 // we can filter the mesh entities and write some individual files
2817 // hopefully
2818
2819 // this is xml so we are going to write a directory with lots of
2820 // xml files
2821 string dirname = outname + "_xml";
2822 boost::filesystem::path pdirname(dirname);
2823
2824 if (!boost::filesystem::is_directory(dirname))
2825 {
2826 boost::filesystem::create_directory(dirname);
2827 }
2828
2829 ASSERTL0(elements.size() == partitions.size(),
2830 "error in partitioned information");
2831
2832 for (int i = 0; i < partitions.size(); i++)
2833 {
2834 TiXmlDocument doc;
2835 TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
2836 doc.LinkEndChild(decl);
2837
2838 TiXmlElement *root = doc.FirstChildElement("NEKTAR");
2839 TiXmlElement *geomTag;
2840
2841 // Try to find existing NEKTAR tag.
2842 if (!root)
2843 {
2844 root = new TiXmlElement("NEKTAR");
2845 doc.LinkEndChild(root);
2846
2847 geomTag = new TiXmlElement("GEOMETRY");
2848 root->LinkEndChild(geomTag);
2849 }
2850 else
2851 {
2852 // Try to find existing GEOMETRY tag.
2853 geomTag = root->FirstChildElement("GEOMETRY");
2854
2855 if (!geomTag)
2856 {
2857 geomTag = new TiXmlElement("GEOMETRY");
2858 root->LinkEndChild(geomTag);
2859 }
2860 }
2861
2862 geomTag->SetAttribute("DIM", m_meshDimension);
2863 geomTag->SetAttribute("SPACE", m_spaceDimension);
2864 geomTag->SetAttribute("PARTITION", partitions[i]);
2865
2866 // Add Mesh //
2867 // Get the elements
2868 HexGeomMap localHex;
2869 PyrGeomMap localPyr;
2870 PrismGeomMap localPrism;
2871 TetGeomMap localTet;
2872 TriGeomMap localTri;
2873 QuadGeomMap localQuad;
2874 SegGeomMap localEdge;
2875 PointGeomMap localVert;
2876 CurveMap localCurveEdge;
2877 CurveMap localCurveFace;
2878
2879 vector<set<unsigned int>> entityIds(4);
2880 entityIds[m_meshDimension] = elements[i];
2881
2882 switch (m_meshDimension)
2883 {
2884 case 3:
2885 {
2886 for (auto &j : entityIds[3])
2887 {
2889 if (m_hexGeoms.count(j))
2890 {
2891 g = m_hexGeoms[j];
2892 localHex[j] = m_hexGeoms[j];
2893 }
2894 else if (m_pyrGeoms.count(j))
2895 {
2896 g = m_pyrGeoms[j];
2897 localPyr[j] = m_pyrGeoms[j];
2898 }
2899 else if (m_prismGeoms.count(j))
2900 {
2901 g = m_prismGeoms[j];
2902 localPrism[j] = m_prismGeoms[j];
2903 }
2904 else if (m_tetGeoms.count(j))
2905 {
2906 g = m_tetGeoms[j];
2907 localTet[j] = m_tetGeoms[j];
2908 }
2909 else
2910 {
2911 ASSERTL0(false, "element in partition not found");
2912 }
2913
2914 for (int k = 0; k < g->GetNumFaces(); k++)
2915 {
2916 entityIds[2].insert(g->GetFid(k));
2917 }
2918 for (int k = 0; k < g->GetNumEdges(); k++)
2919 {
2920 entityIds[1].insert(g->GetEid(k));
2921 }
2922 for (int k = 0; k < g->GetNumVerts(); k++)
2923 {
2924 entityIds[0].insert(g->GetVid(k));
2925 }
2926 }
2927 }
2928 break;
2929 case 2:
2930 {
2931 for (auto &j : entityIds[2])
2932 {
2934 if (m_triGeoms.count(j))
2935 {
2936 g = m_triGeoms[j];
2937 localTri[j] = m_triGeoms[j];
2938 }
2939 else if (m_quadGeoms.count(j))
2940 {
2941 g = m_quadGeoms[j];
2942 localQuad[j] = m_quadGeoms[j];
2943 }
2944 else
2945 {
2946 ASSERTL0(false, "element in partition not found");
2947 }
2948
2949 for (int k = 0; k < g->GetNumEdges(); k++)
2950 {
2951 entityIds[1].insert(g->GetEid(k));
2952 }
2953 for (int k = 0; k < g->GetNumVerts(); k++)
2954 {
2955 entityIds[0].insert(g->GetVid(k));
2956 }
2957 }
2958 }
2959 break;
2960 case 1:
2961 {
2962 for (auto &j : entityIds[1])
2963 {
2965 if (m_segGeoms.count(j))
2966 {
2967 g = m_segGeoms[j];
2968 localEdge[j] = m_segGeoms[j];
2969 }
2970 else
2971 {
2972 ASSERTL0(false, "element in partition not found");
2973 }
2974
2975 for (int k = 0; k < g->GetNumVerts(); k++)
2976 {
2977 entityIds[0].insert(g->GetVid(k));
2978 }
2979 }
2980 }
2981 }
2982
2983 if (m_meshDimension > 2)
2984 {
2985 for (auto &j : entityIds[2])
2986 {
2987 if (m_triGeoms.count(j))
2988 {
2989 localTri[j] = m_triGeoms[j];
2990 }
2991 else if (m_quadGeoms.count(j))
2992 {
2993 localQuad[j] = m_quadGeoms[j];
2994 }
2995 else
2996 {
2997 ASSERTL0(false, "face not found");
2998 }
2999 }
3000 }
3001
3002 if (m_meshDimension > 1)
3003 {
3004 for (auto &j : entityIds[1])
3005 {
3006 if (m_segGeoms.count(j))
3007 {
3008 localEdge[j] = m_segGeoms[j];
3009 }
3010 else
3011 {
3012 ASSERTL0(false, "edge not found");
3013 }
3014 }
3015 }
3016
3017 for (auto &j : entityIds[0])
3018 {
3019 if (m_vertSet.count(j))
3020 {
3021 localVert[j] = m_vertSet[j];
3022 }
3023 else
3024 {
3025 ASSERTL0(false, "vert not found");
3026 }
3027 }
3028
3029 v_WriteVertices(geomTag, localVert);
3030 v_WriteEdges(geomTag, localEdge);
3031 if (m_meshDimension > 1)
3032 {
3033 TiXmlElement *faceTag =
3034 new TiXmlElement(m_meshDimension == 2 ? "ELEMENT" : "FACE");
3035
3036 v_WriteTris(faceTag, localTri);
3037 v_WriteQuads(faceTag, localQuad);
3038 geomTag->LinkEndChild(faceTag);
3039 }
3040 if (m_meshDimension > 2)
3041 {
3042 TiXmlElement *elmtTag = new TiXmlElement("ELEMENT");
3043
3044 v_WriteHexs(elmtTag, localHex);
3045 v_WritePyrs(elmtTag, localPyr);
3046 v_WritePrisms(elmtTag, localPrism);
3047 v_WriteTets(elmtTag, localTet);
3048
3049 geomTag->LinkEndChild(elmtTag);
3050 }
3051
3052 for (auto &j : localTri)
3053 {
3054 if (m_curvedFaces.count(j.first))
3055 {
3056 localCurveFace[j.first] = m_curvedFaces[j.first];
3057 }
3058 }
3059 for (auto &j : localQuad)
3060 {
3061 if (m_curvedFaces.count(j.first))
3062 {
3063 localCurveFace[j.first] = m_curvedFaces[j.first];
3064 }
3065 }
3066 for (auto &j : localEdge)
3067 {
3068 if (m_curvedEdges.count(j.first))
3069 {
3070 localCurveEdge[j.first] = m_curvedEdges[j.first];
3071 }
3072 }
3073
3074 v_WriteCurves(geomTag, localCurveEdge, localCurveFace);
3075
3076 CompositeMap localComp;
3077 std::map<int, std::string> localCompLabels;
3078
3079 for (auto &j : m_meshComposites)
3080 {
3082 int dim = j.second->m_geomVec[0]->GetShapeDim();
3083
3084 for (int k = 0; k < j.second->m_geomVec.size(); k++)
3085 {
3086 if (entityIds[dim].count(j.second->m_geomVec[k]->GetGlobalID()))
3087 {
3088 comp->m_geomVec.push_back(j.second->m_geomVec[k]);
3089 }
3090 }
3091
3092 if (comp->m_geomVec.size())
3093 {
3094 localComp[j.first] = comp;
3095 if (!m_compositesLabels[j.first].empty())
3096 {
3097 localCompLabels[j.first] = m_compositesLabels[j.first];
3098 }
3099 }
3100 }
3101
3102 WriteComposites(geomTag, localComp, localCompLabels);
3103
3104 map<int, CompositeMap> domain;
3105 for (auto &j : localComp)
3106 {
3107 for (auto &dom : m_domain)
3108 {
3109 for (auto &dIt : dom.second)
3110 {
3111 if (j.first == dIt.first)
3112 {
3113 domain[dom.first][j.first] = j.second;
3114 break;
3115 }
3116 }
3117 }
3118 }
3119
3120 WriteDomain(geomTag, domain);
3121
3122 if (m_session->DefinesElement("NEKTAR/CONDITIONS"))
3123 {
3124 std::set<int> vBndRegionIdList;
3125 TiXmlElement *vConditions =
3126 new TiXmlElement(*m_session->GetElement("Nektar/Conditions"));
3127 TiXmlElement *vBndRegions =
3128 vConditions->FirstChildElement("BOUNDARYREGIONS");
3129 // Use fine-level for mesh partition (Parallel-in-Time)
3131 TiXmlElement *vBndConditions =
3132 vConditions->FirstChildElement("BOUNDARYCONDITIONS");
3133 // Use fine-level for mesh partition (Parallel-in-Time)
3135 0);
3136 TiXmlElement *vItem;
3137
3138 if (vBndRegions)
3139 {
3140 // Check for parallel-in-time
3141 bool multiLevel =
3142 vConditions->FirstChildElement("BOUNDARYREGIONS")
3143 ->FirstChildElement("TIMELEVEL") != nullptr;
3144
3145 TiXmlElement *vNewBndRegions =
3146 multiLevel ? new TiXmlElement("TIMELEVEL")
3147 : new TiXmlElement("BOUNDARYREGIONS");
3148 vItem = vBndRegions->FirstChildElement();
3149 while (vItem)
3150 {
3151 std::string vSeqStr =
3152 vItem->FirstChild()->ToText()->Value();
3153 std::string::size_type indxBeg =
3154 vSeqStr.find_first_of('[') + 1;
3155 std::string::size_type indxEnd =
3156 vSeqStr.find_last_of(']') - 1;
3157 vSeqStr = vSeqStr.substr(indxBeg, indxEnd - indxBeg + 1);
3158 std::vector<unsigned int> vSeq;
3159 ParseUtils::GenerateSeqVector(vSeqStr.c_str(), vSeq);
3160
3161 vector<unsigned int> idxList;
3162
3163 for (unsigned int i = 0; i < vSeq.size(); ++i)
3164 {
3165 if (localComp.find(vSeq[i]) != localComp.end())
3166 {
3167 idxList.push_back(vSeq[i]);
3168 }
3169 }
3170 int p = atoi(vItem->Attribute("ID"));
3171
3172 std::string vListStr =
3174
3175 if (vListStr.length() == 0)
3176 {
3177 TiXmlElement *tmp = vItem;
3178 vItem = vItem->NextSiblingElement();
3179 vBndRegions->RemoveChild(tmp);
3180 }
3181 else
3182 {
3183 vListStr = "C[" + vListStr + "]";
3184 TiXmlText *vList = new TiXmlText(vListStr);
3185 TiXmlElement *vNewElement = new TiXmlElement("B");
3186 vNewElement->SetAttribute("ID", p);
3187 vNewElement->LinkEndChild(vList);
3188 vNewBndRegions->LinkEndChild(vNewElement);
3189 vBndRegionIdList.insert(p);
3190 vItem = vItem->NextSiblingElement();
3191 }
3192
3193 // store original bnd region order
3194 m_bndRegOrder[p] = vSeq;
3195 }
3196 if (multiLevel)
3197 {
3198 // Use fine-level for mesh partition (Parallel-in-Time)
3199 size_t timeLevel = 0;
3200 while (vBndRegions)
3201 {
3202 vNewBndRegions->SetAttribute("VALUE", timeLevel);
3203 vConditions->FirstChildElement("BOUNDARYREGIONS")
3204 ->ReplaceChild(vBndRegions, *vNewBndRegions);
3205 vBndRegions = vBndRegions->NextSiblingElement();
3206 timeLevel++;
3207 }
3208 }
3209 else
3210 {
3211 vConditions->ReplaceChild(vBndRegions, *vNewBndRegions);
3212 }
3213 }
3214
3215 if (vBndConditions)
3216 {
3217 vItem = vBndConditions->FirstChildElement();
3218 while (vItem)
3219 {
3220 std::set<int>::iterator x;
3221 if ((x = vBndRegionIdList.find(atoi(vItem->Attribute(
3222 "REF")))) != vBndRegionIdList.end())
3223 {
3224 vItem->SetAttribute("REF", *x);
3225 vItem = vItem->NextSiblingElement();
3226 }
3227 else
3228 {
3229 TiXmlElement *tmp = vItem;
3230 vItem = vItem->NextSiblingElement();
3231 vBndConditions->RemoveChild(tmp);
3232 }
3233 }
3234 }
3235 root->LinkEndChild(vConditions);
3236 }
3237
3238 // Distribute other sections of the XML to each process as is.
3239 TiXmlElement *vSrc =
3240 m_session->GetElement("Nektar")->FirstChildElement();
3241 while (vSrc)
3242 {
3243 std::string vName = boost::to_upper_copy(vSrc->ValueStr());
3244 if (vName != "GEOMETRY" && vName != "CONDITIONS")
3245 {
3246 root->LinkEndChild(new TiXmlElement(*vSrc));
3247 }
3248 vSrc = vSrc->NextSiblingElement();
3249 }
3250
3251 // Save Mesh
3252
3253 boost::format pad("P%1$07d.xml");
3254 pad % partitions[i];
3255 boost::filesystem::path pFilename(pad.str());
3256
3257 boost::filesystem::path fullpath = pdirname / pFilename;
3258 doc.SaveFile(LibUtilities::PortablePath(fullpath));
3259 }
3260}
3261
3263{
3265
3266 for (auto &c : m_meshComposites)
3267 {
3268 bool fillComp = true;
3269 for (auto &d : m_domain[0])
3270 {
3271 if (c.second == d.second)
3272 {
3273 fillComp = false;
3274 }
3275 }
3276 if (fillComp)
3277 {
3278 std::vector<unsigned int> ids;
3279 for (auto &elmt : c.second->m_geomVec)
3280 {
3281 ids.push_back(elmt->GetGlobalID());
3282 }
3283 ret[c.first] = ids;
3284 }
3285 }
3286
3287 return ret;
3288}
3289
3290} // namespace SpatialDomains
3291} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
static void AddInfoTag(TagWriterSharedPtr root, const FieldMetaDataMap &fieldmetadatamap)
Add provenance information to the field metadata map.
Definition: FieldIO.cpp:344
Interpreter class for the evaluation of mathematical expressions.
Definition: Interpreter.h:78
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:198
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
static void GetXMLElementTimeLevel(TiXmlElement *&element, const size_t timeLevel, const bool disableCheck=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:105
static const int kNfaces
Definition: HexGeom.h:60
static const int kNqfaces
Definition: HexGeom.h:58
static const int kNtfaces
Definition: HexGeom.h:59
bool CheckRange(Geometry2D &geom)
Check if goemetry is in range definition if activated.
Definition: MeshGraph.cpp:354
void ReadGeometry(LibUtilities::DomainRangeShPtr rng, bool fillGraph)
Definition: MeshGraph.h:552
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:3978
Geometry2DSharedPtr GetGeometry2D(int gID)
Definition: MeshGraph.h:418
LibUtilities::SessionReaderSharedPtr m_session
Definition: MeshGraph.h:487
std::map< int, CompositeMap > m_domain
Definition: MeshGraph.h:518
CompositeOrdering m_compOrder
Definition: MeshGraph.h:527
void GetCompositeList(const std::string &compositeStr, CompositeMap &compositeVector) const
Definition: MeshGraph.cpp:601
ExpansionInfoMapShPtrMap m_expansionMapShPtrMap
Definition: MeshGraph.h:521
std::string GetCompositeString(CompositeSharedPtr comp)
Returns a string representation of a composite.
Definition: MeshGraph.cpp:2626
std::unordered_map< int, GeometryLinkSharedPtr > m_faceToElMap
Definition: MeshGraph.h:523
std::map< int, MeshEntity > CreateMeshEntities()
Create mesh entities for this graph.
Definition: MeshGraph.cpp:4009
SegGeomSharedPtr GetSegGeom(int id)
Definition: MeshGraph.h:364
CompositeDescriptor CreateCompositeDescriptor()
Definition: MeshGraph.cpp:4109
std::map< int, std::string > m_compositesLabels
Definition: MeshGraph.h:517
PointGeomSharedPtr GetVertex(int id)
Definition: MeshGraph.h:359
LibUtilities::DomainRangeShPtr m_domainRange
Definition: MeshGraph.h:519
BndRegionOrdering m_bndRegOrder
Definition: MeshGraph.h:528
void ResolveGeomRef1D(const std::string &prevToken, const std::string &token, CompositeSharedPtr &composite)
void WriteDefaultExpansion(TiXmlElement *root)
virtual void v_WriteQuads(TiXmlElement *faceTag, QuadGeomMap &quads)
virtual void v_WritePyrs(TiXmlElement *elmtTag, PyrGeomMap &pyrs)
virtual void v_WriteGeometry(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...
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:62
virtual 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)
virtual 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:57
static const int kNtfaces
Definition: PyrGeom.h:56
static const int kNqfaces
Definition: PyrGeom.h:55
static const int kNedges
Definition: QuadGeom.h:76
static const int kNfaces
Definition: TetGeom.h:58
static const int kNqfaces
Definition: TetGeom.h:56
static const int kNtfaces
Definition: TetGeom.h:57
static const int kNedges
Get the orientation of face1.
Definition: TriGeom.h:72
std::map< std::string, std::string > FieldMetaDataMap
Definition: FieldIO.h:52
const std::string kPointsTypeStr[]
Definition: Foundations.hpp:54
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:45
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< DomainRange > DomainRangeShPtr
Definition: DomainRange.h:66
std::shared_ptr< XmlTagWriter > XmlTagWriterSharedPtr
Definition: FieldIOXml.h:169
static DomainRangeShPtr NullDomainRangeShPtr
Definition: DomainRange.h:67
@ SIZE_PointsType
Length of enum list.
Definition: PointsType.h:97
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:57
std::map< int, TriGeomSharedPtr > TriGeomMap
Definition: TriGeom.h:59
std::map< int, std::vector< unsigned int > > CompositeOrdering
Definition: MeshGraph.h:109
std::shared_ptr< QuadGeom > QuadGeomSharedPtr
Definition: HexGeom.h:47
std::map< int, PyrGeomSharedPtr > PyrGeomMap
Definition: PyrGeom.h:78
std::map< int, QuadGeomSharedPtr > QuadGeomMap
Definition: QuadGeom.h:54
std::shared_ptr< PrismGeom > PrismGeomSharedPtr
Definition: PrismGeom.h:85
MeshPartitionFactory & GetMeshPartitionFactory()
std::shared_ptr< Composite > CompositeSharedPtr
Definition: MeshGraph.h:137
std::map< int, SegGeomSharedPtr > SegGeomMap
Definition: SegGeom.h:52
std::shared_ptr< Curve > CurveSharedPtr
Definition: Curve.hpp:60
std::unordered_map< int, CurveSharedPtr > CurveMap
Definition: Curve.hpp:61
std::shared_ptr< HexGeom > HexGeomSharedPtr
Definition: HexGeom.h:87
std::shared_ptr< SegGeom > SegGeomSharedPtr
Definition: Geometry2D.h:62
std::map< int, TetGeomSharedPtr > TetGeomMap
Definition: TetGeom.h:87
std::shared_ptr< PyrGeom > PyrGeomSharedPtr
Definition: PyrGeom.h:77
std::shared_ptr< TetGeom > TetGeomSharedPtr
Definition: TetGeom.h:85
std::map< int, PrismGeomSharedPtr > PrismGeomMap
Definition: PrismGeom.h:86
std::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:60
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
std::shared_ptr< MeshPartition > MeshPartitionSharedPtr
std::shared_ptr< Geometry > GeometrySharedPtr
Definition: Geometry.h:54
std::shared_ptr< TriGeom > TriGeomSharedPtr
Definition: TriGeom.h:58
MeshGraphFactory & GetMeshGraphFactory()
Definition: MeshGraph.cpp:79
std::map< int, HexGeomSharedPtr > HexGeomMap
Definition: HexGeom.h:88
std::map< int, PointGeomSharedPtr > PointGeomMap
Definition: PointGeom.h:54
std::map< int, CompositeSharedPtr > CompositeMap
Definition: MeshGraph.h:138
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:453
std::vector< double > d(NPUPPER *NPUPPER)
std::vector< double > q(NPUPPER *NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble