Nektar++
ExpandMeshByRotation.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: ExpandMeshByRotation.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: Take a mesh and expand it by rotating it 180 degrees around
32// x-width/2, 0
33//
34///////////////////////////////////////////////////////////////////////////////
35
40#include <cstdio>
41#include <cstdlib>
42#include <iomanip>
43#include <map>
44#include <sstream>
45#include <tinyxml.h>
46
47using namespace std;
48using namespace Nektar;
49
50void ExpandVertices(TiXmlElement *mesh, map<int, int> jointVerts,
51 map<int, int> &fullVerts);
52
53void ExpandEdges(TiXmlElement *mesh, map<int, int> &newVerts,
54 map<int, int> jointEdges, map<int, int> &newEdges);
55
56void ExpandElmts(TiXmlElement *mesh, map<int, int> &newEdges, int &nOrigElmts);
57
58void ExpandComposites(TiXmlElement *mesh, map<int, int> fullEdges,
59 int nOrigElmts);
60
61int main(int argc, char *argv[])
62{
63 int i;
64
65 if (argc != 3)
66 {
67 fprintf(stderr, "Usage: ./ExpandMeshByRotation meshfile outfile\n");
68 exit(1);
69 }
70
71 //------------------------------------------------------------
72 // Create Session file which also reads meshfile.
74 LibUtilities::SessionReader::CreateInstance(argc - 1, argv);
75 //-----------------------------------------------------------
76
77 //-------------------------------------------------------------
78 // Read in mesh from input file
79 string meshfile(argv[argc - 2]);
81 SpatialDomains::MeshGraph::Read(vSession);
83 composite = graphShPt->GetComposite(300);
84 std::map<int, int> jointEdges, jointVerts, newVerts, newEdges;
85 int compsize = composite->m_geomVec.size();
86 for (i = 0; i < compsize; ++i)
87 {
89 std::dynamic_pointer_cast<SpatialDomains::Geometry1D>(
90 composite->m_geomVec[i]);
92 std::dynamic_pointer_cast<SpatialDomains::Geometry1D>(
93 composite->m_geomVec[compsize - 1 - i]);
94 jointEdges[tmp1->GetGlobalID()] = tmp2->GetGlobalID();
95 jointVerts[tmp1->GetVid(0)] = tmp2->GetVid(1);
96 jointVerts[tmp1->GetVid(1)] = tmp2->GetVid(0);
97 }
98
99 //------------------------------------------------------------
100 TiXmlDocument &meshdoc = vSession->GetDocument();
101
102 TiXmlHandle docHandle(&meshdoc);
103 TiXmlElement *mesh = docHandle.FirstChildElement("NEKTAR")
104 .FirstChildElement("GEOMETRY")
105 .Element();
106
107 int nOrigElmts;
108 //------------------------------------------------------------
109 // Expand Mesh
110 ExpandVertices(mesh, jointVerts, newVerts);
111
112 ExpandEdges(mesh, newVerts, jointEdges, newEdges);
113
114 ExpandElmts(mesh, newEdges, nOrigElmts);
115
116 ExpandComposites(mesh, newEdges, nOrigElmts);
117
118 meshdoc.SaveFile(argv[argc - 1]);
119}
120
121void ExpandVertices(TiXmlElement *mesh, map<int, int> jointVerts,
122 map<int, int> &newVerts)
123{
124
125 TiXmlElement *element = mesh->FirstChildElement("VERTEX");
126 ASSERTL0(element, "Unable to find mesh VERTEX tag in file.");
127
128 TiXmlElement *vertex = element->FirstChildElement("V");
129
130 int indx;
131 int nextVertexNumber = -1;
132 int err; /// Error value returned by TinyXML.
133
134 vector<NekDouble> xpts, ypts, zpts;
135 NekDouble xval, yval, zval;
136
137 NekDouble yoffset = 0.0;
138 while (vertex)
139 {
140 nextVertexNumber++;
141
142 TiXmlAttribute *vertexAttr = vertex->FirstAttribute();
143 std::string attrName(vertexAttr->Name());
144
145 ASSERTL0(attrName == "ID",
146 (std::string("Unknown attribute name: ") + attrName).c_str());
147
148 err = vertexAttr->QueryIntValue(&indx);
149 ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
150
151 // Now read body of vertex
152 std::string vertexBodyStr;
153
154 TiXmlNode *vertexBody = vertex->FirstChild();
155
156 while (vertexBody)
157 {
158 // Accumulate all non-comment body data.
159 if (vertexBody->Type() == TiXmlNode::TINYXML_TEXT)
160 {
161 vertexBodyStr += vertexBody->ToText()->Value();
162 vertexBodyStr += " ";
163 }
164
165 vertexBody = vertexBody->NextSibling();
166 }
167
168 ASSERTL0(!vertexBodyStr.empty(),
169 "Vertex definitions must contain vertex data.");
170
171 // Get vertex data from the data string.
172 std::istringstream vertexDataStrm(vertexBodyStr.c_str());
173
174 try
175 {
176 while (!vertexDataStrm.fail())
177 {
178 vertexDataStrm >> xval >> yval >> zval;
179 }
180 xpts.push_back(xval);
181 ypts.push_back(yval + yoffset);
182 zpts.push_back(zval);
183 }
184 catch (...)
185 {
186 ASSERTL0(false, "Unable to read VERTEX data.");
187 }
188 vertex = vertex->NextSiblingElement("V");
189 }
190
191 // Add in newvertices
192 int npts = xpts.size();
193 NekDouble xmax = Vmath::Vmax(npts, &xpts[0], 1);
194 int cnt = npts;
195 int cnt1 = npts;
196
197 for (int i = 0; i < npts; ++i)
198 {
199 if (jointVerts.count(i) == 0)
200 {
201 stringstream s;
202 xval = xmax - xpts[i];
203 yval = -ypts[i];
204 s << scientific << setprecision(8) << xval << " " << yval << " "
205 << zpts[i];
206 TiXmlElement *v = new TiXmlElement("V");
207 v->SetAttribute("ID", cnt1);
208 v->LinkEndChild(new TiXmlText(s.str()));
209 element->LinkEndChild(v);
210 newVerts[cnt++] = cnt1++;
211 }
212 else
213 {
214 newVerts[cnt++] = jointVerts[i];
215 }
216 }
217}
218
219void ExpandEdges(TiXmlElement *mesh, map<int, int> &newVerts,
220 map<int, int> jointEdges, map<int, int> &newEdges)
221{
222 /// Look for elements in ELEMENT block.
223 TiXmlElement *field = mesh->FirstChildElement("EDGE");
224
225 ASSERTL0(field, "Unable to find EDGE tag in file.");
226
227 /// All elements are of the form: "<E ID="#"> ... </E>", with
228 /// ? being the element type.
229 /// Read the ID field first.
230 TiXmlElement *edge = field->FirstChildElement("E");
231
232 /// Since all edge data is one big text block, we need to
233 /// accumulate all TINYXML_TEXT data and then parse it. This
234 /// approach effectively skips all comments or other node
235 /// types since we only care about the edge list. We
236 /// cannot handle missing edge numbers as we could with
237 /// missing element numbers due to the text block format.
238 std::string edgeStr;
239 int indx;
240 int nextEdgeNumber = -1;
241
242 map<int, int> edgeVert0, edgeVert1;
243 while (edge)
244 {
245 nextEdgeNumber++;
246
247 int err = edge->QueryIntAttribute("ID", &indx);
248 ASSERTL0(err == TIXML_SUCCESS, "Unable to read edge attribute ID.");
249
250 TiXmlNode *child = edge->FirstChild();
251 edgeStr.clear();
252 if (child->Type() == TiXmlNode::TINYXML_TEXT)
253 {
254 edgeStr += child->ToText()->ValueStr();
255 }
256
257 /// Now parse out the edges, three fields at a time.
258 int vertex1, vertex2;
259 std::istringstream edgeDataStrm(edgeStr.c_str());
260
261 try
262 {
263 while (!edgeDataStrm.fail())
264 {
265 edgeDataStrm >> vertex1 >> vertex2;
266 }
267 edgeVert0[indx] = vertex1;
268 edgeVert1[indx] = vertex2;
269 }
270 catch (...)
271 {
272 NEKERROR(
273 ErrorUtil::efatal,
274 (std::string("Unable to read edge data: ") + edgeStr).c_str());
275 }
276 edge = edge->NextSiblingElement("E");
277 }
278
279 int nedges = edgeVert0.size();
280 int cnt = nedges;
281 int cnt1 = nedges;
282 int norigverts = newVerts.size();
283
284 for (int i = 0; i < nedges; ++i)
285 {
286 if (jointEdges.count(i) == 0)
287 {
288 stringstream s;
289
290 s << setw(5) << newVerts[edgeVert0[i] + norigverts] << " "
291 << newVerts[edgeVert1[i] + norigverts] << " ";
292 TiXmlElement *e = new TiXmlElement("E");
293 e->SetAttribute("ID", cnt1);
294 e->LinkEndChild(new TiXmlText(s.str()));
295 field->LinkEndChild(e);
296 newEdges[cnt++] = cnt1++;
297 }
298 else
299 {
300 newEdges[cnt++] = jointEdges[i];
301 }
302 }
303}
304
305void ExpandElmts(TiXmlElement *mesh, map<int, int> &newEdges, int &nelmts)
306{
307
308 TiXmlElement *field = mesh->FirstChildElement("ELEMENT");
309
310 ASSERTL0(field, "Unable to find ELEMENT tag in file.");
311
312 int nextElementNumber = -1;
313
314 /// All elements are of the form: "<? ID="#"> ... </?>", with
315 /// ? being the element type.
316
317 TiXmlElement *element = field->FirstChildElement();
318
319 map<int, vector<int>> ElmtEdges;
320
321 while (element)
322 {
323 std::string elementType(element->ValueStr());
324
325 ASSERTL0(
326 elementType == "Q" || elementType == "T",
327 (std::string("Unknown 2D element type: ") + elementType).c_str());
328
329 /// These should be ordered.
330 nextElementNumber++;
331
332 /// Read id attribute.
333 int indx;
334 int err = element->QueryIntAttribute("ID", &indx);
335 ASSERTL0(err == TIXML_SUCCESS, "Unable to read element attribute ID.");
336
337 /// Read text element description.
338 TiXmlNode *elementChild = element->FirstChild();
339 std::string elementStr;
340 while (elementChild)
341 {
342 if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
343 {
344 elementStr += elementChild->ToText()->ValueStr();
345 }
346 elementChild = elementChild->NextSibling();
347 }
348
349 ASSERTL0(!elementStr.empty(),
350 "Unable to read element description body.");
351
352 /// Parse out the element components corresponding to type of element.
353 if (elementType == "T")
354 {
355 // Read three edge numbers
356 int edge1, edge2, edge3;
357 std::istringstream elementDataStrm(elementStr.c_str());
358
359 try
360 {
361 elementDataStrm >> edge1;
362 elementDataStrm >> edge2;
363 elementDataStrm >> edge3;
364
365 ASSERTL0(
366 !elementDataStrm.fail(),
367 (std::string("Unable to read element data for TRIANGLE: ") +
368 elementStr)
369 .c_str());
370
371 vector<int> edges;
372 edges.push_back(edge1);
373 edges.push_back(edge2);
374 edges.push_back(edge3);
375
376 ElmtEdges[indx] = edges;
377 }
378 catch (...)
379 {
380 NEKERROR(
381 ErrorUtil::efatal,
382 (std::string("Unable to read element data for TRIANGLE: ") +
383 elementStr)
384 .c_str());
385 }
386 }
387 else if (elementType == "Q")
388 {
389 // Read four edge numbers
390 int edge1, edge2, edge3, edge4;
391 std::istringstream elementDataStrm(elementStr.c_str());
392
393 try
394 {
395 elementDataStrm >> edge1;
396 elementDataStrm >> edge2;
397 elementDataStrm >> edge3;
398 elementDataStrm >> edge4;
399
400 ASSERTL0(
401 !elementDataStrm.fail(),
402 (std::string("Unable to read element data for QUAD: ") +
403 elementStr)
404 .c_str());
405
406 vector<int> edges;
407 edges.push_back(edge1);
408 edges.push_back(edge2);
409 edges.push_back(edge3);
410 edges.push_back(edge4);
411
412 ElmtEdges[indx] = edges;
413 }
414 catch (...)
415 {
416 NEKERROR(
417 ErrorUtil::efatal,
418 (std::string("Unable to read element data for QUAD: ") +
419 elementStr)
420 .c_str());
421 }
422 }
423
424 /// Keep looking
425 element = element->NextSiblingElement();
426 }
427
428 nelmts = ElmtEdges.size();
429 int nedges = newEdges.size();
430
431 for (int i = 0; i < ElmtEdges.size(); ++i)
432 {
433 stringstream s;
434
435 for (int j = 0; j < ElmtEdges[i].size(); ++j)
436 {
437 s << setw(10) << newEdges[ElmtEdges[i][j] + nedges];
438 }
439
440 TiXmlElement *f;
441 switch (ElmtEdges[i].size())
442 {
443 case 3:
444 f = new TiXmlElement("T");
445 break;
446 case 4:
447 f = new TiXmlElement("Q");
448 break;
449 default:
450 abort();
451 }
452 f->SetAttribute("ID", i + nelmts);
453 f->LinkEndChild(new TiXmlText(s.str()));
454 field->LinkEndChild(f);
455 }
456}
457
458// Generate a Nektar++ string describing the vector of ints
459string GetXmlString(char tag, vector<unsigned int> &ids)
460{
461 stringstream st;
462 bool range = false;
463 int vId = ids[0];
464 int prevId = vId;
465
466 st << " " << tag << "[" << vId;
467
468 for (auto it = ids.begin() + 1; it != ids.end(); ++it)
469 {
470 // store previous element ID and get current one
471 prevId = vId;
472 vId = (*it);
473
474 // continue an already started range
475 if (prevId > -1 && vId == prevId + 1)
476 {
477 range = true;
478 // if this is the last element, it's the end of a range, so write
479 if (*it == ids.back())
480 {
481 st << "-" << vId;
482 }
483 continue;
484 }
485
486 // terminate a range, if present
487 if (range)
488 {
489 st << "-" << prevId;
490 range = false;
491 }
492
493 // write what will be either a single entry or start of new range
494 st << "," << vId;
495 }
496 // terminate
497 st << "] ";
498 return st.str();
499}
500
501void ExpandComposites(TiXmlElement *mesh, map<int, int> newEdges,
502 int nOrigElmts)
503{
504 TiXmlElement *field = mesh->FirstChildElement("COMPOSITE");
505 ASSERTL0(field, "Unable to find COMPOSITE tag in file.");
506
507 int nextCompositeNumber = -1;
508
509 /// All elements are of the form: "<C ID = "N"> ... </C>".
510 /// Read the ID field first.
511 TiXmlElement *composite = field->FirstChildElement("C");
512
513 while (composite)
514 {
515 nextCompositeNumber++;
516
517 int indx;
518 int err = composite->QueryIntAttribute("ID", &indx);
519 ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
520
521 TiXmlNode *compositeChild = composite->FirstChild();
522 // This is primarily to skip comments that may be present.
523 // Comments appear as nodes just like elements.
524 // We are specifically looking for text in the body
525 // of the definition.
526 while (compositeChild &&
527 compositeChild->Type() != TiXmlNode::TINYXML_TEXT)
528 {
529 compositeChild = compositeChild->NextSibling();
530 }
531
532 ASSERTL0(compositeChild, "Unable to read composite definition body.");
533 std::string compositeStr = compositeChild->ToText()->ValueStr();
534
535 /// Parse out the element components corresponding to type of element.
536 std::istringstream compositeDataStrm(compositeStr.c_str());
537
538 try
539 {
540
541 std::string compositeElementStr;
542 compositeDataStrm >> compositeElementStr;
543
544 std::istringstream tokenStream(compositeElementStr);
545 char type;
546
547 tokenStream >> type;
548
549 // in what follows we are assuming there is only one block of data
550 std::string::size_type indxBeg =
551 compositeElementStr.find_first_of('[') + 1;
552 std::string::size_type indxEnd =
553 compositeElementStr.find_last_of(']') - 1;
554
555 ASSERTL0(indxBeg <= indxEnd,
556 (std::string("Error reading index definition:") +
557 compositeElementStr)
558 .c_str());
559
560 std::string indxStr =
561 compositeElementStr.substr(indxBeg, indxEnd - indxBeg + 1);
562 std::vector<unsigned int> seqVector;
563
564 bool err = ParseUtils::GenerateSeqVector(indxStr, seqVector);
565
566 ASSERTL0(err, (std::string("Error reading composite elements: ") +
567 indxStr)
568 .c_str());
569
570 switch (type)
571 {
572 case 'E': // Expand edges using newEdges map and known values
573 {
574 int seqlen = seqVector.size();
575 int nedges = newEdges.size();
576
577 map<unsigned int, unsigned int> seqMap;
578
579 for (int i = 0; i < seqlen;
580 ++i) // set up a map of defined edges
581 {
582 seqMap[seqVector[i]] = 1;
583 }
584
585 // if edge does not exist in composite add it to the list
586 for (int i = 0; i < seqlen; ++i)
587 {
588 if (seqMap.count(newEdges[seqVector[i] + nedges]) == 0)
589 {
590 seqVector.push_back(
591 newEdges[seqVector[i] + nedges]);
592 }
593 }
594 }
595 break;
596
597 case 'T':
598 case 'Q': // Expand Triangles & Quads with new elements
599 {
600 int seqlen = seqVector.size();
601
602 for (int i = 0; i < seqlen; ++i)
603 {
604 seqVector.push_back(seqVector[i] + nOrigElmts);
605 }
606
607 break;
608 }
609 default:
610 NEKERROR(ErrorUtil::efatal,
611 (std::string("Unrecognized composite token: ") +
612 compositeElementStr)
613 .c_str());
614 }
615
616 // now redefine string in composite
617
618 composite->ReplaceChild(compositeChild,
619 TiXmlText(GetXmlString(type, seqVector)));
620 }
621 catch (...)
622 {
623 NEKERROR(
624 ErrorUtil::efatal,
625 (std::string("Unable to read COMPOSITE data for composite: ") +
626 compositeStr)
627 .c_str());
628 }
629
630 /// Keep looking
631 composite = composite->NextSiblingElement("C");
632 }
633}
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
void ExpandVertices(TiXmlElement *mesh, map< int, int > jointVerts, map< int, int > &fullVerts)
int main(int argc, char *argv[])
void ExpandComposites(TiXmlElement *mesh, map< int, int > fullEdges, int nOrigElmts)
void ExpandElmts(TiXmlElement *mesh, map< int, int > &newEdges, int &nOrigElmts)
void ExpandEdges(TiXmlElement *mesh, map< int, int > &newVerts, map< int, int > jointEdges, map< int, int > &newEdges)
string GetXmlString(char tag, vector< unsigned int > &ids)
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Composite > CompositeSharedPtr
Definition: MeshGraph.h:137
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
std::shared_ptr< Geometry1D > Geometry1DSharedPtr
Definition: Geometry.h:64
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.cpp:940