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