Nektar++
FieldIO.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: FieldIO.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: I/O routines relating to Fields
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/asio/ip/host_name.hpp>
36 #include <boost/format.hpp>
37 #include <boost/regex.hpp>
38 
42 
43 #include <chrono>
44 #include <ctime>
45 #include <fstream>
46 #include <iomanip>
47 #include <ios>
48 #include <set>
49 
50 #ifdef NEKTAR_USE_MPI
51 #include <mpi.h>
52 #endif
53 
54 #ifndef NEKTAR_VERSION
55 #define NEKTAR_VERSION "Unknown"
56 #endif
57 
58 namespace berrc = boost::system::errc;
59 namespace ip = boost::asio::ip;
60 
61 namespace Nektar
62 {
63 namespace LibUtilities
64 {
65 
67  "io-format", "i", "Default input/output format (e.g. Xml, Hdf5)");
68 
69 /**
70  * @brief Returns the FieldIO factory.
71  */
73 {
74  static FieldIOFactory instance;
75  return instance;
76 }
77 
78 /// Enumerator for auto-detection of FieldIO types.
80 {
82  eHDF5
83 };
84 
85 /**
86  * @brief Determine file type of given input file.
87  *
88  * This method attempts to identify the file type of a given input file @p
89  * filename. It returns a string corresponding to GetFieldIOFactory() or throws
90  * an assertion if it cannot be identified.
91  *
92  * @param filename Input filename
93  * @param comm Communicator for parallel runs
94  *
95  * @return FieldIO format of @p filename.
96  */
97 const std::string FieldIO::GetFileType(const std::string &filename,
98  CommSharedPtr comm)
99 {
100  FieldIOType ioType = eXML;
101  int size = comm->GetSpaceComm()->GetSize();
102  bool root = comm->GetSpaceComm()->TreatAsRankZero();
103 
104  if (size == 1 || root)
105  {
106  std::string datafilename;
107 
108  // If input is a directory, check for root processor file.
109  if (fs::is_directory(filename))
110  {
111  fs::path fullpath = filename;
112  fs::path d = fullpath;
113  boost::regex expr("P\\d{7}.fld");
114  boost::smatch what;
115 
116  bool found = false;
117  for (auto &f : fs::directory_iterator(d))
118  {
119  if (boost::regex_match(f.path().filename().string(), what,
120  expr))
121  {
122  found = true;
123  fullpath = f.path();
124  break;
125  }
126  }
127 
128  ASSERTL0(found, std::string("Failed to open a PXXXXXXX.fld file "
129  "in directory: " +
130  filename)
131  .c_str());
132 
133  datafilename = PortablePath(fullpath);
134  }
135  else
136  {
137  datafilename = filename;
138  }
139 
140  // Read first 8 bytes. If they correspond with magic bytes below it's an
141  // HDF5 file. XML is potentially a nightmare with all the different
142  // encodings so we'll just assume it's OK if it's not HDF.
143  const unsigned char magic[8] = {0x89, 0x48, 0x44, 0x46,
144  0x0d, 0x0a, 0x1a, 0x0a};
145 
146  std::ifstream datafile(datafilename.c_str(), std::ios_base::binary);
147  ASSERTL0(datafile.good(), "Unable to open file: " + filename);
148 
149  ioType = eHDF5;
150  for (unsigned i = 0; i < 8 && datafile.good(); ++i)
151  {
152  int byte = datafile.get();
153  if (byte != magic[i])
154  {
155  ioType = eXML;
156  break;
157  }
158  }
159  }
160 
161  if (size > 1)
162  {
163  int code = (int)ioType;
164  comm->GetSpaceComm()->Bcast(code, 0);
165  ioType = (FieldIOType)code;
166  }
167 
168  std::string iofmt;
169  if (ioType == eXML)
170  {
171  iofmt = "Xml";
172  }
173  else if (ioType == eHDF5)
174  {
175  iofmt = "Hdf5";
176  }
177  else
178  {
179  // Error
180  NEKERROR(ErrorUtil::efatal, "Unknown file format");
181  }
182 
183  return iofmt;
184 }
185 
186 /**
187  * @brief Returns an object for the default FieldIO method.
188  *
189  * This function returns a FieldIO class as determined by the hard-coded default
190  * (XML), which can be overridden by changing the session reader SOLVERINFO
191  * variable FieldIOFormat.
192  *
193  * @param session Session reader
194  *
195  * @return FieldIO object
196  */
199 {
200  std::string iofmt("Xml");
201  if (session->DefinesSolverInfo("IOFormat"))
202  {
203  iofmt = session->GetSolverInfo("IOFormat");
204  }
205 
206  if (session->DefinesCmdLineArgument("io-format"))
207  {
208  iofmt = session->GetCmdLineArgument<std::string>("io-format");
209  }
210 
211  return GetFieldIOFactory().CreateInstance(iofmt, session->GetComm(),
212  session->GetSharedFilesystem());
213 }
214 
215 /**
216  * @brief Construct a FieldIO object for a given input filename.
217  *
218  * This is a convenience function that takes an input filename and constructs
219  * the appropriate FieldIO subclass, using FieldIO::GetFileType.
220  *
221  * @param session Session reader
222  * @param filename Input filename
223  *
224  * @return FieldIO class reader for @p filename.
225  */
228  const std::string &filename)
229 {
230  const std::string iofmt =
231  FieldIO::GetFileType(filename, session->GetComm());
232  return GetFieldIOFactory().CreateInstance(iofmt, session->GetComm(),
233  session->GetSharedFilesystem());
234 }
235 
236 /**
237  * @brief This function allows for data to be written to an FLD file when a
238  * session and/or communicator is not instantiated. Typically used in utilities
239  * which do not take XML input and operate in serial only.
240  *
241  * @param outFile Output filename
242  * @param fielddefs Field definitions that define the output
243  * @param fielddata Binary field data that stores the output corresponding
244  * to @p fielddefs.
245  * @param fieldinfomap Associated field metadata map.
246  */
247 void Write(const std::string &outFile,
248  std::vector<FieldDefinitionsSharedPtr> &fielddefs,
249  std::vector<std::vector<NekDouble>> &fielddata,
250  const FieldMetaDataMap &fieldinfomap, const bool backup)
251 {
252 #ifdef NEKTAR_USE_MPI
253  int size;
254  int init;
255  MPI_Initialized(&init);
256 
257  // If MPI has been initialised we can check the number of processes
258  // and, if > 1, tell the user he should not be running this
259  // function in parallel. If it is not initialised, we do not
260  // initialise it here, and assume the user knows what they are
261  // doing.
262  if (init)
263  {
264  MPI_Comm_size(MPI_COMM_WORLD, &size);
265  ASSERTL0(size == 1,
266  "This static function is not available in parallel. Please"
267  "instantiate a FieldIO object for parallel use.");
268  }
269 #endif
270  CommSharedPtr c = GetCommFactory().CreateInstance("Serial", 0, 0);
271  FieldIOSharedPtr f = GetFieldIOFactory().CreateInstance("Xml", c, false);
272  f->Write(outFile, fielddefs, fielddata, fieldinfomap, backup);
273 }
274 
275 /**
276  * @brief This function allows for data to be imported from an FLD file when a
277  * session and/or communicator is not instantiated. Typically used in utilities
278  * which only operate in serial.
279  *
280  * @param infilename Input filename (or directory if parallel format)
281  * @param fielddefs On return contains field definitions as read from the
282  * input.
283  * @param fielddata On return, contains binary field data that stores the
284  * input corresponding to @p fielddefs.
285  * @param fieldinfo On returnm, contains the associated field metadata map.
286  * @param ElementIDs Element IDs that lie on this processor, which can be
287  * optionally supplied to avoid reading the entire file on
288  * each processor.
289  */
291  const std::string &infilename,
292  std::vector<FieldDefinitionsSharedPtr> &fielddefs,
293  std::vector<std::vector<NekDouble>> &fielddata,
294  FieldMetaDataMap &fieldinfomap, const Array<OneD, int> &ElementIDs)
295 {
296 #ifdef NEKTAR_USE_MPI
297  int size;
298  int init;
299  MPI_Initialized(&init);
300 
301  // If MPI has been initialised we can check the number of processes
302  // and, if > 1, tell the user he should not be running this
303  // function in parallel. If it is not initialised, we do not
304  // initialise it here, and assume the user knows what they are
305  // doing.
306  if (init)
307  {
308  MPI_Comm_size(MPI_COMM_WORLD, &size);
309  ASSERTL0(size == 1,
310  "This static function is not available in parallel. Please"
311  "instantiate a FieldIO object for parallel use.");
312  }
313 #endif
314  CommSharedPtr c = GetCommFactory().CreateInstance("Serial", 0, 0);
315  const std::string iofmt = FieldIO::GetFileType(infilename, c);
316  FieldIOSharedPtr f = GetFieldIOFactory().CreateInstance(iofmt, c, false);
317  f->Import(infilename, fielddefs, fielddata, fieldinfomap, ElementIDs);
318 }
319 
320 /**
321  * @brief Constructor for FieldIO base class.
322  */
323 FieldIO::FieldIO(LibUtilities::CommSharedPtr pComm, bool sharedFilesystem)
324  : m_comm(pComm), m_sharedFilesystem(sharedFilesystem)
325 {
326 }
327 
328 /**
329  * @brief Add provenance information to the field metadata map.
330  *
331  * This routine adds some basic provenance information to the field metadata to
332  * enable better tracking of version information:
333  *
334  * - Nektar++ version
335  * - Date and time of simulation
336  * - Hostname of the machine the simulation was performed on
337  * - git SHA1 and branch name, if Nektar++ was compiled from git and not
338  * e.g. a tarball.
339  *
340  * @param root Root tag, which is encapsulated using the TagWriter
341  * structure to enable multi-file format support.
342  * @param fieldmetadatamap Any existing field metadata.
343  */
345  const FieldMetaDataMap &fieldmetadatamap)
346 {
347  FieldMetaDataMap ProvenanceMap;
348 
349  // Nektar++ release version from VERSION file
350  ProvenanceMap["NektarVersion"] = std::string(NEKTAR_VERSION);
351 
352  // Date/time stamp
353  auto now = std::chrono::system_clock::now();
354  auto now_t = std::chrono::system_clock::to_time_t(now);
355  auto now_tm = *std::localtime(&now_t);
356  char buffer[128];
357  strftime(buffer, sizeof(buffer), "%d-%b-%Y %H:%M:%S", &now_tm);
358  ProvenanceMap["Timestamp"] = buffer;
359 
360  // Hostname
361  boost::system::error_code ec;
362  ProvenanceMap["Hostname"] = ip::host_name(ec);
363 
364  // Git information
365  // If built from a distributed package, do not include this
366  if (NekConstants::kGitSha1 != "GITDIR-NOTFOUND")
367  {
368  ProvenanceMap["GitSHA1"] = NekConstants::kGitSha1;
369  ProvenanceMap["GitBranch"] = NekConstants::kGitBranch;
370  }
371 
372  TagWriterSharedPtr infoTag = root->AddChild("Metadata");
373 
374  TagWriterSharedPtr provTag = infoTag->AddChild("Provenance");
375  for (auto &infoit : ProvenanceMap)
376  {
377  provTag->SetAttr(infoit.first, infoit.second);
378  }
379 
380  //---------------------------------------------
381  // write field info section
382  if (fieldmetadatamap != NullFieldMetaDataMap)
383  {
384  for (auto &infoit : fieldmetadatamap)
385  {
386  infoTag->SetAttr(infoit.first, infoit.second);
387  }
388  }
389 }
390 
391 /**
392  * @brief Set up the filesystem ready for output.
393  *
394  * This function sets up the output given an output filename @p outname. This
395  * will therefore remove any file or directory with the desired output filename
396  * and return the absolute path to the output.
397  *
398  * If @p perRank is set, a new directory will be created to contain one file per
399  * process rank.
400  *
401  * @param outname Desired output filename.
402  * @param perRank True if one file-per-rank output is required.
403  *
404  * @return Absolute path to resulting file.
405  */
406 std::string FieldIO::SetUpOutput(const std::string outname, bool perRank,
407  bool backup)
408 {
409  ASSERTL0(!outname.empty(), "Empty path given to SetUpOutput()");
410 
411  // Create a hash from the filename
412  std::size_t file_id = std::hash<std::string>{}(outname);
413 
414  // Find the minimum and maximum hash for each process
415  std::size_t file_id_max{file_id};
416  std::size_t file_id_min{file_id};
417  m_comm->GetSpaceComm()->AllReduce(file_id_max, ReduceMax);
418  m_comm->GetSpaceComm()->AllReduce(file_id_min, ReduceMin);
419 
420  // Check that each process has the same filename (hash)
421  ASSERTL0(file_id_min == file_id_max,
422  "All processes do not have the same filename.");
423 
424  int nprocs = m_comm->GetSpaceComm()->GetSize();
425  bool root = m_comm->GetSpaceComm()->TreatAsRankZero();
426 
427  // Path to output: will be directory if parallel, normal file if
428  // serial.
429  fs::path specPath(outname), fulloutname;
430 
431  // in case we are rank 0 or not on a shared filesystem, check if the
432  // specPath already exists
433  if (backup && (root || !m_sharedFilesystem) && fs::exists(specPath))
434  {
435  // rename. foo/bar_123.chk -> foo/bar_123.bak0.chk and in case
436  // foo/bar_123.bak0.chk already exists, foo/bar_123.chk ->
437  // foo/bar_123.bak1.chk
438  fs::path bakPath = specPath;
439  int cnt = 0;
440  while (fs::exists(bakPath))
441  {
442  bakPath = specPath.parent_path();
443  bakPath += fs::path(bakPath.extension() == ".pit" ? "/" : "");
444  bakPath += specPath.stem();
445  bakPath += fs::path(".bak" + std::to_string(cnt++));
446  bakPath += specPath.extension();
447  }
448  std::cout << "renaming " << specPath << " -> " << bakPath << std::endl;
449  try
450  {
451  fs::rename(specPath, bakPath);
452  }
453  catch (fs::filesystem_error &e)
454  {
455  ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
456  "Filesystem error: " + std::string(e.what()));
457  }
458  }
459 
460  // wait until rank 0 has moved the old specPath and the changes
461  // have propagated through the filesystem
462  if (backup)
463  {
464  m_comm->GetSpaceComm()->Block();
465  int exists = 1;
466  while (exists && perRank)
467  {
468  exists = fs::exists(specPath);
469  m_comm->GetSpaceComm()->AllReduce(exists, ReduceMax);
470  }
471  }
472 
473  if (nprocs == 1)
474  {
475  fulloutname = specPath;
476  }
477  else
478  {
479  // Guess at filename that might belong to this process.
480  boost::format pad("P%1$07d.%2$s");
481  pad % m_comm->GetSpaceComm()->GetRank() % GetFileEnding();
482 
483  // Generate full path name
484  fs::path poutfile(pad.str());
485  fulloutname = specPath / poutfile;
486  }
487 
488  // Remove any existing file which is in the way
489  if (m_comm->GetSpaceComm()->RemoveExistingFiles() && !backup)
490  {
491  if (m_sharedFilesystem)
492  {
493  // First, each process clears up its .fld file. This might or might
494  // not be there (we might have changed numbers of processors between
495  // runs, for example), but we can try anyway.
496  try
497  {
498  fs::remove_all(fulloutname);
499  }
500  catch (fs::filesystem_error &e)
501  {
502  ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
503  "Filesystem error: " + std::string(e.what()));
504  }
505  }
506 
507  m_comm->GetSpaceComm()->Block();
508 
509  // Now get rank 0 processor to tidy everything else up.
510  if (root || !m_sharedFilesystem)
511  {
512  try
513  {
514  fs::remove_all(specPath);
515  }
516  catch (fs::filesystem_error &e)
517  {
518  ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
519  "Filesystem error: " + std::string(e.what()));
520  }
521  }
522 
523  // wait until rank 0 has removed specPath and the changes
524  // have propagated through the filesystem
525  m_comm->GetSpaceComm()->Block();
526  int exists = 1;
527  while (exists && perRank)
528  {
529  exists = fs::exists(specPath);
530  m_comm->GetSpaceComm()->AllReduce(exists, ReduceMax);
531  }
532  }
533 
534  if (root)
535  {
536  std::cout << "Writing: " << specPath << std::endl;
537  }
538 
539  // serial processing just add ending.
540  if (nprocs == 1)
541  {
542  return LibUtilities::PortablePath(specPath);
543  }
544 
545  // Create the destination directory
546  if (perRank)
547  {
548  try
549  {
550  if (root || !m_sharedFilesystem)
551  {
552  fs::create_directory(specPath);
553  }
554  }
555  catch (fs::filesystem_error &e)
556  {
558  "Filesystem error: " + std::string(e.what()));
559  }
560 
561  m_comm->GetSpaceComm()->Block();
562 
563  // Sit in a loop and make sure target directory has been created
564  int created = 0;
565  while (!created)
566  {
567  created = fs::is_directory(specPath);
568  m_comm->GetSpaceComm()->AllReduce(created, ReduceMin);
569  }
570  }
571  else
572  {
573  fulloutname = specPath;
574  }
575 
576  // Return the full path to the partition for this process
577  return LibUtilities::PortablePath(fulloutname);
578 }
579 
580 /**
581  * @brief Check field definitions for correctness and return storage size.
582  *
583  * @param fielddefs Field definitions to check.
584  */
586 {
587  int i;
588 
589  if (fielddefs->m_elementIDs.size() == 0) // empty partition
590  {
591  return 0;
592  }
593 
594  unsigned int numbasis = 0;
595 
596  // Determine nummodes vector lists are correct length
597  switch (fielddefs->m_shapeType)
598  {
599  case eSegment:
600  numbasis = 1;
601  if (fielddefs->m_numHomogeneousDir)
602  {
603  numbasis += fielddefs->m_numHomogeneousDir;
604  }
605 
606  break;
607  case eTriangle:
608  case eQuadrilateral:
609  if (fielddefs->m_numHomogeneousDir)
610  {
611  numbasis = 3;
612  }
613  else
614  {
615  numbasis = 2;
616  }
617  break;
618  case eTetrahedron:
619  case ePyramid:
620  case ePrism:
621  case eHexahedron:
622  numbasis = 3;
623  break;
624  default:
625  NEKERROR(ErrorUtil::efatal, "Unsupported shape type.");
626  break;
627  }
628 
629  size_t datasize = 0;
630 
631  ASSERTL0(fielddefs->m_basis.size() == numbasis,
632  "Length of basis vector is incorrect");
633 
634  if (fielddefs->m_uniOrder == true)
635  {
636  unsigned int cnt = 0;
637  // calculate datasize
638  switch (fielddefs->m_shapeType)
639  {
640  case eSegment:
641  {
642  int l = fielddefs->m_numModes[cnt++];
643  if (fielddefs->m_numHomogeneousDir == 1)
644  {
645  datasize += l * fielddefs->m_homogeneousZIDs.size();
646  cnt++;
647  }
648  else if (fielddefs->m_numHomogeneousDir == 2)
649  {
650  datasize += l * fielddefs->m_homogeneousYIDs.size();
651  cnt += 2;
652  }
653  else
654  {
655  datasize += l;
656  }
657  }
658  break;
659  case eTriangle:
660  {
661  int l = fielddefs->m_numModes[cnt++];
662  int m = fielddefs->m_numModes[cnt++];
663 
664  if (fielddefs->m_numHomogeneousDir == 1)
665  {
666  datasize += StdTriData::getNumberOfCoefficients(l, m) *
667  fielddefs->m_homogeneousZIDs.size();
668  }
669  else
670  {
671  datasize += StdTriData::getNumberOfCoefficients(l, m);
672  }
673  }
674  break;
675  case eQuadrilateral:
676  {
677  int l = fielddefs->m_numModes[cnt++];
678  int m = fielddefs->m_numModes[cnt++];
679  if (fielddefs->m_numHomogeneousDir == 1)
680  {
681  datasize += l * m * fielddefs->m_homogeneousZIDs.size();
682  }
683  else
684  {
685  datasize += l * m;
686  }
687  }
688  break;
689  case eTetrahedron:
690  {
691  int l = fielddefs->m_numModes[cnt++];
692  int m = fielddefs->m_numModes[cnt++];
693  int n = fielddefs->m_numModes[cnt++];
694  datasize += StdTetData::getNumberOfCoefficients(l, m, n);
695  }
696  break;
697  case ePyramid:
698  {
699  int l = fielddefs->m_numModes[cnt++];
700  int m = fielddefs->m_numModes[cnt++];
701  int n = fielddefs->m_numModes[cnt++];
702  datasize += StdPyrData::getNumberOfCoefficients(l, m, n);
703  }
704  break;
705  case ePrism:
706  {
707  int l = fielddefs->m_numModes[cnt++];
708  int m = fielddefs->m_numModes[cnt++];
709  int n = fielddefs->m_numModes[cnt++];
710  datasize += StdPrismData::getNumberOfCoefficients(l, m, n);
711  }
712  break;
713  case eHexahedron:
714  {
715  int l = fielddefs->m_numModes[cnt++];
716  int m = fielddefs->m_numModes[cnt++];
717  int n = fielddefs->m_numModes[cnt++];
718  datasize += l * m * n;
719  }
720  break;
721  default:
722  NEKERROR(ErrorUtil::efatal, "Unsupported shape type.");
723  break;
724  }
725 
726  datasize *= fielddefs->m_elementIDs.size();
727  }
728  else
729  {
730  unsigned int cnt = 0;
731  // calculate data length
732  for (i = 0; i < fielddefs->m_elementIDs.size(); ++i)
733  {
734  switch (fielddefs->m_shapeType)
735  {
736  case eSegment:
737  {
738  int l = fielddefs->m_numModes[cnt++];
739  if (fielddefs->m_numHomogeneousDir == 1)
740  {
741  datasize += l * fielddefs->m_homogeneousZIDs.size();
742  cnt++;
743  }
744  else if (fielddefs->m_numHomogeneousDir == 2)
745  {
746  datasize += l * fielddefs->m_homogeneousYIDs.size();
747  cnt += 2;
748  }
749  else
750  {
751  datasize += l;
752  }
753  }
754  break;
755  case eTriangle:
756  {
757  int l = fielddefs->m_numModes[cnt++];
758  int m = fielddefs->m_numModes[cnt++];
759  if (fielddefs->m_numHomogeneousDir == 1)
760  {
761  datasize += StdTriData::getNumberOfCoefficients(l, m) *
762  fielddefs->m_homogeneousZIDs.size();
763  cnt++;
764  }
765  else
766  {
767  datasize += StdTriData::getNumberOfCoefficients(l, m);
768  }
769  }
770  break;
771  case eQuadrilateral:
772  {
773  int l = fielddefs->m_numModes[cnt++];
774  int m = fielddefs->m_numModes[cnt++];
775  if (fielddefs->m_numHomogeneousDir == 1)
776  {
777  datasize += l * m * fielddefs->m_homogeneousZIDs.size();
778  cnt++;
779  }
780  else
781  {
782  datasize += l * m;
783  }
784  }
785  break;
786  case eTetrahedron:
787  {
788  int l = fielddefs->m_numModes[cnt++];
789  int m = fielddefs->m_numModes[cnt++];
790  int n = fielddefs->m_numModes[cnt++];
791  datasize += StdTetData::getNumberOfCoefficients(l, m, n);
792  }
793  break;
794  case ePyramid:
795  {
796  int l = fielddefs->m_numModes[cnt++];
797  int m = fielddefs->m_numModes[cnt++];
798  int n = fielddefs->m_numModes[cnt++];
799  datasize += StdPyrData::getNumberOfCoefficients(l, m, n);
800  }
801  break;
802  case ePrism:
803  {
804  int l = fielddefs->m_numModes[cnt++];
805  int m = fielddefs->m_numModes[cnt++];
806  int n = fielddefs->m_numModes[cnt++];
807  datasize += StdPrismData::getNumberOfCoefficients(l, m, n);
808  }
809  break;
810  case eHexahedron:
811  {
812  int l = fielddefs->m_numModes[cnt++];
813  int m = fielddefs->m_numModes[cnt++];
814  int n = fielddefs->m_numModes[cnt++];
815  datasize += l * m * n;
816  }
817  break;
818  default:
819  NEKERROR(ErrorUtil::efatal, "Unsupported shape type.");
820  break;
821  }
822  }
823  }
824 
825  return (int)datasize;
826 }
827 } // namespace LibUtilities
828 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define NEKTAR_VERSION
Definition: FieldIO.cpp:55
#define LIB_UTILITIES_EXPORT
int CheckFieldDefinition(const FieldDefinitionsSharedPtr &fielddefs)
Check field definitions for correctness and return storage size.
Definition: FieldIO.cpp:585
static const std::string GetFileType(const std::string &filename, CommSharedPtr comm)
Determine file type of given input file.
Definition: FieldIO.cpp:97
bool m_sharedFilesystem
Boolean dictating whether we are on a shared filesystem.
Definition: FieldIO.h:284
static std::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
Definition: FieldIO.cpp:226
static std::shared_ptr< FieldIO > CreateDefault(const LibUtilities::SessionReaderSharedPtr session)
Returns an object for the default FieldIO method.
Definition: FieldIO.cpp:197
std::string SetUpOutput(const std::string outname, bool perRank, bool backup=false)
Set up the filesystem ready for output.
Definition: FieldIO.cpp:406
LibUtilities::CommSharedPtr m_comm
Communicator to use when writing parallel format.
Definition: FieldIO.h:278
FieldIO(LibUtilities::CommSharedPtr pComm, bool sharedFilesystem)
Constructor for FieldIO base class.
Definition: FieldIO.cpp:323
std::string GetFileEnding() const
Helper function that determines default file extension.
Definition: FieldIO.h:275
static void AddInfoTag(TagWriterSharedPtr root, const FieldMetaDataMap &fieldmetadatamap)
Add provenance information to the field metadata map.
Definition: FieldIO.cpp:344
Provides a generic Factory class.
Definition: NekFactory.hpp:105
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
static std::string RegisterCmdLineArgument(const std::string &pName, const std::string &pShortName, const std::string &pDescription)
Registers a command-line argument with the session reader.
array buffer
Definition: GsLib.hpp:83
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:284
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:237
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:192
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:114
void Write(const std::string &outFile, std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble >> &fielddata, const FieldMetaDataMap &fieldinfomap, const bool backup)
This function allows for data to be written to an FLD file when a session and/or communicator is not ...
Definition: FieldIO.cpp:247
FieldIOType
Enumerator for auto-detection of FieldIO types.
Definition: FieldIO.cpp:80
std::shared_ptr< TagWriter > TagWriterSharedPtr
Definition: FieldIO.h:80
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:327
void Import(const std::string &infilename, std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble >> &fielddata, FieldMetaDataMap &fieldinfomap, const Array< OneD, int > &ElementIDs)
This function allows for data to be imported from an FLD file when a session and/or communicator is n...
Definition: FieldIO.cpp:290
std::map< std::string, std::string > FieldMetaDataMap
Definition: FieldIO.h:52
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:45
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static FieldMetaDataMap NullFieldMetaDataMap
Definition: FieldIO.h:53
std::shared_ptr< FieldDefinitions > FieldDefinitionsSharedPtr
Definition: FieldIO.h:186
std::string fldCmdFormat
Definition: FieldIO.cpp:66
FieldIOFactory & GetFieldIOFactory()
Returns the FieldIO factory.
Definition: FieldIO.cpp:72
CommFactory & GetCommFactory()
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
const std::string kGitBranch
const std::string kGitSha1
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2