Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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>
46 
47 #include "MeshElements.h"
48 #include "OutputNekpp.h"
49 
50 namespace Nektar
51 {
52  namespace Utilities
53  {
54  ModuleKey OutputNekpp::className =
56  ModuleKey(eOutputModule, "xml"), OutputNekpp::create,
57  "Writes a Nektar++ xml file.");
58 
59  OutputNekpp::OutputNekpp(MeshSharedPtr m) : OutputModule(m)
60  {
61  m_config["z"] = ConfigOption(true, "0",
62  "Compress output file and append a .gz extension.");
63  }
64 
66  {
67 
68  }
69 
71  {
72  if (m_mesh->m_verbose)
73  {
74  cout << "OutputNekpp: Writing file..." << endl;
75  }
76 
77  TiXmlDocument doc;
78  TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "");
79  doc.LinkEndChild( decl );
80 
81  TiXmlElement * root = new TiXmlElement( "NEKTAR" );
82  doc.LinkEndChild( root );
83 
84  // Begin <GEOMETRY> section
85  TiXmlElement * geomTag = new TiXmlElement( "GEOMETRY" );
86  geomTag->SetAttribute("DIM", m_mesh->m_expDim);
87  geomTag->SetAttribute("SPACE", m_mesh->m_spaceDim);
88  root->LinkEndChild( geomTag );
89 
90  WriteXmlNodes (geomTag);
91  WriteXmlEdges (geomTag);
92  WriteXmlFaces (geomTag);
93  WriteXmlElements (geomTag);
94  WriteXmlCurves (geomTag);
95  WriteXmlComposites(geomTag);
96  WriteXmlDomain (geomTag);
97  WriteXmlExpansions(root);
98  WriteXmlConditions(root);
99 
100  // Extract the output filename and extension
101  string filename = m_config["outfile"].as<string>();
102 
103  // Compress output and append .gz extension
104  if (m_config["z"].as<bool>())
105  {
106  filename += ".gz";
107  ofstream fout(filename.c_str(),
108  std::ios_base::out | std::ios_base::binary);
109 
110  std::stringstream decompressed;
111  decompressed << doc;
112  io::filtering_streambuf<io::output> out;
113  out.push(io::gzip_compressor());
114  out.push(fout);
115  io::copy(decompressed, out);
116 
117  fout.close();
118  }
119  else
120  {
121  doc.SaveFile(filename);
122  }
123  }
124 
125  void OutputNekpp::WriteXmlNodes(TiXmlElement * pRoot)
126  {
127  TiXmlElement* verTag = new TiXmlElement( "VERTEX" );
129 
130  std::set<NodeSharedPtr> tmp(
131  m_mesh->m_vertexSet.begin(),
132  m_mesh->m_vertexSet.end());
133 
134  for (it = tmp.begin(); it != tmp.end(); ++it)
135  {
136  NodeSharedPtr n = *it;
137  stringstream s;
138  s << scientific << setprecision(8)
139  << n->m_x << " " << n->m_y << " " << n->m_z;
140  TiXmlElement * v = new TiXmlElement( "V" );
141  v->SetAttribute("ID",n->m_id);
142  v->LinkEndChild(new TiXmlText(s.str()));
143  verTag->LinkEndChild(v);
144  }
145  pRoot->LinkEndChild(verTag);
146  }
147 
148  void OutputNekpp::WriteXmlEdges(TiXmlElement * pRoot)
149  {
150  if (m_mesh->m_expDim >= 2)
151  {
152  TiXmlElement* verTag = new TiXmlElement( "EDGE" );
154  std::set<EdgeSharedPtr> tmp(m_mesh->m_edgeSet.begin(),
155  m_mesh->m_edgeSet.end());
156  for (it = tmp.begin(); it != tmp.end(); ++it)
157  {
158  EdgeSharedPtr ed = *it;
159  stringstream s;
160 
161  s << setw(5) << ed->m_n1->m_id << " " << ed->m_n2->m_id << " ";
162  TiXmlElement * e = new TiXmlElement( "E" );
163  e->SetAttribute("ID",ed->m_id);
164  e->LinkEndChild( new TiXmlText(s.str()) );
165  verTag->LinkEndChild(e);
166  }
167  pRoot->LinkEndChild( verTag );
168  }
169  }
170 
171  void OutputNekpp::WriteXmlFaces(TiXmlElement * pRoot)
172  {
173  if (m_mesh->m_expDim == 3)
174  {
175  TiXmlElement* verTag = new TiXmlElement( "FACE" );
177  std::set<FaceSharedPtr> tmp(
178  m_mesh->m_faceSet.begin(),
179  m_mesh->m_faceSet.end());
180 
181  for (it = tmp.begin(); it != tmp.end(); ++it)
182  {
183  stringstream s;
184  FaceSharedPtr fa = *it;
185 
186  for (int j = 0; j < fa->m_edgeList.size(); ++j)
187  {
188  s << setw(10) << fa->m_edgeList[j]->m_id;
189  }
190  TiXmlElement * f;
191  switch(fa->m_vertexList.size())
192  {
193  case 3:
194  f = new TiXmlElement("T");
195  break;
196  case 4:
197  f = new TiXmlElement("Q");
198  break;
199  default:
200  abort();
201  }
202  f->SetAttribute("ID", fa->m_id);
203  f->LinkEndChild( new TiXmlText(s.str()));
204  verTag->LinkEndChild(f);
205  }
206  pRoot->LinkEndChild( verTag );
207  }
208  }
209 
210  void OutputNekpp::WriteXmlElements(TiXmlElement * pRoot)
211  {
212  TiXmlElement* verTag = new TiXmlElement( "ELEMENT" );
213  vector<ElementSharedPtr> &elmt = m_mesh->m_element[m_mesh->m_expDim];
214 
215  for(int i = 0; i < elmt.size(); ++i)
216  {
217  TiXmlElement *elm_tag = new TiXmlElement(elmt[i]->GetTag());
218  elm_tag->SetAttribute("ID", elmt[i]->GetId());
219  elm_tag->LinkEndChild(new TiXmlText(elmt[i]->GetXmlString()));
220  verTag->LinkEndChild(elm_tag);
221  }
222  pRoot->LinkEndChild(verTag);
223  }
224 
225  void OutputNekpp::WriteXmlCurves(TiXmlElement * pRoot)
226  {
227  int edgecnt = 0;
228 
229  bool curve = false;
231  for (it = m_mesh->m_edgeSet.begin(); it != m_mesh->m_edgeSet.end(); ++it)
232  {
233  if ((*it)->m_edgeNodes.size() > 0)
234  {
235  curve = true;
236  break;
237  }
238  }
239  if (!curve) return;
240 
241  TiXmlElement * curved = new TiXmlElement ("CURVED" );
242 
243  for (it = m_mesh->m_edgeSet.begin(); it != m_mesh->m_edgeSet.end(); ++it)
244  {
245  if ((*it)->m_edgeNodes.size() > 0)
246  {
247  TiXmlElement * e = new TiXmlElement( "E" );
248  e->SetAttribute("ID", edgecnt++);
249  e->SetAttribute("EDGEID", (*it)->m_id);
250  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
251  e->SetAttribute("TYPE",
252  LibUtilities::kPointsTypeStr[(*it)->m_curveType]);
253  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
254  e->LinkEndChild(t0);
255  curved->LinkEndChild(e);
256  }
257  }
258 
259  int facecnt = 0;
260 
261  // 2D elements in 3-space, output face curvature information
262  if (m_mesh->m_expDim == 2 && m_mesh->m_spaceDim == 3)
263  {
265  for (it = m_mesh->m_element[m_mesh->m_expDim].begin();
266  it != m_mesh->m_element[m_mesh->m_expDim].end(); ++it)
267  {
268  // Only generate face curve if there are volume nodes
269  if ((*it)->GetVolumeNodes().size() > 0)
270  {
271  TiXmlElement * e = new TiXmlElement( "F" );
272  e->SetAttribute("ID", facecnt++);
273  e->SetAttribute("FACEID", (*it)->GetId());
274  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
275  e->SetAttribute("TYPE",
276  LibUtilities::kPointsTypeStr[(*it)->GetCurveType()]);
277 
278  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
279  e->LinkEndChild(t0);
280  curved->LinkEndChild(e);
281  }
282  }
283  }
284  else if (m_mesh->m_expDim == 3)
285  {
286  FaceSet::iterator it2;
287  for (it2 = m_mesh->m_faceSet.begin(); it2 != m_mesh->m_faceSet.end(); ++it2)
288  {
289  if ((*it2)->m_faceNodes.size() > 0)
290  {
291  TiXmlElement * f = new TiXmlElement( "F" );
292  f->SetAttribute("ID", facecnt++);
293  f->SetAttribute("FACEID", (*it2)->m_id);
294  f->SetAttribute("NUMPOINTS",(*it2)->GetNodeCount());
295  f->SetAttribute("TYPE",
296  LibUtilities::kPointsTypeStr[(*it2)->m_curveType]);
297  TiXmlText * t0 = new TiXmlText((*it2)->GetXmlCurveString());
298  f->LinkEndChild(t0);
299  curved->LinkEndChild(f);
300  }
301  }
302  }
303 
304  pRoot->LinkEndChild( curved );
305  }
306 
307  void OutputNekpp::WriteXmlComposites(TiXmlElement * pRoot)
308  {
309  TiXmlElement* verTag = new TiXmlElement("COMPOSITE");
312  int j = 0;
313 
314  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it, ++j)
315  {
316  if (it->second->m_items.size() > 0)
317  {
318  TiXmlElement *comp_tag = new TiXmlElement("C"); // Composite
319  bool doSort = true;
320 
321  // Ensure that this composite is not used for periodic BCs!
322  for (it2 = m_mesh->m_condition.begin();
323  it2 != m_mesh->m_condition.end(); ++it2)
324  {
325  ConditionSharedPtr c = it2->second;
326 
327  // Ignore non-periodic boundary conditions.
328  if (find(c->type.begin(), c->type.end(), ePeriodic) ==
329  c->type.end())
330  {
331  continue;
332  }
333 
334  for (int i = 0; i < c->m_composite.size(); ++i)
335  {
336  if (c->m_composite[i] == j)
337  {
338  doSort = false;
339  }
340  }
341  }
342 
343  doSort = doSort && it->second->m_reorder;
344  comp_tag->SetAttribute("ID", it->second->m_id);
345  comp_tag->LinkEndChild(
346  new TiXmlText(it->second->GetXmlString(doSort)));
347  verTag->LinkEndChild(comp_tag);
348  }
349  else
350  {
351  cout << "Composite " << it->second->m_id << " "
352  << "contains nothing." << endl;
353  }
354  }
355 
356  pRoot->LinkEndChild(verTag);
357  }
358 
359  void OutputNekpp::WriteXmlDomain(TiXmlElement * pRoot)
360  {
361  // Write the <DOMAIN> subsection.
362  TiXmlElement * domain = new TiXmlElement ("DOMAIN" );
363  std::string list;
365 
366  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it)
367  {
368  if (it->second->m_items[0]->GetDim() == m_mesh->m_expDim)
369  {
370  if (list.length() > 0)
371  {
372  list += ",";
373  }
374  list += boost::lexical_cast<std::string>(it->second->m_id);
375  }
376  }
377  domain->LinkEndChild( new TiXmlText(" C[" + list + "] "));
378  pRoot->LinkEndChild( domain );
379  }
380 
381  void OutputNekpp::WriteXmlExpansions(TiXmlElement * pRoot)
382  {
383  // Write a default <EXPANSIONS> section.
384  TiXmlElement * expansions = new TiXmlElement ("EXPANSIONS");
386 
387  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it)
388  {
389  if (it->second->m_items[0]->GetDim() == m_mesh->m_expDim)
390  {
391  TiXmlElement * exp = new TiXmlElement ( "E");
392  exp->SetAttribute("COMPOSITE", "C["
393  + boost::lexical_cast<std::string>(it->second->m_id)
394  + "]");
395  exp->SetAttribute("NUMMODES",4);
396  exp->SetAttribute("TYPE","MODIFIED");
397 
398  if (m_mesh->m_fields.size() == 0)
399  {
400  exp->SetAttribute("FIELDS","u");
401  }
402  else
403  {
404  string fstr;
405  for (int i = 0; i < m_mesh->m_fields.size(); ++i)
406  {
407  fstr += m_mesh->m_fields[i]+",";
408  }
409  fstr = fstr.substr(0,fstr.length()-1);
410  exp->SetAttribute("FIELDS", fstr);
411  }
412 
413  expansions->LinkEndChild(exp);
414  }
415  }
416  pRoot->LinkEndChild(expansions);
417  }
418 
419  void OutputNekpp::WriteXmlConditions(TiXmlElement * pRoot)
420  {
421  TiXmlElement *conditions =
422  new TiXmlElement("CONDITIONS");
423  TiXmlElement *boundaryregions =
424  new TiXmlElement("BOUNDARYREGIONS");
425  TiXmlElement *boundaryconditions =
426  new TiXmlElement("BOUNDARYCONDITIONS");
427  TiXmlElement *variables =
428  new TiXmlElement("VARIABLES");
430 
431  for (it = m_mesh->m_condition.begin(); it != m_mesh->m_condition.end(); ++it)
432  {
433  ConditionSharedPtr c = it->second;
434  string tmp;
435 
436  // First set up boundary regions.
437  TiXmlElement *b = new TiXmlElement("B");
438  b->SetAttribute("ID", boost::lexical_cast<string>(it->first));
439 
440  for (int i = 0; i < c->m_composite.size(); ++i)
441  {
442  tmp += boost::lexical_cast<string>(c->m_composite[i]) + ",";
443  }
444 
445  tmp = tmp.substr(0, tmp.length()-1);
446 
447  TiXmlText *t0 = new TiXmlText("C["+tmp+"]");
448  b->LinkEndChild(t0);
449  boundaryregions->LinkEndChild(b);
450 
451  TiXmlElement *region = new TiXmlElement("REGION");
452  region->SetAttribute(
453  "REF", boost::lexical_cast<string>(it->first));
454 
455  for (int i = 0; i < c->type.size(); ++i)
456  {
457  string tagId;
458 
459  switch(c->type[i])
460  {
461  case eDirichlet: tagId = "D"; break;
462  case eNeumann: tagId = "N"; break;
463  case ePeriodic: tagId = "P"; break;
464  case eHOPCondition: tagId = "N"; break;
465  default: break;
466  }
467 
468  TiXmlElement *tag = new TiXmlElement(tagId);
469  tag->SetAttribute("VAR", c->field[i]);
470  tag->SetAttribute("VALUE", c->value[i]);
471 
472  if (c->type[i] == eHOPCondition)
473  {
474  tag->SetAttribute("USERDEFINEDTYPE", "H");
475  }
476 
477  region->LinkEndChild(tag);
478  }
479 
480  boundaryconditions->LinkEndChild(region);
481  }
482 
483  for (int i = 0; i < m_mesh->m_fields.size(); ++i)
484  {
485  TiXmlElement *v = new TiXmlElement("V");
486  v->SetAttribute("ID", boost::lexical_cast<std::string>(i));
487  TiXmlText *t0 = new TiXmlText(m_mesh->m_fields[i]);
488  v->LinkEndChild(t0);
489  variables->LinkEndChild(v);
490  }
491 
492  if (m_mesh->m_fields.size() > 0)
493  {
494  conditions->LinkEndChild(variables);
495  }
496 
497  if (m_mesh->m_condition.size() > 0)
498  {
499  conditions->LinkEndChild(boundaryregions);
500  conditions->LinkEndChild(boundaryconditions);
501  }
502 
503  pRoot->LinkEndChild(conditions);
504  }
505  }
506 }