Nektar++
OutputNekpp.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: OutputNekpp.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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Nektar++ file format output.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <set>
37 #include <string>
38 using namespace std;
39 
40 #include <boost/iostreams/filtering_streambuf.hpp>
41 #include <boost/iostreams/copy.hpp>
42 #include <boost/iostreams/filter/gzip.hpp>
43 namespace io = boost::iostreams;
44 
45 #include <tinyxml.h>
48 
49 #include "../MeshElements.h"
50 #include "OutputNekpp.h"
51 
52 namespace Nektar
53 {
54  namespace Utilities
55  {
56  ModuleKey OutputNekpp::className =
58  ModuleKey(eOutputModule, "xml"), OutputNekpp::create,
59  "Writes a Nektar++ xml file.");
60 
61  OutputNekpp::OutputNekpp(MeshSharedPtr m) : OutputModule(m)
62  {
63  m_config["z"] = ConfigOption(true, "0",
64  "Compress output file and append a .gz extension.");
65  m_config["test"] = ConfigOption(true, "0",
66  "Attempt to load resulting mesh and create meshgraph.");
67  }
68 
70  {
71 
72  }
73 
75  {
76  if (m_mesh->m_verbose)
77  {
78  cout << "OutputNekpp: Writing file..." << endl;
79  }
80 
81  TiXmlDocument doc;
82  TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "");
83  doc.LinkEndChild( decl );
84 
85  TiXmlElement * root = new TiXmlElement( "NEKTAR" );
86  doc.LinkEndChild( root );
87 
88  // Begin <GEOMETRY> section
89  TiXmlElement * geomTag = new TiXmlElement( "GEOMETRY" );
90  geomTag->SetAttribute("DIM", m_mesh->m_expDim);
91  geomTag->SetAttribute("SPACE", m_mesh->m_spaceDim);
92  root->LinkEndChild( geomTag );
93 
94  WriteXmlNodes (geomTag);
95  WriteXmlEdges (geomTag);
96  WriteXmlFaces (geomTag);
97  WriteXmlElements (geomTag);
98  WriteXmlCurves (geomTag);
99  WriteXmlComposites(geomTag);
100  WriteXmlDomain (geomTag);
101  WriteXmlExpansions(root);
102  WriteXmlConditions(root);
103 
104  // Extract the output filename and extension
105  string filename = m_config["outfile"].as<string>();
106 
107  // Compress output and append .gz extension
108  if (m_config["z"].as<bool>())
109  {
110  filename += ".gz";
111  ofstream fout(filename.c_str(),
112  std::ios_base::out | std::ios_base::binary);
113 
114  std::stringstream decompressed;
115  decompressed << doc;
116  io::filtering_streambuf<io::output> out;
117  out.push(io::gzip_compressor());
118  out.push(fout);
119  io::copy(decompressed, out);
120 
121  fout.close();
122  }
123  else
124  {
125  doc.SaveFile(filename);
126  }
127 
128  // Test the resulting XML file by loading it with the session reader
129  // and generating the meshgraph.
130  if (m_config["test"].beenSet)
131  {
132  vector<string> filenames(1);
133  filenames[0] = filename;
134 
137  0, NULL, filenames);
140  }
141  }
142 
143  void OutputNekpp::WriteXmlNodes(TiXmlElement * pRoot)
144  {
145  TiXmlElement* verTag = new TiXmlElement( "VERTEX" );
147 
148  std::set<NodeSharedPtr> tmp(
149  m_mesh->m_vertexSet.begin(),
150  m_mesh->m_vertexSet.end());
151 
152  for (it = tmp.begin(); it != tmp.end(); ++it)
153  {
154  NodeSharedPtr n = *it;
155  stringstream s;
156  s << scientific << setprecision(8)
157  << n->m_x << " " << n->m_y << " " << n->m_z;
158  TiXmlElement * v = new TiXmlElement( "V" );
159  v->SetAttribute("ID",n->m_id);
160  v->LinkEndChild(new TiXmlText(s.str()));
161  verTag->LinkEndChild(v);
162  }
163  pRoot->LinkEndChild(verTag);
164  }
165 
166  void OutputNekpp::WriteXmlEdges(TiXmlElement * pRoot)
167  {
168  if (m_mesh->m_expDim >= 2)
169  {
170  TiXmlElement* verTag = new TiXmlElement( "EDGE" );
172  std::set<EdgeSharedPtr> tmp(m_mesh->m_edgeSet.begin(),
173  m_mesh->m_edgeSet.end());
174  for (it = tmp.begin(); it != tmp.end(); ++it)
175  {
176  EdgeSharedPtr ed = *it;
177  stringstream s;
178 
179  s << setw(5) << ed->m_n1->m_id << " " << ed->m_n2->m_id << " ";
180  TiXmlElement * e = new TiXmlElement( "E" );
181  e->SetAttribute("ID",ed->m_id);
182  e->LinkEndChild( new TiXmlText(s.str()) );
183  verTag->LinkEndChild(e);
184  }
185  pRoot->LinkEndChild( verTag );
186  }
187  }
188 
189  void OutputNekpp::WriteXmlFaces(TiXmlElement * pRoot)
190  {
191  if (m_mesh->m_expDim == 3)
192  {
193  TiXmlElement* verTag = new TiXmlElement( "FACE" );
195  std::set<FaceSharedPtr> tmp(
196  m_mesh->m_faceSet.begin(),
197  m_mesh->m_faceSet.end());
198 
199  for (it = tmp.begin(); it != tmp.end(); ++it)
200  {
201  stringstream s;
202  FaceSharedPtr fa = *it;
203 
204  for (int j = 0; j < fa->m_edgeList.size(); ++j)
205  {
206  s << setw(10) << fa->m_edgeList[j]->m_id;
207  }
208  TiXmlElement * f;
209  switch(fa->m_vertexList.size())
210  {
211  case 3:
212  f = new TiXmlElement("T");
213  break;
214  case 4:
215  f = new TiXmlElement("Q");
216  break;
217  default:
218  abort();
219  }
220  f->SetAttribute("ID", fa->m_id);
221  f->LinkEndChild( new TiXmlText(s.str()));
222  verTag->LinkEndChild(f);
223  }
224  pRoot->LinkEndChild( verTag );
225  }
226  }
227 
228  void OutputNekpp::WriteXmlElements(TiXmlElement * pRoot)
229  {
230  TiXmlElement* verTag = new TiXmlElement( "ELEMENT" );
231  vector<ElementSharedPtr> &elmt = m_mesh->m_element[m_mesh->m_expDim];
232 
233  for(int i = 0; i < elmt.size(); ++i)
234  {
235  TiXmlElement *elm_tag = new TiXmlElement(elmt[i]->GetTag());
236  elm_tag->SetAttribute("ID", elmt[i]->GetId());
237  elm_tag->LinkEndChild(new TiXmlText(elmt[i]->GetXmlString()));
238  verTag->LinkEndChild(elm_tag);
239  }
240  pRoot->LinkEndChild(verTag);
241  }
242 
243  void OutputNekpp::WriteXmlCurves(TiXmlElement * pRoot)
244  {
245  int edgecnt = 0;
246 
247  bool curve = false;
249  if (m_mesh->m_expDim > 1)
250  {
251  for (it = m_mesh->m_edgeSet.begin(); it != m_mesh->m_edgeSet.end(); ++it)
252  {
253  if ((*it)->m_edgeNodes.size() > 0)
254  {
255  curve = true;
256  break;
257  }
258  }
259  }
260  else if (m_mesh->m_expDim == 1)
261  {
262  for (int i = 0; i < m_mesh->m_element[1].size(); ++i)
263  {
264  if (m_mesh->m_element[1][i]->GetVolumeNodes().size() > 0)
265  {
266  curve = true;
267  break;
268  }
269  }
270  }
271  if (!curve) return;
272 
273  TiXmlElement * curved = new TiXmlElement ("CURVED" );
274 
275  for (it = m_mesh->m_edgeSet.begin(); it != m_mesh->m_edgeSet.end(); ++it)
276  {
277  if ((*it)->m_edgeNodes.size() > 0)
278  {
279  TiXmlElement * e = new TiXmlElement( "E" );
280  e->SetAttribute("ID", edgecnt++);
281  e->SetAttribute("EDGEID", (*it)->m_id);
282  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
283  e->SetAttribute("TYPE",
284  LibUtilities::kPointsTypeStr[(*it)->m_curveType]);
285  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
286  e->LinkEndChild(t0);
287  curved->LinkEndChild(e);
288  }
289  }
290 
291  int facecnt = 0;
292 
293  // 2D elements in 3-space, output face curvature information
294  if (m_mesh->m_expDim == 1 && m_mesh->m_spaceDim > 1)
295  {
297  for (it = m_mesh->m_element[m_mesh->m_expDim].begin();
298  it != m_mesh->m_element[m_mesh->m_expDim].end(); ++it)
299  {
300  // Only generate face curve if there are volume nodes
301  if ((*it)->GetVolumeNodes().size() > 0)
302  {
303  TiXmlElement * e = new TiXmlElement( "E" );
304  e->SetAttribute("ID", facecnt++);
305  e->SetAttribute("EDGEID", (*it)->GetId());
306  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
307  e->SetAttribute("TYPE",
308  LibUtilities::kPointsTypeStr[(*it)->GetCurveType()]);
309 
310  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
311  e->LinkEndChild(t0);
312  curved->LinkEndChild(e);
313  }
314  }
315  }
316  else if (m_mesh->m_expDim == 2 && m_mesh->m_spaceDim == 3)
317  {
319  for (it = m_mesh->m_element[m_mesh->m_expDim].begin();
320  it != m_mesh->m_element[m_mesh->m_expDim].end(); ++it)
321  {
322  // Only generate face curve if there are volume nodes
323  if ((*it)->GetVolumeNodes().size() > 0)
324  {
325  TiXmlElement * e = new TiXmlElement( "F" );
326  e->SetAttribute("ID", facecnt++);
327  e->SetAttribute("FACEID", (*it)->GetId());
328  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
329  e->SetAttribute("TYPE",
330  LibUtilities::kPointsTypeStr[(*it)->GetCurveType()]);
331 
332  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
333  e->LinkEndChild(t0);
334  curved->LinkEndChild(e);
335  }
336  }
337  }
338  else if (m_mesh->m_expDim == 3)
339  {
340  FaceSet::iterator it2;
341  for (it2 = m_mesh->m_faceSet.begin(); it2 != m_mesh->m_faceSet.end(); ++it2)
342  {
343  if ((*it2)->m_faceNodes.size() > 0)
344  {
345  TiXmlElement * f = new TiXmlElement( "F" );
346  f->SetAttribute("ID", facecnt++);
347  f->SetAttribute("FACEID", (*it2)->m_id);
348  f->SetAttribute("NUMPOINTS",(*it2)->GetNodeCount());
349  f->SetAttribute("TYPE",
350  LibUtilities::kPointsTypeStr[(*it2)->m_curveType]);
351  TiXmlText * t0 = new TiXmlText((*it2)->GetXmlCurveString());
352  f->LinkEndChild(t0);
353  curved->LinkEndChild(f);
354  }
355  }
356  }
357 
358  pRoot->LinkEndChild( curved );
359  }
360 
361  void OutputNekpp::WriteXmlComposites(TiXmlElement * pRoot)
362  {
363  TiXmlElement* verTag = new TiXmlElement("COMPOSITE");
366  int j = 0;
367 
368  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it, ++j)
369  {
370  if (it->second->m_items.size() > 0)
371  {
372  TiXmlElement *comp_tag = new TiXmlElement("C"); // Composite
373  bool doSort = true;
374 
375  // Ensure that this composite is not used for periodic BCs!
376  for (it2 = m_mesh->m_condition.begin();
377  it2 != m_mesh->m_condition.end(); ++it2)
378  {
379  ConditionSharedPtr c = it2->second;
380 
381  // Ignore non-periodic boundary conditions.
382  if (find(c->type.begin(), c->type.end(), ePeriodic) ==
383  c->type.end())
384  {
385  continue;
386  }
387 
388  for (int i = 0; i < c->m_composite.size(); ++i)
389  {
390  if (c->m_composite[i] == j)
391  {
392  doSort = false;
393  }
394  }
395  }
396 
397  doSort = doSort && it->second->m_reorder;
398  comp_tag->SetAttribute("ID", it->second->m_id);
399  if(it->second->m_label.size())
400  {
401  comp_tag->SetAttribute("LABEL", it->second->m_label);
402  }
403  comp_tag->LinkEndChild(
404  new TiXmlText(it->second->GetXmlString(doSort)));
405  verTag->LinkEndChild(comp_tag);
406  }
407  else
408  {
409  cout << "Composite " << it->second->m_id << " "
410  << "contains nothing." << endl;
411  }
412  }
413 
414  pRoot->LinkEndChild(verTag);
415  }
416 
417  void OutputNekpp::WriteXmlDomain(TiXmlElement * pRoot)
418  {
419  // Write the <DOMAIN> subsection.
420  TiXmlElement * domain = new TiXmlElement ("DOMAIN" );
421  std::string list;
423 
424  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it)
425  {
426  if (it->second->m_items[0]->GetDim() == m_mesh->m_expDim)
427  {
428  if (list.length() > 0)
429  {
430  list += ",";
431  }
432  list += boost::lexical_cast<std::string>(it->second->m_id);
433  }
434  }
435  domain->LinkEndChild( new TiXmlText(" C[" + list + "] "));
436  pRoot->LinkEndChild( domain );
437  }
438 
439  void OutputNekpp::WriteXmlExpansions(TiXmlElement * pRoot)
440  {
441  // Write a default <EXPANSIONS> section.
442  TiXmlElement * expansions = new TiXmlElement ("EXPANSIONS");
444 
445  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it)
446  {
447  if (it->second->m_items[0]->GetDim() == m_mesh->m_expDim)
448  {
449  TiXmlElement * exp = new TiXmlElement ( "E");
450  exp->SetAttribute("COMPOSITE", "C["
451  + boost::lexical_cast<std::string>(it->second->m_id)
452  + "]");
453  exp->SetAttribute("NUMMODES",4);
454  exp->SetAttribute("TYPE","MODIFIED");
455 
456  if (m_mesh->m_fields.size() == 0)
457  {
458  exp->SetAttribute("FIELDS","u");
459  }
460  else
461  {
462  string fstr;
463  for (int i = 0; i < m_mesh->m_fields.size(); ++i)
464  {
465  fstr += m_mesh->m_fields[i]+",";
466  }
467  fstr = fstr.substr(0,fstr.length()-1);
468  exp->SetAttribute("FIELDS", fstr);
469  }
470 
471  expansions->LinkEndChild(exp);
472  }
473  }
474  pRoot->LinkEndChild(expansions);
475  }
476 
477  void OutputNekpp::WriteXmlConditions(TiXmlElement * pRoot)
478  {
479  TiXmlElement *conditions =
480  new TiXmlElement("CONDITIONS");
481  TiXmlElement *boundaryregions =
482  new TiXmlElement("BOUNDARYREGIONS");
483  TiXmlElement *boundaryconditions =
484  new TiXmlElement("BOUNDARYCONDITIONS");
485  TiXmlElement *variables =
486  new TiXmlElement("VARIABLES");
488 
489  for (it = m_mesh->m_condition.begin(); it != m_mesh->m_condition.end(); ++it)
490  {
491  ConditionSharedPtr c = it->second;
492  string tmp;
493 
494  // First set up boundary regions.
495  TiXmlElement *b = new TiXmlElement("B");
496  b->SetAttribute("ID", boost::lexical_cast<string>(it->first));
497 
498  for (int i = 0; i < c->m_composite.size(); ++i)
499  {
500  tmp += boost::lexical_cast<string>(c->m_composite[i]) + ",";
501  }
502 
503  tmp = tmp.substr(0, tmp.length()-1);
504 
505  TiXmlText *t0 = new TiXmlText("C["+tmp+"]");
506  b->LinkEndChild(t0);
507  boundaryregions->LinkEndChild(b);
508 
509  TiXmlElement *region = new TiXmlElement("REGION");
510  region->SetAttribute(
511  "REF", boost::lexical_cast<string>(it->first));
512 
513  for (int i = 0; i < c->type.size(); ++i)
514  {
515  string tagId;
516 
517  switch(c->type[i])
518  {
519  case eDirichlet: tagId = "D"; break;
520  case eNeumann: tagId = "N"; break;
521  case ePeriodic: tagId = "P"; break;
522  case eHOPCondition: tagId = "N"; break;
523  default: break;
524  }
525 
526  TiXmlElement *tag = new TiXmlElement(tagId);
527  tag->SetAttribute("VAR", c->field[i]);
528  tag->SetAttribute("VALUE", c->value[i]);
529 
530  if (c->type[i] == eHOPCondition)
531  {
532  tag->SetAttribute("USERDEFINEDTYPE", "H");
533  }
534 
535  region->LinkEndChild(tag);
536  }
537 
538  boundaryconditions->LinkEndChild(region);
539  }
540 
541  for (int i = 0; i < m_mesh->m_fields.size(); ++i)
542  {
543  TiXmlElement *v = new TiXmlElement("V");
544  v->SetAttribute("ID", boost::lexical_cast<std::string>(i));
545  TiXmlText *t0 = new TiXmlText(m_mesh->m_fields[i]);
546  v->LinkEndChild(t0);
547  variables->LinkEndChild(v);
548  }
549 
550  if (m_mesh->m_fields.size() > 0)
551  {
552  conditions->LinkEndChild(variables);
553  }
554 
555  if (m_mesh->m_condition.size() > 0)
556  {
557  conditions->LinkEndChild(boundaryregions);
558  conditions->LinkEndChild(boundaryconditions);
559  }
560 
561  pRoot->LinkEndChild(conditions);
562  }
563  }
564 }
void WriteXmlCurves(TiXmlElement *pRoot)
Writes the section of the XML file if needed.
virtual void Process()
Write mesh to output file.
Definition: OutputNekpp.cpp:74
pair< ModuleType, string > ModuleKey
static boost::shared_ptr< MeshGraph > Read(const LibUtilities::SessionReaderSharedPtr &pSession, DomainRangeShPtr &rng=NullDomainRangeShPtr)
Definition: MeshGraph.cpp:119
void WriteXmlFaces(TiXmlElement *pRoot)
Writes the section of the XML file if needed.
Abstract base class for output modules.
const std::string kPointsTypeStr[]
Definition: Foundations.hpp:69
void WriteXmlNodes(TiXmlElement *pRoot)
Writes the section of the XML file.
boost::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: MeshElements.h:318
map< string, ConfigOption > m_config
List of configuration values.
STL namespace.
MeshSharedPtr m_mesh
Mesh object.
boost::shared_ptr< Face > FaceSharedPtr
Shared pointer to a face.
Definition: MeshElements.h:550
boost::shared_ptr< Node > NodeSharedPtr
Shared pointer to a Node.
Definition: MeshElements.h:195
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:50
boost::shared_ptr< Condition > ConditionSharedPtr
static SessionReaderSharedPtr CreateInstance(int argc, char *argv[])
Creates an instance of the SessionReader class.
string GetXmlString(char tag, vector< unsigned int > &ids)
boost::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Represents a command-line configuration option.
void WriteXmlExpansions(TiXmlElement *pRoot)
Writes the section of the XML file.
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
void WriteXmlDomain(TiXmlElement *pRoot)
Writes the section of the XML file.
void WriteXmlComposites(TiXmlElement *pRoot)
Writes the section of the XML file.
void WriteXmlElements(TiXmlElement *pRoot)
Writes the section of the XML file.
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:312
void WriteXmlConditions(TiXmlElement *pRoot)
Writes the section of the XML file.
void WriteXmlEdges(TiXmlElement *pRoot)
Writes the section of the XML file.
boost::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:432
ModuleFactory & GetModuleFactory()
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215