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