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 
47 using namespace std;
48 using namespace Nektar;
49 
50 void ExpandVertices(TiXmlElement *mesh, map<int, int> jointVerts,
51  map<int, int> &fullVerts);
52 
53 void ExpandEdges(TiXmlElement *mesh, map<int, int> &newVerts,
54  map<int, int> jointEdges, map<int, int> &newEdges);
55 
56 void ExpandElmts(TiXmlElement *mesh, map<int, int> &newEdges, int &nOrigElmts);
57 
58 void ExpandComposites(TiXmlElement *mesh, map<int, int> fullEdges,
59  int nOrigElmts);
60 
61 int 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 
121 void 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 
219 void 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 
305 void 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
459 string 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 
501 void 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:172
std::shared_ptr< Geometry1D > Geometry1DSharedPtr
Definition: Geometry.h:63
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:945