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