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 = ObjPoolManager<Curve>::AllocateUniquePtr(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] = std::move(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(
1310 indx, spaceDimension, vertices,
1311 it->second.get()));
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.get()));
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.get()));
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(
1553 indx,
1555 indx, spaceDimension, vertices, it->second.get()));
1556 }
1557 }
1558 catch (...)
1559 {
1561 (std::string("Unable to read element data for segment: ") +
1562 elementStr)
1563 .c_str());
1564 }
1565 /// Keep looking for additional segments
1566 segment = segment->NextSiblingElement("S");
1567 }
1568}
1569
1571{
1572 auto &curvedFaces = m_meshGraph->GetCurvedFaces();
1573
1574 /// Look for elements in ELEMENT block.
1575 TiXmlElement *field = m_xmlGeom->FirstChildElement("ELEMENT");
1576
1577 ASSERTL0(field, "Unable to find ELEMENT tag in file.");
1578
1579 // Set up curve map for curved elements on an embedded manifold.
1580 CurveMap::iterator it;
1581
1582 /// All elements are of the form: "<? ID="#"> ... </?>", with
1583 /// ? being the element type.
1584
1585 TiXmlElement *element = field->FirstChildElement();
1586
1587 while (element)
1588 {
1589 std::string elementType(element->ValueStr());
1590
1591 ASSERTL0(
1592 elementType == "Q" || elementType == "T",
1593 (std::string("Unknown 2D element type: ") + elementType).c_str());
1594
1595 /// Read id attribute.
1596 int indx;
1597 int err = element->QueryIntAttribute("ID", &indx);
1598 ASSERTL0(err == TIXML_SUCCESS, "Unable to read element attribute ID.");
1599
1600 it = curvedFaces.find(indx);
1601
1602 /// Read text element description.
1603 TiXmlNode *elementChild = element->FirstChild();
1604 std::string elementStr;
1605 while (elementChild)
1606 {
1607 if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
1608 {
1609 elementStr += elementChild->ToText()->ValueStr();
1610 }
1611 elementChild = elementChild->NextSibling();
1612 }
1613
1614 ASSERTL0(!elementStr.empty(),
1615 "Unable to read element description body.");
1616
1617 /// Parse out the element components corresponding to type of
1618 /// element.
1619 if (elementType == "T")
1620 {
1621 // Read three edge numbers
1622 int edge1, edge2, edge3;
1623 std::istringstream elementDataStrm(elementStr.c_str());
1624
1625 try
1626 {
1627 elementDataStrm >> edge1;
1628 elementDataStrm >> edge2;
1629 elementDataStrm >> edge3;
1630
1631 ASSERTL0(
1632 !elementDataStrm.fail(),
1633 (std::string("Unable to read element data for TRIANGLE: ") +
1634 elementStr)
1635 .c_str());
1636
1637 /// Create a TriGeom to hold the new definition.
1638 std::array<SegGeom *, TriGeom::kNedges> edges = {
1639 m_meshGraph->GetSegGeom(edge1),
1640 m_meshGraph->GetSegGeom(edge2),
1641 m_meshGraph->GetSegGeom(edge3)};
1642
1643 if (it == curvedFaces.end())
1644 {
1645 m_meshGraph->AddGeom(
1647 indx, edges));
1648 }
1649 else
1650 {
1651 m_meshGraph->AddGeom(
1653 indx, edges, it->second.get()));
1654 }
1655 }
1656 catch (...)
1657 {
1658 NEKERROR(
1660 (std::string("Unable to read element data for TRIANGLE: ") +
1661 elementStr)
1662 .c_str());
1663 }
1664 }
1665 else if (elementType == "Q")
1666 {
1667 // Read four edge numbers
1668 int edge1, edge2, edge3, edge4;
1669 std::istringstream elementDataStrm(elementStr.c_str());
1670
1671 try
1672 {
1673 elementDataStrm >> edge1;
1674 elementDataStrm >> edge2;
1675 elementDataStrm >> edge3;
1676 elementDataStrm >> edge4;
1677
1678 ASSERTL0(
1679 !elementDataStrm.fail(),
1680 (std::string("Unable to read element data for QUAD: ") +
1681 elementStr)
1682 .c_str());
1683
1684 /// Create a QuadGeom to hold the new definition.
1685 std::array<SegGeom *, QuadGeom::kNedges> edges = {
1686 m_meshGraph->GetSegGeom(edge1),
1687 m_meshGraph->GetSegGeom(edge2),
1688 m_meshGraph->GetSegGeom(edge3),
1689 m_meshGraph->GetSegGeom(edge4)};
1690
1691 if (it == curvedFaces.end())
1692 {
1693 m_meshGraph->AddGeom(
1695 indx, edges));
1696 }
1697 else
1698 {
1699 m_meshGraph->AddGeom(
1701 indx, edges, it->second.get()));
1702 }
1703 }
1704 catch (...)
1705 {
1706 NEKERROR(
1708 (std::string("Unable to read element data for QUAD: ") +
1709 elementStr)
1710 .c_str());
1711 }
1712 }
1713 /// Keep looking
1714 element = element->NextSiblingElement();
1715 }
1716}
1717
1719{
1720 /// Look for elements in ELEMENT block.
1721 TiXmlElement *field = m_xmlGeom->FirstChildElement("ELEMENT");
1722
1723 ASSERTL0(field, "Unable to find ELEMENT tag in file.");
1724
1725 /// All elements are of the form: "<? ID="#"> ... </?>", with
1726 /// ? being the element type.
1727
1728 TiXmlElement *element = field->FirstChildElement();
1729
1730 while (element)
1731 {
1732 std::string elementType(element->ValueStr());
1733
1734 // A - tet, P - pyramid, R - prism, H - hex
1735 ASSERTL0(
1736 elementType == "A" || elementType == "P" || elementType == "R" ||
1737 elementType == "H",
1738 (std::string("Unknown 3D element type: ") + elementType).c_str());
1739
1740 /// Read id attribute.
1741 int indx;
1742 int err = element->QueryIntAttribute("ID", &indx);
1743 ASSERTL0(err == TIXML_SUCCESS, "Unable to read element attribute ID.");
1744
1745 /// Read text element description.
1746 TiXmlNode *elementChild = element->FirstChild();
1747 std::string elementStr;
1748 while (elementChild)
1749 {
1750 if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
1751 {
1752 elementStr += elementChild->ToText()->ValueStr();
1753 }
1754 elementChild = elementChild->NextSibling();
1755 }
1756
1757 ASSERTL0(!elementStr.empty(),
1758 "Unable to read element description body.");
1759
1760 std::istringstream elementDataStrm(elementStr.c_str());
1761
1762 /// Parse out the element components corresponding to type of
1763 /// element.
1764
1765 // Tetrahedral
1766 if (elementType == "A")
1767 {
1768 try
1769 {
1770 /// Create arrays for the tri and quad faces.
1771 constexpr int kNfaces = TetGeom::kNfaces;
1772 constexpr int kNtfaces = TetGeom::kNtfaces;
1773 constexpr int kNqfaces = TetGeom::kNqfaces;
1774 std::array<TriGeom *, kNtfaces> tfaces;
1775 int Ntfaces = 0;
1776 int Nqfaces = 0;
1777
1778 /// Fill the arrays and make sure there aren't too many
1779 /// faces.
1780 std::stringstream errorstring;
1781 errorstring << "Element " << indx << " must have " << kNtfaces
1782 << " triangle face(s), and " << kNqfaces
1783 << " quadrilateral face(s).";
1784 for (int i = 0; i < kNfaces; i++)
1785 {
1786 int faceID;
1787 elementDataStrm >> faceID;
1788 Geometry2D *face = m_meshGraph->GetGeometry2D(faceID);
1789 if (face == nullptr ||
1792 {
1793 std::stringstream errorstring;
1794 errorstring << "Element " << indx
1795 << " has invalid face: " << faceID;
1796 ASSERTL0(false, errorstring.str().c_str());
1797 }
1798 else if (face->GetShapeType() == LibUtilities::eTriangle)
1799 {
1800 ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1801 tfaces[Ntfaces++] = static_cast<TriGeom *>(face);
1802 }
1803 else if (face->GetShapeType() ==
1805 {
1806 ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1807 }
1808 }
1809
1810 /// Make sure all of the face indicies could be read, and
1811 /// that there weren't too few.
1812 ASSERTL0(!elementDataStrm.fail(),
1813 (std::string(
1814 "Unable to read element data for TETRAHEDRON: ") +
1815 elementStr)
1816 .c_str());
1817 ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1818 ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1819
1820 auto tetGeom =
1822 m_meshGraph->PopulateFaceToElMap(tetGeom.get(), kNfaces);
1823 m_meshGraph->AddGeom(indx, std::move(tetGeom));
1824 }
1825 catch (...)
1826 {
1828 (std::string(
1829 "Unable to read element data for TETRAHEDRON: ") +
1830 elementStr)
1831 .c_str());
1832 }
1833 }
1834 // Pyramid
1835 else if (elementType == "P")
1836 {
1837 try
1838 {
1839 /// Create arrays for the tri and quad faces.
1840 constexpr int kNfaces = PyrGeom::kNfaces;
1841 constexpr int kNtfaces = PyrGeom::kNtfaces;
1842 constexpr int kNqfaces = PyrGeom::kNqfaces;
1843 std::array<Geometry2D *, kNfaces> faces;
1844 int Nfaces = 0;
1845 int Ntfaces = 0;
1846 int Nqfaces = 0;
1847
1848 /// Fill the arrays and make sure there aren't too many
1849 /// faces.
1850 std::stringstream errorstring;
1851 errorstring << "Element " << indx << " must have " << kNtfaces
1852 << " triangle face(s), and " << kNqfaces
1853 << " quadrilateral face(s).";
1854 for (int i = 0; i < kNfaces; i++)
1855 {
1856 int faceID;
1857 elementDataStrm >> faceID;
1858 Geometry2D *face = m_meshGraph->GetGeometry2D(faceID);
1859 if (face == nullptr ||
1862 {
1863 std::stringstream errorstring;
1864 errorstring << "Element " << indx
1865 << " has invalid face: " << faceID;
1866 ASSERTL0(false, errorstring.str().c_str());
1867 }
1868 else if (face->GetShapeType() == LibUtilities::eTriangle)
1869 {
1870 ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1871 faces[Nfaces++] = static_cast<TriGeom *>(face);
1872 Ntfaces++;
1873 }
1874 else if (face->GetShapeType() ==
1876 {
1877 ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1878 faces[Nfaces++] = static_cast<QuadGeom *>(face);
1879 Nqfaces++;
1880 }
1881 }
1882
1883 /// Make sure all of the face indicies could be read, and
1884 /// that there weren't too few.
1885 ASSERTL0(
1886 !elementDataStrm.fail(),
1887 (std::string("Unable to read element data for PYRAMID: ") +
1888 elementStr)
1889 .c_str());
1890 ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1891 ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1892
1893 auto pyrGeom =
1895 m_meshGraph->PopulateFaceToElMap(pyrGeom.get(), kNfaces);
1896 m_meshGraph->AddGeom(indx, std::move(pyrGeom));
1897 }
1898 catch (...)
1899 {
1900 NEKERROR(
1902 (std::string("Unable to read element data for PYRAMID: ") +
1903 elementStr)
1904 .c_str());
1905 }
1906 }
1907 // Prism
1908 else if (elementType == "R")
1909 {
1910 try
1911 {
1912 /// Create arrays for the tri and quad faces.
1913 constexpr int kNfaces = PrismGeom::kNfaces;
1914 constexpr int kNtfaces = PrismGeom::kNtfaces;
1915 constexpr int kNqfaces = PrismGeom::kNqfaces;
1916 std::array<Geometry2D *, kNfaces> faces;
1917 int Ntfaces = 0;
1918 int Nqfaces = 0;
1919 int Nfaces = 0;
1920
1921 /// Fill the arrays and make sure there aren't too many
1922 /// faces.
1923 std::stringstream errorstring;
1924 errorstring << "Element " << indx << " must have " << kNtfaces
1925 << " triangle face(s), and " << kNqfaces
1926 << " quadrilateral face(s).";
1927
1928 for (int i = 0; i < kNfaces; i++)
1929 {
1930 int faceID;
1931 elementDataStrm >> faceID;
1932 Geometry2D *face = m_meshGraph->GetGeometry2D(faceID);
1933 if (face == nullptr ||
1936 {
1937 std::stringstream errorstring;
1938 errorstring << "Element " << indx
1939 << " has invalid face: " << faceID;
1940 ASSERTL0(false, errorstring.str().c_str());
1941 }
1942 else if (face->GetShapeType() == LibUtilities::eTriangle)
1943 {
1944 ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
1945 faces[Nfaces++] = static_cast<TriGeom *>(face);
1946 Ntfaces++;
1947 }
1948 else if (face->GetShapeType() ==
1950 {
1951 ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
1952 faces[Nfaces++] = static_cast<QuadGeom *>(face);
1953 Nqfaces++;
1954 }
1955 }
1956
1957 /// Make sure all of the face indices could be read, and
1958 /// that there weren't too few.
1959 ASSERTL0(
1960 !elementDataStrm.fail(),
1961 (std::string("Unable to read element data for PRISM: ") +
1962 elementStr)
1963 .c_str());
1964 ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
1965 ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
1966
1967 auto prismGeom =
1969 m_meshGraph->PopulateFaceToElMap(prismGeom.get(), kNfaces);
1970 m_meshGraph->AddGeom(indx, std::move(prismGeom));
1971 }
1972 catch (...)
1973 {
1974 NEKERROR(
1976 (std::string("Unable to read element data for PRISM: ") +
1977 elementStr)
1978 .c_str());
1979 }
1980 }
1981 // Hexahedral
1982 else if (elementType == "H")
1983 {
1984 try
1985 {
1986 /// Create arrays for the tri and quad faces.
1987 constexpr int kNfaces = HexGeom::kNfaces;
1988 constexpr int kNtfaces = HexGeom::kNtfaces;
1989 constexpr int kNqfaces = HexGeom::kNqfaces;
1990 // TriGeomUniquePtr tfaces[kNtfaces];
1991 std::array<QuadGeom *, kNqfaces> qfaces;
1992 int Ntfaces = 0;
1993 int Nqfaces = 0;
1994
1995 /// Fill the arrays and make sure there aren't too many
1996 /// faces.
1997 std::stringstream errorstring;
1998 errorstring << "Element " << indx << " must have " << kNtfaces
1999 << " triangle face(s), and " << kNqfaces
2000 << " quadrilateral face(s).";
2001 for (int i = 0; i < kNfaces; i++)
2002 {
2003 int faceID;
2004 elementDataStrm >> faceID;
2005 Geometry2D *face = m_meshGraph->GetGeometry2D(faceID);
2006 if (face == nullptr ||
2009 {
2010 std::stringstream errorstring;
2011 errorstring << "Element " << indx
2012 << " has invalid face: " << faceID;
2013 ASSERTL0(false, errorstring.str().c_str());
2014 }
2015 else if (face->GetShapeType() == LibUtilities::eTriangle)
2016 {
2017 ASSERTL0(Ntfaces < kNtfaces, errorstring.str().c_str());
2018 }
2019 else if (face->GetShapeType() ==
2021 {
2022 ASSERTL0(Nqfaces < kNqfaces, errorstring.str().c_str());
2023 qfaces[Nqfaces++] = static_cast<QuadGeom *>(face);
2024 }
2025 }
2026
2027 /// Make sure all of the face indicies could be read, and
2028 /// that there weren't too few.
2029 ASSERTL0(!elementDataStrm.fail(),
2030 (std::string(
2031 "Unable to read element data for HEXAHEDRAL: ") +
2032 elementStr)
2033 .c_str());
2034 ASSERTL0(Ntfaces == kNtfaces, errorstring.str().c_str());
2035 ASSERTL0(Nqfaces == kNqfaces, errorstring.str().c_str());
2036
2037 auto hexGeom =
2039 m_meshGraph->PopulateFaceToElMap(hexGeom.get(), kNfaces);
2040 m_meshGraph->AddGeom(indx, std::move(hexGeom));
2041 }
2042 catch (...)
2043 {
2045 (std::string(
2046 "Unable to read element data for HEXAHEDRAL: ") +
2047 elementStr)
2048 .c_str());
2049 }
2050 }
2051 /// Keep looking
2052 element = element->NextSiblingElement();
2053 }
2054}
2055
2057{
2058 auto &meshComposites = m_meshGraph->GetComposites();
2059 auto &compositesLabels = m_meshGraph->GetCompositesLabels();
2060
2061 TiXmlElement *field = nullptr;
2062
2063 /// Look for elements in ELEMENT block.
2064 field = m_xmlGeom->FirstChildElement("COMPOSITE");
2065
2066 ASSERTL0(field, "Unable to find COMPOSITE tag in file.");
2067
2068 TiXmlElement *node = field->FirstChildElement("C");
2069
2070 // Sequential counter for the composite numbers.
2071 int nextCompositeNumber = -1;
2072
2073 while (node)
2074 {
2075 /// All elements are of the form: "<? ID="#"> ... </?>", with
2076 /// ? being the element type.
2077
2078 nextCompositeNumber++;
2079
2080 int indx;
2081 int err = node->QueryIntAttribute("ID", &indx);
2082 ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
2083 // ASSERTL0(indx == nextCompositeNumber, "Composite IDs must begin with
2084 // zero and be sequential.");
2085
2086 TiXmlNode *compositeChild = node->FirstChild();
2087 // This is primarily to skip comments that may be present.
2088 // Comments appear as nodes just like elements.
2089 // We are specifically looking for text in the body
2090 // of the definition.
2091 while (compositeChild &&
2092 compositeChild->Type() != TiXmlNode::TINYXML_TEXT)
2093 {
2094 compositeChild = compositeChild->NextSibling();
2095 }
2096
2097 ASSERTL0(compositeChild, "Unable to read composite definition body.");
2098 std::string compositeStr = compositeChild->ToText()->ValueStr();
2099
2100 /// Parse out the element components corresponding to type of element.
2101
2102 std::istringstream compositeDataStrm(compositeStr.c_str());
2103
2104 try
2105 {
2106 bool first = true;
2107 std::string prevCompositeElementStr;
2108
2109 while (!compositeDataStrm.fail())
2110 {
2111 std::string compositeElementStr;
2112 compositeDataStrm >> compositeElementStr;
2113
2114 if (!compositeDataStrm.fail())
2115 {
2116 if (first)
2117 {
2118 first = false;
2119 meshComposites[indx] =
2121 }
2122
2123 if (compositeElementStr.length() > 0)
2124 {
2125 ResolveGeomRef(prevCompositeElementStr,
2126 compositeElementStr,
2127 meshComposites[indx]);
2128 }
2129 prevCompositeElementStr = compositeElementStr;
2130 }
2131 }
2132 }
2133 catch (...)
2134 {
2135 NEKERROR(
2137 (std::string("Unable to read COMPOSITE data for composite: ") +
2138 compositeStr)
2139 .c_str());
2140 }
2141
2142 // Read optional name as string and save to compositeLabels if exists
2143 std::string name;
2144 err = node->QueryStringAttribute("NAME", &name);
2145 if (err == TIXML_SUCCESS)
2146 {
2147 compositesLabels[indx] = name;
2148 }
2149
2150 /// Keep looking for additional composite definitions.
2151 node = node->NextSiblingElement("C");
2152 }
2153
2154 ASSERTL0(nextCompositeNumber >= 0,
2155 "At least one composite must be specified.");
2156}
2157
2158void MeshGraphIOXml::ResolveGeomRef(const std::string &prevToken,
2159 const std::string &token,
2160 CompositeSharedPtr &composite)
2161{
2162 int meshDimension = m_meshGraph->GetMeshDimension();
2163
2164 switch (meshDimension)
2165 {
2166 case 1:
2167 ResolveGeomRef1D(prevToken, token, composite);
2168 break;
2169 case 2:
2170 ResolveGeomRef2D(prevToken, token, composite);
2171 break;
2172 case 3:
2173 ResolveGeomRef3D(prevToken, token, composite);
2174 break;
2175 }
2176}
2177
2178void MeshGraphIOXml::ResolveGeomRef1D(const std::string &prevToken,
2179 const std::string &token,
2180 CompositeSharedPtr &composite)
2181{
2182 try
2183 {
2184 std::istringstream tokenStream(token);
2185 std::istringstream prevTokenStream(prevToken);
2186
2187 char type;
2188 char prevType;
2189
2190 tokenStream >> type;
2191
2192 std::string::size_type indxBeg = token.find_first_of('[') + 1;
2193 std::string::size_type indxEnd = token.find_last_of(']') - 1;
2194
2195 ASSERTL0(
2196 indxBeg <= indxEnd,
2197 (std::string("Error reading index definition:") + token).c_str());
2198
2199 std::string indxStr = token.substr(indxBeg, indxEnd - indxBeg + 1);
2200
2201 typedef std::vector<unsigned int> SeqVectorType;
2202 SeqVectorType seqVector;
2203
2204 if (!ParseUtils::GenerateSeqVector(indxStr.c_str(), seqVector))
2205 {
2207 (std::string("Ill-formed sequence definition: ") + indxStr)
2208 .c_str());
2209 }
2210
2211 prevTokenStream >> prevType;
2212
2213 // All composites must be of the same dimension.
2214 bool validSequence =
2215 (prevToken.empty() || // No previous, then current is just fine.
2216 (type == 'V' && prevType == 'V') ||
2217 (type == 'S' && prevType == 'S'));
2218
2219 ASSERTL0(validSequence,
2220 std::string("Invalid combination of composite items: ") +
2221 type + " and " + prevType + ".");
2222
2223 switch (type)
2224 {
2225 case 'V': // Vertex
2226 for (SeqVectorType::iterator iter = seqVector.begin();
2227 iter != seqVector.end(); ++iter)
2228 {
2229 composite->m_geomVec.push_back(
2230 m_meshGraph->GetPointGeom(*iter));
2231 }
2232 break;
2233
2234 case 'S': // Segment
2235 for (SeqVectorType::iterator iter = seqVector.begin();
2236 iter != seqVector.end(); ++iter)
2237 {
2238 composite->m_geomVec.push_back(
2239 m_meshGraph->GetSegGeom(*iter));
2240 }
2241 break;
2242
2243 default:
2245 "Unrecognized composite token: " + token);
2246 }
2247 }
2248 catch (...)
2249 {
2251 "Problem processing composite token: " + token);
2252 }
2253
2254 return;
2255}
2256
2257void MeshGraphIOXml::ResolveGeomRef2D(const std::string &prevToken,
2258 const std::string &token,
2259 CompositeSharedPtr &composite)
2260{
2261 try
2262 {
2263 std::istringstream tokenStream(token);
2264 std::istringstream prevTokenStream(prevToken);
2265
2266 char type;
2267 char prevType;
2268
2269 tokenStream >> type;
2270
2271 std::string::size_type indxBeg = token.find_first_of('[') + 1;
2272 std::string::size_type indxEnd = token.find_last_of(']') - 1;
2273
2274 ASSERTL0(
2275 indxBeg <= indxEnd,
2276 (std::string("Error reading index definition:") + token).c_str());
2277
2278 std::string indxStr = token.substr(indxBeg, indxEnd - indxBeg + 1);
2279 std::vector<unsigned int> seqVector;
2280 std::vector<unsigned int>::iterator seqIter;
2281
2282 bool err = ParseUtils::GenerateSeqVector(indxStr.c_str(), seqVector);
2283
2284 ASSERTL0(err,
2285 (std::string("Error reading composite elements: ") + indxStr)
2286 .c_str());
2287
2288 prevTokenStream >> prevType;
2289
2290 // All composites must be of the same dimension.
2291 bool validSequence =
2292 (prevToken.empty() || // No previous, then current is just fine.
2293 (type == 'V' && prevType == 'V') ||
2294 (type == 'E' && prevType == 'E') ||
2295 ((type == 'T' || type == 'Q') &&
2296 (prevType == 'T' || prevType == 'Q')));
2297
2298 ASSERTL0(validSequence,
2299 std::string("Invalid combination of composite items: ") +
2300 type + " and " + prevType + ".");
2301
2302 switch (type)
2303 {
2304 case 'E': // Edge
2305 {
2306 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2307 ++seqIter)
2308 {
2309 composite->m_geomVec.push_back(
2310 m_meshGraph->GetSegGeom(*seqIter));
2311 }
2312 break;
2313 }
2314
2315 case 'T': // Triangle
2316 {
2317 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2318 ++seqIter)
2319 {
2320 auto tri = m_meshGraph->GetTriGeom(*seqIter);
2321 if (m_meshGraph->CheckRange(*tri))
2322 {
2323 composite->m_geomVec.push_back(tri);
2324 }
2325 }
2326 break;
2327 }
2328
2329 case 'Q': // Quad
2330 {
2331 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2332 ++seqIter)
2333 {
2334 auto quad = m_meshGraph->GetQuadGeom(*seqIter);
2335 if (m_meshGraph->CheckRange(*quad))
2336 {
2337 composite->m_geomVec.push_back(quad);
2338 }
2339 }
2340 break;
2341 }
2342
2343 case 'V': // Vertex
2344 {
2345 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2346 ++seqIter)
2347 {
2348 composite->m_geomVec.push_back(
2349 m_meshGraph->GetPointGeom(*seqIter));
2350 }
2351 break;
2352 }
2353
2354 default:
2356 "Unrecognized composite token: " + token);
2357 }
2358 }
2359 catch (...)
2360 {
2362 "Problem processing composite token: " + token);
2363 }
2364
2365 return;
2366}
2367
2368void MeshGraphIOXml::ResolveGeomRef3D(const std::string &prevToken,
2369 const std::string &token,
2370 CompositeSharedPtr &composite)
2371{
2372 try
2373 {
2374 std::istringstream tokenStream(token);
2375 std::istringstream prevTokenStream(prevToken);
2376
2377 char type;
2378 char prevType;
2379
2380 tokenStream >> type;
2381
2382 std::string::size_type indxBeg = token.find_first_of('[') + 1;
2383 std::string::size_type indxEnd = token.find_last_of(']') - 1;
2384
2385 ASSERTL0(indxBeg <= indxEnd,
2386 "Error reading index definition: " + token);
2387
2388 std::string indxStr = token.substr(indxBeg, indxEnd - indxBeg + 1);
2389
2390 std::vector<unsigned int> seqVector;
2391 std::vector<unsigned int>::iterator seqIter;
2392
2393 bool err = ParseUtils::GenerateSeqVector(indxStr.c_str(), seqVector);
2394
2395 ASSERTL0(err, "Error reading composite elements: " + indxStr);
2396
2397 prevTokenStream >> prevType;
2398
2399 // All composites must be of the same dimension. This map makes things
2400 // clean to compare.
2401 std::map<char, int> typeMap;
2402 typeMap['V'] = 1; // Vertex
2403 typeMap['E'] = 1; // Edge
2404 typeMap['T'] = 2; // Triangle
2405 typeMap['Q'] = 2; // Quad
2406 typeMap['A'] = 3; // Tet
2407 typeMap['P'] = 3; // Pyramid
2408 typeMap['R'] = 3; // Prism
2409 typeMap['H'] = 3; // Hex
2410
2411 // Make sure only geoms of the same dimension are combined.
2412 bool validSequence =
2413 (prevToken.empty() || (typeMap[type] == typeMap[prevType]));
2414
2415 ASSERTL0(validSequence,
2416 std::string("Invalid combination of composite items: ") +
2417 type + " and " + prevType + ".");
2418
2419 switch (type)
2420 {
2421 case 'V': // Vertex
2422 {
2423 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2424 ++seqIter)
2425 {
2426 composite->m_geomVec.push_back(
2427 m_meshGraph->GetPointGeom(*seqIter));
2428 }
2429 break;
2430 }
2431
2432 case 'E': // Edge
2433 {
2434 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2435 ++seqIter)
2436 {
2437 composite->m_geomVec.push_back(
2438 m_meshGraph->GetSegGeom(*seqIter));
2439 }
2440 break;
2441 }
2442
2443 case 'F': // Face
2444 {
2445 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2446 ++seqIter)
2447 {
2448 Geometry2D *face = m_meshGraph->GetGeometry2D(*seqIter);
2449 if (face == nullptr)
2450 {
2452 "Unknown face index: " +
2453 std::to_string(*seqIter));
2454 }
2455 else
2456 {
2457 if (m_meshGraph->CheckRange(*face))
2458 {
2459 composite->m_geomVec.push_back(face);
2460 }
2461 }
2462 }
2463 break;
2464 }
2465
2466 case 'T': // Triangle
2467 {
2468 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2469 ++seqIter)
2470 {
2471 auto geom = m_meshGraph->GetTriGeom(*seqIter);
2472
2473 if (m_meshGraph->CheckRange(*geom))
2474 {
2475 composite->m_geomVec.push_back(geom);
2476 }
2477 }
2478 break;
2479 }
2480
2481 case 'Q': // Quad
2482 {
2483 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2484 ++seqIter)
2485 {
2486 auto geom = m_meshGraph->GetQuadGeom(*seqIter);
2487
2488 if (m_meshGraph->CheckRange(*geom))
2489 {
2490 composite->m_geomVec.push_back(geom);
2491 }
2492 }
2493 break;
2494 }
2495
2496 // Tetrahedron
2497 case 'A':
2498 {
2499 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2500 ++seqIter)
2501 {
2502 auto geom = m_meshGraph->GetTetGeom(*seqIter);
2503
2504 if (m_meshGraph->CheckRange(*geom))
2505 {
2506 composite->m_geomVec.push_back(geom);
2507 }
2508 }
2509 break;
2510 }
2511
2512 // Pyramid
2513 case 'P':
2514 {
2515 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2516 ++seqIter)
2517 {
2518 auto geom = m_meshGraph->GetPyrGeom(*seqIter);
2519
2520 if (m_meshGraph->CheckRange(*geom))
2521 {
2522 composite->m_geomVec.push_back(geom);
2523 }
2524 }
2525 break;
2526 }
2527
2528 // Prism
2529 case 'R':
2530 {
2531 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2532 ++seqIter)
2533 {
2534 auto geom = m_meshGraph->GetPrismGeom(*seqIter);
2535
2536 if (m_meshGraph->CheckRange(*geom))
2537 {
2538 composite->m_geomVec.push_back(geom);
2539 }
2540 }
2541 break;
2542 }
2543
2544 // Hex
2545 case 'H':
2546 {
2547 for (seqIter = seqVector.begin(); seqIter != seqVector.end();
2548 ++seqIter)
2549 {
2550 auto geom = m_meshGraph->GetHexGeom(*seqIter);
2551
2552 if (m_meshGraph->CheckRange(*geom))
2553 {
2554 composite->m_geomVec.push_back(geom);
2555 }
2556 }
2557 break;
2558 }
2559
2560 default:
2562 "Unrecognized composite token: " + token);
2563 }
2564 }
2565 catch (...)
2566 {
2568 "Problem processing composite token: " + token);
2569 }
2570
2571 return;
2572}
2573
2574void WriteVert(PointGeom *vert, TiXmlElement *vertTag)
2575{
2576 std::stringstream s;
2577 s << std::scientific << std::setprecision(8) << (*vert)(0) << " "
2578 << (*vert)(1) << " " << (*vert)(2);
2579 TiXmlElement *v = new TiXmlElement("V");
2580 v->SetAttribute("ID", vert->GetGlobalID());
2581 v->LinkEndChild(new TiXmlText(s.str()));
2582 vertTag->LinkEndChild(v);
2583}
2584
2585void MeshGraphIOXml::v_WriteVertices(TiXmlElement *geomTag,
2586 std::vector<int> keysToWrite)
2587{
2588 TiXmlElement *vertTag = new TiXmlElement("VERTEX");
2589
2590 if (keysToWrite.empty())
2591 {
2592 for (auto [id, vert] : m_meshGraph->GetGeomMap<PointGeom>())
2593 {
2594 WriteVert(vert, vertTag);
2595 }
2596 }
2597 else
2598 {
2599 for (int id : keysToWrite)
2600 {
2601 WriteVert(m_meshGraph->GetPointGeom(id), vertTag);
2602 }
2603 }
2604
2605 geomTag->LinkEndChild(vertTag);
2606}
2607
2608void WriteEdge(SegGeom *seg, TiXmlElement *edgeTag, std::string &tag,
2609 int edgeID)
2610{
2611 std::stringstream s;
2612 s << seg->GetVid(0) << " " << seg->GetVid(1);
2613 TiXmlElement *e = new TiXmlElement(tag);
2614 e->SetAttribute("ID", edgeID);
2615 e->LinkEndChild(new TiXmlText(s.str()));
2616 edgeTag->LinkEndChild(e);
2617}
2618
2619void MeshGraphIOXml::v_WriteEdges(TiXmlElement *geomTag,
2620 std::vector<int> keysToWrite)
2621{
2622 int meshDimension = m_meshGraph->GetMeshDimension();
2623
2624 TiXmlElement *edgeTag =
2625 new TiXmlElement(meshDimension == 1 ? "ELEMENT" : "EDGE");
2626 std::string tag = meshDimension == 1 ? "S" : "E";
2627
2628 if (keysToWrite.empty())
2629 {
2630 for (auto [id, seg] : m_meshGraph->GetGeomMap<SegGeom>())
2631 {
2632 WriteEdge(seg, edgeTag, tag, id);
2633 }
2634 }
2635 else
2636 {
2637 for (int id : keysToWrite)
2638 {
2639 WriteEdge(m_meshGraph->GetSegGeom(id), edgeTag, tag, id);
2640 }
2641 }
2642
2643 geomTag->LinkEndChild(edgeTag);
2644}
2645
2646void WriteTri(TriGeom *tri, TiXmlElement *faceTag, std::string &tag, int triID)
2647{
2648 std::stringstream s;
2649 s << tri->GetEid(0) << " " << tri->GetEid(1) << " " << tri->GetEid(2);
2650 TiXmlElement *t = new TiXmlElement(tag);
2651 t->SetAttribute("ID", triID);
2652 t->LinkEndChild(new TiXmlText(s.str()));
2653 faceTag->LinkEndChild(t);
2654}
2655void MeshGraphIOXml::v_WriteTris(TiXmlElement *faceTag,
2656 std::vector<int> keysToWrite)
2657{
2658 std::string tag = "T";
2659
2660 if (keysToWrite.empty())
2661 {
2662 for (auto [id, tri] : m_meshGraph->GetGeomMap<TriGeom>())
2663 {
2664 WriteTri(tri, faceTag, tag, id);
2665 }
2666 }
2667 else
2668 {
2669 for (int id : keysToWrite)
2670 {
2671 WriteTri(m_meshGraph->GetTriGeom(id), faceTag, tag, id);
2672 }
2673 }
2674}
2675
2676void WriteQuad(QuadGeom *quad, TiXmlElement *faceTag, std::string &tag,
2677 int quadID)
2678{
2679 std::stringstream s;
2680 s << quad->GetEid(0) << " " << quad->GetEid(1) << " " << quad->GetEid(2)
2681 << " " << quad->GetEid(3);
2682 TiXmlElement *q = new TiXmlElement(tag);
2683 q->SetAttribute("ID", quadID);
2684 q->LinkEndChild(new TiXmlText(s.str()));
2685 faceTag->LinkEndChild(q);
2686}
2687void MeshGraphIOXml::v_WriteQuads(TiXmlElement *faceTag,
2688 std::vector<int> keysToWrite)
2689{
2690 std::string tag = "Q";
2691
2692 if (keysToWrite.empty())
2693 {
2694 for (auto [id, quad] : m_meshGraph->GetGeomMap<QuadGeom>())
2695 {
2696 WriteQuad(quad, faceTag, tag, id);
2697 }
2698 }
2699 else
2700 {
2701 for (int id : keysToWrite)
2702 {
2703 WriteQuad(m_meshGraph->GetQuadGeom(id), faceTag, tag, id);
2704 }
2705 }
2706}
2707
2708void WriteHex(HexGeom *hex, TiXmlElement *elmtTag, std::string &tag, int hexID)
2709{
2710 std::stringstream s;
2711 s << hex->GetFid(0) << " " << hex->GetFid(1) << " " << hex->GetFid(2) << " "
2712 << hex->GetFid(3) << " " << hex->GetFid(4) << " " << hex->GetFid(5)
2713 << " ";
2714 TiXmlElement *h = new TiXmlElement(tag);
2715 h->SetAttribute("ID", hexID);
2716 h->LinkEndChild(new TiXmlText(s.str()));
2717 elmtTag->LinkEndChild(h);
2718}
2719void MeshGraphIOXml::v_WriteHexs(TiXmlElement *elmtTag,
2720 std::vector<int> keysToWrite)
2721{
2722 std::string tag = "H";
2723
2724 if (keysToWrite.empty())
2725 {
2726 for (auto [id, hex] : m_meshGraph->GetGeomMap<HexGeom>())
2727 {
2728 WriteHex(hex, elmtTag, tag, id);
2729 }
2730 }
2731 else
2732 {
2733 for (int id : keysToWrite)
2734 {
2735 WriteHex(m_meshGraph->GetHexGeom(id), elmtTag, tag, id);
2736 }
2737 }
2738}
2739
2740void WritePrism(PrismGeom *pri, TiXmlElement *elmtTag, std::string &tag,
2741 int priID)
2742{
2743 std::stringstream s;
2744 s << pri->GetFid(0) << " " << pri->GetFid(1) << " " << pri->GetFid(2) << " "
2745 << pri->GetFid(3) << " " << pri->GetFid(4) << " ";
2746 TiXmlElement *p = new TiXmlElement(tag);
2747 p->SetAttribute("ID", priID);
2748 p->LinkEndChild(new TiXmlText(s.str()));
2749 elmtTag->LinkEndChild(p);
2750}
2751void MeshGraphIOXml::v_WritePrisms(TiXmlElement *elmtTag,
2752 std::vector<int> keysToWrite)
2753{
2754 std::string tag = "R";
2755
2756 if (keysToWrite.empty())
2757 {
2758 for (auto [id, prism] : m_meshGraph->GetGeomMap<PrismGeom>())
2759 {
2760 WritePrism(prism, elmtTag, tag, id);
2761 }
2762 }
2763 else
2764 {
2765 for (int id : keysToWrite)
2766 {
2767 WritePrism(m_meshGraph->GetPrismGeom(id), elmtTag, tag, id);
2768 }
2769 }
2770}
2771
2772void WritePyr(PyrGeom *pyr, TiXmlElement *elmtTag, std::string &tag, int pyrID)
2773{
2774 std::stringstream s;
2775 s << pyr->GetFid(0) << " " << pyr->GetFid(1) << " " << pyr->GetFid(2) << " "
2776 << pyr->GetFid(3) << " " << pyr->GetFid(4) << " ";
2777 TiXmlElement *p = new TiXmlElement(tag);
2778 p->SetAttribute("ID", pyrID);
2779 p->LinkEndChild(new TiXmlText(s.str()));
2780 elmtTag->LinkEndChild(p);
2781}
2782void MeshGraphIOXml::v_WritePyrs(TiXmlElement *elmtTag,
2783 std::vector<int> keysToWrite)
2784{
2785 std::string tag = "P";
2786
2787 if (keysToWrite.empty())
2788 {
2789 for (auto [id, pyr] : m_meshGraph->GetGeomMap<PyrGeom>())
2790 {
2791 WritePyr(pyr, elmtTag, tag, id);
2792 }
2793 }
2794 else
2795 {
2796 for (int id : keysToWrite)
2797 {
2798 WritePyr(m_meshGraph->GetPyrGeom(id), elmtTag, tag, id);
2799 }
2800 }
2801}
2802
2803void WriteTet(TetGeom *tet, TiXmlElement *elmtTag, std::string &tag, int tetID)
2804{
2805 std::stringstream s;
2806 s << tet->GetFid(0) << " " << tet->GetFid(1) << " " << tet->GetFid(2) << " "
2807 << tet->GetFid(3) << " ";
2808 TiXmlElement *t = new TiXmlElement(tag);
2809 t->SetAttribute("ID", tetID);
2810 t->LinkEndChild(new TiXmlText(s.str()));
2811 elmtTag->LinkEndChild(t);
2812}
2813void MeshGraphIOXml::v_WriteTets(TiXmlElement *elmtTag,
2814 std::vector<int> keysToWrite)
2815{
2816 std::string tag = "A";
2817
2818 if (keysToWrite.empty())
2819 {
2820 for (auto [id, tet] : m_meshGraph->GetGeomMap<TetGeom>())
2821 {
2822 WriteTet(tet, elmtTag, tag, id);
2823 }
2824 }
2825 else
2826 {
2827 for (int id : keysToWrite)
2828 {
2829 WriteTet(m_meshGraph->GetTetGeom(id), elmtTag, tag, id);
2830 }
2831 }
2832}
2833
2834void WriteCurvedEdge(CurveUniquePtr &curve, TiXmlElement *curveTag,
2835 int &curveId)
2836{
2837 TiXmlElement *c = new TiXmlElement("E");
2838 std::stringstream s;
2839 s.precision(8);
2840
2841 for (int j = 0; j < curve->m_points.size(); ++j)
2842 {
2843 PointGeom *p = curve->m_points[j];
2844 s << std::scientific << (*p)(0) << " " << (*p)(1) << " " << (*p)(2)
2845 << " ";
2846 }
2847
2848 c->SetAttribute("ID", curveId++);
2849 c->SetAttribute("EDGEID", curve->m_curveID);
2850 c->SetAttribute("NUMPOINTS", curve->m_points.size());
2851 c->SetAttribute("TYPE", LibUtilities::kPointsTypeStr[curve->m_ptype]);
2852 c->LinkEndChild(new TiXmlText(s.str()));
2853 curveTag->LinkEndChild(c);
2854}
2855void WriteCurvedFace(CurveUniquePtr &curve, TiXmlElement *curveTag,
2856 int &curveId)
2857{
2858 TiXmlElement *c = new TiXmlElement("F");
2859 std::stringstream s;
2860 s.precision(8);
2861
2862 for (int j = 0; j < curve->m_points.size(); ++j)
2863 {
2864 PointGeom *p = curve->m_points[j];
2865 s << std::scientific << (*p)(0) << " " << (*p)(1) << " " << (*p)(2)
2866 << " ";
2867 }
2868
2869 c->SetAttribute("ID", curveId++);
2870 c->SetAttribute("FACEID", curve->m_curveID);
2871 c->SetAttribute("NUMPOINTS", curve->m_points.size());
2872 c->SetAttribute("TYPE", LibUtilities::kPointsTypeStr[curve->m_ptype]);
2873 c->LinkEndChild(new TiXmlText(s.str()));
2874 curveTag->LinkEndChild(c);
2875}
2876void MeshGraphIOXml::v_WriteCurves(TiXmlElement *geomTag, CurveMap &edges,
2877 CurveMap &faces,
2878 std::vector<int> *keysToWriteEdges,
2879 std::vector<int> *keysToWriteFaces)
2880{
2881 TiXmlElement *curveTag = new TiXmlElement("CURVED");
2882 int curveId = 0;
2883
2884 if (keysToWriteEdges == nullptr)
2885 {
2886 for (auto &i : edges)
2887 {
2888 WriteCurvedEdge(i.second, curveTag, curveId);
2889 }
2890 }
2891 else
2892 {
2893 for (int key : *keysToWriteEdges)
2894 {
2895 WriteCurvedEdge(edges[key], curveTag, curveId);
2896 }
2897 }
2898
2899 if (keysToWriteFaces == nullptr)
2900 {
2901 for (auto &i : faces)
2902 {
2903 WriteCurvedFace(i.second, curveTag, curveId);
2904 }
2905 }
2906 else
2907 {
2908 for (int key : *keysToWriteFaces)
2909 {
2910 WriteCurvedFace(faces[key], curveTag, curveId);
2911 }
2912 }
2913
2914 geomTag->LinkEndChild(curveTag);
2915}
2916
2917void MeshGraphIOXml::WriteComposites(TiXmlElement *geomTag, CompositeMap &comps,
2918 std::map<int, std::string> &compLabels)
2919{
2920 auto &compositesLabels = m_meshGraph->GetCompositesLabels();
2921 TiXmlElement *compTag = new TiXmlElement("COMPOSITE");
2922
2923 for (auto &cIt : comps)
2924 {
2925 if (cIt.second->m_geomVec.size() == 0)
2926 {
2927 continue;
2928 }
2929
2930 TiXmlElement *c = new TiXmlElement("C");
2931 c->SetAttribute("ID", cIt.first);
2932 if (!compositesLabels[cIt.first].empty())
2933 {
2934 c->SetAttribute("NAME", compLabels[cIt.first]);
2935 }
2936 c->LinkEndChild(new TiXmlText(GetCompositeString(cIt.second)));
2937 compTag->LinkEndChild(c);
2938 }
2939
2940 geomTag->LinkEndChild(compTag);
2941}
2942
2943void MeshGraphIOXml::WriteDomain(TiXmlElement *geomTag,
2944 std::map<int, CompositeMap> &domainMap)
2945{
2946 TiXmlElement *domTag = new TiXmlElement("DOMAIN");
2947
2948 std::vector<unsigned int> idxList;
2949 for (auto &domain : domainMap)
2950 {
2951 TiXmlElement *c = new TiXmlElement("D");
2952 idxList.clear();
2953 std::stringstream s;
2954 s << " "
2955 << "C"
2956 << "[";
2957
2958 for (const auto &elem : domain.second)
2959 {
2960 idxList.push_back(elem.first);
2961 }
2962
2963 s << ParseUtils::GenerateSeqString(idxList) << "] ";
2964 c->SetAttribute("ID", domain.first);
2965 c->LinkEndChild(new TiXmlText(s.str()));
2966 domTag->LinkEndChild(c);
2967 }
2968
2969 geomTag->LinkEndChild(domTag);
2970}
2971
2973{
2974 int meshDimension = m_meshGraph->GetMeshDimension();
2975 auto &meshComposites = m_meshGraph->GetComposites();
2976
2977 TiXmlElement *expTag = new TiXmlElement("EXPANSIONS");
2978
2979 for (auto it = meshComposites.begin(); it != meshComposites.end(); it++)
2980 {
2981 if (it->second->m_geomVec[0]->GetShapeDim() == meshDimension)
2982 {
2983 TiXmlElement *exp = new TiXmlElement("E");
2984 exp->SetAttribute("COMPOSITE",
2985 "C[" + std::to_string(it->first) + "]");
2986 exp->SetAttribute("NUMMODES", 4);
2987 exp->SetAttribute("TYPE", "MODIFIED");
2988 exp->SetAttribute("FIELDS", "u");
2989
2990 expTag->LinkEndChild(exp);
2991 }
2992 }
2993 root->LinkEndChild(expTag);
2994}
2995
2996/**
2997 * @brief Write out an XML file containing the GEOMETRY block
2998 * representing this MeshGraph instance inside a NEKTAR tag.
2999 */
3001 const std::string &outfilename, bool defaultExp,
3002 const LibUtilities::FieldMetaDataMap &metadata)
3003{
3004 int meshDimension = m_meshGraph->GetMeshDimension();
3005 int spaceDimension = m_meshGraph->GetSpaceDimension();
3006
3007 // Create empty TinyXML document.
3008 TiXmlDocument doc;
3009 TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
3010 doc.LinkEndChild(decl);
3011
3012 TiXmlElement *root = new TiXmlElement("NEKTAR");
3013 doc.LinkEndChild(root);
3014 TiXmlElement *geomTag = new TiXmlElement("GEOMETRY");
3015 root->LinkEndChild(geomTag);
3016
3017 // Add provenance information using FieldIO library.
3019 new LibUtilities::XmlTagWriter(root)),
3020 metadata);
3021
3022 // Update attributes with dimensions.
3023 geomTag->SetAttribute("DIM", meshDimension);
3024 geomTag->SetAttribute("SPACE", spaceDimension);
3025
3026 if (m_session != nullptr && !m_session->GetComm()->IsSerial())
3027 {
3028 geomTag->SetAttribute("PARTITION", m_session->GetComm()->GetRank());
3029 }
3030
3031 // Clear existing elements.
3032 geomTag->Clear();
3033
3034 // Write out informatio
3035 v_WriteVertices(geomTag);
3036 v_WriteEdges(geomTag);
3037 if (meshDimension > 1)
3038 {
3039 TiXmlElement *faceTag =
3040 new TiXmlElement(meshDimension == 2 ? "ELEMENT" : "FACE");
3041
3042 v_WriteTris(faceTag);
3043 v_WriteQuads(faceTag);
3044 geomTag->LinkEndChild(faceTag);
3045 }
3046 if (meshDimension > 2)
3047 {
3048 TiXmlElement *elmtTag = new TiXmlElement("ELEMENT");
3049
3050 v_WriteHexs(elmtTag);
3051 v_WritePyrs(elmtTag);
3052 v_WritePrisms(elmtTag);
3053 v_WriteTets(elmtTag);
3054
3055 geomTag->LinkEndChild(elmtTag);
3056 }
3057 v_WriteCurves(geomTag, m_meshGraph->GetCurvedEdges(),
3058 m_meshGraph->GetCurvedFaces());
3059 WriteComposites(geomTag, m_meshGraph->GetComposites(),
3060 m_meshGraph->GetCompositesLabels());
3061 WriteDomain(geomTag, m_meshGraph->GetDomain());
3062
3063 if (defaultExp)
3064 {
3066 }
3067
3068 auto &movement = m_meshGraph->GetMovement();
3069 if (movement)
3070 {
3071 movement->WriteMovement(root);
3072 }
3073
3074 // Save file.
3075 doc.SaveFile(outfilename);
3076}
3077
3079 std::string outname, std::vector<std::set<unsigned int>> elements,
3080 std::vector<unsigned int> partitions)
3081{
3082 // so in theory this function is used by the mesh partitioner
3083 // giving instructions on how to write out a paritioned mesh.
3084 // the theory goes that the elements stored in the meshgraph are the
3085 // "whole" mesh so based on the information from the elmements list
3086 // we can filter the mesh entities and write some individual files
3087 // hopefully
3088
3089 // this is xml so we are going to write a directory with lots of
3090 // xml files
3091 std::string dirname = outname + "_xml";
3092 fs::path pdirname(dirname);
3093
3094 if (!fs::is_directory(dirname))
3095 {
3096 fs::create_directory(dirname);
3097 }
3098
3099 ASSERTL0(elements.size() == partitions.size(),
3100 "error in partitioned information");
3101
3102 for (int i = 0; i < partitions.size(); i++)
3103 {
3104 TiXmlDocument doc;
3105 TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
3106 doc.LinkEndChild(decl);
3107
3108 TiXmlElement *root = doc.FirstChildElement("NEKTAR");
3109 TiXmlElement *geomTag;
3110
3111 // Try to find existing NEKTAR tag.
3112 if (!root)
3113 {
3114 root = new TiXmlElement("NEKTAR");
3115 doc.LinkEndChild(root);
3116
3117 geomTag = new TiXmlElement("GEOMETRY");
3118 root->LinkEndChild(geomTag);
3119 }
3120 else
3121 {
3122 // Try to find existing GEOMETRY tag.
3123 geomTag = root->FirstChildElement("GEOMETRY");
3124
3125 if (!geomTag)
3126 {
3127 geomTag = new TiXmlElement("GEOMETRY");
3128 root->LinkEndChild(geomTag);
3129 }
3130 }
3131
3132 int meshDimension = m_meshGraph->GetMeshDimension();
3133 int spaceDimension = m_meshGraph->GetSpaceDimension();
3134
3135 geomTag->SetAttribute("DIM", meshDimension);
3136 geomTag->SetAttribute("SPACE", spaceDimension);
3137 geomTag->SetAttribute("PARTITION", partitions[i]);
3138
3139 // Add Mesh //
3140 // Get the elements
3141 auto &vertSet = m_meshGraph->GetGeomMap<PointGeom>();
3142 auto &segGeoms = m_meshGraph->GetGeomMap<SegGeom>();
3143 auto &triGeoms = m_meshGraph->GetGeomMap<TriGeom>();
3144 auto &quadGeoms = m_meshGraph->GetGeomMap<QuadGeom>();
3145 auto &tetGeoms = m_meshGraph->GetGeomMap<TetGeom>();
3146 auto &pyrGeoms = m_meshGraph->GetGeomMap<PyrGeom>();
3147 auto &prismGeoms = m_meshGraph->GetGeomMap<PrismGeom>();
3148 auto &hexGeoms = m_meshGraph->GetGeomMap<HexGeom>();
3149 auto &curvedEdges = m_meshGraph->GetCurvedEdges();
3150 auto &curvedFaces = m_meshGraph->GetCurvedFaces();
3151 auto &meshComposites = m_meshGraph->GetComposites();
3152 auto &globalDomain = m_meshGraph->GetDomain();
3153
3154 std::vector<int> localHexKeys;
3155 std::vector<int> localPyrKeys;
3156 std::vector<int> localPrismKeys;
3157 std::vector<int> localTetKeys;
3158 std::vector<int> localTriKeys;
3159 std::vector<int> localQuadKeys;
3160 std::vector<int> localEdgeKeys;
3161 std::vector<int> localVertKeys;
3162 std::vector<int> localCurveEdgeKeys;
3163 std::vector<int> localCurveFaceKeys;
3164
3165 std::vector<std::set<unsigned int>> entityIds(4);
3166 entityIds[meshDimension] = elements[i];
3167
3168 switch (meshDimension)
3169 {
3170 case 3:
3171 {
3172 for (auto &j : entityIds[3])
3173 {
3174 Geometry *g = nullptr;
3175
3176 if (auto it{hexGeoms.find(j)}; it != hexGeoms.end())
3177 {
3178 g = (*it).second;
3179 localHexKeys.push_back(j);
3180 }
3181 else if (auto it{pyrGeoms.find(j)}; it != pyrGeoms.end())
3182 {
3183 g = (*it).second;
3184 localPyrKeys.push_back(j);
3185 }
3186 else if (auto it{prismGeoms.find(j)};
3187 it != prismGeoms.end())
3188 {
3189 g = (*it).second;
3190 localPrismKeys.push_back(j);
3191 }
3192 else if (auto it{tetGeoms.find(j)}; it != tetGeoms.end())
3193 {
3194 g = (*it).second;
3195 localTetKeys.push_back(j);
3196 }
3197 else
3198 {
3199 ASSERTL0(false, "element in partition not found");
3200 }
3201
3202 for (int k = 0; k < g->GetNumFaces(); k++)
3203 {
3204 entityIds[2].insert(g->GetFid(k));
3205 }
3206 for (int k = 0; k < g->GetNumEdges(); k++)
3207 {
3208 entityIds[1].insert(g->GetEid(k));
3209 }
3210 for (int k = 0; k < g->GetNumVerts(); k++)
3211 {
3212 entityIds[0].insert(g->GetVid(k));
3213 }
3214 }
3215 }
3216 break;
3217 case 2:
3218 {
3219 for (auto &j : entityIds[2])
3220 {
3221 Geometry *g = nullptr;
3222 if (auto it{triGeoms.find(j)}; it != triGeoms.end())
3223 {
3224 g = (*it).second;
3225 localTriKeys.push_back(j);
3226 }
3227 else if (auto it{quadGeoms.find(j)}; it != quadGeoms.end())
3228 {
3229 g = (*it).second;
3230 localQuadKeys.push_back(j);
3231 }
3232 else
3233 {
3234 ASSERTL0(false, "element in partition not found");
3235 }
3236
3237 for (int k = 0; k < g->GetNumEdges(); k++)
3238 {
3239 entityIds[1].insert(g->GetEid(k));
3240 }
3241 for (int k = 0; k < g->GetNumVerts(); k++)
3242 {
3243 entityIds[0].insert(g->GetVid(k));
3244 }
3245 }
3246 }
3247 break;
3248 case 1:
3249 {
3250 for (auto &j : entityIds[1])
3251 {
3252 Geometry *g = nullptr;
3253 if (auto it{segGeoms.find(j)}; it != segGeoms.end())
3254 {
3255 g = (*it).second;
3256 localEdgeKeys.push_back(j);
3257 }
3258 else
3259 {
3260 ASSERTL0(false, "element in partition not found");
3261 }
3262
3263 for (int k = 0; k < g->GetNumVerts(); k++)
3264 {
3265 entityIds[0].insert(g->GetVid(k));
3266 }
3267 }
3268 }
3269 }
3270
3271 if (meshDimension > 2)
3272 {
3273 for (auto &j : entityIds[2])
3274 {
3275 if (triGeoms.find(j) != triGeoms.end())
3276 {
3277 localTriKeys.push_back(j);
3278 }
3279 else if (quadGeoms.find(j) != quadGeoms.end())
3280 {
3281 localQuadKeys.push_back(j);
3282 }
3283 else
3284 {
3285 ASSERTL0(false, "face not found");
3286 }
3287 }
3288 }
3289
3290 if (meshDimension > 1)
3291 {
3292 for (auto &j : entityIds[1])
3293 {
3294 if (segGeoms.find(j) != segGeoms.end())
3295 {
3296 localEdgeKeys.push_back(j);
3297 }
3298 else
3299 {
3300 ASSERTL0(false, "edge not found");
3301 }
3302 }
3303 }
3304
3305 for (auto &j : entityIds[0])
3306 {
3307 if (vertSet.find(j) != vertSet.end())
3308 {
3309 localVertKeys.push_back(j);
3310 }
3311 else
3312 {
3313 ASSERTL0(false, "vert not found");
3314 }
3315 }
3316
3317 if (!localVertKeys.empty())
3318 {
3319 v_WriteVertices(geomTag, localVertKeys);
3320 }
3321
3322 if (!localEdgeKeys.empty())
3323 {
3324 v_WriteEdges(geomTag, localEdgeKeys);
3325 }
3326
3327 if (meshDimension > 1)
3328 {
3329 TiXmlElement *faceTag =
3330 new TiXmlElement(meshDimension == 2 ? "ELEMENT" : "FACE");
3331
3332 if (!localTriKeys.empty())
3333 {
3334 v_WriteTris(faceTag, localTriKeys);
3335 }
3336
3337 if (!localQuadKeys.empty())
3338 {
3339 v_WriteQuads(faceTag, localQuadKeys);
3340 }
3341
3342 geomTag->LinkEndChild(faceTag);
3343 }
3344 if (meshDimension > 2)
3345 {
3346 TiXmlElement *elmtTag = new TiXmlElement("ELEMENT");
3347
3348 if (!localHexKeys.empty())
3349 {
3350 v_WriteHexs(elmtTag, localHexKeys);
3351 }
3352 if (!localPyrKeys.empty())
3353 {
3354 v_WritePyrs(elmtTag, localPyrKeys);
3355 }
3356 if (!localPrismKeys.empty())
3357 {
3358 v_WritePrisms(elmtTag, localPrismKeys);
3359 }
3360 if (!localTetKeys.empty())
3361 {
3362 v_WriteTets(elmtTag, localTetKeys);
3363 }
3364
3365 geomTag->LinkEndChild(elmtTag);
3366 }
3367
3368 for (auto &j : localTriKeys)
3369 {
3370 if (curvedFaces.count(j))
3371 {
3372 localCurveFaceKeys.push_back(j);
3373 }
3374 }
3375 for (auto &j : localQuadKeys)
3376 {
3377 if (curvedFaces.count(j))
3378 {
3379 localCurveFaceKeys.push_back(j);
3380 }
3381 }
3382 for (auto &j : localEdgeKeys)
3383 {
3384 if (curvedEdges.count(j))
3385 {
3386 localCurveEdgeKeys.push_back(j);
3387 }
3388 }
3389
3390 v_WriteCurves(geomTag, curvedEdges, curvedFaces, &localCurveEdgeKeys,
3391 &localCurveFaceKeys);
3392
3393 CompositeMap localComp;
3394 std::map<int, std::string> localCompLabels;
3395
3396 for (auto &j : meshComposites)
3397 {
3399 int dim = j.second->m_geomVec[0]->GetShapeDim();
3400
3401 for (int k = 0; k < j.second->m_geomVec.size(); k++)
3402 {
3403 if (entityIds[dim].count(j.second->m_geomVec[k]->GetGlobalID()))
3404 {
3405 comp->m_geomVec.push_back(j.second->m_geomVec[k]);
3406 }
3407 }
3408
3409 if (comp->m_geomVec.size())
3410 {
3411 localComp[j.first] = comp;
3412 auto compositesLabels = m_meshGraph->GetCompositesLabels();
3413 if (!compositesLabels[j.first].empty())
3414 {
3415 localCompLabels[j.first] = compositesLabels[j.first];
3416 }
3417 }
3418 }
3419
3420 WriteComposites(geomTag, localComp, localCompLabels);
3421
3422 std::map<int, CompositeMap> domain;
3423 for (auto &j : localComp)
3424 {
3425 for (auto &dom : globalDomain)
3426 {
3427 for (auto &dIt : dom.second)
3428 {
3429 if (j.first == dIt.first)
3430 {
3431 domain[dom.first][j.first] = j.second;
3432 break;
3433 }
3434 }
3435 }
3436 }
3437
3438 WriteDomain(geomTag, domain);
3439
3440 if (m_session->DefinesElement("NEKTAR/CONDITIONS"))
3441 {
3442 std::set<int> vBndRegionIdList;
3443 TiXmlElement *vConditions =
3444 new TiXmlElement(*m_session->GetElement("Nektar/Conditions"));
3445 TiXmlElement *vBndRegions =
3446 vConditions->FirstChildElement("BOUNDARYREGIONS");
3447 // Use fine-level for mesh partition (Parallel-in-Time)
3449 TiXmlElement *vBndConditions =
3450 vConditions->FirstChildElement("BOUNDARYCONDITIONS");
3451 // Use fine-level for mesh partition (Parallel-in-Time)
3453 0);
3454 TiXmlElement *vItem;
3455
3456 if (vBndRegions)
3457 {
3458 // Check for parallel-in-time
3459 bool multiLevel =
3460 vConditions->FirstChildElement("BOUNDARYREGIONS")
3461 ->FirstChildElement("TIMELEVEL") != nullptr;
3462
3463 TiXmlElement *vNewBndRegions =
3464 multiLevel ? new TiXmlElement("TIMELEVEL")
3465 : new TiXmlElement("BOUNDARYREGIONS");
3466 vItem = vBndRegions->FirstChildElement();
3467 auto graph_bndRegOrder = m_meshGraph->GetBndRegionOrdering();
3468 while (vItem)
3469 {
3470 std::string vSeqStr =
3471 vItem->FirstChild()->ToText()->Value();
3472 std::string::size_type indxBeg =
3473 vSeqStr.find_first_of('[') + 1;
3474 std::string::size_type indxEnd =
3475 vSeqStr.find_last_of(']') - 1;
3476 vSeqStr = vSeqStr.substr(indxBeg, indxEnd - indxBeg + 1);
3477 std::vector<unsigned int> vSeq;
3478 ParseUtils::GenerateSeqVector(vSeqStr.c_str(), vSeq);
3479
3480 std::vector<unsigned int> idxList;
3481
3482 for (unsigned int i = 0; i < vSeq.size(); ++i)
3483 {
3484 if (localComp.find(vSeq[i]) != localComp.end())
3485 {
3486 idxList.push_back(vSeq[i]);
3487 }
3488 }
3489 int p = atoi(vItem->Attribute("ID"));
3490
3491 std::string vListStr =
3493
3494 if (vListStr.length() == 0)
3495 {
3496 TiXmlElement *tmp = vItem;
3497 vItem = vItem->NextSiblingElement();
3498 vBndRegions->RemoveChild(tmp);
3499 }
3500 else
3501 {
3502 vListStr = "C[" + vListStr + "]";
3503 TiXmlText *vList = new TiXmlText(vListStr);
3504 TiXmlElement *vNewElement = new TiXmlElement("B");
3505 vNewElement->SetAttribute("ID", p);
3506 vNewElement->LinkEndChild(vList);
3507 vNewBndRegions->LinkEndChild(vNewElement);
3508 vBndRegionIdList.insert(p);
3509 vItem = vItem->NextSiblingElement();
3510 }
3511
3512 // store original bnd region order
3513 m_bndRegOrder[p] = vSeq;
3514 graph_bndRegOrder[p] = vSeq;
3515 }
3516 if (multiLevel)
3517 {
3518 // Use fine-level for mesh partition (Parallel-in-Time)
3519 size_t timeLevel = 0;
3520 while (vBndRegions)
3521 {
3522 vNewBndRegions->SetAttribute("VALUE", timeLevel);
3523 vConditions->FirstChildElement("BOUNDARYREGIONS")
3524 ->ReplaceChild(vBndRegions, *vNewBndRegions);
3525 vBndRegions = vBndRegions->NextSiblingElement();
3526 timeLevel++;
3527 }
3528 }
3529 else
3530 {
3531 vConditions->ReplaceChild(vBndRegions, *vNewBndRegions);
3532 }
3533 }
3534
3535 if (vBndConditions)
3536 {
3537 vItem = vBndConditions->FirstChildElement();
3538 while (vItem)
3539 {
3540 std::set<int>::iterator x;
3541 if ((x = vBndRegionIdList.find(atoi(vItem->Attribute(
3542 "REF")))) != vBndRegionIdList.end())
3543 {
3544 vItem->SetAttribute("REF", *x);
3545 vItem = vItem->NextSiblingElement();
3546 }
3547 else
3548 {
3549 TiXmlElement *tmp = vItem;
3550 vItem = vItem->NextSiblingElement();
3551 vBndConditions->RemoveChild(tmp);
3552 }
3553 }
3554 }
3555 root->LinkEndChild(vConditions);
3556 }
3557
3558 // Distribute other sections of the XML to each process as is.
3559 TiXmlElement *vSrc =
3560 m_session->GetElement("Nektar")->FirstChildElement();
3561 while (vSrc)
3562 {
3563 std::string vName = boost::to_upper_copy(vSrc->ValueStr());
3564 if (vName != "GEOMETRY" && vName != "CONDITIONS")
3565 {
3566 root->LinkEndChild(new TiXmlElement(*vSrc));
3567 }
3568 vSrc = vSrc->NextSiblingElement();
3569 }
3570
3571 // Save Mesh
3572
3573 boost::format pad("P%1$07d.xml");
3574 pad % partitions[i];
3575 fs::path pFilename(pad.str());
3576
3577 fs::path fullpath = pdirname / pFilename;
3578 doc.SaveFile(LibUtilities::PortablePath(fullpath));
3579 }
3580}
3581
3583{
3584 auto &meshComposites = m_meshGraph->GetComposites();
3585 auto &domain = m_meshGraph->GetDomain();
3586
3588
3589 for (auto &c : meshComposites)
3590 {
3591 bool fillComp = true;
3592 for (auto &d : domain[0])
3593 {
3594 if (c.second == d.second)
3595 {
3596 fillComp = false;
3597 }
3598 }
3599 if (fillComp)
3600 {
3601 std::vector<unsigned int> ids;
3602 for (auto &elmt : c.second->m_geomVec)
3603 {
3604 ids.push_back(elmt->GetGlobalID());
3605 }
3606 ret[c.first] = ids;
3607 }
3608 }
3609
3610 return ret;
3611}
3612
3613} // 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:84
LibUtilities::ShapeType GetShapeType(void)
Get the geometric shape type of this object.
Definition Geometry.h:294
int GetNumFaces() const
Get the number of faces of this object.
Definition Geometry.h:411
int GetVid(int i) const
Returns global id of vertex i of this object.
Definition Geometry.h:345
int GetGlobalID(void) const
Get the ID of this object.
Definition Geometry.h:314
int GetFid(int i) const
Get the ID of face i of this object.
Definition Geometry.cpp:91
int GetNumEdges() const
Get the number of edges of this object.
Definition Geometry.h:403
int GetNumVerts() const
Get the number of vertices of this object.
Definition Geometry.h:395
int GetEid(int i) const
Get the ID of edge i of this object.
Definition Geometry.cpp:83
static const int kNfaces
Definition HexGeom.h:55
static const int kNqfaces
Definition HexGeom.h:53
static const int kNtfaces
Definition HexGeom.h:54
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.
virtual void v_WriteCurves(TiXmlElement *geomTag, CurveMap &edges, CurveMap &faces, std::vector< int > *keysToWriteEdges=nullptr, std::vector< int > *keysToWriteFaces=nullptr)
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 >())
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:55
static const int kNtfaces
Definition PyrGeom.h:54
static const int kNqfaces
Definition PyrGeom.h:53
static const int kNfaces
Definition TetGeom.h:55
static const int kNqfaces
Definition TetGeom.h:53
static const int kNtfaces
Definition TetGeom.h:54
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
unique_ptr_objpool< Curve > CurveUniquePtr
Definition Geometry.h:70
std::map< int, std::vector< unsigned int > > CompositeOrdering
Definition MeshGraph.h:177
void WriteVert(PointGeom *vert, TiXmlElement *vertTag)
void WriteCurvedFace(CurveUniquePtr &curve, TiXmlElement *curveTag, int &curveId)
std::map< int, CurveUniquePtr > CurveMap
Definition Geometry.h:71
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:185
void WriteEdge(SegGeom *seg, TiXmlElement *edgeTag, std::string &tag, int edgeID)
void WriteCurvedEdge(CurveUniquePtr &curve, TiXmlElement *curveTag, int &curveId)
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:186