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