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>
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  for (it = m_mesh->m_edgeSet.begin(); it != m_mesh->m_edgeSet.end(); ++it)
250  {
251  if ((*it)->m_edgeNodes.size() > 0)
252  {
253  curve = true;
254  break;
255  }
256  }
257  if (!curve) return;
258 
259  TiXmlElement * curved = new TiXmlElement ("CURVED" );
260 
261  for (it = m_mesh->m_edgeSet.begin(); it != m_mesh->m_edgeSet.end(); ++it)
262  {
263  if ((*it)->m_edgeNodes.size() > 0)
264  {
265  TiXmlElement * e = new TiXmlElement( "E" );
266  e->SetAttribute("ID", edgecnt++);
267  e->SetAttribute("EDGEID", (*it)->m_id);
268  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
269  e->SetAttribute("TYPE",
270  LibUtilities::kPointsTypeStr[(*it)->m_curveType]);
271  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
272  e->LinkEndChild(t0);
273  curved->LinkEndChild(e);
274  }
275  }
276 
277  int facecnt = 0;
278 
279  // 2D elements in 3-space, output face curvature information
280  if (m_mesh->m_expDim == 2 && m_mesh->m_spaceDim == 3)
281  {
283  for (it = m_mesh->m_element[m_mesh->m_expDim].begin();
284  it != m_mesh->m_element[m_mesh->m_expDim].end(); ++it)
285  {
286  // Only generate face curve if there are volume nodes
287  if ((*it)->GetVolumeNodes().size() > 0)
288  {
289  TiXmlElement * e = new TiXmlElement( "F" );
290  e->SetAttribute("ID", facecnt++);
291  e->SetAttribute("FACEID", (*it)->GetId());
292  e->SetAttribute("NUMPOINTS", (*it)->GetNodeCount());
293  e->SetAttribute("TYPE",
294  LibUtilities::kPointsTypeStr[(*it)->GetCurveType()]);
295 
296  TiXmlText * t0 = new TiXmlText((*it)->GetXmlCurveString());
297  e->LinkEndChild(t0);
298  curved->LinkEndChild(e);
299  }
300  }
301  }
302  else if (m_mesh->m_expDim == 3)
303  {
304  FaceSet::iterator it2;
305  for (it2 = m_mesh->m_faceSet.begin(); it2 != m_mesh->m_faceSet.end(); ++it2)
306  {
307  if ((*it2)->m_faceNodes.size() > 0)
308  {
309  TiXmlElement * f = new TiXmlElement( "F" );
310  f->SetAttribute("ID", facecnt++);
311  f->SetAttribute("FACEID", (*it2)->m_id);
312  f->SetAttribute("NUMPOINTS",(*it2)->GetNodeCount());
313  f->SetAttribute("TYPE",
314  LibUtilities::kPointsTypeStr[(*it2)->m_curveType]);
315  TiXmlText * t0 = new TiXmlText((*it2)->GetXmlCurveString());
316  f->LinkEndChild(t0);
317  curved->LinkEndChild(f);
318  }
319  }
320  }
321 
322  pRoot->LinkEndChild( curved );
323  }
324 
325  void OutputNekpp::WriteXmlComposites(TiXmlElement * pRoot)
326  {
327  TiXmlElement* verTag = new TiXmlElement("COMPOSITE");
330  int j = 0;
331 
332  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it, ++j)
333  {
334  if (it->second->m_items.size() > 0)
335  {
336  TiXmlElement *comp_tag = new TiXmlElement("C"); // Composite
337  bool doSort = true;
338 
339  // Ensure that this composite is not used for periodic BCs!
340  for (it2 = m_mesh->m_condition.begin();
341  it2 != m_mesh->m_condition.end(); ++it2)
342  {
343  ConditionSharedPtr c = it2->second;
344 
345  // Ignore non-periodic boundary conditions.
346  if (find(c->type.begin(), c->type.end(), ePeriodic) ==
347  c->type.end())
348  {
349  continue;
350  }
351 
352  for (int i = 0; i < c->m_composite.size(); ++i)
353  {
354  if (c->m_composite[i] == j)
355  {
356  doSort = false;
357  }
358  }
359  }
360 
361  doSort = doSort && it->second->m_reorder;
362  comp_tag->SetAttribute("ID", it->second->m_id);
363  comp_tag->LinkEndChild(
364  new TiXmlText(it->second->GetXmlString(doSort)));
365  verTag->LinkEndChild(comp_tag);
366  }
367  else
368  {
369  cout << "Composite " << it->second->m_id << " "
370  << "contains nothing." << endl;
371  }
372  }
373 
374  pRoot->LinkEndChild(verTag);
375  }
376 
377  void OutputNekpp::WriteXmlDomain(TiXmlElement * pRoot)
378  {
379  // Write the <DOMAIN> subsection.
380  TiXmlElement * domain = new TiXmlElement ("DOMAIN" );
381  std::string list;
383 
384  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it)
385  {
386  if (it->second->m_items[0]->GetDim() == m_mesh->m_expDim)
387  {
388  if (list.length() > 0)
389  {
390  list += ",";
391  }
392  list += boost::lexical_cast<std::string>(it->second->m_id);
393  }
394  }
395  domain->LinkEndChild( new TiXmlText(" C[" + list + "] "));
396  pRoot->LinkEndChild( domain );
397  }
398 
399  void OutputNekpp::WriteXmlExpansions(TiXmlElement * pRoot)
400  {
401  // Write a default <EXPANSIONS> section.
402  TiXmlElement * expansions = new TiXmlElement ("EXPANSIONS");
404 
405  for (it = m_mesh->m_composite.begin(); it != m_mesh->m_composite.end(); ++it)
406  {
407  if (it->second->m_items[0]->GetDim() == m_mesh->m_expDim)
408  {
409  TiXmlElement * exp = new TiXmlElement ( "E");
410  exp->SetAttribute("COMPOSITE", "C["
411  + boost::lexical_cast<std::string>(it->second->m_id)
412  + "]");
413  exp->SetAttribute("NUMMODES",4);
414  exp->SetAttribute("TYPE","MODIFIED");
415 
416  if (m_mesh->m_fields.size() == 0)
417  {
418  exp->SetAttribute("FIELDS","u");
419  }
420  else
421  {
422  string fstr;
423  for (int i = 0; i < m_mesh->m_fields.size(); ++i)
424  {
425  fstr += m_mesh->m_fields[i]+",";
426  }
427  fstr = fstr.substr(0,fstr.length()-1);
428  exp->SetAttribute("FIELDS", fstr);
429  }
430 
431  expansions->LinkEndChild(exp);
432  }
433  }
434  pRoot->LinkEndChild(expansions);
435  }
436 
437  void OutputNekpp::WriteXmlConditions(TiXmlElement * pRoot)
438  {
439  TiXmlElement *conditions =
440  new TiXmlElement("CONDITIONS");
441  TiXmlElement *boundaryregions =
442  new TiXmlElement("BOUNDARYREGIONS");
443  TiXmlElement *boundaryconditions =
444  new TiXmlElement("BOUNDARYCONDITIONS");
445  TiXmlElement *variables =
446  new TiXmlElement("VARIABLES");
448 
449  for (it = m_mesh->m_condition.begin(); it != m_mesh->m_condition.end(); ++it)
450  {
451  ConditionSharedPtr c = it->second;
452  string tmp;
453 
454  // First set up boundary regions.
455  TiXmlElement *b = new TiXmlElement("B");
456  b->SetAttribute("ID", boost::lexical_cast<string>(it->first));
457 
458  for (int i = 0; i < c->m_composite.size(); ++i)
459  {
460  tmp += boost::lexical_cast<string>(c->m_composite[i]) + ",";
461  }
462 
463  tmp = tmp.substr(0, tmp.length()-1);
464 
465  TiXmlText *t0 = new TiXmlText("C["+tmp+"]");
466  b->LinkEndChild(t0);
467  boundaryregions->LinkEndChild(b);
468 
469  TiXmlElement *region = new TiXmlElement("REGION");
470  region->SetAttribute(
471  "REF", boost::lexical_cast<string>(it->first));
472 
473  for (int i = 0; i < c->type.size(); ++i)
474  {
475  string tagId;
476 
477  switch(c->type[i])
478  {
479  case eDirichlet: tagId = "D"; break;
480  case eNeumann: tagId = "N"; break;
481  case ePeriodic: tagId = "P"; break;
482  case eHOPCondition: tagId = "N"; break;
483  default: break;
484  }
485 
486  TiXmlElement *tag = new TiXmlElement(tagId);
487  tag->SetAttribute("VAR", c->field[i]);
488  tag->SetAttribute("VALUE", c->value[i]);
489 
490  if (c->type[i] == eHOPCondition)
491  {
492  tag->SetAttribute("USERDEFINEDTYPE", "H");
493  }
494 
495  region->LinkEndChild(tag);
496  }
497 
498  boundaryconditions->LinkEndChild(region);
499  }
500 
501  for (int i = 0; i < m_mesh->m_fields.size(); ++i)
502  {
503  TiXmlElement *v = new TiXmlElement("V");
504  v->SetAttribute("ID", boost::lexical_cast<std::string>(i));
505  TiXmlText *t0 = new TiXmlText(m_mesh->m_fields[i]);
506  v->LinkEndChild(t0);
507  variables->LinkEndChild(v);
508  }
509 
510  if (m_mesh->m_fields.size() > 0)
511  {
512  conditions->LinkEndChild(variables);
513  }
514 
515  if (m_mesh->m_condition.size() > 0)
516  {
517  conditions->LinkEndChild(boundaryregions);
518  conditions->LinkEndChild(boundaryconditions);
519  }
520 
521  pRoot->LinkEndChild(conditions);
522  }
523  }
524 }