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