Nektar++
library/FieldUtils/OutputModules/OutputVtk.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: OutputVtk.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: VTK file format output.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include <set>
36 #include <string>
37 #include <iomanip>
38 using namespace std;
39 
40 #include <boost/core/ignore_unused.hpp>
41 #include <boost/format.hpp>
42 
44 
45 #include "OutputVtk.h"
46 
47 namespace Nektar
48 {
49 namespace FieldUtils
50 {
51 
52 ModuleKey OutputVtk::m_className = GetModuleFactory().RegisterCreatorFunction(
53  ModuleKey(eOutputModule, "vtu"), OutputVtk::create, "Writes a VTU file.");
54 
55 OutputVtk::OutputVtk(FieldSharedPtr f) : OutputFileBase(f)
56 {
57  m_requireEquiSpaced = true;
58 }
59 
61 {
62 }
63 
64 void OutputVtk::OutputFromPts(po::variables_map &vm)
65 {
66  int i, j;
67  LibUtilities::PtsFieldSharedPtr fPts = m_f->m_fieldPts;
68 
69  // Extract the output filename and extension
70  string filename = PrepareOutput(vm);
71 
72  // Write solution.
73  ofstream outfile(filename.c_str());
74  WriteVtkHeader(outfile);
75  int nfields = 0;
76  int dim = fPts->GetDim();
77 
78  int nvert = 1;
79  int vtktype = 1;
80  switch (fPts->GetPtsType())
81  {
84  {
86  "VTK output needs setting up for ePtsFile and ePtsLine");
87  break;
88  }
90  {
92  "VTK output needs setting up for PtsPlane");
93  break;
94  }
96  {
98  "VTK output needs setting up for PtsBox");
99  break;
100  }
102  {
103  nvert = 2;
104  vtktype = 3;
105  break;
106  }
108  {
109  nvert = 3;
110  vtktype = 5;
111  break;
112  }
114  {
115  nvert = 4;
116  vtktype = 10;
117  break;
118  }
119  default:
120  NEKERROR(ErrorUtil::efatal, "ptsType not supported yet.");
121  }
122 
123  vector<Array<OneD, int> > ptsConn;
124  fPts->GetConnectivity(ptsConn);
125 
126  nfields = fPts->GetNFields();
127 
128  int nPts = fPts->GetNpoints();
129  int numBlocks = 0;
130  for (i = 0; i < ptsConn.size(); ++i)
131  {
132  numBlocks += ptsConn[i].num_elements() / nvert;
133  }
134 
135  // write out pieces of data.
136  outfile << " <Piece NumberOfPoints=\"" << nPts
137  << "\" NumberOfCells=\"" << numBlocks << "\">" << endl;
138  outfile << " <Points>" << endl;
139  outfile << " <DataArray type=\"Float64\" "
140  << "NumberOfComponents=\"" << 3 << "\" format=\"ascii\">"
141  << endl;
142  for (i = 0; i < nPts; ++i)
143  {
144  for (j = 0; j < dim; ++j)
145  {
146  outfile << " " << setprecision(8) << scientific
147  << fPts->GetPointVal(j, i) << " ";
148  }
149  for (j = dim; j < 3; ++j)
150  {
151  // pack to 3D since paraview does not seem to handle 2D
152  outfile << " 0.000000";
153  }
154  outfile << endl;
155  }
156  outfile << " </DataArray>" << endl;
157  outfile << " </Points>" << endl;
158  outfile << " <Cells>" << endl;
159  outfile << " <DataArray type=\"Int32\" "
160  << "Name=\"connectivity\" format=\"ascii\">" << endl;
161 
162  // dump connectivity data if it exists
163  outfile << " ";
164  int cnt = 1;
165  for (i = 0; i < ptsConn.size(); ++i)
166  {
167  for (j = 0; j < ptsConn[i].num_elements(); ++j)
168  {
169  outfile << ptsConn[i][j] << " ";
170  if ((!(cnt % nvert)) && cnt)
171  {
172  outfile << std::endl;
173  outfile << " ";
174  }
175  cnt++;
176  }
177  }
178  outfile << " </DataArray>" << endl;
179  outfile << " <DataArray type=\"Int32\" "
180  << "Name=\"offsets\" format=\"ascii\">" << endl;
181 
182  outfile << " ";
183  for (i = 0; i < numBlocks; ++i)
184  {
185  outfile << i * nvert + nvert << " ";
186  }
187  outfile << endl;
188  outfile << " </DataArray>" << endl;
189  outfile << " <DataArray type=\"UInt8\" "
190  << "Name=\"types\" format=\"ascii\">" << endl;
191  outfile << " ";
192  for (i = 0; i < numBlocks; ++i)
193  {
194  outfile << vtktype << " ";
195  }
196  outfile << endl;
197  outfile << " </DataArray>" << endl;
198  outfile << " </Cells>" << endl;
199  outfile << " <PointData>" << endl;
200 
201  // printing the fields
202  for (j = 0; j < nfields; ++j)
203  {
204  outfile << " <DataArray type=\"Float64\" Name=\""
205  << m_f->m_variables[j] << "\">" << endl;
206  outfile << " ";
207  for (i = 0; i < fPts->GetNpoints(); ++i)
208  {
209  outfile << fPts->GetPointVal(dim + j, i) << " ";
210  }
211  outfile << endl;
212  outfile << " </DataArray>" << endl;
213  }
214 
215  outfile << " </PointData>" << endl;
216  outfile << " </Piece>" << endl;
217 
218  WriteVtkFooter(outfile);
219  cout << "Written file: " << filename << endl;
220 
221  // output parallel outline info if necessary
222  if ( (m_f->m_comm->GetRank() == 0) &&
223  (m_f->m_comm->GetSize() != 1))
224  {
225  WritePVtu(vm);
226  cout << "Written file: " << filename << endl;
227  }
228 }
229 
230 void OutputVtk::OutputFromExp(po::variables_map &vm)
231 {
232  int i,j;
233  // Extract the output filename and extension
234  string filename = PrepareOutput(vm);
235 
236  // Write solution.
237  ofstream outfile(filename.c_str());
238  WriteVtkHeader(outfile);
239  int nfields = m_f->m_variables.size();
240 
241  int nstrips;
242  m_f->m_session->LoadParameter("Strip_Z", nstrips, 1);
243 
244  // Homogeneous strip variant
245  for (int s = 0; s < nstrips; ++s)
246  {
247  // For each field write out field data for each expansion.
248  for (i = 0; i < m_f->m_exp[0]->GetNumElmts(); ++i)
249  {
250  m_f->m_exp[0]->WriteVtkPieceHeader(outfile, i, s);
251 
252  // For this expansion write out each field.
253  for (j = 0; j < nfields; ++j)
254  {
255  m_f->m_exp[s * nfields + j]->WriteVtkPieceData(
256  outfile, i, m_f->m_variables[j]);
257  }
258  m_f->m_exp[0]->WriteVtkPieceFooter(outfile, i);
259  }
260  }
261 
262  if (m_f->m_exp[0]->GetNumElmts() == 0)
263  {
264  WriteEmptyVtkPiece(outfile);
265  }
266 
267  WriteVtkFooter(outfile);
268  cout << "Written file: " << filename << endl;
269 
270  // output parallel outline info if necessary
271  if ( (m_f->m_comm->GetRank() == 0) &&
272  (m_f->m_comm->GetSize() != 1))
273  {
274  WritePVtu(vm);
275  }
276 }
277 
278 void OutputVtk::OutputFromData(po::variables_map &vm)
279 {
280  boost::ignore_unused(vm);
281  NEKERROR(ErrorUtil::efatal, "OutputVtk can't write using only FieldData.");
282 }
283 
284 fs::path OutputVtk::GetPath(std::string &filename,
285  po::variables_map &vm)
286 {
287  boost::ignore_unused(vm);
288 
289  int nprocs = m_f->m_comm->GetSize();
290  fs::path specPath;
291  if (nprocs == 1)
292  {
293  specPath = fs::path(filename);
294  }
295  else
296  {
297  // replace .vtu by _vtu
298  int dot = filename.find_last_of('.');
299  string path = filename.substr(0, dot) + "_vtu";
300  specPath = fs::path(path);
301  }
302  return fs::path(specPath);
303 }
304 
305 fs::path OutputVtk::GetFullOutName(std::string &filename,
306  po::variables_map &vm)
307 {
308  int nprocs = m_f->m_comm->GetSize();
309 
310  fs::path fulloutname;
311  if (nprocs == 1)
312  {
313  fulloutname = filename;
314  }
315  else
316  {
317  // Guess at filename that might belong to this process.
318  boost::format pad("P%1$07d.%2$s");
319  pad % m_f->m_comm->GetRank() % "vtu";
320 
321  // Generate full path name
322  fs::path specPath = GetPath(filename, vm);
323  fs::path poutfile(pad.str());
324  fulloutname = specPath / poutfile;
325  }
326  return fulloutname;
327 }
328 
329 void OutputVtk::WriteVtkHeader(std::ostream &outfile)
330 {
331  outfile << "<?xml version=\"1.0\"?>" << endl;
332  outfile << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" "
333  << "byte_order=\"LittleEndian\">" << endl;
334  outfile << " <UnstructuredGrid>" << endl;
335 }
336 
337 void OutputVtk::WriteVtkFooter(std::ostream &outfile)
338 {
339  outfile << " </UnstructuredGrid>" << endl;
340  outfile << "</VTKFile>" << endl;
341 }
342 
343 void OutputVtk::WriteEmptyVtkPiece(std::ofstream &outfile)
344 {
345  // write out empty piece of data.
346  outfile << " <Piece NumberOfPoints=\"" << 0 << "\" NumberOfCells=\"" << 0
347  << "\">" << endl;
348  outfile << " <Points>" << endl;
349  outfile << " <DataArray type=\"Float64\" "
350  << "NumberOfComponents=\"" << 3 << "\" format=\"ascii\">" << endl;
351  outfile << " </DataArray>" << endl;
352  outfile << " </Points>" << endl;
353  outfile << " <Cells>" << endl;
354  outfile << " <DataArray type=\"Int32\" "
355  << "Name=\"connectivity\" format=\"ascii\">" << endl;
356  outfile << " </DataArray>" << endl;
357  outfile << " <DataArray type=\"Int32\" "
358  << "Name=\"offsets\" format=\"ascii\">" << endl;
359 
360  outfile << " ";
361  outfile << endl;
362  outfile << " </DataArray>" << endl;
363  outfile << " <DataArray type=\"UInt8\" "
364  << "Name=\"types\" format=\"ascii\">" << endl;
365  outfile << " ";
366  outfile << endl;
367  outfile << " </DataArray>" << endl;
368  outfile << " </Cells>" << endl;
369  outfile << " <PointData>" << endl;
370 
371  outfile << " </PointData>" << endl;
372  outfile << " </Piece>" << endl;
373 }
374 
375 void OutputVtk::WritePVtu(po::variables_map &vm)
376 {
377  string filename = m_config["outfile"].as<string>();
378  int dot = filename.find_last_of('.');
379  string body = filename.substr(0, dot);
380  filename = body + ".pvtu";
381 
382  ofstream outfile(filename.c_str());
383 
384  int nprocs = m_f->m_comm->GetSize();
385  string path = LibUtilities::PortablePath(GetPath(filename,vm));
386 
387  outfile << "<?xml version=\"1.0\"?>" << endl;
388  outfile << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" "
389  << "byte_order=\"LittleEndian\">" << endl;
390  outfile << "<PUnstructuredGrid GhostLevel=\"0\">" << endl;
391  outfile << "<PPoints> " << endl;
392  outfile << "<PDataArray type=\"Float64\" NumberOfComponents=\"" << 3
393  << "\"/> " << endl;
394  outfile << "</PPoints>" << endl;
395  outfile << "<PCells>" << endl;
396  outfile << "<PDataArray type=\"Int32\" Name=\"connectivity\" "
397  "NumberOfComponents=\"1\"/>"
398  << endl;
399  outfile << "<PDataArray type=\"Int32\" Name=\"offsets\" "
400  "NumberOfComponents=\"1\"/>"
401  << endl;
402  outfile << "<PDataArray type=\"UInt8\" Name=\"types\" "
403  "NumberOfComponents=\"1\"/>"
404  << endl;
405  outfile << "</PCells>" << endl;
406  outfile << "<PPointData Scalars=\"Material\">" << endl;
407  for (int i = 0; i < m_f->m_variables.size(); ++i)
408  {
409  outfile << "<PDataArray type=\"Float64\" Name=\""
410  << m_f->m_variables[i] << "\"/>" << endl;
411  }
412  outfile << "</PPointData>" << endl;
413 
414  for (int i = 0; i < nprocs; ++i)
415  {
416  boost::format pad("P%1$07d.vtu");
417  pad % i;
418  outfile << "<Piece Source=\"" << path << "/" << pad.str()
419  << "\"/>" << endl;
420  }
421  outfile << "</PUnstructuredGrid>" << endl;
422  outfile << "</VTKFile>" << endl;
423 
424  cout << "Written file: " << filename << endl;
425 }
426 
427 std::string OutputVtk::PrepareOutput(po::variables_map &vm)
428 {
429  // Extract the output filename and extension
430  string filename = m_config["outfile"].as<string>();
431 
432  fs::path specPath = GetPath(filename,vm);
433  fs::path fulloutname = GetFullOutName(filename,vm);
434  filename = LibUtilities::PortablePath(fulloutname);
435 
436  if (m_f->m_comm->GetSize() != 1)
437  {
438  if (m_f->m_comm->TreatAsRankZero())
439  {
440  try
441  {
442  fs::create_directory(specPath);
443  }
444  catch (fs::filesystem_error &e)
445  {
446  ASSERTL0(false, "Filesystem error: " + string(e.what()));
447  }
448  cout << "Writing files to directory: " << specPath << endl;
449  }
450  m_f->m_comm->Block();
451  }
452  else
453  {
454  cout << "Writing: " << specPath << endl;
455  }
456  return filename;
457 }
458 
459 }
460 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
virtual void OutputFromPts(po::variables_map &vm)
Write from pts to output file.
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
std::map< std::string, ConfigOption > m_config
List of configuration values.
virtual fs::path GetFullOutName(std::string &filename, po::variables_map &vm)
Converter from fld to vtk.
virtual void OutputFromExp(po::variables_map &vm)
Write from m_exp to output file.
STL namespace.
std::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:762
std::shared_ptr< PtsField > PtsFieldSharedPtr
Definition: PtsField.h:179
std::pair< ModuleType, std::string > ModuleKey
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:41
virtual fs::path GetPath(std::string &filename, po::variables_map &vm)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
virtual void OutputFromData(po::variables_map &vm)
Write from data to output file.
ModuleFactory & GetModuleFactory()
FieldSharedPtr m_f
Field object.