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