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