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
58namespace berrc = boost::system::errc;
59namespace ip = boost::asio::ip;
60
61namespace Nektar
62{
63namespace 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 */
97const 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 */
247void 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);
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);
317 f->Import(infilename, fielddefs, fielddata, fieldinfomap, ElementIDs);
318}
319
320/**
321 * @brief Constructor for FieldIO base class.
322 */
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 */
406std::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 {
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:282
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
FieldIOType
Enumerator for auto-detection of FieldIO types.
Definition: FieldIO.cpp:80
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::shared_ptr< TagWriter > TagWriterSharedPtr
Definition: FieldIO.h:80
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:327
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
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
CommFactory & GetCommFactory()
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:57
const std::string kGitBranch
Definition: GitRevision.h:46
const std::string kGitSha1
Definition: GitRevision.h:45
std::vector< double > d(NPUPPER *NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2