Nektar++
BasicUtils/SessionReader.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File SessionReader.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Session reader
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #ifndef TIXML_USE_STL
36 #define TIXML_USE_STL
37 #endif
38 
41 
42 #include <iostream>
43 #include <fstream>
44 #include <string>
45 
46 #include <boost/iostreams/filtering_streambuf.hpp>
47 #include <boost/iostreams/copy.hpp>
48 #include <boost/iostreams/filter/gzip.hpp>
49 #include <boost/algorithm/string.hpp>
50 
51 #include <tinyxml.h>
52 
59 
60 #include <boost/program_options.hpp>
61 #include <boost/format.hpp>
62 
63 #ifndef NEKTAR_VERSION
64 #define NEKTAR_VERSION "Unknown"
65 #endif
66 
67 using namespace std;
68 
69 namespace po = boost::program_options;
70 namespace io = boost::iostreams;
71 
72 namespace Nektar
73 {
74  namespace LibUtilities
75  {
76  /**
77  * @class SessionReader
78  *
79  * This class provides an interface to Nektar++-specific content in a
80  * supplied XML document. It also initialises a Nektar++ session
81  * including setting up communication for parallel execution and where
82  * necessary partitioning the supplied mesh for running across multiple
83  * processes.
84  *
85  * A session should be initialised at the beginning of a user's
86  * application by passing the command-line arguments. This not only
87  * allows the SessionReader to extract the name of the XML document to
88  * load containing Nektar++ session information, but also supplies the
89  * MPI arguments necessary for setting up parallel communication. The
90  * SessionReader should be initialised using the #CreateInstance
91  * function:
92  * @code
93  * LibUtilities::SessionReaderSharedPtr vSession
94  * = LibUtilities::SessionReader::CreateInstance(argc, argv);
95  * @endcode
96  * The instance \c vSession can now be passed to other key Nektar++
97  * components during their construction.
98  * @note At the end of the user application, it is important to call the
99  * #Finalise routine in order to finalise any MPI communication and
100  * correctly free resources.
101  *
102  * The SessionReader class provides streamlined, validated access to
103  * session parameters, solver information and functions defined within a
104  * Nektar++ XML document. The available routines and their usage is
105  * documented below.
106  *
107  * In the case of solver information properties, the classes to which
108  * these parameters are pertinent may register with the SessionReader
109  * class the set of valid values for a given property. Such values may
110  * also be associated with an enumeration value for more transparent use
111  * of the property values in code.
112  */
113 
114  /**
115  * This map of maps stores the list of valid string values for a number
116  * of solver information parameters. The top level map connects
117  * different parameter names to their list of possible values. The list
118  * of possible values is also a map, mapping a valid string to a
119  * corresponding enum value.
120  *
121  * This list is populated through the #RegisterEnumValue static member
122  * function which is called statically from various classes to register
123  * the valid values for solver info parameters associated with them. The
124  * map is therefore fully populated before the SessionReader class is
125  * instantiated and a file is read in and parsed.
126  */
127  EnumMapList& SessionReader::GetSolverInfoEnums()
128  {
129  static EnumMapList solverInfoEnums;
130  return solverInfoEnums;
131  }
132 
133 
134  /**
135  * List of default values for solver information parameters to be used
136  * in the case of them not being provided.
137  *
138  * This list is populated through the #RegisterDefaultSolverInfo static
139  * member variable which is called statically from various classes to
140  * register the default value for a given parameter.
141  */
142  SolverInfoMap& SessionReader::GetSolverInfoDefaults()
143  {
144  static SolverInfoMap solverInfoMap;
145  return solverInfoMap;
146  }
147 
148 
149  /**
150  * List of values for GlobalSysSoln parameters to be used to override
151  * details given in SolverInfo
152  *
153  * This list is populated by ReadGlobalSysSoln if the
154  * GLOBALSYSSOLNINFO section is defined in the input file.
155  * This List allows for details to define for the Global Sys
156  * solver for each variable.
157  */
158  GloSysSolnInfoList& SessionReader::GetGloSysSolnList()
159  {
160  static GloSysSolnInfoList gloSysSolnInfoList;
161  return gloSysSolnInfoList;
162  }
163 
164  /**
165  * Lists the possible command-line argument which can be specified for
166  * this executable.
167  *
168  * This list is populated through the #RegisterCmdLineArgument static
169  * member function which is called statically from various classes to
170  * register command-line arguments they need.
171  */
172  CmdLineArgMap& SessionReader::GetCmdLineArgMap()
173  {
174  static CmdLineArgMap cmdLineArguments;
175  return cmdLineArguments;
176  }
177 
178 
179  /**
180  * This constructor parses the command-line arguments given to the user
181  * application to set up any MPI communication, read supplied XML
182  * session files, and partition meshes where necessary.
183  *
184  * @param argc Number of command-line arguments
185  * @param argv Array of command-line arguments
186  */
187  SessionReader::SessionReader(int argc, char *argv[])
188  {
189  m_xmlDoc = 0;
190  m_filenames = ParseCommandLineArguments(argc, argv);
191 
192  ASSERTL0(m_filenames.size() > 0, "No session file(s) given.");
193 
194  m_sessionName = ParseSessionName(m_filenames);
195 
196  // Create communicator
197  CreateComm(argc, argv);
198 
199  TestSharedFilesystem();
200 
201  // If running in parallel change the default global sys solution
202  // type.
203  if (m_comm->GetSize() > 1)
204  {
205  GetSolverInfoDefaults()["GLOBALSYSSOLN"] =
206  "IterativeStaticCond";
207  }
208 
210  m_interpreter->SetRandomSeed((m_comm->GetRank() + 1)
211  * (unsigned int)time(NULL));
212 
213  // Split up the communicator
214  PartitionComm();
215  }
216 
217 
218  /**
219  *
220  */
221  SessionReader::SessionReader(
222  int argc,
223  char *argv[],
224  const std::vector<std::string> &pFilenames,
225  const CommSharedPtr &pComm)
226  {
227  ASSERTL0(pFilenames.size() > 0, "No filenames specified.");
228 
229  ParseCommandLineArguments(argc, argv);
230  m_xmlDoc = 0;
231  m_filenames = pFilenames;
232 
233  m_sessionName = ParseSessionName(m_filenames);
234 
235  // Create communicator
236  if (!pComm.get())
237  {
238  CreateComm(argc, argv);
239  }
240  else
241  {
242  m_comm = pComm;
243  }
244 
245  TestSharedFilesystem();
246 
247  // If running in parallel change the default global sys solution
248  // type.
249  if (m_comm->GetSize() > 1)
250  {
251  GetSolverInfoDefaults()["GLOBALSYSSOLN"] =
252  "IterativeStaticCond";
253  }
254 
256  m_interpreter->SetRandomSeed((m_comm->GetRank() + 1)
257  * (unsigned int)time(NULL));
258 
259  // Split up the communicator
260  PartitionComm();
261  }
262 
263 
264  /**
265  *
266  */
267  SessionReader::~SessionReader()
268  {
269  if (m_xmlDoc)
270  {
271  delete m_xmlDoc;
272  }
273  }
274 
275 
276  /**
277  * Performs the main initialisation of the object. The XML file provided
278  * on the command-line is loaded and any mesh partitioning is done. The
279  * resulting process-specific XML file (containing the process's
280  * geometry partition) is then reloaded and parsed.
281  */
282  void SessionReader::InitSession(
283  const std::vector<std::string> &filenames)
284  {
285  // Re-load filenames for session if required.
286  if (filenames.size() > 0)
287  {
288  m_filenames = filenames;
289  }
290 
291  // Merge document if required.
292  if (m_xmlDoc)
293  {
294  delete m_xmlDoc;
295  }
296 
297  m_xmlDoc = MergeDoc(m_filenames);
298 
299  // Parse the XML data in #m_xmlDoc
300  ParseDocument();
301 
302  // Override SOLVERINFO and parameters with any specified on the
303  // command line.
304  CmdLineOverride();
305 
306  // Verify SOLVERINFO values
307  VerifySolverInfo();
308 
309  // In verbose mode, print out parameters and solver info sections
310  if (m_verbose && m_comm)
311  {
312  if (m_comm->TreatAsRankZero() && m_parameters.size() > 0)
313  {
314  cout << "Parameters:" << endl;
315  for (auto &x : m_parameters)
316  {
317  cout << "\t" << x.first << " = " << x.second << endl;
318  }
319  cout << endl;
320  }
321 
322  if (m_comm->TreatAsRankZero() && m_solverInfo.size() > 0)
323  {
324  cout << "Solver Info:" << endl;
325  for (auto &x : m_solverInfo)
326  {
327  cout << "\t" << x.first << " = " << x.second << endl;
328  }
329  cout << endl;
330  }
331  }
332  }
333 
334  void SessionReader::TestSharedFilesystem()
335  {
336  m_sharedFilesystem = false;
337 
338  if (m_comm->GetSize() > 1)
339  {
340  if (m_comm->GetRank() == 0)
341  {
342  std::ofstream testfile("shared-fs-testfile");
343  testfile << "" << std::endl;
344  ASSERTL1(!testfile.fail(), "Test file creation failed");
345  testfile.close();
346  }
347  m_comm->Block();
348 
349  int exists = (bool)boost::filesystem::exists("shared-fs-testfile");
350  m_comm->AllReduce(exists, LibUtilities::ReduceSum);
351 
352  m_sharedFilesystem = (exists == m_comm->GetSize());
353 
354  if ((m_sharedFilesystem && m_comm->GetRank() == 0) ||
355  !m_sharedFilesystem)
356  {
357  std::remove("shared-fs-testfile");
358  }
359  }
360  else
361  {
362  m_sharedFilesystem = false;
363  }
364 
365  if (m_verbose && m_comm->GetRank() == 0 && m_sharedFilesystem)
366  {
367  cout << "Shared filesystem detected" << endl;
368  }
369  }
370 
371 
372  /**
373  * @brief Parses the command-line arguments for known options and
374  * filenames.
375  */
376  std::vector<std::string> SessionReader::ParseCommandLineArguments(
377  int argc, char *argv[])
378  {
379  // List the publically visible options (listed using --help)
380  po::options_description desc("Allowed options");
381  desc.add_options()
382  ("verbose,v", "be verbose")
383  ("version,V", "print version information")
384  ("help,h", "print this help message")
385  ("solverinfo,I", po::value<vector<std::string> >(),
386  "override a SOLVERINFO property")
387  ("parameter,P", po::value<vector<std::string> >(),
388  "override a parameter")
389  ("npx", po::value<int>(),
390  "number of procs in X-dir")
391  ("npy", po::value<int>(),
392  "number of procs in Y-dir")
393  ("npz", po::value<int>(),
394  "number of procs in Z-dir")
395  ("nsz", po::value<int>(),
396  "number of slices in Z-dir")
397  ("part-only", po::value<int>(),
398  "only partition mesh into N partitions.")
399  ("part-only-overlapping", po::value<int>(),
400  "only partition mesh into N overlapping partitions.")
401  ("part-info", "Output partition information")
402 #ifdef NEKTAR_USE_CWIPI
403  ("cwipi", po::value<std::string>(),
404  "set CWIPI name")
405 #endif
406  ;
407 
408  for (auto &cmdIt : GetCmdLineArgMap())
409  {
410  std::string names = cmdIt.first;
411  if (cmdIt.second.shortName != "")
412  {
413  names += "," + cmdIt.second.shortName;
414  }
415  if (cmdIt.second.isFlag)
416  {
417  desc.add_options()
418  (names.c_str(), cmdIt.second.description.c_str())
419  ;
420  }
421  else
422  {
423  desc.add_options()
424  (names.c_str(), po::value<std::string>(),
425  cmdIt.second.description.c_str())
426  ;
427  }
428  }
429 
430  // List hidden options (e.g. session file arguments are not actually
431  // specified using the input-file option by the user).
432  po::options_description hidden("Hidden options");
433  hidden.add_options()
434  ("input-file", po::value< vector<string> >(),
435  "input filename")
436  ;
437 
438  // Combine all options for the parser
439  po::options_description all("All options");
440  all.add(desc).add(hidden);
441 
442  // Session file is a positional option
443  po::positional_options_description p;
444  p.add("input-file", -1);
445 
446  // Parse the command-line options
447  po::parsed_options parsed = po::command_line_parser(argc, argv).
448  options(all).
449  positional(p).
450  allow_unregistered().
451  run();
452 
453  // Extract known options to map and update
454  po::store(parsed, m_cmdLineOptions);
455  po::notify(m_cmdLineOptions);
456 
457  // Help message
458  if (m_cmdLineOptions.count("help"))
459  {
460  cout << desc;
461  exit(0);
462  }
463 
464  // Version information
465  if (m_cmdLineOptions.count("version"))
466  {
467  cout << "Nektar++ version " << NEKTAR_VERSION;
468 
469  if (NekConstants::kGitSha1 != "GITDIR-NOTFOUND")
470  {
471  string sha1(NekConstants::kGitSha1);
472  string branch(NekConstants::kGitBranch);
473  boost::replace_all(branch, "refs/heads/", "");
474 
475  cout << " (git changeset " << sha1.substr(0, 8) << ", ";
476 
477  if (branch == "")
478  {
479  cout << "detached head";
480  }
481  else
482  {
483  cout << "head " << branch;
484  }
485 
486  cout << ")";
487  }
488 
489  cout << endl;
490  exit(0);
491  }
492 
493  // Enable verbose mode
494  if (m_cmdLineOptions.count("verbose"))
495  {
496  m_verbose = true;
497  }
498  else
499  {
500  m_verbose = false;
501  }
502 
503  // Print a warning for unknown options
504  for (auto &x : parsed.options)
505  {
506  if (x.unregistered)
507  {
508  cout << "Warning: Unknown option: " << x.string_key
509  << endl;
510  }
511  }
512 
513  // Return the vector of filename(s) given as positional options
514  if (m_cmdLineOptions.count("input-file"))
515  {
516  return m_cmdLineOptions["input-file"].as<
517  std::vector<std::string> >();
518  }
519  else
520  {
521  return std::vector<std::string>();
522  }
523  }
524 
525 
526  /**
527  *
528  */
529  std::string SessionReader::ParseSessionName(
530  std::vector<std::string> &filenames)
531  {
532  ASSERTL0(!filenames.empty(),
533  "At least one filename expected.");
534 
535  std::string retval = "";
536 
537  // First input file defines the session name
538  std::string fname = filenames[0];
539 
540  // If loading a pre-partitioned mesh, remove _xml extension
541  if (fname.size() > 4 &&
542  fname.substr(fname.size() - 4, 4) == "_xml")
543  {
544  retval = fname.substr(0, fname.find_last_of("_"));
545  }
546  // otherwise remove the .xml extension
547  else if (fname.size() > 4 &&
548  fname.substr(fname.size() - 4, 4) == ".xml")
549  {
550  retval = fname.substr(0, fname.find_last_of("."));
551  }
552  // If compressed .xml.gz, remove both extensions
553  else if (fname.size() > 7 &&
554  fname.substr(fname.size() - 7, 7) == ".xml.gz")
555  {
556  retval = fname.substr(0, fname.find_last_of("."));
557  retval = retval.substr(0, retval.find_last_of("."));
558  }
559 
560  return retval;
561  }
562 
563 
564  /**
565  *
566  */
567  TiXmlDocument& SessionReader::GetDocument()
568  {
569  ASSERTL1(m_xmlDoc, "XML Document not defined.");
570  return *m_xmlDoc;
571  }
572 
573 
574  /**
575  * The single parameter specifies a path to the requested element in a
576  * similar format to the filesystem path. Given the following XML:
577  * @code
578  * <NEKTAR>
579  * <CONDITIONS>
580  * <PARAMETERS>
581  * ...
582  * </PARAMETERS>
583  * </CONDITIONS>
584  * </NEKTAR>
585  * @endcode
586  * the PARAMETERS element would be retrieved by requesting the path:
587  * @code
588  * Nektar/Conditions/Parameters
589  * @endcode
590  * @note Paths are case-insensitive.
591  *
592  * @param pPath Path to requested element.
593  *
594  * @return Direct pointer to requested XML Element.
595  */
596  TiXmlElement* SessionReader::GetElement(const string& pPath)
597  {
598  std::string vPath = boost::to_upper_copy(pPath);
599  std::vector<std::string> st;
600  boost::split(st, vPath, boost::is_any_of("\\/ "));
601  ASSERTL0(st.size() > 0, "No path given in XML element request.");
602 
603  TiXmlElement* vReturn = m_xmlDoc->FirstChildElement(st[0].c_str());
604  ASSERTL0(vReturn, std::string("Cannot find element '")
605  + st[0] + std::string("'."));
606  for (int i = 1; i < st.size(); ++i)
607  {
608  vReturn = vReturn->FirstChildElement(st[i].c_str());
609  ASSERTL0(vReturn, std::string("Cannot find element '")
610  + st[i] + std::string("'."));
611  }
612  return vReturn;
613  }
614 
615 
616  /**
617  *
618  */
619  bool SessionReader::DefinesElement(const std::string &pPath) const
620  {
621  std::string vPath = boost::to_upper_copy(pPath);
622  std::vector<std::string> st;
623  boost::split(st, vPath, boost::is_any_of("\\/ "));
624  ASSERTL0(st.size() > 0, "No path given in XML element request.");
625 
626  TiXmlElement* vReturn = m_xmlDoc->FirstChildElement(st[0].c_str());
627  ASSERTL0(vReturn, std::string("Cannot find element '")
628  + st[0] + std::string("'."));
629  for (int i = 1; i < st.size(); ++i)
630  {
631  vReturn = vReturn->FirstChildElement(st[i].c_str());
632  if (!vReturn) return false;
633  }
634  return true;
635  }
636 
637 
638  /**
639  *
640  */
641  const std::vector<std::string>& SessionReader::GetFilenames() const
642  {
643  return m_filenames;
644  }
645 
646 
647  /**
648  *
649  */
650  const std::string& SessionReader::GetSessionName() const
651  {
652  return m_sessionName;
653  }
654 
655 
656  /**
657  * Output is of the form [sessionName]_P[idx] where idx is the rank
658  * of the process.
659  */
660  const std::string SessionReader::GetSessionNameRank() const
661  {
662  std::string dirname = m_sessionName + "_xml";
663  fs::path pdirname(dirname);
664 
665  std::string vFilename = "P" + boost::lexical_cast<std::string>(m_comm->GetRowComm()->GetRank());
666  fs::path pFilename(vFilename);
667 
668  fs::path fullpath = pdirname / pFilename;
669 
670  return PortablePath(fullpath);
671  }
672 
673  /**
674  *
675  */
676  CommSharedPtr SessionReader::GetComm()
677  {
678  return m_comm;
679  }
680 
681  bool SessionReader::GetSharedFilesystem()
682  {
683  return m_sharedFilesystem;
684  }
685 
686  /**
687  * This routine finalises any parallel communication.
688  *
689  * @note This routine should be called at the very end of a users
690  * application.
691  */
693  {
694  m_comm->Finalise();
695  }
696 
697 
698  /**
699  *
700  */
701  bool SessionReader::DefinesParameter(const std::string& pName) const
702  {
703  std::string vName = boost::to_upper_copy(pName);
704  return m_parameters.find(vName) != m_parameters.end();
705  }
706 
707 
708  /**
709  * If the parameter is not defined, termination occurs. Therefore, the
710  * parameters existence should be tested for using #DefinesParameter
711  * before calling this function.
712  *
713  * @param pName The name of a floating-point parameter.
714  * @returns The value of the floating-point parameter.
715  */
716  const NekDouble& SessionReader::GetParameter(
717  const std::string& pName) const
718  {
719  std::string vName = boost::to_upper_copy(pName);
720  auto paramIter = m_parameters.find(vName);
721 
722  ASSERTL0(paramIter != m_parameters.end(),
723  "Unable to find requested parameter: " + pName);
724 
725  return paramIter->second;
726  }
727 
728 
729  /**
730  *
731  */
732  void SessionReader::LoadParameter(
733  const std::string &pName, int &pVar) const
734  {
735  std::string vName = boost::to_upper_copy(pName);
736  auto paramIter = m_parameters.find(vName);
737  ASSERTL0(paramIter != m_parameters.end(), "Required parameter '" +
738  pName + "' not specified in session.");
739  pVar = (int)round(paramIter->second);
740  }
741 
742 
743  /**
744  *
745  */
746  void SessionReader::LoadParameter(
747  const std::string &pName, int &pVar, const int &pDefault) const
748  {
749  std::string vName = boost::to_upper_copy(pName);
750  auto paramIter = m_parameters.find(vName);
751  if(paramIter != m_parameters.end())
752  {
753  pVar = (int)round(paramIter->second);
754  }
755  else
756  {
757  pVar = pDefault;
758  }
759  }
760 
761 
762  /**
763  *
764  */
765  void SessionReader::LoadParameter(
766  const std::string &pName, NekDouble& pVar) const
767  {
768  std::string vName = boost::to_upper_copy(pName);
769  auto paramIter = m_parameters.find(vName);
770  ASSERTL0(paramIter != m_parameters.end(), "Required parameter '" +
771  pName + "' not specified in session.");
772  pVar = paramIter->second;
773  }
774 
775 
776  /**
777  *
778  */
779  void SessionReader::LoadParameter(
780  const std::string &pName,
781  NekDouble &pVar,
782  const NekDouble &pDefault) const
783  {
784  std::string vName = boost::to_upper_copy(pName);
785  auto paramIter = m_parameters.find(vName);
786  if(paramIter != m_parameters.end())
787  {
788  pVar = paramIter->second;
789  }
790  else
791  {
792  pVar = pDefault;
793  }
794  }
795 
796 
797 
798  /**
799  *
800  */
801  void SessionReader::SetParameter(const std::string &pName, int &pVar)
802  {
803  std::string vName = boost::to_upper_copy(pName);
804  m_parameters[vName] = pVar;
805  }
806 
807 
808  /**
809  *
810  */
811  void SessionReader::SetParameter(
812  const std::string &pName, NekDouble& pVar)
813  {
814  std::string vName = boost::to_upper_copy(pName);
815  m_parameters[vName] = pVar;
816  }
817 
818 
819 
820  /**
821  *
822  */
823  bool SessionReader::DefinesSolverInfo(const std::string &pName) const
824  {
825  std::string vName = boost::to_upper_copy(pName);
826  auto infoIter = m_solverInfo.find(vName);
827  return (infoIter != m_solverInfo.end());
828  }
829 
830 
831  /**
832  *
833  */
834  const std::string& SessionReader::GetSolverInfo(
835  const std::string &pProperty) const
836  {
837  std::string vProperty = boost::to_upper_copy(pProperty);
838  auto iter = m_solverInfo.find(vProperty);
839 
840  ASSERTL1(iter != m_solverInfo.end(),
841  "Unable to find requested property: " + pProperty);
842 
843  return iter->second;
844  }
845 
846  /**
847  *
848  */
849  void SessionReader::SetSolverInfo(
850  const std::string &pProperty, const std::string &pValue)
851  {
852  std::string vProperty = boost::to_upper_copy(pProperty);
853  auto iter = m_solverInfo.find(vProperty);
854 
855  ASSERTL1(iter != m_solverInfo.end(),
856  "Unable to find requested property: " + pProperty);
857 
858  iter->second = pValue;
859  }
860 
861  /**
862  *
863  */
864  void SessionReader::LoadSolverInfo(
865  const std::string &pName,
866  std::string &pVar,
867  const std::string &pDefault) const
868  {
869  std::string vName = boost::to_upper_copy(pName);
870  auto infoIter = m_solverInfo.find(vName);
871  if(infoIter != m_solverInfo.end())
872  {
873  pVar = infoIter->second;
874  }
875  else
876  {
877  pVar = pDefault;
878  }
879  }
880 
881 
882  /**
883  *
884  */
885  void SessionReader::MatchSolverInfo(
886  const std::string &pName,
887  const std::string &pTrueVal,
888  bool &pVar,
889  const bool &pDefault) const
890  {
891  std::string vName = boost::to_upper_copy(pName);
892  auto infoIter = m_solverInfo.find(vName);
893  if(infoIter != m_solverInfo.end())
894  {
895  pVar = boost::iequals(infoIter->second, pTrueVal);
896  }
897  else
898  {
899  pVar = pDefault;
900  }
901  }
902 
903 
904  /**
905  *
906  */
907  bool SessionReader::MatchSolverInfo(
908  const std::string &pName,
909  const std::string &pTrueVal) const
910  {
911  if (DefinesSolverInfo(pName))
912  {
913  std::string vName = boost::to_upper_copy(pName);
914  auto iter = m_solverInfo.find(vName);
915  if(iter != m_solverInfo.end())
916  {
917  return boost::iequals(iter->second, pTrueVal);
918  }
919  }
920  return false;
921  }
922 
923 
924  /**
925  *
926  */
927  bool SessionReader::DefinesGlobalSysSolnInfo(const std::string &pVariable,
928  const std::string &pProperty) const
929  {
930  auto iter = GetGloSysSolnList().find(pVariable);
931  if(iter == GetGloSysSolnList().end())
932  {
933  return false;
934  }
935 
936  std::string vProperty = boost::to_upper_copy(pProperty);
937 
938  auto iter1 = iter->second.find(vProperty);
939  if(iter1 == iter->second.end())
940  {
941  return false;
942  }
943 
944  return true;
945  }
946 
947 
948  /**
949  *
950  */
951  const std::string &SessionReader::GetGlobalSysSolnInfo(const std::string &pVariable, const std::string &pProperty) const
952  {
953  auto iter = GetGloSysSolnList().find(pVariable);
954  ASSERTL0(iter != GetGloSysSolnList().end(),
955  "Failed to find variable in GlobalSysSolnInfoList");
956 
957  std::string vProperty = boost::to_upper_copy(pProperty);
958  auto iter1 = iter->second.find(vProperty);
959 
960  ASSERTL0(iter1 != iter->second.end(),
961  "Failed to find property: " + vProperty + " in GlobalSysSolnInfoList");
962 
963  return iter1->second;
964  }
965 
966  std::string SessionReader::GetGeometryType() const
967  {
968  TiXmlElement *xmlGeom = m_xmlDoc->FirstChildElement("NEKTAR")
969  ->FirstChildElement("GEOMETRY");
970  TiXmlAttribute *attr = xmlGeom->FirstAttribute();
971  while (attr)
972  {
973  std::string attrName(attr->Name());
974  if (attrName == "HDF5FILE")
975  {
976  // there is a file pointer, therefore is HDF5
977  return "HDF5";
978  }
979  // Get the next attribute.
980  attr = attr->Next();
981  }
982 
983  // Check the VERTEX block. If this is compressed, assume the file is
984  // compressed, otherwise assume uncompressed.
985  TiXmlElement *element = xmlGeom->FirstChildElement("VERTEX");
986  string IsCompressed;
987  element->QueryStringAttribute("COMPRESSED", &IsCompressed);
988 
989  if (IsCompressed.size() > 0)
990  {
991  return "XmlCompressed";
992  }
993 
994  // no file pointer or compressed, just standard xml
995  return "Xml";
996  }
997 
998  /**
999  *
1000  */
1001  bool SessionReader::DefinesGeometricInfo(const std::string &pName) const
1002  {
1003  std::string vName = boost::to_upper_copy(pName);
1004  return m_geometricInfo.find(vName) != m_geometricInfo.end();
1005  }
1006 
1007 
1008  /**
1009  *
1010  */
1011  void SessionReader::LoadGeometricInfo(
1012  const std::string &pName,
1013  std::string &pVar,
1014  const std::string &pDefault) const
1015  {
1016  std::string vName = boost::to_upper_copy(pName);
1017  auto iter = m_geometricInfo.find(vName);
1018  if(iter != m_geometricInfo.end())
1019  {
1020  pVar = iter->second;
1021  }
1022  else
1023  {
1024  pVar = pDefault;
1025  }
1026  }
1027 
1028 
1029  /**
1030  *
1031  */
1032  void SessionReader::LoadGeometricInfo(
1033  const std::string &pName,
1034  bool &pVar,
1035  const bool &pDefault) const
1036  {
1037  std::string vName = boost::to_upper_copy(pName);
1038  auto iter = m_geometricInfo.find(vName);
1039  if(iter != m_geometricInfo.end())
1040  {
1041  if (iter->second == "TRUE")
1042  {
1043  pVar = true;
1044  }
1045  else
1046  {
1047  pVar = false;
1048  }
1049  }
1050  else
1051  {
1052  pVar = pDefault;
1053  }
1054  }
1055 
1056 
1057  /**
1058  *
1059  */
1060  void SessionReader::LoadGeometricInfo(
1061  const std::string &pName,
1062  NekDouble &pVar,
1063  const NekDouble &pDefault) const
1064  {
1065  std::string vName = boost::to_upper_copy(pName);
1066  auto iter = m_geometricInfo.find(vName);
1067  if(iter != m_geometricInfo.end())
1068  {
1069  pVar = std::atoi(iter->second.c_str());
1070  }
1071  else
1072  {
1073  pVar = pDefault;
1074  }
1075  }
1076 
1077 
1078  /**
1079  *
1080  */
1081  void SessionReader::MatchGeometricInfo(
1082  const std::string &pName,
1083  const std::string &pTrueVal,
1084  bool &pVar,
1085  const bool &pDefault) const
1086  {
1087  std::string vName = boost::to_upper_copy(pName);
1088  auto iter = m_geometricInfo.find(vName);
1089  if(iter != m_geometricInfo.end())
1090  {
1091  pVar = boost::iequals(iter->second, pTrueVal);
1092  }
1093  else
1094  {
1095  pVar = pDefault;
1096  }
1097  }
1098 
1099 
1100  /**
1101  *
1102  */
1103  const std::string& SessionReader::GetVariable(
1104  const unsigned int &idx) const
1105  {
1106  ASSERTL0(idx < m_variables.size(), "Variable index out of range.");
1107  return m_variables[idx];
1108  }
1109 
1110 
1111 
1112  /**
1113  *
1114  */
1115  void SessionReader::SetVariable(const unsigned int &idx,
1116  std::string newname)
1117  {
1118  ASSERTL0(idx < m_variables.size(), "Variable index out of range.");
1119  m_variables[idx] = newname;
1120  }
1121 
1122 
1123  /**
1124  *
1125  */
1126  std::vector<std::string> SessionReader::GetVariables() const
1127  {
1128  return m_variables;
1129  }
1130 
1131 
1132  /**
1133  *
1134  */
1135  bool SessionReader::DefinesFunction(const std::string &pName) const
1136  {
1137  std::string vName = boost::to_upper_copy(pName);
1138  return m_functions.find(vName) != m_functions.end();
1139  }
1140 
1141 
1142  /**
1143  *
1144  */
1145  bool SessionReader::DefinesFunction(
1146  const std::string &pName,
1147  const std::string &pVariable,
1148  const int pDomain) const
1149  {
1150  std::string vName = boost::to_upper_copy(pName);
1151 
1152  // Check function exists
1153  auto it1 = m_functions.find(vName);
1154  if (it1 != m_functions.end())
1155  {
1156  pair<std::string, int> key(pVariable,pDomain);
1157  pair<std::string, int> defkey("*",pDomain);
1158  bool varExists =
1159  it1->second.find(key) != it1->second.end() ||
1160  it1->second.find(defkey) != it1->second.end();
1161  return varExists;
1162  }
1163  return false;
1164  }
1165 
1166 
1167  /**
1168  *
1169  */
1170  EquationSharedPtr SessionReader::GetFunction(
1171  const std::string &pName,
1172  const std::string &pVariable,
1173  const int pDomain) const
1174  {
1175  std::string vName = boost::to_upper_copy(pName);
1176  auto it1 = m_functions.find(vName);
1177 
1178  ASSERTL0(it1 != m_functions.end(),
1179  std::string("No such function '") + pName
1180  + std::string("' has been defined in the session file."));
1181 
1182  // Check for specific and wildcard definitions
1183  pair<std::string,int> key(pVariable,pDomain);
1184  pair<std::string,int> defkey("*",pDomain);
1185 
1186  auto it2 = it1->second.find(key);
1187  auto it3 = it1->second.find(defkey);
1188  bool specific = it2 != it1->second.end();
1189  bool wildcard = it3 != it1->second.end();
1190 
1191  // Check function is defined somewhere
1192  ASSERTL0(specific || wildcard,
1193  "No such variable " + pVariable
1194  + " in domain " + boost::lexical_cast<string>(pDomain)
1195  + " defined for function " + pName
1196  + " in session file.");
1197 
1198  // If not specific, must be wildcard
1199  if (!specific)
1200  {
1201  it2 = it3;
1202  }
1203 
1204  ASSERTL0((it2->second.m_type == eFunctionTypeExpression),
1205  std::string("Function is defined by a file."));
1206  return it2->second.m_expression;
1207  }
1208 
1209 
1210  /**
1211  *
1212  */
1213  EquationSharedPtr SessionReader::GetFunction(
1214  const std::string &pName,
1215  const unsigned int &pVar,
1216  const int pDomain) const
1217  {
1218  ASSERTL0(pVar < m_variables.size(), "Variable index out of range.");
1219  return GetFunction(pName, m_variables[pVar],pDomain);
1220  }
1221 
1222 
1223  /**
1224  *
1225  */
1226  enum FunctionType SessionReader::GetFunctionType(
1227  const std::string &pName,
1228  const std::string &pVariable,
1229  const int pDomain) const
1230  {
1231  std::string vName = boost::to_upper_copy(pName);
1232  auto it1 = m_functions.find(vName);
1233 
1234  ASSERTL0 (it1 != m_functions.end(),
1235  std::string("Function '") + pName
1236  + std::string("' not found."));
1237 
1238  // Check for specific and wildcard definitions
1239  pair<std::string,int> key(pVariable,pDomain);
1240  pair<std::string,int> defkey("*",pDomain);
1241 
1242  auto it2 = it1->second.find(key);
1243  auto it3 = it1->second.find(defkey);
1244  bool specific = it2 != it1->second.end();
1245  bool wildcard = it3 != it1->second.end();
1246 
1247  // Check function is defined somewhere
1248  ASSERTL0(specific || wildcard,
1249  "No such variable " + pVariable
1250  + " in domain " + boost::lexical_cast<string>(pDomain)
1251  + " defined for function " + pName
1252  + " in session file.");
1253 
1254  // If not specific, must be wildcard
1255  if (!specific)
1256  {
1257  it2 = it3;
1258  }
1259 
1260  return it2->second.m_type;
1261  }
1262 
1263 
1264  /**
1265  *
1266  */
1267  enum FunctionType SessionReader::GetFunctionType(
1268  const std::string &pName,
1269  const unsigned int &pVar,
1270  const int pDomain) const
1271  {
1272  ASSERTL0(pVar < m_variables.size(), "Variable index out of range.");
1273  return GetFunctionType(pName, m_variables[pVar],pDomain);
1274  }
1275 
1276 
1277  /**
1278  *
1279  */
1280  std::string SessionReader::GetFunctionFilename(
1281  const std::string &pName,
1282  const std::string &pVariable,
1283  const int pDomain) const
1284  {
1285  std::string vName = boost::to_upper_copy(pName);
1286  auto it1 = m_functions.find(vName);
1287 
1288  ASSERTL0 (it1 != m_functions.end(),
1289  std::string("Function '") + pName
1290  + std::string("' not found."));
1291 
1292  // Check for specific and wildcard definitions
1293  pair<std::string,int> key(pVariable,pDomain);
1294  pair<std::string,int> defkey("*",pDomain);
1295 
1296  auto it2 = it1->second.find(key);
1297  auto it3 = it1->second.find(defkey);
1298  bool specific = it2 != it1->second.end();
1299  bool wildcard = it3 != it1->second.end();
1300 
1301  // Check function is defined somewhere
1302  ASSERTL0(specific || wildcard,
1303  "No such variable " + pVariable
1304  + " in domain " + boost::lexical_cast<string>(pDomain)
1305  + " defined for function " + pName
1306  + " in session file.");
1307 
1308  // If not specific, must be wildcard
1309  if (!specific)
1310  {
1311  it2 = it3;
1312  }
1313 
1314  return it2->second.m_filename;
1315  }
1316 
1317 
1318  /**
1319  *
1320  */
1321  std::string SessionReader::GetFunctionFilename(
1322  const std::string &pName,
1323  const unsigned int &pVar,
1324  const int pDomain) const
1325  {
1326  ASSERTL0(pVar < m_variables.size(), "Variable index out of range.");
1327  return GetFunctionFilename(pName, m_variables[pVar],pDomain);
1328  }
1329 
1330 
1331  /**
1332  *
1333  */
1334  std::string SessionReader::GetFunctionFilenameVariable(
1335  const std::string &pName,
1336  const std::string &pVariable,
1337  const int pDomain) const
1338  {
1339  std::string vName = boost::to_upper_copy(pName);
1340  auto it1 = m_functions.find(vName);
1341 
1342  ASSERTL0 (it1 != m_functions.end(),
1343  std::string("Function '") + pName
1344  + std::string("' not found."));
1345 
1346  // Check for specific and wildcard definitions
1347  pair<std::string,int> key(pVariable,pDomain);
1348  pair<std::string,int> defkey("*",pDomain);
1349 
1350  auto it2 = it1->second.find(key);
1351  auto it3 = it1->second.find(defkey);
1352  bool specific = it2 != it1->second.end();
1353  bool wildcard = it3 != it1->second.end();
1354 
1355  // Check function is defined somewhere
1356  ASSERTL0(specific || wildcard,
1357  "No such variable " + pVariable
1358  + " in domain " + boost::lexical_cast<string>(pDomain)
1359  + " defined for function " + pName
1360  + " in session file.");
1361 
1362  // If not specific, must be wildcard
1363  if (!specific)
1364  {
1365  it2 = it3;
1366  }
1367 
1368  return it2->second.m_fileVariable;
1369  }
1370 
1371 
1372  /**
1373  *
1374  */
1375  bool SessionReader::DefinesTag(const std::string &pName) const
1376  {
1377  std::string vName = boost::to_upper_copy(pName);
1378  return m_tags.find(vName) != m_tags.end();
1379  }
1380 
1381 
1382  /**
1383  *
1384  */
1385  void SessionReader::SetTag(
1386  const std::string &pName,
1387  const std::string &pValue)
1388  {
1389  std::string vName = boost::to_upper_copy(pName);
1390  m_tags[vName] = pValue;
1391  }
1392 
1393 
1394  /**
1395  *
1396  */
1397  const std::string &SessionReader::GetTag(const std::string& pName) const
1398  {
1399  std::string vName = boost::to_upper_copy(pName);
1400  auto vTagIterator = m_tags.find(vName);
1401  ASSERTL0(vTagIterator != m_tags.end(),
1402  "Requested tag does not exist.");
1403  return vTagIterator->second;
1404  }
1405 
1406 
1407  /**
1408  *
1409  */
1410  const FilterMap &SessionReader::GetFilters() const
1411  {
1412  return m_filters;
1413  }
1414 
1415 
1416  /**
1417  *
1418  */
1419  bool SessionReader::DefinesCmdLineArgument(
1420  const std::string& pName) const
1421  {
1422  return (m_cmdLineOptions.find(pName) != m_cmdLineOptions.end());
1423  }
1424 
1425 
1426  /**
1427  *
1428  */
1429  void SessionReader::SubstituteExpressions(std::string& pExpr)
1430  {
1431  for (auto &exprIter : m_expressions)
1432  {
1433  boost::replace_all(pExpr, exprIter.first, exprIter.second);
1434  }
1435  }
1436 
1437  /**
1438  *
1439  */
1440  void SessionReader::LoadDoc(
1441  const std::string &pFilename,
1442  TiXmlDocument* pDoc) const
1443  {
1444  if (pFilename.size() > 3 &&
1445  pFilename.substr(pFilename.size() - 3, 3) == ".gz")
1446  {
1447  ifstream file(pFilename.c_str(),
1448  ios_base::in | ios_base::binary);
1449  ASSERTL0(file.good(), "Unable to open file: " + pFilename);
1450  stringstream ss;
1451  io::filtering_streambuf<io::input> in;
1452  in.push(io::gzip_decompressor());
1453  in.push(file);
1454  try
1455  {
1456  io::copy(in, ss);
1457  ss >> (*pDoc);
1458  }
1459  catch (io::gzip_error&)
1460  {
1461  NEKERROR(ErrorUtil::efatal,
1462  "Error: File '" + pFilename + "' is corrupt.");
1463  }
1464  }
1465  else if (pFilename.size() > 4 &&
1466  pFilename.substr(pFilename.size() - 4, 4) == "_xml")
1467  {
1468  fs::path pdirname(pFilename);
1469  boost::format pad("P%1$07d.xml");
1470  pad % m_comm->GetRank();
1471  fs::path pRankFilename(pad.str());
1472  fs::path fullpath = pdirname / pRankFilename;
1473 
1474  ifstream file(PortablePath(fullpath).c_str());
1475  ASSERTL0(file.good(), "Unable to open file: " + fullpath.string());
1476  file >> (*pDoc);
1477  }
1478  else
1479  {
1480  ifstream file(pFilename.c_str());
1481  ASSERTL0(file.good(), "Unable to open file: " + pFilename);
1482  file >> (*pDoc);
1483  }
1484  }
1485 
1486  /**
1487  *
1488  */
1489  TiXmlDocument *SessionReader::MergeDoc(
1490  const std::vector<std::string> &pFilenames) const
1491  {
1492  ASSERTL0(pFilenames.size() > 0, "No filenames for merging.");
1493 
1494  // Read the first document
1495  TiXmlDocument *vMainDoc = new TiXmlDocument;
1496  LoadDoc(pFilenames[0], vMainDoc);
1497 
1498  TiXmlHandle vMainHandle(vMainDoc);
1499  TiXmlElement* vMainNektar =
1500  vMainHandle.FirstChildElement("NEKTAR").Element();
1501 
1502  // Read all subsequent XML documents.
1503  // For each element within the NEKTAR tag, use it to replace the
1504  // version already present in the loaded XML data.
1505  for (int i = 1; i < pFilenames.size(); ++i)
1506  {
1507  if((pFilenames[i].compare(pFilenames[i].size()-3,3,"xml") == 0)
1508  ||(pFilenames[i].compare(pFilenames[i].size()-6,6,"xml.gz") == 0))
1509  {
1510  TiXmlDocument* vTempDoc = new TiXmlDocument;
1511  LoadDoc(pFilenames[i], vTempDoc);
1512 
1513  TiXmlHandle docHandle(vTempDoc);
1514  TiXmlElement* vTempNektar;
1515  vTempNektar = docHandle.FirstChildElement("NEKTAR").Element();
1516  ASSERTL0(vTempNektar, "Unable to find NEKTAR tag in file.");
1517  TiXmlElement* p = vTempNektar->FirstChildElement();
1518 
1519  while (p)
1520  {
1521  TiXmlElement *vMainEntry =
1522  vMainNektar->FirstChildElement(p->Value());
1523 
1524  // First check if the new item is in fact blank
1525  if (!p->FirstChild() && vMainEntry)
1526  {
1527  std::string warningmsg =
1528  "File " + pFilenames[i] + " contains " +
1529  "an empty XML element " +
1530  std::string(p->Value()) +
1531  " which will be ignored.";
1532  NEKERROR(ErrorUtil::ewarning, warningmsg.c_str());
1533  }
1534  else
1535  {
1536  if (vMainEntry)
1537  {
1538  vMainNektar->RemoveChild(vMainEntry);
1539  }
1540  TiXmlElement *q = new TiXmlElement(*p);
1541  vMainNektar->LinkEndChild(q);
1542  }
1543  p = p->NextSiblingElement();
1544  }
1545 
1546  delete vTempDoc;
1547  }
1548  }
1549  return vMainDoc;
1550  }
1551 
1552 
1553  /**
1554  *
1555  */
1556  void SessionReader::ParseDocument()
1557  {
1558  // Check we actually have a document loaded.
1559  ASSERTL0(m_xmlDoc, "No XML document loaded.");
1560 
1561  // Look for all data in CONDITIONS block.
1562  TiXmlHandle docHandle(m_xmlDoc);
1563  TiXmlElement* e;
1564  e = docHandle.FirstChildElement("NEKTAR").
1565  FirstChildElement("CONDITIONS").Element();
1566 
1567  // Read the various sections of the CONDITIONS block
1568  ReadParameters (e);
1569  ReadSolverInfo (e);
1570  ReadGlobalSysSolnInfo (e);
1571  ReadExpressions (e);
1572  ReadVariables (e);
1573  ReadFunctions (e);
1574 
1575  e = docHandle.FirstChildElement("NEKTAR").
1576  FirstChildElement("FILTERS").Element();
1577 
1578  ReadFilters(e);
1579  }
1580 
1581 
1582  /**
1583  *
1584  */
1585  void SessionReader::CreateComm(
1586  int &argc,
1587  char* argv[])
1588  {
1589  if (argc == 0)
1590  {
1591  m_comm = GetCommFactory().CreateInstance("Serial", 0, 0);
1592  }
1593  else
1594  {
1595  string vCommModule("Serial");
1596  if (GetCommFactory().ModuleExists("ParallelMPI"))
1597  {
1598  vCommModule = "ParallelMPI";
1599  }
1600  if (m_cmdLineOptions.count("cwipi") && GetCommFactory().ModuleExists("CWIPI"))
1601  {
1602  vCommModule = "CWIPI";
1603  }
1604 
1605  m_comm = GetCommFactory().CreateInstance(vCommModule, argc, argv);
1606  }
1607  }
1608 
1609  /**
1610  * Splits the processes into a cartesian grid and creates communicators
1611  * for each row and column of the grid. The grid is defined by the
1612  * PROC_X parameter which, if specified, gives the number of processes
1613  * spanned by the Fourier direction. PROC_X must exactly divide the
1614  * total number of processes or an error is thrown.
1615  */
1616  void SessionReader::PartitionComm()
1617  {
1618  if (m_comm->GetSize() > 1)
1619  {
1620  int nProcZ = 1;
1621  int nProcY = 1;
1622  int nProcX = 1;
1623  int nStripZ = 1;
1624  if (DefinesCmdLineArgument("npx")) {
1625  nProcX = GetCmdLineArgument<int>("npx");
1626  }
1627  if (DefinesCmdLineArgument("npy")) {
1628  nProcY = GetCmdLineArgument<int>("npy");
1629  }
1630  if (DefinesCmdLineArgument("npz")) {
1631  nProcZ = GetCmdLineArgument<int>("npz");
1632  }
1633  if (DefinesCmdLineArgument("nsz")) {
1634  nStripZ = GetCmdLineArgument<int>("nsz");
1635  }
1636  ASSERTL0(m_comm->GetSize() % (nProcZ*nProcY*nProcX) == 0,
1637  "Cannot exactly partition using PROC_Z value.");
1638  ASSERTL0(nProcZ % nProcY == 0,
1639  "Cannot exactly partition using PROC_Y value.");
1640  ASSERTL0(nProcY % nProcX == 0,
1641  "Cannot exactly partition using PROC_X value.");
1642 
1643  // Number of processes associated with the spectral method
1644  int nProcSm = nProcZ * nProcY * nProcX;
1645 
1646  // Number of processes associated with the spectral element
1647  // method.
1648  int nProcSem = m_comm->GetSize() / nProcSm;
1649 
1650  m_comm->SplitComm(nProcSm,nProcSem);
1651  m_comm->GetColumnComm()->SplitComm(nProcZ/nStripZ,nStripZ);
1652  m_comm->GetColumnComm()->GetColumnComm()->SplitComm(
1653  (nProcY*nProcX),nProcZ/nStripZ);
1654  m_comm->GetColumnComm()->GetColumnComm()->GetColumnComm()
1655  ->SplitComm(nProcX,nProcY);
1656  }
1657  }
1658 
1659 
1660  /**
1661  *
1662  */
1663  void SessionReader::ReadParameters(TiXmlElement *conditions)
1664  {
1665  m_parameters.clear();
1666 
1667  if (!conditions)
1668  {
1669  return;
1670  }
1671 
1672  TiXmlElement *parametersElement = conditions->FirstChildElement(
1673  "PARAMETERS");
1674 
1675  // See if we have parameters defined. They are optional so we go on
1676  // if not.
1677  if (parametersElement)
1678  {
1679  TiXmlElement *parameter =
1680  parametersElement->FirstChildElement("P");
1681 
1682  ParameterMap caseSensitiveParameters;
1683 
1684  // Multiple nodes will only occur if there is a comment in
1685  // between definitions.
1686  while (parameter)
1687  {
1688  stringstream tagcontent;
1689  tagcontent << *parameter;
1690  TiXmlNode *node = parameter->FirstChild();
1691 
1692  while (node && node->Type() != TiXmlNode::TINYXML_TEXT)
1693  {
1694  node = node->NextSibling();
1695  }
1696 
1697  if (node)
1698  {
1699  // Format is "paramName = value"
1700  std::string line = node->ToText()->Value(), lhs, rhs;
1701 
1702  try {
1703  ParseEquals(line, lhs, rhs);
1704  }
1705  catch (...)
1706  {
1707  NEKERROR(ErrorUtil::efatal,
1708  "Syntax error in parameter expression '"
1709  + line + "' in XML element: \n\t'"
1710  + tagcontent.str() + "'");
1711  }
1712 
1713  // We want the list of parameters to have their RHS
1714  // evaluated, so we use the expression evaluator to do
1715  // the dirty work.
1716  if (!lhs.empty() && !rhs.empty())
1717  {
1718  NekDouble value=0.0;
1719  try
1720  {
1721  LibUtilities::Equation expession(
1722  m_interpreter, rhs);
1723  value = expession.Evaluate();
1724  }
1725  catch (const std::runtime_error &)
1726  {
1727  NEKERROR(ErrorUtil::efatal,
1728  "Error evaluating parameter expression"
1729  " '" + rhs + "' in XML element: \n\t'"
1730  + tagcontent.str() + "'");
1731  }
1732  m_interpreter->SetParameter(lhs, value);
1733  caseSensitiveParameters[lhs] = value;
1734  boost::to_upper(lhs);
1735  m_parameters[lhs] = value;
1736  }
1737  }
1738 
1739  parameter = parameter->NextSiblingElement();
1740  }
1741  }
1742  }
1743 
1744 
1745  /**
1746  *
1747  */
1748  void SessionReader::ReadSolverInfo(TiXmlElement *conditions)
1749  {
1750  m_solverInfo.clear();
1751  m_solverInfo = GetSolverInfoDefaults();
1752 
1753  if (!conditions)
1754  {
1755  return;
1756  }
1757 
1758  TiXmlElement *solverInfoElement =
1759  conditions->FirstChildElement("SOLVERINFO");
1760 
1761  if (solverInfoElement)
1762  {
1763  TiXmlElement *solverInfo =
1764  solverInfoElement->FirstChildElement("I");
1765 
1766  while (solverInfo)
1767  {
1768  std::stringstream tagcontent;
1769  tagcontent << *solverInfo;
1770  // read the property name
1771  ASSERTL0(solverInfo->Attribute("PROPERTY"),
1772  "Missing PROPERTY attribute in solver info "
1773  "XML element: \n\t'" + tagcontent.str() + "'");
1774  std::string solverProperty =
1775  solverInfo->Attribute("PROPERTY");
1776  ASSERTL0(!solverProperty.empty(),
1777  "PROPERTY attribute must be non-empty in XML "
1778  "element: \n\t'" + tagcontent.str() + "'");
1779 
1780  // make sure that solver property is capitalised
1781  std::string solverPropertyUpper =
1782  boost::to_upper_copy(solverProperty);
1783 
1784  // read the value
1785  ASSERTL0(solverInfo->Attribute("VALUE"),
1786  "Missing VALUE attribute in solver info "
1787  "XML element: \n\t'" + tagcontent.str() + "'");
1788  std::string solverValue = solverInfo->Attribute("VALUE");
1789  ASSERTL0(!solverValue.empty(),
1790  "VALUE attribute must be non-empty in XML "
1791  "element: \n\t'" + tagcontent.str() + "'");
1792 
1793  // Set Variable
1794  m_solverInfo[solverPropertyUpper] = solverValue;
1795  solverInfo = solverInfo->NextSiblingElement("I");
1796  }
1797  }
1798 
1799  if (m_comm && m_comm->GetRowComm()->GetSize() > 1)
1800  {
1801  ASSERTL0(
1802  m_solverInfo["GLOBALSYSSOLN"] == "IterativeFull" ||
1803  m_solverInfo["GLOBALSYSSOLN"] == "IterativeStaticCond" ||
1804  m_solverInfo["GLOBALSYSSOLN"] ==
1805  "IterativeMultiLevelStaticCond" ||
1806  m_solverInfo["GLOBALSYSSOLN"] == "XxtFull" ||
1807  m_solverInfo["GLOBALSYSSOLN"] == "XxtStaticCond" ||
1808  m_solverInfo["GLOBALSYSSOLN"] ==
1809  "XxtMultiLevelStaticCond" ||
1810  m_solverInfo["GLOBALSYSSOLN"] == "PETScFull" ||
1811  m_solverInfo["GLOBALSYSSOLN"] == "PETScStaticCond" ||
1812  m_solverInfo["GLOBALSYSSOLN"] ==
1813  "PETScMultiLevelStaticCond",
1814  "A parallel solver must be used when run in parallel.");
1815  }
1816  }
1817 
1818 
1819 
1820  /**
1821  *
1822  */
1823  void SessionReader::ReadGlobalSysSolnInfo(TiXmlElement *conditions)
1824  {
1825  GetGloSysSolnList().clear();
1826 
1827  if (!conditions)
1828  {
1829  return;
1830  }
1831 
1832  TiXmlElement *GlobalSys =
1833  conditions->FirstChildElement("GLOBALSYSSOLNINFO");
1834 
1835  if(!GlobalSys)
1836  {
1837  return;
1838  }
1839 
1840  TiXmlElement *VarInfo = GlobalSys->FirstChildElement("V");
1841 
1842  while (VarInfo)
1843  {
1844  std::stringstream tagcontent;
1845  tagcontent << *VarInfo;
1846  ASSERTL0(VarInfo->Attribute("VAR"),
1847  "Missing VAR attribute in GobalSysSolnInfo XML "
1848  "element: \n\t'" + tagcontent.str() + "'");
1849 
1850  std::string VarList = VarInfo->Attribute("VAR");
1851  ASSERTL0(!VarList.empty(),
1852  "VAR attribute must be non-empty in XML element:\n\t'"
1853  + tagcontent.str() + "'");
1854 
1855  // generate a list of variables.
1856  std::vector<std::string> varStrings;
1857  bool valid = ParseUtils::GenerateVector(VarList, varStrings);
1858 
1859  ASSERTL0(valid,"Unable to process list of variable in XML "
1860  "element \n\t'" + tagcontent.str() + "'");
1861 
1862  if(varStrings.size())
1863  {
1864  TiXmlElement *SysSolnInfo = VarInfo->FirstChildElement("I");
1865 
1866  while (SysSolnInfo)
1867  {
1868  tagcontent.clear();
1869  tagcontent << *SysSolnInfo;
1870  // read the property name
1871  ASSERTL0(SysSolnInfo->Attribute("PROPERTY"),
1872  "Missing PROPERTY attribute in "
1873  "GlobalSysSolnInfo for variable(s) '"
1874  + VarList + "' in XML element: \n\t'"
1875  + tagcontent.str() + "'");
1876 
1877  std::string SysSolnProperty =
1878  SysSolnInfo->Attribute("PROPERTY");
1879 
1880  ASSERTL0(!SysSolnProperty.empty(),
1881  "GlobalSysSolnIno properties must have a "
1882  "non-empty name for variable(s) : '"
1883  + VarList + "' in XML element: \n\t'"
1884  + tagcontent.str() + "'");
1885 
1886  // make sure that solver property is capitalised
1887  std::string SysSolnPropertyUpper =
1888  boost::to_upper_copy(SysSolnProperty);
1889 
1890  // read the value
1891  ASSERTL0(SysSolnInfo->Attribute("VALUE"),
1892  "Missing VALUE attribute in GlobalSysSolnInfo "
1893  "for variable(s) '" + VarList
1894  + "' in XML element: \n\t"
1895  + tagcontent.str() + "'");
1896 
1897  std::string SysSolnValue =
1898  SysSolnInfo->Attribute("VALUE");
1899  ASSERTL0(!SysSolnValue.empty(),
1900  "GlobalSysSolnInfo properties must have a "
1901  "non-empty value for variable(s) '"
1902  + VarList + "' in XML element: \n\t'"
1903  + tagcontent.str() + "'");
1904 
1905  // Store values under variable map.
1906  for(int i = 0; i < varStrings.size(); ++i)
1907  {
1908  auto x = GetGloSysSolnList().find(varStrings[i]);
1909  if (x == GetGloSysSolnList().end())
1910  {
1911  (GetGloSysSolnList()[varStrings[i]])[
1912  SysSolnPropertyUpper] = SysSolnValue;
1913  }
1914  else
1915  {
1916  x->second[SysSolnPropertyUpper] = SysSolnValue;
1917  }
1918  }
1919 
1920  SysSolnInfo = SysSolnInfo->NextSiblingElement("I");
1921  }
1922  VarInfo = VarInfo->NextSiblingElement("V");
1923  }
1924  }
1925 
1926  if (m_verbose && GetGloSysSolnList().size() > 0 && m_comm)
1927  {
1928  if(m_comm->GetRank() == 0)
1929  {
1930  cout << "GlobalSysSoln Info:" << endl;
1931 
1932  for (auto &x : GetGloSysSolnList())
1933  {
1934  cout << "\t Variable: " << x.first << endl;
1935 
1936  for (auto &y : x.second)
1937  {
1938  cout << "\t\t " << y.first << " = " << y.second
1939  << endl;
1940  }
1941  }
1942  cout << endl;
1943  }
1944  }
1945  }
1946 
1947 
1948  /**
1949  *
1950  */
1951  void SessionReader::ReadExpressions(TiXmlElement *conditions)
1952  {
1953  m_expressions.clear();
1954 
1955  if (!conditions)
1956  {
1957  return;
1958  }
1959 
1960  TiXmlElement *expressionsElement =
1961  conditions->FirstChildElement("EXPRESSIONS");
1962 
1963  if (expressionsElement)
1964  {
1965  TiXmlElement *expr = expressionsElement->FirstChildElement("E");
1966 
1967  while (expr)
1968  {
1969  stringstream tagcontent;
1970  tagcontent << *expr;
1971  ASSERTL0(expr->Attribute("NAME"),
1972  "Missing NAME attribute in expression "
1973  "definition: \n\t'" + tagcontent.str() + "'");
1974  std::string nameString = expr->Attribute("NAME");
1975  ASSERTL0(!nameString.empty(),
1976  "Expressions must have a non-empty name: \n\t'"
1977  + tagcontent.str() + "'");
1978 
1979  ASSERTL0(expr->Attribute("VALUE"),
1980  "Missing VALUE attribute in expression "
1981  "definition: \n\t'" + tagcontent.str() + "'");
1982  std::string valString = expr->Attribute("VALUE");
1983  ASSERTL0(!valString.empty(),
1984  "Expressions must have a non-empty value: \n\t'"
1985  + tagcontent.str() + "'");
1986 
1987  auto exprIter = m_expressions.find(nameString);
1988  ASSERTL0(exprIter == m_expressions.end(),
1989  std::string("Expression '") + nameString
1990  + std::string("' already specified."));
1991 
1992  m_expressions[nameString] = valString;
1993  expr = expr->NextSiblingElement("E");
1994  }
1995  }
1996  }
1997 
1998 
1999  /**
2000  *
2001  */
2002  void SessionReader::ReadVariables(TiXmlElement *conditions)
2003  {
2004  m_variables.clear();
2005 
2006  if (!conditions)
2007  {
2008  return;
2009  }
2010 
2011  TiXmlElement *variablesElement =
2012  conditions->FirstChildElement("VARIABLES");
2013 
2014  // See if we have parameters defined. They are optional so we go on
2015  // if not.
2016  if (variablesElement)
2017  {
2018  TiXmlElement *varElement =
2019  variablesElement->FirstChildElement("V");
2020 
2021  // Sequential counter for the composite numbers.
2022  int nextVariableNumber = -1;
2023 
2024  while (varElement)
2025  {
2026  stringstream tagcontent;
2027  tagcontent << *varElement;
2028 
2029  /// All elements are of the form: "<V ID="#"> name = value
2030  /// </V>", with ? being the element type.
2031  nextVariableNumber++;
2032 
2033  int i;
2034  int err = varElement->QueryIntAttribute("ID", &i);
2035  ASSERTL0(err == TIXML_SUCCESS,
2036  "Variables must have a unique ID number attribute "
2037  "in XML element: \n\t'" + tagcontent.str() + "'");
2038  ASSERTL0(i == nextVariableNumber,
2039  "ID numbers for variables must begin with zero and"
2040  " be sequential in XML element: \n\t'"
2041  + tagcontent.str() + "'");
2042 
2043  TiXmlNode* varChild = varElement->FirstChild();
2044  // This is primarily to skip comments that may be present.
2045  // Comments appear as nodes just like elements. We are
2046  // specifically looking for text in the body of the
2047  // definition.
2048  while(varChild && varChild->Type() != TiXmlNode::TINYXML_TEXT)
2049  {
2050  varChild = varChild->NextSibling();
2051  }
2052 
2053  ASSERTL0(varChild,
2054  "Unable to read variable definition body for "
2055  "variable with ID "
2056  + boost::lexical_cast<string>(i)
2057  + " in XML element: \n\t'"
2058  + tagcontent.str() + "'");
2059  std::string variableName = varChild->ToText()->ValueStr();
2060 
2061  std::istringstream variableStrm(variableName);
2062  variableStrm >> variableName;
2063 
2064  ASSERTL0(std::find(m_variables.begin(), m_variables.end(),
2065  variableName) == m_variables.end(),
2066  "Variable with ID "
2067  + boost::lexical_cast<string>(i)
2068  + " in XML element \n\t'" + tagcontent.str()
2069  + "'\nhas already been defined.");
2070 
2071  m_variables.push_back(variableName);
2072 
2073  varElement = varElement->NextSiblingElement("V");
2074  }
2075 
2076  ASSERTL0(nextVariableNumber > -1,
2077  "Number of variables must be greater than zero.");
2078  }
2079  }
2080 
2081 
2082  /**
2083  *
2084  */
2085  void SessionReader::ReadFunctions(TiXmlElement *conditions)
2086  {
2087  m_functions.clear();
2088 
2089  if (!conditions)
2090  {
2091  return;
2092  }
2093 
2094  // Scan through conditions section looking for functions.
2095  TiXmlElement *function = conditions->FirstChildElement("FUNCTION");
2096  while (function)
2097  {
2098  stringstream tagcontent;
2099  tagcontent << *function;
2100 
2101  // Every function must have a NAME attribute
2102  ASSERTL0(function->Attribute("NAME"),
2103  "Functions must have a NAME attribute defined in XML "
2104  "element: \n\t'" + tagcontent.str() + "'");
2105  std::string functionStr = function->Attribute("NAME");
2106  ASSERTL0(!functionStr.empty(),
2107  "Functions must have a non-empty name in XML "
2108  "element: \n\t'" + tagcontent.str() + "'");
2109 
2110  // Store function names in uppercase to remain case-insensitive.
2111  boost::to_upper(functionStr);
2112 
2113  // Retrieve first entry (variable, or file)
2114  TiXmlElement *variable = function->FirstChildElement();
2115 
2116  // Create new function structure with default type of none.
2117  FunctionVariableMap functionVarMap;
2118 
2119  // Process all entries in the function block
2120  while (variable)
2121  {
2123  std::string conditionType = variable->Value();
2124 
2125  // If no var is specified, assume wildcard
2126  std::string variableStr;
2127  if (!variable->Attribute("VAR"))
2128  {
2129  variableStr = "*";
2130  }
2131  else
2132  {
2133  variableStr = variable->Attribute("VAR");
2134  }
2135 
2136  // Parse list of variables
2137  std::vector<std::string> variableList;
2138  ParseUtils::GenerateVector(variableStr, variableList);
2139 
2140  // If no domain string put to 0
2141  std::string domainStr;
2142  if (!variable->Attribute("DOMAIN"))
2143  {
2144  domainStr = "0";
2145  }
2146  else
2147  {
2148  domainStr = variable->Attribute("DOMAIN");
2149  }
2150 
2151  // If no domain string put to 0
2152  std::string evarsStr = "x y z t";
2153  if (variable->Attribute("EVARS"))
2154  {
2155  evarsStr = evarsStr + std::string(" ") + variable->Attribute("EVARS");
2156  }
2157 
2158  // Parse list of variables
2159  std::vector<std::string> varSplit;
2160  std::vector<unsigned int> domainList;
2161  ParseUtils::GenerateSeqVector(domainStr, domainList);
2162 
2163  // Expressions are denoted by E
2164  if (conditionType == "E")
2165  {
2166  funcDef.m_type = eFunctionTypeExpression;
2167 
2168  // Expression must have a VALUE.
2169  ASSERTL0(variable->Attribute("VALUE"),
2170  "Attribute VALUE expected for function '"
2171  + functionStr + "'.");
2172  std::string fcnStr = variable->Attribute("VALUE");
2173 
2174  ASSERTL0(!fcnStr.empty(),
2175  (std::string("Expression for var: ")
2176  + variableStr
2177  + std::string(" must be specified.")).c_str());
2178 
2179  SubstituteExpressions(fcnStr);
2180 
2181  // set expression
2183  ::AllocateSharedPtr(m_interpreter, fcnStr, evarsStr);
2184  }
2185 
2186  // Files are denoted by F
2187  else if (conditionType == "F")
2188  {
2189  if (variable->Attribute("TIMEDEPENDENT") &&
2190  boost::lexical_cast<bool>(variable->Attribute("TIMEDEPENDENT")))
2191  {
2193  }
2194  else
2195  {
2196  funcDef.m_type = eFunctionTypeFile;
2197  }
2198 
2199  // File must have a FILE.
2200  ASSERTL0(variable->Attribute("FILE"),
2201  "Attribute FILE expected for function '"
2202  + functionStr + "'.");
2203  std::string filenameStr = variable->Attribute("FILE");
2204 
2205  ASSERTL0(!filenameStr.empty(),
2206  "A filename must be specified for the FILE "
2207  "attribute of function '" + functionStr
2208  + "'.");
2209 
2210  std::vector<std::string> fSplit;
2211  boost::split(fSplit, filenameStr, boost::is_any_of(":"));
2212 
2213  ASSERTL0(fSplit.size() == 1 || fSplit.size() == 2,
2214  "Incorrect filename specification in function "
2215  + functionStr + "'. "
2216  "Specify variables inside file as: "
2217  "filename:var1,var2");
2218 
2219  // set the filename
2220  funcDef.m_filename = fSplit[0];
2221 
2222  if (fSplit.size() == 2)
2223  {
2224  ASSERTL0(variableList[0] != "*",
2225  "Filename variable mapping not valid "
2226  "when using * as a variable inside "
2227  "function '" + functionStr + "'.");
2228 
2229  boost::split(
2230  varSplit, fSplit[1], boost::is_any_of(","));
2231  ASSERTL0(varSplit.size() == variableList.size(),
2232  "Filename variables should contain the "
2233  "same number of variables defined in "
2234  "VAR in function " + functionStr + "'.");
2235  }
2236  }
2237 
2238  // Nothing else supported so throw an error
2239  else
2240  {
2241  stringstream tagcontent;
2242  tagcontent << *variable;
2243 
2244  NEKERROR(ErrorUtil::efatal,
2245  "Identifier " + conditionType + " in function "
2246  + std::string(function->Attribute("NAME"))
2247  + " is not recognised in XML element: \n\t'"
2248  + tagcontent.str() + "'");
2249  }
2250 
2251 
2252 
2253  // Add variables to function
2254  for (unsigned int i = 0; i < variableList.size(); ++i)
2255  {
2256  for(unsigned int j = 0; j < domainList.size(); ++j)
2257  {
2258  // Check it has not already been defined
2259  pair<std::string,int> key(variableList[i],domainList[j]);
2260  auto fcnsIter = functionVarMap.find(key);
2261  ASSERTL0(fcnsIter == functionVarMap.end(),
2262  "Error setting expression '" + variableList[i]
2263  + " in domain "
2264  + boost::lexical_cast<std::string>(domainList[j])
2265  + "' in function '" + functionStr + "'. "
2266  "Expression has already been defined.");
2267 
2268  if (varSplit.size() > 0)
2269  {
2270  FunctionVariableDefinition funcDef2 = funcDef;
2271  funcDef2.m_fileVariable = varSplit[i];
2272  functionVarMap[key] = funcDef2;
2273  }
2274  else
2275  {
2276  functionVarMap[key] = funcDef;
2277  }
2278  }
2279  }
2280 
2281  variable = variable->NextSiblingElement();
2282  }
2283  // Add function definition to map
2284  m_functions[functionStr] = functionVarMap;
2285  function = function->NextSiblingElement("FUNCTION");
2286  }
2287  }
2288 
2289 
2290  /**
2291  *
2292  */
2293  void SessionReader::ReadFilters(TiXmlElement *filters)
2294  {
2295  if (!filters)
2296  {
2297  return;
2298  }
2299 
2300  m_filters.clear();
2301 
2302  TiXmlElement *filter = filters->FirstChildElement("FILTER");
2303  while (filter)
2304  {
2305  ASSERTL0(filter->Attribute("TYPE"),
2306  "Missing attribute 'TYPE' for filter.");
2307  std::string typeStr = filter->Attribute("TYPE");
2308 
2309  std::map<std::string, std::string> vParams;
2310 
2311  TiXmlElement *param = filter->FirstChildElement("PARAM");
2312  while (param)
2313  {
2314  ASSERTL0(param->Attribute("NAME"),
2315  "Missing attribute 'NAME' for parameter in filter "
2316  + typeStr + "'.");
2317  std::string nameStr = param->Attribute("NAME");
2318 
2319  ASSERTL0(param->GetText(), "Empty value string for param.");
2320  std::string valueStr = param->GetText();
2321 
2322  vParams[nameStr] = valueStr;
2323 
2324  param = param->NextSiblingElement("PARAM");
2325  }
2326 
2327  m_filters.push_back(
2328  std::pair<std::string, FilterParams>(typeStr, vParams));
2329 
2330  filter = filter->NextSiblingElement("FILTER");
2331  }
2332  }
2333 
2334  void SessionReader::ParseEquals(
2335  const std::string &line,
2336  std::string &lhs,
2337  std::string &rhs)
2338  {
2339  /// Pull out lhs and rhs and eliminate any spaces.
2340  size_t beg = line.find_first_not_of(" ");
2341  size_t end = line.find_first_of("=");
2342  // Check for no parameter name
2343  if (beg == end) throw 1;
2344  // Check for no parameter value
2345  if (end != line.find_last_of("=")) throw 1;
2346  // Check for no equals sign
2347  if (end == std::string::npos) throw 1;
2348 
2349  lhs = line.substr(line.find_first_not_of(" "),
2350  end-beg);
2351  lhs = lhs .substr(0, lhs.find_last_not_of(" ")+1);
2352  rhs = line.substr(line.find_last_of("=")+1);
2353  rhs = rhs .substr(rhs.find_first_not_of(" "));
2354  rhs = rhs .substr(0, rhs.find_last_not_of(" ")+1);
2355  }
2356 
2357  /**
2358  *
2359  */
2360  void SessionReader::CmdLineOverride()
2361  {
2362  // Parse solver info overrides
2363  if (m_cmdLineOptions.count("solverinfo"))
2364  {
2365  std::vector<std::string> solverInfoList =
2366  m_cmdLineOptions["solverinfo"].as<
2367  std::vector<std::string> >();
2368 
2369  for (size_t i = 0; i < solverInfoList.size(); ++i)
2370  {
2371  std::string lhs, rhs;
2372 
2373  try
2374  {
2375  ParseEquals(solverInfoList[i], lhs, rhs);
2376  }
2377  catch (...)
2378  {
2379  NEKERROR(ErrorUtil::efatal,
2380  "Parse error with command line "
2381  "option: "+solverInfoList[i]);
2382  }
2383 
2384  std::string lhsUpper = boost::to_upper_copy(lhs);
2385  m_solverInfo[lhsUpper] = rhs;
2386  }
2387  }
2388 
2389  if (m_cmdLineOptions.count("parameter"))
2390  {
2391  std::vector<std::string> parametersList =
2392  m_cmdLineOptions["parameter"].as<
2393  std::vector<std::string> >();
2394 
2395  for (size_t i = 0; i < parametersList.size(); ++i)
2396  {
2397  std::string lhs, rhs;
2398 
2399  try
2400  {
2401  ParseEquals(parametersList[i], lhs, rhs);
2402  }
2403  catch (...)
2404  {
2405  NEKERROR(ErrorUtil::efatal,
2406  "Parse error with command line "
2407  "option: "+parametersList[i]);
2408  }
2409 
2410  std::string lhsUpper = boost::to_upper_copy(lhs);
2411 
2412  try
2413  {
2414  m_parameters[lhsUpper] =
2415  boost::lexical_cast<NekDouble>(rhs);
2416  }
2417  catch (...)
2418  {
2419  NEKERROR(ErrorUtil::efatal,
2420  "Unable to convert string: "+rhs+
2421  "to double value.");
2422  }
2423  }
2424  }
2425  }
2426 
2427  void SessionReader::VerifySolverInfo()
2428  {
2429  for (auto &x : m_solverInfo)
2430  {
2431  std::string solverProperty = x.first;
2432  std::string solverValue = x.second;
2433 
2434  auto propIt = GetSolverInfoEnums().find(solverProperty);
2435  if (propIt != GetSolverInfoEnums().end())
2436  {
2437  auto valIt = propIt->second.find(solverValue);
2438  ASSERTL0(valIt != propIt->second.end(),
2439  "Value '" + solverValue + "' is not valid for "
2440  "property '" + solverProperty + "'");
2441  }
2442  }
2443  }
2444 
2445 
2446  void SessionReader::SetUpXmlDoc(void)
2447  {
2448  m_xmlDoc = MergeDoc(m_filenames);
2449  }
2450 
2451  InterpreterSharedPtr SessionReader::GetInterpreter()
2452  {
2453  return m_interpreter;
2454  }
2455  }
2456 }
std::map< std::string, std::string > SolverInfoMap
Definition: SessionReader.h:57
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
static void Finalise(gs_data *pGsh)
Deallocates the GSLib mapping data.
Definition: GsLib.hpp:226
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
std::map< std::pair< std::string, int >, FunctionVariableDefinition > FunctionVariableMap
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
STL namespace.
def copy(self)
Definition: pycml.py:2663
#define NEKTAR_VERSION
CommFactory & GetCommFactory()
StandardMatrixTag & lhs
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
const std::string kGitSha1
bool ModuleExists(tKey idKey)
Checks if a particular module is available.
Definition: NekFactory.hpp:215
std::map< std::string, GloSysInfoMap > GloSysSolnInfoList
Definition: SessionReader.h:80
std::vector< std::pair< std::string, FilterParams > > FilterMap
Definition: SessionReader.h:65
std::shared_ptr< Interpreter > InterpreterSharedPtr
Definition: Interpreter.h:325
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:41
NekDouble Evaluate() const
Definition: Equation.cpp:95
double NekDouble
const std::string kGitBranch
std::shared_ptr< Equation > EquationSharedPtr
Definition: Equation.h:131
std::map< std::string, NekDouble > ParameterMap
Definition: SessionReader.h:58
std::map< std::string, EnumMap > EnumMapList
Definition: SessionReader.h:77
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:358
std::map< std::string, CmdLineArg > CmdLineArgMap
Definition: SessionReader.h:74
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250