Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: I/O routines relating to Fields
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <boost/format.hpp>
37 #include <boost/date_time/posix_time/posix_time.hpp>
38 #include <boost/date_time/posix_time/posix_time_io.hpp>
39 #include <boost/asio/ip/host_name.hpp>
40 #include <boost/archive/iterators/base64_from_binary.hpp>
41 #include <boost/archive/iterators/binary_from_base64.hpp>
42 #include <boost/archive/iterators/transform_width.hpp>
43 #include <boost/iostreams/copy.hpp>
44 #include <boost/iostreams/filter/zlib.hpp>
45 #include <boost/iostreams/filtering_stream.hpp>
46 #include <boost/assign/list_of.hpp>
47 
53 
54 #include "zlib.h"
55 #include <set>
56 
57 #ifdef NEKTAR_USE_MPI
58 #include <mpi.h>
59 #endif
60 
61 // Buffer size for zlib compression/decompression
62 #define CHUNK 16384
63 
64 #ifndef NEKTAR_VERSION
65 #define NEKTAR_VERSION "Unknown"
66 #endif
67 
68 namespace ptime = boost::posix_time;
69 namespace ip = boost::asio::ip;
70 namespace berrc = boost::system::errc;
71 
72 namespace Nektar
73 {
74  namespace LibUtilities
75  {
76  /**
77  * This function allows for data to be written to an FLD file when a
78  * session and/or communicator is not instantiated. Typically used in
79  * utilities which do not take XML input and operate in serial only.
80  */
81  void Write( const std::string &outFile,
82  std::vector<FieldDefinitionsSharedPtr> &fielddefs,
83  std::vector<std::vector<NekDouble> > &fielddata,
84  const FieldMetaDataMap &fieldinfomap)
85  {
86 #ifdef NEKTAR_USE_MPI
87  int size;
88  int init;
89  MPI_Initialized(&init);
90 
91  // If MPI has been initialised we can check the number of processes
92  // and, if > 1, tell the user he should not be running this
93  // function in parallel. If it is not initialised, we do not
94  // initialise it here, and assume the user knows what they are
95  // doing.
96  if (init)
97  {
98  MPI_Comm_size( MPI_COMM_WORLD, &size );
99  ASSERTL0(size == 1,
100  "This static function is not available in parallel. Please"
101  "instantiate a FieldIO object for parallel use.");
102  }
103 #endif
104  CommSharedPtr c = GetCommFactory().CreateInstance("Serial", 0, 0);
105  FieldIO f(c);
106  f.Write(outFile, fielddefs, fielddata, fieldinfomap);
107  }
108 
109 
110  /**
111  * This function allows for data to be imported from an FLD file when
112  * a session and/or communicator is not instantiated. Typically used in
113  * utilities which only operate in serial.
114  */
116  const std::string& infilename,
117  std::vector<FieldDefinitionsSharedPtr> &fielddefs,
118  std::vector<std::vector<NekDouble> > &fielddata,
119  FieldMetaDataMap &fieldinfomap,
120  const Array<OneD, int> ElementiDs)
121  {
122 #ifdef NEKTAR_USE_MPI
123  int size;
124  int init;
125  MPI_Initialized(&init);
126 
127  // If MPI has been initialised we can check the number of processes
128  // and, if > 1, tell the user he should not be running this
129  // function in parallel. If it is not initialised, we do not
130  // initialise it here, and assume the user knows what they are
131  // doing.
132  if (init)
133  {
134  MPI_Comm_size( MPI_COMM_WORLD, &size );
135  ASSERTL0(size == 1,
136  "This static function is not available in parallel. Please"
137  "instantiate a FieldIO object for parallel use.");
138  }
139 #endif
140  CommSharedPtr c = GetCommFactory().CreateInstance("Serial", 0, 0);
141  FieldIO f(c);
142  f.Import(infilename, fielddefs, fielddata, fieldinfomap, ElementiDs);
143  }
144 
145 
146  /**
147  *
148  */
150  bool sharedFilesystem) :
151  m_comm(pComm),
152  m_sharedFilesystem(sharedFilesystem)
153  {
154  }
155 
156 
157  /**
158  *
159  */
160  void FieldIO::Write(const std::string &outFile,
161  std::vector<FieldDefinitionsSharedPtr> &fielddefs,
162  std::vector<std::vector<NekDouble> > &fielddata,
163  const FieldMetaDataMap &fieldmetadatamap)
164  {
165  // Check everything seems sensible
166  ASSERTL1(fielddefs.size() == fielddata.size(),
167  "Length of fielddefs and fielddata incompatible");
168  for (int f = 0; f < fielddefs.size(); ++f)
169  {
170  ASSERTL1(fielddata[f].size() > 0,
171  "Fielddata vector must contain at least one value.");
172 
173  ASSERTL1(fielddata[f].size() ==
174  fielddefs[f]->m_fields.size() *
175  CheckFieldDefinition(fielddefs[f]),
176  "Invalid size of fielddata vector.");
177  }
178 
179  // Prepare to write out data. In parallel, we must create directory
180  // and determine the full pathname to the file to write out.
181  // Any existing file/directory which is in the way is removed.
182  std::string filename = SetUpOutput(outFile);
183  if (m_comm->GetSize() > 1)
184  {
185  SetUpFieldMetaData(outFile, fielddefs, fieldmetadatamap);
186  }
187 
188  // Create the file (partition)
189  TiXmlDocument doc;
190  TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "utf-8", "");
191  doc.LinkEndChild(decl);
192 
193  TiXmlElement * root = new TiXmlElement("NEKTAR");
194  doc.LinkEndChild(root);
195 
196  AddInfoTag(root,fieldmetadatamap);
197 
198  for (int f = 0; f < fielddefs.size(); ++f)
199  {
200  //---------------------------------------------
201  // Write ELEMENTS
202  TiXmlElement * elemTag = new TiXmlElement("ELEMENTS");
203  root->LinkEndChild(elemTag);
204 
205  // Write FIELDS
206  std::string fieldsString;
207  {
208  std::stringstream fieldsStringStream;
209  bool first = true;
210  for (std::vector<int>::size_type i = 0; i
211  < fielddefs[f]->m_fields.size(); i++)
212  {
213  if (!first)
214  fieldsStringStream << ",";
215  fieldsStringStream << fielddefs[f]->m_fields[i];
216  first = false;
217  }
218  fieldsString = fieldsStringStream.str();
219  }
220  elemTag->SetAttribute("FIELDS", fieldsString);
221 
222  // Write SHAPE
223  std::string shapeString;
224  {
225  std::stringstream shapeStringStream;
226  shapeStringStream << ShapeTypeMap[fielddefs[f]->m_shapeType];
227  if(fielddefs[f]->m_numHomogeneousDir == 1)
228  {
229  shapeStringStream << "-HomogenousExp1D";
230  }
231  else if (fielddefs[f]->m_numHomogeneousDir == 2)
232  {
233  shapeStringStream << "-HomogenousExp2D";
234  }
235 
236  if (fielddefs[f]->m_homoStrips)
237  {
238  shapeStringStream << "-Strips";
239  }
240 
241  shapeString = shapeStringStream.str();
242  }
243  elemTag->SetAttribute("SHAPE", shapeString);
244 
245  // Write BASIS
246  std::string basisString;
247  {
248  std::stringstream basisStringStream;
249  bool first = true;
250  for (std::vector<BasisType>::size_type i = 0; i < fielddefs[f]->m_basis.size(); i++)
251  {
252  if (!first)
253  basisStringStream << ",";
254  basisStringStream
255  << BasisTypeMap[fielddefs[f]->m_basis[i]];
256  first = false;
257  }
258  basisString = basisStringStream.str();
259  }
260  elemTag->SetAttribute("BASIS", basisString);
261 
262  // Write homogeneuous length details
263  if(fielddefs[f]->m_numHomogeneousDir)
264  {
265  std::string homoLenString;
266  {
267  std::stringstream homoLenStringStream;
268  bool first = true;
269  for (int i = 0; i < fielddefs[f]->m_numHomogeneousDir; ++i)
270  {
271  if (!first)
272  homoLenStringStream << ",";
273  homoLenStringStream
274  << fielddefs[f]->m_homogeneousLengths[i];
275  first = false;
276  }
277  homoLenString = homoLenStringStream.str();
278  }
279  elemTag->SetAttribute("HOMOGENEOUSLENGTHS", homoLenString);
280  }
281 
282  // Write homogeneuous planes/lines details
283  if(fielddefs[f]->m_numHomogeneousDir)
284  {
285  if(fielddefs[f]->m_homogeneousYIDs.size() > 0)
286  {
287  std::string homoYIDsString;
288  {
289  std::stringstream homoYIDsStringStream;
290  bool first = true;
291  for(int i = 0; i < fielddefs[f]->m_homogeneousYIDs.size(); i++)
292  {
293  if (!first)
294  homoYIDsStringStream << ",";
295  homoYIDsStringStream << fielddefs[f]->m_homogeneousYIDs[i];
296  first = false;
297  }
298  homoYIDsString = homoYIDsStringStream.str();
299  }
300  elemTag->SetAttribute("HOMOGENEOUSYIDS", homoYIDsString);
301  }
302 
303  if(fielddefs[f]->m_homogeneousZIDs.size() > 0)
304  {
305  std::string homoZIDsString;
306  {
307  std::stringstream homoZIDsStringStream;
308  bool first = true;
309  for(int i = 0; i < fielddefs[f]->m_homogeneousZIDs.size(); i++)
310  {
311  if (!first)
312  homoZIDsStringStream << ",";
313  homoZIDsStringStream << fielddefs[f]->m_homogeneousZIDs[i];
314  first = false;
315  }
316  homoZIDsString = homoZIDsStringStream.str();
317  }
318  elemTag->SetAttribute("HOMOGENEOUSZIDS", homoZIDsString);
319  }
320 
321  if(fielddefs[f]->m_homogeneousSIDs.size() > 0)
322  {
323  std::string homoSIDsString;
324  {
325  std::stringstream homoSIDsStringStream;
326  bool first = true;
327  for(int i = 0; i < fielddefs[f]->m_homogeneousSIDs.size(); i++)
328  {
329  if (!first)
330  homoSIDsStringStream << ",";
331  homoSIDsStringStream << fielddefs[f]->m_homogeneousSIDs[i];
332  first = false;
333  }
334  homoSIDsString = homoSIDsStringStream.str();
335  }
336  elemTag->SetAttribute("HOMOGENEOUSSIDS", homoSIDsString);
337  }
338  }
339 
340  // Write NUMMODESPERDIR
341  std::string numModesString;
342  {
343  std::stringstream numModesStringStream;
344 
345  if (fielddefs[f]->m_uniOrder)
346  {
347  numModesStringStream << "UNIORDER:";
348  // Just dump single definition
349  bool first = true;
350  for (std::vector<int>::size_type i = 0; i
351  < fielddefs[f]->m_basis.size(); i++)
352  {
353  if (!first)
354  numModesStringStream << ",";
355  numModesStringStream << fielddefs[f]->m_numModes[i];
356  first = false;
357  }
358  }
359  else
360  {
361  numModesStringStream << "MIXORDER:";
362  bool first = true;
363  for (std::vector<int>::size_type i = 0; i
364  < fielddefs[f]->m_numModes.size(); i++)
365  {
366  if (!first)
367  numModesStringStream << ",";
368  numModesStringStream << fielddefs[f]->m_numModes[i];
369  first = false;
370  }
371  }
372 
373  numModesString = numModesStringStream.str();
374  }
375  elemTag->SetAttribute("NUMMODESPERDIR", numModesString);
376 
377  // Write ID
378  // Should ideally look at ways of compressing this stream
379  // if just sequential;
380  std::string idString;
381  {
382  std::stringstream idStringStream;
383  GenerateSeqString(fielddefs[f]->m_elementIDs,idString);
384  }
385  elemTag->SetAttribute("ID", idString);
386  elemTag->SetAttribute("COMPRESSED",
388 
389  // Add this information for future compatibility
390  // issues, for exmaple in case we end up using a 128
391  // bit machine.
392  elemTag->SetAttribute("BITSIZE",
394  std::string base64string;
396  fielddata[f], base64string),
397  "Failed to compress field data.");
398 
399  elemTag->LinkEndChild(new TiXmlText(base64string));
400 
401  }
402  doc.SaveFile(filename);
403  }
404 
405 
406  /**
407  *
408  */
409  void FieldIO::Import(const std::string& infilename,
410  std::vector<FieldDefinitionsSharedPtr> &fielddefs,
411  std::vector<std::vector<NekDouble> > &fielddata,
412  FieldMetaDataMap &fieldmetadatamap,
413  const Array<OneD, int> ElementIDs)
414  {
415 
416  std::string infile = infilename;
417 
418  fs::path pinfilename(infilename);
419 
420  if(fs::is_directory(pinfilename)) // check to see that infile is a directory
421  {
422  fs::path infofile("Info.xml");
423  fs::path fullpath = pinfilename / infofile;
424  infile = PortablePath(fullpath);
425 
426  std::vector<std::string> filenames;
427  std::vector<std::vector<unsigned int> > elementIDs_OnPartitions;
428 
429 
430  ImportMultiFldFileIDs(infile,filenames, elementIDs_OnPartitions,
431  fieldmetadatamap);
432 
433  // Load metadata
434  ImportFieldMetaData(infile,fieldmetadatamap);
435 
436  if(ElementIDs == NullInt1DArray) //load all fields
437  {
438  for(int i = 0; i < filenames.size(); ++i)
439  {
440  fs::path pfilename(filenames[i]);
441  fullpath = pinfilename / pfilename;
442  string fname = PortablePath(fullpath);
443 
444  TiXmlDocument doc1(fname);
445  bool loadOkay1 = doc1.LoadFile();
446 
447  std::stringstream errstr;
448  errstr << "Unable to load file: " << fname << std::endl;
449  errstr << "Reason: " << doc1.ErrorDesc() << std::endl;
450  errstr << "Position: Line " << doc1.ErrorRow() << ", Column " << doc1.ErrorCol() << std::endl;
451  ASSERTL0(loadOkay1, errstr.str());
452 
453  ImportFieldDefs(doc1, fielddefs, false);
454  if(fielddata != NullVectorNekDoubleVector)
455  {
456  ImportFieldData(doc1, fielddefs, fielddata);
457  }
458  }
459 
460  }
461  else // only load relevant partitions
462  {
463  int i,j;
464  map<int,vector<int> > FileIDs;
465  map<int,vector<int> >::iterator it;
466  set<int> LoadFile;
467 
468  for(i = 0; i < elementIDs_OnPartitions.size(); ++i)
469  {
470  for(j = 0; j < elementIDs_OnPartitions[i].size(); ++j)
471  {
472  FileIDs[elementIDs_OnPartitions[i][j]].push_back(i);
473  }
474  }
475 
476  for(i = 0; i < ElementIDs.num_elements(); ++i)
477  {
478  it = FileIDs.find(ElementIDs[i]);
479  if (it != FileIDs.end())
480  {
481  for (j = 0; j < it->second.size(); ++j)
482  {
483  LoadFile.insert(it->second[j]);
484  }
485  }
486  }
487 
488  set<int>::iterator iter;
489  for(iter = LoadFile.begin(); iter != LoadFile.end(); ++iter)
490  {
491  fs::path pfilename(filenames[*iter]);
492  fullpath = pinfilename / pfilename;
493  string fname = PortablePath(fullpath);
494  TiXmlDocument doc1(fname);
495  bool loadOkay1 = doc1.LoadFile();
496 
497  std::stringstream errstr;
498  errstr << "Unable to load file: " << fname << std::endl;
499  errstr << "Reason: " << doc1.ErrorDesc() << std::endl;
500  errstr << "Position: Line " << doc1.ErrorRow() << ", Column " << doc1.ErrorCol() << std::endl;
501  ASSERTL0(loadOkay1, errstr.str());
502 
503  ImportFieldDefs(doc1, fielddefs, false);
504  if(fielddata != NullVectorNekDoubleVector)
505  {
506  ImportFieldData(doc1, fielddefs, fielddata);
507  }
508  }
509  }
510  }
511  else // serial format case
512  {
513 
514  TiXmlDocument doc(infile);
515  bool loadOkay = doc.LoadFile();
516 
517  std::stringstream errstr;
518  errstr << "Unable to load file: " << infile << std::endl;
519  errstr << "Reason: " << doc.ErrorDesc() << std::endl;
520  errstr << "Position: Line " << doc.ErrorRow() << ", Column " <<
521  doc.ErrorCol() << std::endl;
522  ASSERTL0(loadOkay, errstr.str());
523 
524  ImportFieldMetaData(doc,fieldmetadatamap);
525  ImportFieldDefs(doc, fielddefs, false);
526  if(fielddata != NullVectorNekDoubleVector)
527  {
528  ImportFieldData(doc, fielddefs, fielddata);
529  }
530  }
531  }
532 
533 
534  /**
535  *
536  */
537  void FieldIO::WriteMultiFldFileIDs(const std::string &outFile,
538  const std::vector<std::string> fileNames,
539  std::vector<std::vector<unsigned int> > &elementList,
540  const FieldMetaDataMap &fieldmetadatamap)
541  {
542  TiXmlDocument doc;
543  TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "utf-8", "");
544  doc.LinkEndChild(decl);
545 
546  ASSERTL0(fileNames.size() == elementList.size(),"Outfile names and list of elements ids does not match");
547 
548  TiXmlElement * root = new TiXmlElement("NEKTAR");
549  doc.LinkEndChild(root);
550 
551  AddInfoTag(root,fieldmetadatamap);
552 
553  for (int t = 0; t < fileNames.size(); ++t)
554  {
555  if(elementList[t].size())
556  {
557  TiXmlElement * elemIDs = new TiXmlElement("Partition");
558  root->LinkEndChild(elemIDs);
559 
560  elemIDs->SetAttribute("FileName",fileNames[t]);
561 
562  string IDstring;
563 
564  GenerateSeqString(elementList[t],IDstring);
565 
566  elemIDs->LinkEndChild(new TiXmlText(IDstring));
567  }
568  }
569 
570  doc.SaveFile(outFile);
571  }
572 
573 
574  /**
575  *
576  */
577  void FieldIO::ImportMultiFldFileIDs(const std::string &inFile,
578  std::vector<std::string> &fileNames,
579  std::vector<std::vector<unsigned int> > &elementList,
580  FieldMetaDataMap &fieldmetadatamap)
581  {
582  TiXmlDocument doc(inFile);
583  bool loadOkay = doc.LoadFile();
584 
585 
586  std::stringstream errstr;
587  errstr << "Unable to load file: " << inFile<< std::endl;
588  errstr << "Reason: " << doc.ErrorDesc() << std::endl;
589  errstr << "Position: Line " << doc.ErrorRow() << ", Column " << doc.ErrorCol() << std::endl;
590  ASSERTL0(loadOkay, errstr.str());
591 
592  // Handle on XML document
593  TiXmlHandle docHandle(&doc);
594 
595  // Retrieve main NEKTAR tag - XML specification states one
596  // top-level element tag per file.
597  TiXmlElement* master = doc.FirstChildElement("NEKTAR");
598  ASSERTL0(master, "Unable to find NEKTAR tag in file.");
599 
600  // Partition element tag name
601  std::string strPartition = "Partition";
602 
603  // First attempt to get the first Partition element
604  TiXmlElement* fldfileIDs = master->FirstChildElement(strPartition.c_str());
605  if (!fldfileIDs)
606  {
607  // If this files try previous name
608  strPartition = "MultipleFldFiles";
609  fldfileIDs = master->FirstChildElement("MultipleFldFiles");
610  }
611  ASSERTL0(fldfileIDs,
612  "Unable to find 'Partition' or 'MultipleFldFiles' tag "
613  "within nektar tag.");
614 
615  while (fldfileIDs)
616  {
617  // Read file name of partition file
618  const char *attr = fldfileIDs->Attribute("FileName");
619  ASSERTL0(attr, "'FileName' not provided as an attribute of '"
620  + strPartition + "' tag.");
621  fileNames.push_back(std::string(attr));
622 
623  const char* elementIDs = fldfileIDs->GetText();
624  ASSERTL0(elementIDs, "Element IDs not specified.");
625 
626  std::string elementIDsStr(elementIDs);
627 
628  std::vector<unsigned int> idvec;
629  ParseUtils::GenerateSeqVector(elementIDsStr.c_str(),idvec);
630 
631  elementList.push_back(idvec);
632 
633  fldfileIDs = fldfileIDs->NextSiblingElement(strPartition.c_str());
634  }
635  }
636 
637  void FieldIO::ImportFieldMetaData(std::string filename,
638  FieldMetaDataMap &fieldmetadatamap)
639  {
640  TiXmlDocument doc(filename);
641  bool loadOkay = doc.LoadFile();
642 
643  std::stringstream errstr;
644  errstr << "Unable to load file: " << filename << std::endl;
645  errstr << "Reason: " << doc.ErrorDesc() << std::endl;
646  errstr << "Position: Line " << doc.ErrorRow() << ", Column " << doc.ErrorCol() << std::endl;
647  ASSERTL0(loadOkay, errstr.str());
648 
649  ImportFieldMetaData(doc,fieldmetadatamap);
650  }
651 
652 
653  void FieldIO::ImportFieldMetaData(TiXmlDocument &doc,
654  FieldMetaDataMap &fieldmetadatamap)
655  {
656 
657  TiXmlHandle docHandle(&doc);
658  TiXmlElement* master = 0; // Master tag within which all data is contained.
659  TiXmlElement* metadata = 0;
660 
661  master = doc.FirstChildElement("NEKTAR");
662  ASSERTL0(master, "Unable to find NEKTAR tag in file.");
663  std::string strLoop = "NEKTAR";
664 
665  // Retain original metadata structure for backwards compatibility
666  // TODO: Remove old metadata format
667  metadata = master->FirstChildElement("FIELDMETADATA");
668  if(metadata)
669  {
670  TiXmlElement *param = metadata->FirstChildElement("P");
671 
672  while (param)
673  {
674  TiXmlAttribute *paramAttr = param->FirstAttribute();
675  std::string attrName(paramAttr->Name());
676  std::string paramString;
677 
678  if(attrName == "PARAM")
679  {
680  paramString.insert(0,paramAttr->Value());
681  }
682  else
683  {
684  ASSERTL0(false,"PARAM not provided as an attribute in FIELDMETADATA section");
685  }
686 
687  // Now read body of param
688  std::string paramBodyStr;
689 
690  TiXmlNode *paramBody = param->FirstChild();
691 
692  paramBodyStr += paramBody->ToText()->Value();
693 
694  fieldmetadatamap[paramString] = paramBodyStr;
695  param = param->NextSiblingElement("P");
696  }
697  }
698 
699  // New metadata format
700  metadata = master->FirstChildElement("Metadata");
701  if(metadata)
702  {
703  TiXmlElement *param = metadata->FirstChildElement();
704 
705  while (param)
706  {
707  std::string paramString = param->Value();
708  if (paramString != "Provenance")
709  {
710  // Now read body of param
711  TiXmlNode *paramBody = param->FirstChild();
712  std::string paramBodyStr = paramBody->ToText()->Value();
713 
714  fieldmetadatamap[paramString] = paramBodyStr;
715  }
716  param = param->NextSiblingElement();
717  }
718  }
719 
720  }
721 
722 
723  /**
724  * The bool decides if the FieldDefs are in <EXPANSIONS> or in <NEKTAR>.
725  */
726  void FieldIO::ImportFieldDefs(TiXmlDocument &doc, std::vector<FieldDefinitionsSharedPtr> &fielddefs,
727  bool expChild)
728  {
729  TiXmlHandle docHandle(&doc);
730  TiXmlElement* master = NULL; // Master tag within which all data is contained.
731 
732  master = doc.FirstChildElement("NEKTAR");
733  ASSERTL0(master, "Unable to find NEKTAR tag in file.");
734  std::string strLoop = "NEKTAR";
735  TiXmlElement* loopXml = master;
736 
737  TiXmlElement *expansionTypes;
738  if(expChild)
739  {
740  expansionTypes = master->FirstChildElement("EXPANSIONS");
741  ASSERTL0(expansionTypes, "Unable to find EXPANSIONS tag in file.");
742  loopXml = expansionTypes;
743  strLoop = "EXPANSIONS";
744  }
745 
746  // Loop through all nektar tags, finding all of the element tags.
747  while (loopXml)
748  {
749  TiXmlElement* element = loopXml->FirstChildElement("ELEMENTS");
750  ASSERTL0(element, "Unable to find ELEMENTS tag within nektar tag.");
751 
752  while (element)
753  {
754  // Extract the attributes.
755  std::string idString;
756  std::string shapeString;
757  std::string basisString;
758  std::string homoLengthsString;
759  std::string homoSIDsString;
760  std::string homoZIDsString;
761  std::string homoYIDsString;
762  std::string numModesString;
763  std::string numPointsString;
764  std::string fieldsString;
765  std::string pointsString;
766  bool pointDef = false;
767  bool numPointDef = false;
768  TiXmlAttribute *attr = element->FirstAttribute();
769  while (attr)
770  {
771  std::string attrName(attr->Name());
772  if (attrName == "FIELDS")
773  {
774  fieldsString.insert(0, attr->Value());
775  }
776  else if (attrName == "SHAPE")
777  {
778  shapeString.insert(0, attr->Value());
779  }
780  else if (attrName == "BASIS")
781  {
782  basisString.insert(0, attr->Value());
783  }
784  else if (attrName == "HOMOGENEOUSLENGTHS")
785  {
786  homoLengthsString.insert(0,attr->Value());
787  }
788  else if (attrName == "HOMOGENEOUSSIDS")
789  {
790  homoSIDsString.insert(0,attr->Value());
791  }
792  else if (attrName == "HOMOGENEOUSZIDS")
793  {
794  homoZIDsString.insert(0,attr->Value());
795  }
796  else if (attrName == "HOMOGENEOUSYIDS")
797  {
798  homoYIDsString.insert(0,attr->Value());
799  }
800  else if (attrName == "NUMMODESPERDIR")
801  {
802  numModesString.insert(0, attr->Value());
803  }
804  else if (attrName == "ID")
805  {
806  idString.insert(0, attr->Value());
807  }
808  else if (attrName == "POINTSTYPE")
809  {
810  pointsString.insert(0, attr->Value());
811  pointDef = true;
812  }
813  else if (attrName == "NUMPOINTSPERDIR")
814  {
815  numPointsString.insert(0, attr->Value());
816  numPointDef = true;
817  }
818  else if (attrName == "COMPRESSED")
819  {
820  if(!boost::iequals(attr->Value(),
822  {
823  WARNINGL0(false, "Compressed formats do not "
824  "match. Expected: "
826  + " but got "+ string(attr->Value()));
827  }
828  }
829  else if (attrName =="BITSIZE")
830  {
831  // This information is for future
832  // compatibility issues, for exmaple in
833  // case we end up using a 128 bit machine.
834  // Currently just do nothing
835  }
836  else
837  {
838  std::string errstr("Unknown attribute: ");
839  errstr += attrName;
840  ASSERTL1(false, errstr.c_str());
841  }
842 
843  // Get the next attribute.
844  attr = attr->Next();
845  }
846 
847 
848  // Check to see if using strips formulation
849  bool strips = false;
850  if(shapeString.find("Strips")!=string::npos)
851  {
852  strips = true;
853  }
854 
855  // Check to see if homogeneous expansion and if so
856  // strip down the shapeString definition
857  int numHomoDir = 0;
858  size_t loc;
859  //---> This finds the first location of 'n'!
860  if((loc = shapeString.find_first_of("-"))!=string::npos)
861  {
862  if(shapeString.find("Exp1D")!=string::npos)
863  {
864  numHomoDir = 1;
865  }
866  else // HomogeneousExp1D
867  {
868  numHomoDir = 2;
869  }
870 
871  shapeString.erase(loc,shapeString.length());
872  }
873 
874  // Reconstruct the fielddefs.
875  std::vector<unsigned int> elementIds;
876  {
877  bool valid = ParseUtils::GenerateSeqVector(idString.c_str(), elementIds);
878  ASSERTL0(valid, "Unable to correctly parse the element ids.");
879  }
880 
881  // Get the geometrical shape
882  ShapeType shape;
883  bool valid = false;
884  for (unsigned int j = 0; j < SIZE_ShapeType; j++)
885  {
886  if (ShapeTypeMap[j] == shapeString)
887  {
888  shape = (ShapeType) j;
889  valid = true;
890  break;
891  }
892  }
893 
894  ASSERTL0(valid, std::string("Unable to correctly parse the shape type: ").append(shapeString).c_str());
895 
896  // Get the basis
897  std::vector<std::string> basisStrings;
898  std::vector<BasisType> basis;
899  valid = ParseUtils::GenerateOrderedStringVector(basisString.c_str(), basisStrings);
900  ASSERTL0(valid, "Unable to correctly parse the basis types.");
901  for (std::vector<std::string>::size_type i = 0; i < basisStrings.size(); i++)
902  {
903  valid = false;
904  for (unsigned int j = 0; j < SIZE_BasisType; j++)
905  {
906  if (BasisTypeMap[j] == basisStrings[i])
907  {
908  basis.push_back((BasisType) j);
909  valid = true;
910  break;
911  }
912  }
913  ASSERTL0(valid, std::string("Unable to correctly parse the basis type: ").append(basisStrings[i]).c_str());
914  }
915 
916  // Get homoLengths
917  std::vector<NekDouble> homoLengths;
918  if(numHomoDir)
919  {
920  valid = ParseUtils::GenerateUnOrderedVector(homoLengthsString.c_str(), homoLengths);
921  ASSERTL0(valid, "Unable to correctly parse the number of homogeneous lengths.");
922  }
923 
924  // Get Homogeneous strips IDs
925  std::vector<unsigned int> homoSIDs;
926  if(strips)
927  {
928  valid = ParseUtils::GenerateSeqVector(homoSIDsString.c_str(), homoSIDs);
929  ASSERTL0(valid, "Unable to correctly parse homogeneous strips IDs.");
930  }
931  // Get Homogeneous points IDs
932  std::vector<unsigned int> homoZIDs;
933  std::vector<unsigned int> homoYIDs;
934 
935  if(numHomoDir == 1)
936  {
937  valid = ParseUtils::GenerateSeqVector(homoZIDsString.c_str(), homoZIDs);
938  ASSERTL0(valid, "Unable to correctly parse homogeneous planes IDs.");
939  }
940 
941  if(numHomoDir == 2)
942  {
943  valid = ParseUtils::GenerateSeqVector(homoZIDsString.c_str(), homoZIDs);
944  ASSERTL0(valid, "Unable to correctly parse homogeneous lines IDs in z-direction.");
945  valid = ParseUtils::GenerateSeqVector(homoYIDsString.c_str(), homoYIDs);
946  ASSERTL0(valid, "Unable to correctly parse homogeneous lines IDs in y-direction.");
947  }
948 
949 
950  // Get points type
951  std::vector<PointsType> points;
952 
953  if(pointDef)
954  {
955  std::vector<std::string> pointsStrings;
956  valid = ParseUtils::GenerateOrderedStringVector(pointsString.c_str(), pointsStrings);
957  ASSERTL0(valid, "Unable to correctly parse the points types.");
958  for (std::vector<std::string>::size_type i = 0; i < pointsStrings.size(); i++)
959  {
960  valid = false;
961  for (unsigned int j = 0; j < SIZE_PointsType; j++)
962  {
963  if (kPointsTypeStr[j] == pointsStrings[i])
964  {
965  points.push_back((PointsType) j);
966  valid = true;
967  break;
968  }
969  }
970 
971  ASSERTL0(valid, std::string("Unable to correctly parse the points type: ").append(pointsStrings[i]).c_str());
972  }
973  }
974 
975  // Get numModes
976  std::vector<unsigned int> numModes;
977  bool UniOrder = false;
978 
979  if(strstr(numModesString.c_str(),"UNIORDER:"))
980  {
981  UniOrder = true;
982  }
983 
984  valid = ParseUtils::GenerateOrderedVector(numModesString.c_str()+9, numModes);
985  ASSERTL0(valid, "Unable to correctly parse the number of modes.");
986 
987  // Get numPoints
988  std::vector<unsigned int> numPoints;
989  if(numPointDef)
990  {
991  valid = ParseUtils::GenerateOrderedVector(numPointsString.c_str(), numPoints);
992  ASSERTL0(valid, "Unable to correctly parse the number of points.");
993  }
994 
995  // Get fields names
996  std::vector<std::string> Fields;
997  valid = ParseUtils::GenerateOrderedStringVector(fieldsString.c_str(), Fields);
998  ASSERTL0(valid, "Unable to correctly parse the number of fields.");
999 
1000  FieldDefinitionsSharedPtr fielddef =
1002  elementIds, basis, UniOrder, numModes, Fields, numHomoDir,
1003  homoLengths, strips, homoSIDs, homoZIDs, homoYIDs,
1004  points, pointDef, numPoints, numPointDef);
1005 
1006  fielddefs.push_back(fielddef);
1007 
1008  element = element->NextSiblingElement("ELEMENTS");
1009  }
1010  loopXml = loopXml->NextSiblingElement(strLoop);
1011  }
1012  }
1013 
1014 
1015  /**
1016  *
1017  */
1018  void FieldIO::ImportFieldData(TiXmlDocument &doc, const std::vector<FieldDefinitionsSharedPtr> &fielddefs, std::vector<std::vector<NekDouble> > &fielddata)
1019  {
1020  int cntdumps = 0;
1021 
1022  TiXmlHandle docHandle(&doc);
1023  TiXmlElement* master = NULL; // Master tag within which all data is contained.
1024 
1025  master = doc.FirstChildElement("NEKTAR");
1026  ASSERTL0(master, "Unable to find NEKTAR tag in file.");
1027 
1028  // Loop through all nektar tags, finding all of the element tags.
1029  while (master)
1030  {
1031  TiXmlElement* element = master->FirstChildElement("ELEMENTS");
1032  ASSERTL0(element, "Unable to find ELEMENTS tag within nektar tag.");
1033  while (element)
1034  {
1035  // Extract the body, which the "data".
1036  TiXmlNode* elementChild = element->FirstChild();
1037  ASSERTL0(elementChild, "Unable to extract the data from the element tag.");
1038  std::string elementStr;
1039  while(elementChild)
1040  {
1041  if (elementChild->Type() == TiXmlNode::TINYXML_TEXT)
1042  {
1043  elementStr += elementChild->ToText()->ValueStr();
1044  }
1045  elementChild = elementChild->NextSibling();
1046  }
1047 
1048  std::vector<NekDouble> elementFieldData;
1049  // Convert from base64 to binary.
1050 
1051  const char *CompressStr = element->Attribute("COMPRESSED");
1052  if(CompressStr)
1053  {
1054  if(!boost::iequals(CompressStr,
1056  {
1057  WARNINGL0(false, "Compressed formats do not match. "
1058  "Expected: "
1060  + " but got "+ string(CompressStr));
1061  }
1062  }
1063 
1065  elementStr,
1066  elementFieldData),
1067  "Failed to decompress field data.");
1068 
1069 
1070  fielddata.push_back(elementFieldData);
1071 
1072  int datasize = CheckFieldDefinition(fielddefs[cntdumps]);
1073  ASSERTL0(fielddata[cntdumps].size() == datasize*fielddefs[cntdumps]->m_fields.size(),"Input data is not the same length as header infoarmation");
1074 
1075  cntdumps++;
1076 
1077  element = element->NextSiblingElement("ELEMENTS");
1078  }
1079  master = master->NextSiblingElement("NEKTAR");
1080  }
1081  }
1082 
1083  /**
1084  * \brief add information about provenance and fieldmetadata
1085  */
1086  void FieldIO::AddInfoTag(TiXmlElement * root,
1087  const FieldMetaDataMap &fieldmetadatamap)
1088  {
1089  FieldMetaDataMap ProvenanceMap;
1090 
1091  // Nektar++ release version from VERSION file
1092  ProvenanceMap["NektarVersion"] = string(NEKTAR_VERSION);
1093 
1094  // Date/time stamp
1095  ptime::time_facet *facet = new ptime::time_facet("%d-%b-%Y %H:%M:%S");
1096  std::stringstream wss;
1097  wss.imbue(locale(wss.getloc(), facet));
1098  wss << ptime::second_clock::local_time();
1099  ProvenanceMap["Timestamp"] = wss.str();
1100 
1101  // Hostname
1102  boost::system::error_code ec;
1103  ProvenanceMap["Hostname"] = ip::host_name(ec);
1104 
1105  // Git information
1106  // If built from a distributed package, do not include this
1107  if (NekConstants::kGitSha1 != "GITDIR-NOTFOUND")
1108  {
1109  ProvenanceMap["GitSHA1"] = NekConstants::kGitSha1;
1110  ProvenanceMap["GitBranch"] = NekConstants::kGitBranch;
1111  }
1112 
1113  TiXmlElement * infoTag = new TiXmlElement("Metadata");
1114  root->LinkEndChild(infoTag);
1115 
1116  TiXmlElement * v;
1117  FieldMetaDataMap::const_iterator infoit;
1118 
1119  TiXmlElement * provTag = new TiXmlElement("Provenance");
1120  infoTag->LinkEndChild(provTag);
1121  for (infoit = ProvenanceMap.begin(); infoit != ProvenanceMap.end(); ++infoit)
1122  {
1123  v = new TiXmlElement( (infoit->first).c_str() );
1124  v->LinkEndChild(new TiXmlText((infoit->second).c_str()));
1125  provTag->LinkEndChild(v);
1126  }
1127 
1128  //---------------------------------------------
1129  // write field info section
1130  if(fieldmetadatamap != NullFieldMetaDataMap)
1131  {
1132  for(infoit = fieldmetadatamap.begin(); infoit != fieldmetadatamap.end(); ++infoit)
1133  {
1134  v = new TiXmlElement( (infoit->first).c_str() );
1135  v->LinkEndChild(new TiXmlText((infoit->second).c_str()));
1136  infoTag->LinkEndChild(v);
1137  }
1138  }
1139  }
1140 
1141 
1142  /**
1143  *
1144  */
1145  void FieldIO::GenerateSeqString(const std::vector<unsigned int> &elmtids,
1146  std::string &idString)
1147  {
1148  std::stringstream idStringStream;
1149  bool setdash = true;
1150  unsigned int endval;
1151 
1152  idStringStream << elmtids[0];
1153  for (int i = 1; i < elmtids.size(); ++i)
1154  {
1155  if(elmtids[i] == elmtids[i-1]+1)
1156  {
1157  if(setdash)
1158  {
1159  idStringStream << "-";
1160  setdash = false;
1161  }
1162 
1163  if(i == elmtids.size()-1) // last element
1164  {
1165  idStringStream << elmtids[i];
1166  }
1167  else
1168  {
1169  endval = elmtids[i];
1170  }
1171  }
1172  else
1173  {
1174  if(setdash == false) // finish off previous dash sequence
1175  {
1176  idStringStream << endval;
1177  setdash = true;
1178  }
1179 
1180 
1181  idStringStream << "," << elmtids[i];
1182  }
1183  }
1184  idString = idStringStream.str();
1185  }
1186 
1187 
1188  /**
1189  *
1190  */
1191  std::string FieldIO::SetUpOutput(const std::string outname)
1192  {
1193  ASSERTL0(!outname.empty(), "Empty path given to SetUpOutput()");
1194 
1195  int nprocs = m_comm->GetSize();
1196  int rank = m_comm->GetRank();
1197 
1198  // Path to output: will be directory if parallel, normal file if
1199  // serial.
1200  fs::path specPath (outname);
1201  fs::path fulloutname;
1202 
1203  if (nprocs == 1)
1204  {
1205  fulloutname = specPath;
1206  }
1207  else
1208  {
1209  // Guess at filename that might belong to this process.
1210  boost::format pad("P%1$07d.%2$s");
1211  pad % m_comm->GetRank() % GetFileEnding();
1212 
1213  // Generate full path name
1214  fs::path poutfile(pad.str());
1215  fulloutname = specPath / poutfile;
1216  }
1217 
1218  // Remove any existing file which is in the way
1219  if (m_comm->RemoveExistingFiles())
1220  {
1221  if (m_sharedFilesystem)
1222  {
1223  // First, each process clears up its .fld file. This might
1224  // or might not be there (we might have changed numbers of
1225  // processors between runs, for example), but we can try
1226  // anyway.
1227  try
1228  {
1229  fs::remove_all(fulloutname);
1230  }
1231  catch (fs::filesystem_error& e)
1232  {
1233  ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
1234  "Filesystem error: " + string(e.what()));
1235  }
1236  }
1237 
1238  m_comm->Block();
1239 
1240  // Now get rank 0 processor to tidy everything else up.
1241  if (rank == 0 || !m_sharedFilesystem)
1242  {
1243  try
1244  {
1245  fs::remove_all(specPath);
1246  }
1247  catch (fs::filesystem_error& e)
1248  {
1249  ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
1250  "Filesystem error: " + string(e.what()));
1251  }
1252  }
1253 
1254  m_comm->Block();
1255  }
1256 
1257  // serial processing just add ending.
1258  if(nprocs == 1)
1259  {
1260  cout << "Writing: " << specPath << endl;
1261  return LibUtilities::PortablePath(specPath);
1262  }
1263 
1264  // Create the destination directory
1265  try
1266  {
1267  if (rank == 0 || !m_sharedFilesystem)
1268  {
1269  fs::create_directory(specPath);
1270  }
1271  }
1272  catch (fs::filesystem_error& e)
1273  {
1274  ASSERTL0(false, "Filesystem error: " + string(e.what()));
1275  }
1276 
1277  m_comm->Block();
1278 
1279  // Sit in a loop and make sure target directory has been created
1280  int created = 0;
1281  while (!created)
1282  {
1283  created = fs::is_directory(specPath);
1284  m_comm->AllReduce(created, ReduceMin);
1285  }
1286 
1287  // Return the full path to the partition for this process
1288  return LibUtilities::PortablePath(fulloutname);
1289  }
1290 
1291 
1293  const string outname,
1294  const vector< FieldDefinitionsSharedPtr > &fielddefs,
1295  const FieldMetaDataMap &fieldmetadatamap)
1296  {
1297  ASSERTL0(!outname.empty(), "Empty path given to SetUpFieldMetaData()");
1298 
1299  int nprocs = m_comm->GetSize();
1300  int rank = m_comm->GetRank();
1301 
1302  fs::path specPath (outname);
1303 
1304  // Compute number of elements on this process and share with other
1305  // processes. Also construct list of elements on this process from
1306  // available vector of field definitions.
1307  std::vector<unsigned int> elmtnums(nprocs,0);
1308  std::vector<unsigned int> idlist;
1309  int i;
1310  for (i = 0; i < fielddefs.size(); ++i)
1311  {
1312  elmtnums[rank] += fielddefs[i]->m_elementIDs.size();
1313  idlist.insert(idlist.end(), fielddefs[i]->m_elementIDs.begin(),
1314  fielddefs[i]->m_elementIDs.end());
1315  }
1316  m_comm->AllReduce(elmtnums,LibUtilities::ReduceMax);
1317 
1318  // Collate per-process element lists on root process to generate
1319  // the info file.
1320  if (rank == 0)
1321  {
1322  std::vector<std::vector<unsigned int> > ElementIDs(nprocs);
1323 
1324  // Populate the list of element ID lists from all processes
1325  ElementIDs[0] = idlist;
1326  for (i = 1; i < nprocs; ++i)
1327  {
1328  std::vector<unsigned int> tmp(elmtnums[i]);
1329  m_comm->Recv(i, tmp);
1330  ElementIDs[i] = tmp;
1331  }
1332 
1333  // Set up output names
1334  std::vector<std::string> filenames;
1335  for(int i = 0; i < nprocs; ++i)
1336  {
1337  boost::format pad("P%1$07d.%2$s");
1338  pad % i % GetFileEnding();
1339  filenames.push_back(pad.str());
1340  }
1341 
1342  // Write the Info.xml file
1343  string infofile = LibUtilities::PortablePath(
1344  specPath / fs::path("Info.xml"));
1345 
1346  cout << "Writing: " << specPath << endl;
1347  WriteMultiFldFileIDs(infofile, filenames, ElementIDs,
1348  fieldmetadatamap);
1349  }
1350  else
1351  {
1352  // Send this process's ID list to the root process
1353  m_comm->Send(0, idlist);
1354  }
1355 
1356  }
1357 
1358 
1359  /**
1360  *
1361  */
1363  {
1364  int i;
1365 
1366  if(fielddefs->m_elementIDs.size() == 0) // empty partition
1367  {
1368  return 0;
1369  }
1370  //ASSERTL0(fielddefs->m_elementIDs.size() > 0, "Fielddefs vector must contain at least one element of data .");
1371 
1372  unsigned int numbasis = 0;
1373 
1374  // Determine nummodes vector lists are correct length
1375  switch(fielddefs->m_shapeType)
1376  {
1377  case eSegment:
1378  numbasis = 1;
1379  if(fielddefs->m_numHomogeneousDir)
1380  {
1381  numbasis += fielddefs->m_numHomogeneousDir;
1382  }
1383 
1384  break;
1385  case eTriangle:
1386  case eQuadrilateral:
1387  if(fielddefs->m_numHomogeneousDir)
1388  {
1389  numbasis = 3;
1390  }
1391  else
1392  {
1393  numbasis = 2;
1394  }
1395  break;
1396  case eTetrahedron:
1397  case ePyramid:
1398  case ePrism:
1399  case eHexahedron:
1400  numbasis = 3;
1401  break;
1402  default:
1403  ASSERTL0(false, "Unsupported shape type.");
1404  break;
1405  }
1406 
1407  unsigned int datasize = 0;
1408 
1409  ASSERTL0(fielddefs->m_basis.size() == numbasis, "Length of basis vector is incorrect");
1410 
1411  if(fielddefs->m_uniOrder == true)
1412  {
1413  unsigned int cnt = 0;
1414  // calculate datasize
1415  switch(fielddefs->m_shapeType)
1416  {
1417  case eSegment:
1418  {
1419  int l = fielddefs->m_numModes[cnt++];
1420  if(fielddefs->m_numHomogeneousDir == 1)
1421  {
1422  datasize += l*fielddefs->m_numModes[cnt++];
1423  }
1424  else if(fielddefs->m_numHomogeneousDir == 2)
1425  {
1426  int m = fielddefs->m_numModes[cnt++];
1427  datasize += l*m*fielddefs->m_numModes[cnt++];
1428  }
1429  else
1430  {
1431  datasize += l;
1432  }
1433  }
1434  break;
1435  case eTriangle:
1436  {
1437  int l = fielddefs->m_numModes[cnt++];
1438  int m = fielddefs->m_numModes[cnt++];
1439 
1440  if(fielddefs->m_numHomogeneousDir == 1)
1441  {
1442  datasize += StdTriData::getNumberOfCoefficients(l,m)*
1443  fielddefs->m_homogeneousZIDs.size();
1444  }
1445  else
1446  {
1447  datasize += StdTriData::getNumberOfCoefficients(l,m);
1448  }
1449  }
1450  break;
1451  case eQuadrilateral:
1452  {
1453  int l = fielddefs->m_numModes[cnt++];
1454  int m = fielddefs->m_numModes[cnt++];
1455  if(fielddefs->m_numHomogeneousDir == 1)
1456  {
1457  datasize += l*m*fielddefs->m_homogeneousZIDs.size();
1458  }
1459  else
1460  {
1461  datasize += l*m;
1462  }
1463  }
1464  break;
1465  case eTetrahedron:
1466  {
1467  int l = fielddefs->m_numModes[cnt++];
1468  int m = fielddefs->m_numModes[cnt++];
1469  int n = fielddefs->m_numModes[cnt++];
1470  datasize += StdTetData::getNumberOfCoefficients(l,m,n);
1471  }
1472  break;
1473  case ePyramid:
1474  {
1475  int l = fielddefs->m_numModes[cnt++];
1476  int m = fielddefs->m_numModes[cnt++];
1477  int n = fielddefs->m_numModes[cnt++];
1478  datasize += StdPyrData::getNumberOfCoefficients(l,m,n);
1479  }
1480  break;
1481  case ePrism:
1482  {
1483  int l = fielddefs->m_numModes[cnt++];
1484  int m = fielddefs->m_numModes[cnt++];
1485  int n = fielddefs->m_numModes[cnt++];
1486  datasize += StdPrismData::getNumberOfCoefficients(l,m,n);
1487  }
1488  break;
1489  case eHexahedron:
1490  {
1491  int l = fielddefs->m_numModes[cnt++];
1492  int m = fielddefs->m_numModes[cnt++];
1493  int n = fielddefs->m_numModes[cnt++];
1494  datasize += l*m*n;
1495  }
1496  break;
1497  default:
1498  ASSERTL0(false, "Unsupported shape type.");
1499  break;
1500  }
1501 
1502  datasize *= fielddefs->m_elementIDs.size();
1503  }
1504  else
1505  {
1506  unsigned int cnt = 0;
1507  // calculate data length
1508  for(i = 0; i < fielddefs->m_elementIDs.size(); ++i)
1509  {
1510  switch(fielddefs->m_shapeType)
1511  {
1512  case eSegment:
1513  {
1514  int l = fielddefs->m_numModes[cnt++];
1515  if(fielddefs->m_numHomogeneousDir == 1)
1516  {
1517  datasize += l*fielddefs->m_numModes[cnt++];
1518  }
1519  else if(fielddefs->m_numHomogeneousDir == 2)
1520  {
1521  int m = fielddefs->m_numModes[cnt++];
1522  datasize += l*m*fielddefs->m_numModes[cnt++];
1523  }
1524  else
1525  {
1526  datasize += l;
1527  }
1528  }
1529  break;
1530  case eTriangle:
1531  {
1532  int l = fielddefs->m_numModes[cnt++];
1533  int m = fielddefs->m_numModes[cnt++];
1534  if(fielddefs->m_numHomogeneousDir == 1)
1535  {
1536  datasize += StdTriData::getNumberOfCoefficients(l,m)*
1537  fielddefs->m_homogeneousZIDs.size();
1538  cnt++;
1539  }
1540  else
1541  {
1542  datasize += StdTriData::getNumberOfCoefficients(l,m);
1543  }
1544  }
1545  break;
1546  case eQuadrilateral:
1547  {
1548  int l = fielddefs->m_numModes[cnt++];
1549  int m = fielddefs->m_numModes[cnt++];
1550  if(fielddefs->m_numHomogeneousDir == 1)
1551  {
1552  datasize += l*m*fielddefs->
1553  m_homogeneousZIDs.size();
1554  cnt++;
1555  }
1556  else
1557  {
1558  datasize += l*m;
1559  }
1560  }
1561  break;
1562  case eTetrahedron:
1563  {
1564  int l = fielddefs->m_numModes[cnt++];
1565  int m = fielddefs->m_numModes[cnt++];
1566  int n = fielddefs->m_numModes[cnt++];
1567  datasize += StdTetData::getNumberOfCoefficients(l,m,n);
1568  }
1569  break;
1570  case ePyramid:
1571  {
1572  int l = fielddefs->m_numModes[cnt++];
1573  int m = fielddefs->m_numModes[cnt++];
1574  int n = fielddefs->m_numModes[cnt++];
1575  datasize += StdPyrData::getNumberOfCoefficients(l,m,n);
1576  }
1577  break;
1578  case ePrism:
1579  {
1580  int l = fielddefs->m_numModes[cnt++];
1581  int m = fielddefs->m_numModes[cnt++];
1582  int n = fielddefs->m_numModes[cnt++];
1583  datasize += StdPrismData::getNumberOfCoefficients(l,m,n);
1584  }
1585  break;
1586  case eHexahedron:
1587  {
1588  int l = fielddefs->m_numModes[cnt++];
1589  int m = fielddefs->m_numModes[cnt++];
1590  int n = fielddefs->m_numModes[cnt++];
1591  datasize += l*m*n;
1592  }
1593  break;
1594  default:
1595  ASSERTL0(false, "Unsupported shape type.");
1596  break;
1597  }
1598  }
1599  }
1600 
1601  return datasize;
1602  }
1603  }
1604 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:188
static bool GenerateOrderedStringVector(const char *const str, std::vector< std::string > &vec)
Definition: ParseUtils.hpp:143
void ImportFieldDefs(TiXmlDocument &doc, std::vector< FieldDefinitionsSharedPtr > &fielddefs, bool expChild)
Imports the definition of the fields.
Definition: FieldIO.cpp:726
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:286
static bool GenerateOrderedVector(const char *const str, std::vector< unsigned int > &vec)
Definition: ParseUtils.hpp:97
tBaseSharedPtr CreateInstance(tKey idKey BOOST_PP_COMMA_IF(MAX_PARAM) BOOST_PP_ENUM_BINARY_PARAMS(MAX_PARAM, tParam, x))
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:162
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
const char *const BasisTypeMap[]
Definition: Foundations.hpp:47
void ImportFieldData(TiXmlDocument &doc, const std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble > > &fielddata)
Imports the data fileds.
Definition: FieldIO.cpp:1018
const std::string kPointsTypeStr[]
Definition: Foundations.hpp:69
FieldIO(LibUtilities::CommSharedPtr pComm, bool sharedFilesystem=false)
Constructor.
Definition: FieldIO.cpp:149
void Import(const std::string &infilename, std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble > > &fielddata=NullVectorNekDoubleVector, FieldMetaDataMap &fieldinfomap=NullFieldMetaDataMap, const Array< OneD, int > ElementiDs=NullInt1DArray)
Imports an FLD file.
Definition: FieldIO.cpp:409
boost::shared_ptr< FieldDefinitions > FieldDefinitionsSharedPtr
Definition: FieldIO.h:118
void ImportMultiFldFileIDs(const std::string &inFile, std::vector< std::string > &fileNames, std::vector< std::vector< unsigned int > > &elementList, FieldMetaDataMap &fieldmetadatamap)
Definition: FieldIO.cpp:577
std::string SetUpOutput(const std::string outname)
Definition: FieldIO.cpp:1191
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:186
static bool GenerateSeqVector(const char *const str, std::vector< unsigned int > &vec)
Definition: ParseUtils.hpp:79
std::map< std::string, std::string > FieldMetaDataMap
Definition: FieldIO.h:53
CommFactory & GetCommFactory()
Definition: Comm.cpp:64
int CheckFieldDefinition(const FieldDefinitionsSharedPtr &fielddefs)
Definition: FieldIO.cpp:1362
const char *const ShapeTypeMap[]
Definition: ShapeType.hpp:66
void Import(const std::string &infilename, std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble > > &fielddata, FieldMetaDataMap &fieldinfomap, const Array< OneD, int > ElementiDs)
Imports an FLD file.
Definition: FieldIO.cpp:115
void GenerateSeqString(const std::vector< unsigned int > &elmtids, std::string &idString)
Definition: FieldIO.cpp:1145
bool m_sharedFilesystem
True if same filesystem accessible by all processes.
Definition: FieldIO.h:194
boost::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
void AddInfoTag(TiXmlElement *root, const FieldMetaDataMap &fieldmetadatamap)
add information about provenance and fieldmetadata
Definition: FieldIO.cpp:1086
const std::string kGitSha1
#define LIB_UTILITIES_EXPORT
#define WARNINGL0(condition, msg)
Definition: ErrorUtil.hpp:194
static std::vector< std::vector< NekDouble > > NullVectorNekDoubleVector
Definition: FieldIO.h:55
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:111
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:41
const std::string kGitBranch
LibUtilities::CommSharedPtr m_comm
Communicator to use when writing parallel format.
Definition: FieldIO.h:191
int ZlibEncodeToBase64Str(std::vector< T > &in, std::string &out64)
Definition: CompressData.h:151
void SetUpFieldMetaData(const std::string outname, const std::vector< FieldDefinitionsSharedPtr > &fielddefs, const FieldMetaDataMap &fieldmetadatamap)
Definition: FieldIO.cpp:1292
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:232
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
#define NEKTAR_VERSION
Definition: FieldIO.cpp:65
void WriteMultiFldFileIDs(const std::string &outfile, const std::vector< std::string > fileNames, std::vector< std::vector< unsigned int > > &elementList, const FieldMetaDataMap &fieldinfomap=NullFieldMetaDataMap)
Definition: FieldIO.cpp:537
Class for operating on FLD files.
Definition: FieldIO.h:137
void ImportFieldMetaData(std::string filename, FieldMetaDataMap &fieldmetadatamap)
Imports the definition of the meta data.
Definition: FieldIO.cpp:637
virtual std::string GetFileEnding() const
Definition: FieldIO.h:218
void Write(const std::string &outFile, std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble > > &fielddata, const FieldMetaDataMap &fieldinfomap=NullFieldMetaDataMap)
Write data in FLD format.
Definition: FieldIO.cpp:160
void Write(const std::string &outFile, std::vector< FieldDefinitionsSharedPtr > &fielddefs, std::vector< std::vector< NekDouble > > &fielddata, const FieldMetaDataMap &fieldinfomap)
Write a field file in serial only.
Definition: FieldIO.cpp:81
static Array< OneD, int > NullInt1DArray
static bool GenerateUnOrderedVector(const char *const str, std::vector< NekDouble > &vec)
Definition: ParseUtils.hpp:128
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:218
static FieldMetaDataMap NullFieldMetaDataMap
Definition: FieldIO.h:54
int ZlibDecodeFromBase64Str(std::string &in64, std::vector< T > &out)
Definition: CompressData.h:243