Nektar++
OutputTecplot.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////
2 //
3 // File: OutputTecplot.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: Dat file format output.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include <iomanip>
36 #include <set>
37 #include <string>
38 using namespace std;
39 
40 #include <boost/core/ignore_unused.hpp>
41 
44 
45 #include "OutputTecplot.h"
46 
47 namespace Nektar
48 {
49 namespace FieldUtils
50 {
51 
52 std::string TecplotZoneTypeMap[] = {
53  "ORDERED",
54  "LINESEG",
55  "TRIANGLE",
56  "QUADRILATERAL",
57  "TETRAHEDRON",
58  "BRICK",
59  "POLYGON",
60  "POLYHEDRON"
61 };
62 
63 ModuleKey OutputTecplot::m_className =
65  ModuleKey(eOutputModule, "dat"),
66  OutputTecplot::create,
67  "Writes a Tecplot file.");
68 ModuleKey OutputTecplotBinary::m_className =
70  ModuleKey(eOutputModule, "plt"),
71  OutputTecplotBinary::create,
72  "Writes a Tecplot file in binary plt format.");
73 
74 OutputTecplot::OutputTecplot(FieldSharedPtr f) : OutputFileBase(f),
75  m_binary(false),
76  m_oneOutputFile(false)
77 {
78  m_requireEquiSpaced = true;
79  m_config["double"] =
80  ConfigOption(true, "0", "Write double-precision format data:"
81  "more accurate but more disk space"
82  " required");
83 }
84 
86 {
87 }
88 
89 void OutputTecplot::Process(po::variables_map &vm)
90 {
91 
92  if(m_config["writemultiplefiles"].as<bool>())
93  {
94  m_oneOutputFile = false;
95  }
96  else
97  {
98  m_oneOutputFile = (m_f->m_comm->GetSize()> 1);
99  }
100 
102 }
103 
104 /**
105  * @brief Helper function to write binary data to stream.
106  */
107 template<typename T> void WriteStream(std::ostream &outfile, T data)
108 {
109  T tmp = data;
110  outfile.write(reinterpret_cast<char *>(&tmp), sizeof(T));
111 }
112 
113 /**
114  * @brief Specialisation of WriteStream to support writing std::string.
115  *
116  * Tecplot binary formats represent all strings by writing out their characters
117  * as 32-bit integers, followed by a 32-bit integer null (0) character to denote
118  * the end of the string.
119  */
120 template<> void WriteStream(std::ostream &outfile, std::string data)
121 {
122  // Convert string to array of int32_t
123  for (std::string::size_type i = 0; i < data.size(); ++i)
124  {
125  char strChar = data[i];
126  NekInt32 strCharInt = strChar;
127  WriteStream(outfile, strCharInt);
128  }
129 
130  // Now dump out zero character to terminate
131  WriteStream(outfile, 0);
132 }
133 
134 /**
135  * @brief Specialisation of WriteStream to support writing Nektar::Array
136  * datatype.
137  */
138 template<typename T> void WriteStream(std::ostream &outfile,
139  Array<OneD, T> data)
140 {
141  outfile.write(reinterpret_cast<char *>(&data[0]),
142  data.num_elements() * sizeof(T));
143 }
144 
145 /**
146  * @brief Specialisation of WriteStream to support writing std::vector datatype.
147  */
148 template<typename T> void WriteStream(std::ostream &outfile,
149  std::vector<T> data)
150 {
151  outfile.write(reinterpret_cast<char *>(&data[0]),
152  data.size() * sizeof(T));
153 }
154 
155 void OutputTecplot::OutputFromPts(po::variables_map &vm)
156 {
157  LibUtilities::PtsFieldSharedPtr fPts = m_f->m_fieldPts;
158 
159  // do not output if zone is empty
160  if (fPts->GetNpoints() == 0)
161  {
162  return;
163  }
164 
165  int rank = m_f->m_comm->GetRank();
166  m_numBlocks = 0;
167 
168  m_coordim = fPts->GetDim();
169 
170  // Grab connectivity information.
171  fPts->GetConnectivity(m_conn);
172 
173  switch (fPts->GetPtsType())
174  {
176  m_numPoints.resize(1);
177  m_numPoints[0] = fPts->GetNpoints();
178  m_f->m_comm->AllReduce(m_numPoints[0], LibUtilities::ReduceSum);
180  break;
182  m_numPoints.resize(1);
183  m_numPoints[0] = fPts->GetPointsPerEdge(0);
185  break;
187  m_numPoints.resize(2);
188  m_numPoints[0] = fPts->GetPointsPerEdge(0);
189  m_numPoints[1] = fPts->GetPointsPerEdge(1);
191  break;
193  m_numPoints.resize(3);
194  m_numPoints[0] = fPts->GetPointsPerEdge(0);
195  m_numPoints[1] = fPts->GetPointsPerEdge(1);
196  m_numPoints[2] = fPts->GetPointsPerEdge(2);
198  break;
200  {
202  for (int i = 0; i < m_conn.size(); ++i)
203  {
204  m_numBlocks += m_conn[i].num_elements() / 3;
205  }
206  break;
207  }
209  {
211  for (int i = 0; i < m_conn.size(); ++i)
212  {
213  m_numBlocks += m_conn[i].num_elements() / 4;
214  }
215  break;
216  }
217  default:
218  ASSERTL0(false, "This points type is not supported yet.");
219  }
220 
221  // Get fields and coordinates
222  m_fields =
223  Array<OneD, Array<OneD, NekDouble> >(m_f->m_variables.size()+m_coordim);
224 
225  // We can just grab everything from points. This should be a
226  // reference, not a copy.
227  fPts->GetPts(m_fields);
228 
229  // Only write header if we're root or FE block; binary files always
230  // write header
231  m_writeHeader =
232  (m_zoneType != eOrdered || rank == 0) || m_binary;
233 
234  WriteTecplotFile(vm);
235 }
236 
237 void OutputTecplot::OutputFromExp(po::variables_map &vm)
238 {
239  m_numBlocks = 0;
240  m_writeHeader = true;
241 
242  // Calculate number of FE blocks
244 
245  // Calculate coordinate dimension
246  int nBases = m_f->m_exp[0]->GetExp(0)->GetNumBases();
247 
248  m_coordim = m_f->m_exp[0]->GetExp(0)->GetCoordim();
249  int totpoints = m_f->m_exp[0]->GetTotPoints();
250 
251  if (m_f->m_numHomogeneousDir > 0)
252  {
253  int nPlanes = m_f->m_exp[0]->GetZIDs().num_elements();
254  if (nPlanes == 1) // halfMode case
255  {
256  // do nothing
257  }
258  else
259  {
260  // If Fourier points, output extra plane to fill domain
261  if (m_f->m_exp[0]->GetExpType() == MultiRegions::e3DH1D)
262  {
263  nPlanes += 1;
264  totpoints += m_f->m_exp[0]->GetPlane(0)->GetTotPoints();
265  }
266  nBases += m_f->m_numHomogeneousDir;
267  m_coordim += m_f->m_numHomogeneousDir;
268  NekDouble tmp = m_numBlocks * (nPlanes - 1);
269  m_numBlocks = (int)tmp;
270  }
271  }
272 
273  m_zoneType = (TecplotZoneType)(2*(nBases-1) + 1);
274 
275  // Calculate connectivity
277 
278  // Set up storage for output fields
279  m_fields =
280  Array<OneD, Array<OneD, NekDouble> >(m_f->m_variables.size()+m_coordim);
281 
282  // Get coordinates
283  for (int i = 0; i < m_coordim; ++i)
284  {
285  m_fields[i] = Array<OneD, NekDouble>(totpoints);
286  }
287 
288  if (m_coordim == 1)
289  {
290  m_f->m_exp[0]->GetCoords(m_fields[0]);
291  }
292  else if (m_coordim == 2)
293  {
294  m_f->m_exp[0]->GetCoords(m_fields[0], m_fields[1]);
295  }
296  else
297  {
298  m_f->m_exp[0]->GetCoords(m_fields[0], m_fields[1], m_fields[2]);
299  }
300 
301  if (m_f->m_exp[0]->GetExpType() == MultiRegions::e3DH1D)
302  {
303  // Copy values
304  for (int i = 0; i < m_f->m_variables.size(); ++i)
305  {
306  m_fields[i + m_coordim] = Array<OneD, NekDouble>(totpoints);
307  Vmath::Vcopy( m_f->m_exp[0]->GetTotPoints(),
308  m_f->m_exp[i]->UpdatePhys(), 1,
309  m_fields[i + m_coordim], 1);
310  }
311  }
312  else
313  {
314  // Add references to m_fields
315  for (int i = 0; i < m_f->m_variables.size(); ++i)
316  {
317  m_fields[i + m_coordim] = m_f->m_exp[i]->UpdatePhys();
318  }
319  }
320 
321  // If Fourier, fill extra plane with data
322  if (m_f->m_exp[0]->GetExpType() == MultiRegions::e3DH1D)
323  {
324  int points_on_plane = m_f->m_exp[0]->GetPlane(0)->GetTotPoints();
325  const int offset = totpoints-points_on_plane;
326  NekDouble z = m_fields[m_coordim-1][totpoints-2*points_on_plane] +
327  (m_fields[m_coordim-1][points_on_plane] - m_fields[m_coordim-1][0]);
328  // x and y
329  Array<OneD, NekDouble> tmp = m_fields[0] + offset;
330  Vmath::Vcopy(points_on_plane, m_fields[0], 1, tmp, 1 );
331  tmp = m_fields[1] + offset;
332  Vmath::Vcopy(points_on_plane, m_fields[1], 1, tmp, 1 );
333  // z coordinate
334  tmp = m_fields[2] + offset;
335  Vmath::Vcopy(points_on_plane, m_fields[2], 1, tmp, 1 );
336  Vmath::Sadd(points_on_plane, z, m_fields[2], 1, tmp, 1 );
337 
338  //variables
339  for (int i = 0; i < m_f->m_variables.size(); ++i)
340  {
341  tmp = m_fields[i + m_coordim] + offset;
342  Vmath::Vcopy(points_on_plane, m_fields[i + m_coordim], 1, tmp, 1 );
343  }
344  }
345 
346  WriteTecplotFile(vm);
347 }
348 
349 void OutputTecplot::OutputFromData(po::variables_map &vm)
350 {
351  boost::ignore_unused(vm);
352 
354  "OutputTecplot can't write using only FieldData.");
355 }
356 
357 fs::path OutputTecplot::GetPath(std::string &filename,
358  po::variables_map &vm)
359 {
360  boost::ignore_unused(vm);
361 
362  int nprocs = m_f->m_comm->GetSize();
363  string returnstr(filename);
364 
365  // Amend for parallel output if required
366  if (nprocs != 1 && !m_oneOutputFile)
367  {
368  int rank = m_f->m_comm->GetRank();
369  int dot = filename.find_last_of('.');
370  string ext = filename.substr(dot, filename.length() - dot);
371  string procId = "_P" + boost::lexical_cast<std::string>(rank);
372  string start = filename.substr(0, dot);
373  returnstr = start + procId + ext;
374  }
375  return fs::path(returnstr);
376 }
377 
378 fs::path OutputTecplot::GetFullOutName(std::string &filename,
379  po::variables_map &vm)
380 {
381  return GetPath(filename, vm);
382 }
383 
384 void OutputTecplot::WriteTecplotFile(po::variables_map &vm)
385 {
386  // Variable names
387  std::string coordVars[] = { "x", "y", "z" };
388  vector<string> variables = m_f->m_variables;
389  variables.insert(variables.begin(), coordVars, coordVars + m_coordim);
390 
391  int nprocs = m_f->m_comm->GetSize();
392  int rank = m_f->m_comm->GetRank();
393 
394 
395  // Extract the output filename and extension
396  string filename = m_config["outfile"].as<string>();
397  string outFile = LibUtilities::PortablePath(GetFullOutName(filename, vm));
398  // Open output file
399  ofstream outfile;
400  if ((m_oneOutputFile && rank == 0) || !m_oneOutputFile)
401  {
402  outfile.open(outFile.c_str(), m_binary ? ios::binary : ios::out);
403  }
404 
405  if (m_oneOutputFile)
406  {
407  // Reduce on number of blocks and number of points.
408  m_f->m_comm->AllReduce(m_numBlocks, LibUtilities::ReduceSum);
409 
410  // Root process needs to know how much data everyone else has for
411  // writing in parallel.
412  m_rankFieldSizes = Array<OneD, int>(nprocs, 0);
413  m_rankConnSizes = Array<OneD, int>(nprocs, 0);
414  m_rankFieldSizes[rank] = m_fields[0].num_elements();
415 
416  m_totConn = 0;
417  for (int i = 0; i < m_conn.size(); ++i)
418  {
419  m_totConn += m_conn[i].num_elements();
420  }
421 
422  m_rankConnSizes[rank] = m_totConn;
423 
424  m_f->m_comm->AllReduce(m_rankFieldSizes, LibUtilities::ReduceSum);
425  m_f->m_comm->AllReduce(m_rankConnSizes, LibUtilities::ReduceSum);
426  }
427 
428  if (m_writeHeader)
429  {
430  WriteTecplotHeader(outfile, variables);
431  }
432 
433  // Write zone data.
434  WriteTecplotZone(outfile);
435 
436  // If we're a FE block format, write connectivity (m_conn will be empty for
437  // point data).
438  WriteTecplotConnectivity(outfile);
439 
440  if ((m_oneOutputFile && rank == 0) || !m_oneOutputFile)
441  {
442  cout << "Written file: " << GetFullOutName(filename,vm) << endl;
443  }
444 }
445 
446 /**
447  * @brief Write Tecplot files header
448  *
449  * @param outfile Output file name
450  * @param var Variables names
451  */
452 void OutputTecplot::WriteTecplotHeader(std::ofstream &outfile,
453  std::vector<std::string> &var)
454 {
455  outfile << "Variables = " << var[0];
456 
457  for (int i = 1; i < var.size(); ++i)
458  {
459  outfile << ", " << var[i];
460  }
461 
462  outfile << std::endl << std::endl;
463 }
464 
465 /**
466  * @brief Write Tecplot files header in binary format
467  *
468  * @param outfile Output file name
469  * @param var Variables names
470  */
471 void OutputTecplotBinary::WriteTecplotHeader(std::ofstream &outfile,
472  std::vector<std::string> &var)
473 {
474  if (m_oneOutputFile && m_f->m_comm->GetRank() > 0)
475  {
476  return;
477  }
478 
479  // Version number
480  outfile << "#!TDV112";
481 
482  // Int value of 1 for endian check
483  WriteStream(outfile, 1);
484 
485  // We'll probably write a full solution field
486  WriteStream(outfile, 0);
487 
488  // Title
489  std::string title = "";
490  WriteStream(outfile, title);
491 
492  // Number of variables
493  WriteStream(outfile, (int)var.size());
494 
495  for (int i = 0; i < var.size(); ++i)
496  {
497  WriteStream(outfile, var[i]);
498  }
499 }
500 
501 
502 /**
503  * Write Tecplot zone output in ASCII
504  *
505  * @param outfile Output file name.
506  * @param expansion Expansion that is considered
507  */
508 void OutputTecplot::WriteTecplotZone(std::ofstream &outfile)
509 {
510  bool useDoubles = m_config["double"].as<bool>();
511 
512  if (useDoubles)
513  {
514  int precision = std::numeric_limits<double>::max_digits10;
515  outfile << std::setprecision(precision);
516 
517  }
518 
519  // Write either points or finite element block
520  if (m_zoneType != eOrdered)
521  {
522  if ((m_oneOutputFile && m_f->m_comm->GetRank() == 0) || !m_oneOutputFile)
523  {
524  // Number of points in zone
525  int nPoints = m_oneOutputFile ?
526  Vmath::Vsum(m_f->m_comm->GetSize(), m_rankFieldSizes, 1) :
527  m_fields[0].num_elements();
528 
529  outfile << "Zone, N=" << nPoints << ", E="
530  << m_numBlocks << ", F=FEBlock, ET="
531  << TecplotZoneTypeMap[m_zoneType] << std::endl;
532  }
533 
534 
535  if (m_oneOutputFile && m_f->m_comm->GetRank() == 0)
536  {
537  for (int j = 0; j < m_fields.num_elements(); ++j)
538  {
539  for (int i = 0; i < m_fields[j].num_elements(); ++i)
540  {
541  if ((!(i % 1000)) && i)
542  {
543  outfile << std::endl;
544  }
545  outfile << m_fields[j][i] << " ";
546  }
547 
548  for (int n = 1; n < m_f->m_comm->GetSize(); ++n)
549  {
550  if(m_rankFieldSizes[n])
551  {
553  m_f->m_comm->Recv(n, tmp);
554 
555  for (int i = 0; i < m_rankFieldSizes[n]; ++i)
556  {
557  if ((!(i % 1000)) && i)
558  {
559  outfile << std::endl;
560  }
561  outfile << tmp[i] << " ";
562  }
563  }
564  }
565  outfile << std::endl;
566  }
567  }
568  else if (m_oneOutputFile && m_f->m_comm->GetRank() > 0)
569  {
570  if(m_fields[0].num_elements())
571  {
572  for (int i = 0; i < m_fields.num_elements(); ++i)
573  {
574  m_f->m_comm->Send(0, m_fields[i]);
575  }
576  }
577  }
578  else
579  {
580  // Write out coordinates and field data: ordered by field
581  // and then its data.
582  for (int j = 0; j < m_fields.num_elements(); ++j)
583  {
584  for (int i = 0; i < m_fields[j].num_elements(); ++i)
585  {
586  if ((!(i % 1000)) && i)
587  {
588  outfile << std::endl;
589  }
590  outfile << m_fields[j][i] << " ";
591  }
592  outfile << std::endl;
593  }
594  }
595  }
596  else
597  {
598  if((m_oneOutputFile && m_f->m_comm->GetRank() == 0) || !m_oneOutputFile)
599  {
600  std::string dirs[] = { "I", "J", "K" };
601  outfile << "Zone";
602  for (int i = 0; i < m_numPoints.size(); ++i)
603  {
604  outfile << ", " << dirs[i] << "=" << m_numPoints[i];
605  }
606  outfile << ", F=POINT" << std::endl;
607  }
608 
609  if (m_oneOutputFile && m_f->m_comm->GetRank() == 0)
610  {
611  Array<OneD, NekDouble> tmp(m_fields.num_elements());
612  for (int i = 0; i < m_fields[0].num_elements(); ++i)
613  {
614  for (int j = 0; j < m_fields.num_elements(); ++j)
615  {
616  outfile << setw(12) << m_fields[j][i] << " ";
617  }
618  outfile << std::endl;
619  }
620 
621  for (int n = 1; n < m_f->m_comm->GetSize(); ++n)
622  {
623  for (int i = 0; i < m_rankFieldSizes[n]; ++i)
624  {
625  m_f->m_comm->Recv(n, tmp);
626  for (int j = 0; j < m_fields.num_elements(); ++j)
627  {
628  outfile << setw(12) << tmp[j] << " ";
629  }
630  outfile << std::endl;
631  }
632  }
633  }
634  else if (m_oneOutputFile && m_f->m_comm->GetRank() > 0)
635  {
636  Array<OneD, NekDouble> tmp(m_fields.num_elements());
637  for (int i = 0; i < m_fields[0].num_elements(); ++i)
638  {
639  for (int j = 0; j < m_fields.num_elements(); ++j)
640  {
641  tmp[j] = m_fields[j][i];
642  }
643  m_f->m_comm->Send(0, tmp);
644  }
645  }
646  else
647  {
648  // Write out coordinates and field data: ordered by each
649  // point then each field.
650  for (int i = 0; i < m_fields[0].num_elements(); ++i)
651  {
652  for (int j = 0; j < m_fields.num_elements(); ++j)
653  {
654  outfile << setw(12) << m_fields[j][i] << " ";
655  }
656  outfile << std::endl;
657  }
658  }
659  }
660 }
661 
662 /**
663  * @brief Write either double-precision or single-precision output of field
664  * data.
665  *
666  * @param outfile Output file name.
667  * @param expansion Expansion that is considered
668  */
669 void OutputTecplotBinary::WriteDoubleOrFloat(std::ofstream &outfile,
671 {
672  // Data format: either double or single depending on user options
673  bool useDoubles = m_config["double"].as<bool>();
674 
675  if (useDoubles)
676  {
677  // For doubles, we can just write data.
678  WriteStream(outfile, data);
679  }
680  else
681  {
682  // For single precision, needs typecast first.
683  int nPts = data.num_elements();
684  vector<float> tmp(data.num_elements());
685  std::copy(&data[0], &data[0] + nPts, &tmp[0]);
686  WriteStream(outfile, tmp);
687  }
688 }
689 
690 /**
691  * Write Tecplot zone output in binary
692  *
693  * @param outfile Output file name.
694  * @param expansion Expansion that is considered
695  */
696 void OutputTecplotBinary::WriteTecplotZone(std::ofstream &outfile)
697 {
698  Array<OneD, NekDouble> fieldMin(m_fields.num_elements());
699  Array<OneD, NekDouble> fieldMax(m_fields.num_elements());
700 
701  // Data format: either double or single depending on user options
702  bool useDoubles = m_config["double"].as<bool>();
703 
704  if ((m_oneOutputFile && m_f->m_comm->GetRank() == 0) || !m_oneOutputFile)
705  {
706  // Don't bother naming zone
707  WriteStream(outfile, 299.0f); // Zone marker
708 
709  // Write same name as preplot
710  int rank = m_f->m_comm->GetRank();
711  string zonename = "ZONE " + boost::lexical_cast<string>(rank);
712  WriteStream(outfile, zonename);
713 
714  WriteStream(outfile, -1); // No parent zone
715  WriteStream(outfile, -1); // No strand ID
716  WriteStream(outfile, 0.0); // Solution time
717  WriteStream(outfile, -1); // Unused, set to -1
718 
719  // Zone type: 1 = lineseg, 3 = quad, 5 = brick
720  WriteStream(outfile, (int)m_zoneType);
721 
722  WriteStream(outfile, 0); // Data at nodes
723  WriteStream(outfile, 0); // No 1-1 face neighbours
724  WriteStream(outfile, 0); // No user-defined connections
725 
726  if (m_zoneType == eOrdered)
727  {
728  for (int i = 0; i < m_numPoints.size(); ++i)
729  {
730  WriteStream(outfile, m_numPoints[i]);
731  }
732 
733  for (int i = m_numPoints.size(); i < 3; ++i)
734  {
735  WriteStream(outfile, 0);
736  }
737  }
738  else
739  {
740  // Number of points in zone
741  int nPoints = m_oneOutputFile ?
742  Vmath::Vsum(m_f->m_comm->GetSize(), m_rankFieldSizes, 1) :
743  m_fields[0].num_elements();
744 
745  WriteStream(outfile, nPoints); // Total number of points
746  WriteStream(outfile, m_numBlocks); // Number of blocks
747  WriteStream(outfile, 0); // Unused
748  WriteStream(outfile, 0); // Unused
749  WriteStream(outfile, 0); // Unused
750  }
751 
752  WriteStream(outfile, 0); // No auxiliary data names
753 
754  // Finalise header
755  WriteStream(outfile, 357.0f);
756 
757  // Now start to write data section so that we can dump geometry
758  // information
759 
760  // Data marker
761  WriteStream(outfile, 299.0f);
762 
763  for (int j = 0; j < m_fields.num_elements(); ++j)
764  {
765  WriteStream(outfile, useDoubles ? 2 : 1);
766  }
767 
768  // No passive variables or variable sharing, no zone connectivity
769  // sharing (we only dump one zone)
770  WriteStream(outfile, 0);
771  WriteStream(outfile, 0);
772  WriteStream(outfile, -1);
773  }
774 
775  for (int i = 0; i < m_fields.num_elements(); ++i)
776  {
777  fieldMin[i] = Vmath::Vmin(m_fields[i].num_elements(), m_fields[i], 1);
778  fieldMax[i] = Vmath::Vmax(m_fields[i].num_elements(), m_fields[i], 1);
779  }
780 
781  m_f->m_comm->AllReduce(fieldMin, LibUtilities::ReduceMin);
782  m_f->m_comm->AllReduce(fieldMax, LibUtilities::ReduceMax);
783 
784  // Write out min/max of field data
785  if ((m_oneOutputFile && m_f->m_comm->GetRank() == 0) || !m_oneOutputFile)
786  {
787  for (int i = 0; i < m_fields.num_elements(); ++i)
788  {
789  WriteStream(outfile, fieldMin[i]);
790  WriteStream(outfile, fieldMax[i]);
791  }
792  }
793 
794  if (m_oneOutputFile && m_f->m_comm->GetRank() == 0)
795  {
796  for (int i = 0; i < m_fields.num_elements(); ++i)
797  {
798  WriteDoubleOrFloat(outfile, m_fields[i]);
799 
800  for (int n = 1; n < m_f->m_comm->GetSize(); ++n)
801  {
803  m_f->m_comm->Recv(n, tmp);
804  WriteDoubleOrFloat(outfile, tmp);
805  }
806  }
807  }
808  else if (m_oneOutputFile && m_f->m_comm->GetRank() > 0)
809  {
810  for (int i = 0; i < m_fields.num_elements(); ++i)
811  {
812  m_f->m_comm->Send(0, m_fields[i]);
813  }
814  }
815  else
816  {
817  for (int i = 0; i < m_fields.num_elements(); ++i)
818  {
819  WriteDoubleOrFloat(outfile, m_fields[i]);
820  }
821  }
822 }
823 
824 /**
825  * @brief Write Tecplot connectivity information (ASCII)
826  *
827  * @param outfile Output file
828  */
829 void OutputTecplot::WriteTecplotConnectivity(std::ofstream &outfile)
830 {
831  // Ordered data have no connectivity information.
832  if (m_zoneType == eOrdered)
833  {
834  return;
835  }
836 
837  if (m_oneOutputFile && m_f->m_comm->GetRank() > 0)
838  {
839  // Need to amalgamate connectivity information
840  if (m_totConn)
841  {
843  for (int i = 0, cnt = 0; i < m_conn.size(); ++i)
844  {
845  if(m_conn[i].num_elements())
846  {
847  Vmath::Vcopy(m_conn[i].num_elements(), &m_conn[i][0], 1,
848  &conn[cnt], 1);
849  cnt += m_conn[i].num_elements();
850  }
851  }
852  m_f->m_comm->Send(0, conn);
853  }
854  }
855  else
856  {
857  int cnt = 1;
858  for (int i = 0; i < m_conn.size(); ++i)
859  {
860  const int nConn = m_conn[i].num_elements();
861  for (int j = 0; j < nConn; ++j,++cnt)
862  {
863  outfile << m_conn[i][j] + 1 << " ";
864  if (!(cnt % 1000))
865  {
866  outfile << std::endl;
867  }
868  }
869  }
870  outfile << endl;
871 
872  if (m_oneOutputFile && m_f->m_comm->GetRank() == 0)
873  {
874  int offset = m_rankFieldSizes[0];
875 
876  for (int n = 1; n < m_f->m_comm->GetSize(); ++n)
877  {
878  if(m_rankConnSizes[n])
879  {
881  m_f->m_comm->Recv(n, conn);
882  for (int j = 0; j < conn.num_elements(); ++j)
883  {
884  outfile << conn[j] + offset + 1 << " ";
885  if ((!(j % 1000)) && j)
886  {
887  outfile << std::endl;
888  }
889  }
890  }
891  offset += m_rankFieldSizes[n];
892  }
893  }
894  }
895 }
896 
898 {
899  if (m_oneOutputFile && m_f->m_comm->GetRank() > 0)
900  {
901  // Need to amalgamate connectivity information
903  for (int i = 0, cnt = 0; i < m_conn.size(); ++i)
904  {
905  Vmath::Vcopy(m_conn[i].num_elements(), &m_conn[i][0], 1,
906  &conn[cnt], 1);
907  cnt += m_conn[i].num_elements();
908  }
909  m_f->m_comm->Send(0, conn);
910  }
911  else
912  {
913  for (int i = 0; i < m_conn.size(); ++i)
914  {
915  WriteStream(outfile, m_conn[i]);
916  }
917 
918  if (m_oneOutputFile && m_f->m_comm->GetRank() == 0)
919  {
920  int offset = m_rankFieldSizes[0];
921 
922  for (int n = 1; n < m_f->m_comm->GetSize(); ++n)
923  {
925  m_f->m_comm->Recv(n, conn);
926 
927  for (int j = 0; j < conn.num_elements(); ++j)
928  {
929  conn[j] += offset;
930  }
931 
932  WriteStream(outfile, conn);
933  offset += m_rankFieldSizes[n];
934  }
935  }
936  }
937 }
938 
939 /**
940  * @brief Calculate number of Tecplot blocks.
941  *
942  * @param outfile Output file
943  */
945 {
946  int returnval = 0;
947 
948  if (m_f->m_exp[0]->GetExp(0)->GetNumBases() == 1)
949  {
950  for (int i = 0; i < m_f->m_exp[0]->GetNumElmts(); ++i)
951  {
952  returnval += (m_f->m_exp[0]->GetExp(i)->GetNumPoints(0) - 1);
953  }
954  }
955  else if (m_f->m_exp[0]->GetExp(0)->GetNumBases() == 2)
956  {
957  for (int i = 0; i < m_f->m_exp[0]->GetNumElmts(); ++i)
958  {
959  returnval += (m_f->m_exp[0]->GetExp(i)->GetNumPoints(0) - 1) *
960  (m_f->m_exp[0]->GetExp(i)->GetNumPoints(1) - 1);
961  }
962  }
963  else
964  {
965  for (int i = 0; i < m_f->m_exp[0]->GetNumElmts(); ++i)
966  {
967  returnval += (m_f->m_exp[0]->GetExp(i)->GetNumPoints(0) - 1) *
968  (m_f->m_exp[0]->GetExp(i)->GetNumPoints(1) - 1) *
969  (m_f->m_exp[0]->GetExp(i)->GetNumPoints(2) - 1);
970  }
971  }
972 
973  return returnval;
974 }
975 
976 /**
977  * @brief Calculate connectivity information for each expansion dimension.
978  *
979  * @param outfile Output file
980  */
982 {
983  int i, j, k, l;
984  int nbase = m_f->m_exp[0]->GetExp(0)->GetNumBases();
985  int cnt = 0;
986 
987  m_conn.resize(m_f->m_exp[0]->GetNumElmts());
988 
989  for (i = 0; i < m_f->m_exp[0]->GetNumElmts(); ++i)
990  {
991  cnt = m_f->m_exp[0]->GetPhys_Offset(i);
992 
993  if (nbase == 1)
994  {
995  int cnt2 = 0;
996  int np0 = m_f->m_exp[0]->GetExp(i)->GetNumPoints(0);
997  int nPlanes = 1;
998 
999  if (m_f->m_exp[0]->GetExpType() == MultiRegions::e2DH1D)
1000  {
1001  nPlanes = m_f->m_exp[0]->GetZIDs().num_elements();
1002 
1003  if (nPlanes > 1)
1004  {
1005  int totPoints = m_f->m_exp[0]->GetPlane(0)->GetTotPoints();
1006 
1007  Array<OneD, int> conn(4 * (np0 - 1) * (nPlanes - 1));
1008  for (int n = 1; n < nPlanes; ++n)
1009  {
1010  for (k = 1; k < np0; ++k)
1011  {
1012  conn[cnt2++] = cnt + (n - 1) * totPoints + k;
1013  conn[cnt2++] = cnt + (n - 1) * totPoints + k - 1;
1014  conn[cnt2++] = cnt + n * totPoints + k - 1;
1015  conn[cnt2++] = cnt + n * totPoints + k;
1016  }
1017  }
1018  m_conn[i] = conn;
1019  }
1020  }
1021 
1022  if (nPlanes == 1)
1023  {
1024  Array<OneD, int> conn(2 * (np0 - 1));
1025 
1026  for (k = 1; k < np0; ++k)
1027  {
1028  conn[cnt2++] = cnt + k;
1029  conn[cnt2++] = cnt + k - 1;
1030  }
1031 
1032  m_conn[i] = conn;
1033  }
1034  }
1035  else if (nbase == 2)
1036  {
1037  int np0 = m_f->m_exp[0]->GetExp(i)->GetNumPoints(0);
1038  int np1 = m_f->m_exp[0]->GetExp(i)->GetNumPoints(1);
1039  int totPoints = m_f->m_exp[0]->GetTotPoints();
1040  int nPlanes = 1;
1041  int cnt2 = 0;
1042 
1043  if (m_f->m_exp[0]->GetExpType() == MultiRegions::e3DH1D)
1044  {
1045  nPlanes = m_f->m_exp[0]->GetZIDs().num_elements();
1046 
1047  // default to 2D case for HalfMode when nPlanes = 1
1048  if (nPlanes > 1)
1049  {
1050  // If Fourier points, output extra plane to fill domain
1051  nPlanes += 1;
1052  totPoints = m_f->m_exp[0]->GetPlane(0)->GetTotPoints();
1053 
1055  conn(8 * (np1 - 1) * (np0 - 1) * (nPlanes - 1));
1056 
1057  for (int n = 1; n < nPlanes; ++n)
1058  {
1059  for (j = 1; j < np1; ++j)
1060  {
1061  for (k = 1; k < np0; ++k)
1062  {
1063  conn[cnt2++] = cnt + (n - 1) * totPoints +
1064  (j - 1) * np0 + k - 1;
1065  conn[cnt2++] = cnt + (n - 1) * totPoints +
1066  (j - 1) * np0 + k;
1067  conn[cnt2++] = cnt + (n - 1) * totPoints +
1068  j * np0 + k;
1069  conn[cnt2++] = cnt + (n - 1) * totPoints +
1070  j * np0 + k - 1;
1071  conn[cnt2++] = cnt + n * totPoints +
1072  (j - 1) * np0 + k - 1;
1073  conn[cnt2++] = cnt + n * totPoints +
1074  (j - 1) * np0 + k;
1075  conn[cnt2++] = cnt + n * totPoints +
1076  j * np0 + k;
1077  conn[cnt2++] = cnt + n * totPoints +
1078  j * np0 + k - 1;
1079  }
1080  }
1081  }
1082  m_conn[i] = conn;
1083  }
1084  }
1085 
1086  if (nPlanes == 1)
1087  {
1088  Array<OneD, int> conn(4 * (np0 - 1) * (np1 - 1));
1089  for (j = 1; j < np1; ++j)
1090  {
1091  for (k = 1; k < np0; ++k)
1092  {
1093  conn[cnt2++] = cnt + (j - 1) * np0 + k - 1;
1094  conn[cnt2++] = cnt + (j - 1) * np0 + k;
1095  conn[cnt2++] = cnt + j * np0 + k;
1096  conn[cnt2++] = cnt + j * np0 + k - 1;
1097  }
1098  }
1099  m_conn[i] = conn;
1100  }
1101  }
1102  else if (nbase == 3)
1103  {
1104  int np0 = m_f->m_exp[0]->GetExp(i)->GetNumPoints(0);
1105  int np1 = m_f->m_exp[0]->GetExp(i)->GetNumPoints(1);
1106  int np2 = m_f->m_exp[0]->GetExp(i)->GetNumPoints(2);
1107  int cnt2 = 0;
1108 
1109  Array<OneD, int> conn(8 * (np0 - 1) * (np1 - 1) * (np2 - 1));
1110 
1111  for (j = 1; j < np2; ++j)
1112  {
1113  for (k = 1; k < np1; ++k)
1114  {
1115  for (l = 1; l < np0; ++l)
1116  {
1117  conn[cnt2++] =
1118  cnt + (j - 1) * np0 * np1 + (k - 1) * np0 + l - 1;
1119  conn[cnt2++] =
1120  cnt + (j - 1) * np0 * np1 + (k - 1) * np0 + l;
1121  conn[cnt2++] =
1122  cnt + (j - 1) * np0 * np1 + k * np0 + l;
1123  conn[cnt2++] =
1124  cnt + (j - 1) * np0 * np1 + k * np0 + l - 1;
1125  conn[cnt2++] =
1126  cnt + j * np0 * np1 + (k - 1) * np0 + l - 1;
1127  conn[cnt2++] =
1128  cnt + j * np0 * np1 + (k - 1) * np0 + l;
1129  conn[cnt2++] =
1130  cnt + j * np0 * np1 + k * np0 + l;
1131  conn[cnt2++] =
1132  cnt + j * np0 * np1 + k * np0 + l - 1;
1133  }
1134  }
1135  }
1136 
1137  m_conn[i] = conn;
1138  }
1139  else
1140  {
1141  ASSERTL0(false, "Not set up for this dimension");
1142  }
1143 
1144  }
1145 }
1146 }
1147 }
virtual fs::path GetPath(std::string &filename, po::variables_map &vm)
#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 mod...
Definition: ErrorUtil.hpp:209
virtual fs::path GetFullOutName(std::string &filename, po::variables_map &vm)
std::map< std::string, ConfigOption > m_config
List of configuration values.
Represents a command-line configuration option.
TecplotZoneType m_zoneType
Tecplot zone type of output.
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:782
T Vmin(int n, const T *x, const int incx)
Return the minimum element in x - called vmin to avoid conflict with min.
Definition: Vmath.cpp:874
Array< OneD, int > m_rankConnSizes
Each rank&#39;s connectivity sizes.
Converter from fld to vtk.
virtual void WriteTecplotHeader(std::ofstream &outfile, std::vector< std::string > &var)
Write Tecplot files header in binary format.
STL namespace.
bool m_oneOutputFile
True if writing a single output file.
void WriteDoubleOrFloat(std::ofstream &outfile, Array< OneD, NekDouble > &data)
Write either double-precision or single-precision output of field data.
std::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:762
def copy(self)
Definition: pycml.py:2663
bool m_writeHeader
True if writing header.
virtual void WriteTecplotConnectivity(std::ofstream &outfile)
Write Tecplot connectivity information (ASCII)
std::shared_ptr< PtsField > PtsFieldSharedPtr
Definition: PtsField.h:179
std::pair< ModuleType, std::string > ModuleKey
void CalculateConnectivity()
Calculate connectivity information for each expansion dimension.
virtual void OutputFromData(po::variables_map &vm)
Write from data to output file.
virtual void WriteTecplotHeader(std::ofstream &outfile, std::vector< std::string > &var)
Write Tecplot files header.
Array< OneD, int > m_rankFieldSizes
Each rank&#39;s field sizes.
virtual void WriteTecplotZone(std::ofstream &outfile)
virtual void OutputFromExp(po::variables_map &vm)
Write from m_exp to output file.
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:41
double NekDouble
vector< Array< OneD, int > > m_conn
Connectivty for each block: one per element.
int m_numBlocks
Number of blocks in Tecplot file.
int m_totConn
Total number of connectivity entries.
std::int32_t NekInt32
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.cpp:318
void WriteTecplotFile(po::variables_map &vm)
std::string TecplotZoneTypeMap[]
virtual void OutputFromPts(po::variables_map &vm)
Write from pts to output file.
int GetNumTecplotBlocks()
Calculate number of Tecplot blocks.
virtual void Process(po::variables_map &vm)
Write fld to output file.
virtual void Process(po::variables_map &vm)
Write fld to output file.
int m_coordim
Coordinate dimension of output.
Array< OneD, Array< OneD, NekDouble > > m_fields
Field data to output.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
bool m_binary
True if writing binary field output.
Definition: OutputTecplot.h:98
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:740
void WriteStream(std::ostream &outfile, T data)
Helper function to write binary data to stream.
virtual void WriteTecplotConnectivity(std::ofstream &outfile)
Write Tecplot connectivity information (ASCII)
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
virtual void WriteTecplotZone(std::ofstream &outfile)
vector< int > m_numPoints
Number of points per block in Tecplot file.
ModuleFactory & GetModuleFactory()
FieldSharedPtr m_f
Field object.