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