SessionReader.cpp 89.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
///////////////////////////////////////////////////////////////////////////////
//
// File SessionReader.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Session reader
//
///////////////////////////////////////////////////////////////////////////////

#ifndef TIXML_USE_STL
#define TIXML_USE_STL
#endif

40
#include <LibUtilities/BasicUtils/SessionReader.h>
41
#include <LibUtilities/BasicConst/GitRevision.h>
42

43
#include <iostream>
44
#include <fstream>
45 46 47
#include <string>
using namespace std;

48 49 50
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
51
#include <boost/algorithm/string.hpp>
52
#include <tinyxml.h>
53
#include <LibUtilities/BasicUtils/ErrorUtil.hpp>
54 55
#include <LibUtilities/BasicUtils/Equation.h>
#include <LibUtilities/Memory/NekMemoryManager.hpp>
56
#include <LibUtilities/BasicUtils/MeshPartition.h>
57
#include <LibUtilities/BasicUtils/ParseUtils.hpp>
58
#include <LibUtilities/BasicUtils/FileSystem.h>
59

60
#include <boost/program_options.hpp>
61
#include <boost/format.hpp>
62

63 64 65 66
#ifndef NEKTAR_VERSION
#define NEKTAR_VERSION "Unknown"
#endif

67
namespace po = boost::program_options;
68
namespace io = boost::iostreams;
69

70 71 72 73
namespace Nektar
{
    namespace LibUtilities
    {
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
        /**
         * @class SessionReader
         *
         * This class provides an interface to Nektar++-specific content in a
         * supplied XML document. It also initialises a Nektar++ session
         * including setting up communication for parallel execution and where
         * necessary partitioning the supplied mesh for running across multiple
         * processes.
         *
         * A session should be initialised at the beginning of a user's
         * application by passing the command-line arguments. This not only
         * allows the SessionReader to extract the name of the XML document to
         * load containing Nektar++ session information, but also supplies the
         * MPI arguments necessary for setting up parallel communication. The
         * SessionReader should be initialised using the #CreateInstance
         * function:
         * @code
         * LibUtilities::SessionReaderSharedPtr vSession
         *          = LibUtilities::SessionReader::CreateInstance(argc, argv);
         * @endcode
         * The instance \c vSession can now be passed to other key Nektar++
         * components during their construction.
         * @note At the end of the user application, it is important to call the
         * #Finalise routine in order to finalise any MPI communication and
         * correctly free resources.
         *
         * The SessionReader class provides streamlined, validated access to
         * session parameters, solver information and functions defined within a
         * Nektar++ XML document. The available routines and their usage is
         * documented below.
         *
         * In the case of solver information properties, the classes to which
         * these parameters are pertinent may register with the SessionReader
         * class the set of valid values for a given property. Such values may
         * also be associated with an enumeration value for more transparent use
         * of the property values in code.
         */

112 113 114 115 116 117 118 119 120 121 122 123 124
        /**
         * This map of maps stores the list of valid string values for a number
         * of solver information parameters. The top level map connects
         * different parameter names to their list of possible values. The list
         * of possible values is also a map, mapping a valid string to a
         * corresponding enum value.
         *
         * This list is populated through the #RegisterEnumValue static member
         * function which is called statically from various classes to register
         * the valid values for solver info parameters associated with them. The
         * map is therefore fully populated before the SessionReader class is
         * instantiated and a file is read in and parsed.
         */
125 126 127 128 129
        EnumMapList& SessionReader::GetSolverInfoEnums()
        {
            static EnumMapList solverInfoEnums;
            return solverInfoEnums;
        }
130 131 132 133 134 135 136 137 138 139


        /**
         * List of default values for solver information parameters to be used
         * in the case of them not being provided.
         *
         * This list is populated through the #RegisterDefaultSolverInfo static
         * member variable which is called statically from various classes to
         * register the default value for a given parameter.
         */
140 141 142 143 144
        SolverInfoMap& SessionReader::GetSolverInfoDefaults()
        {
            static SolverInfoMap solverInfoMap;
            return solverInfoMap;
        }
145 146


147 148 149 150 151 152 153 154 155
        /**
         * List of values for GlobalSysSoln parameters to be used to override
         * details given in SolverInfo
         *
         * This list is populated by ReadGlobalSysSoln if the
         * GLOBALSYSSOLNINFO section is defined in the input file.
         * This List allows for details to define for the Global Sys
         * solver for each variable. 
         */
156 157 158 159 160
        GloSysSolnInfoList& SessionReader::GetGloSysSolnList()
        {
            static GloSysSolnInfoList gloSysSolnInfoList;
            return gloSysSolnInfoList;
        }
161

162 163 164 165 166 167 168 169
        /**
         * Lists the possible command-line argument which can be specified for
         * this executable.
         *
         * This list is populated through the #RegisterCmdLineArgument static
         * member function which is called statically from various classes to
         * register command-line arguments they need.
         */
170 171 172 173 174
        CmdLineArgMap& SessionReader::GetCmdLineArgMap()
        {
            static CmdLineArgMap cmdLineArguments;
            return cmdLineArguments;
        }
175 176


177 178 179 180 181 182 183 184
        /**
         * This constructor parses the command-line arguments given to the user
         * application to set up any MPI communication, read supplied XML
         * session files, and partition meshes where necessary.
         *
         * @param   argc        Number of command-line arguments
         * @param   argv        Array of command-line arguments
         */
185 186
        SessionReader::SessionReader(int argc, char *argv[])
        {
Chris Cantwell's avatar
Chris Cantwell committed
187
            m_xmlDoc    = 0;
188
            m_filenames = ParseCommandLineArguments(argc, argv);
189

190
            ASSERTL0(m_filenames.size() > 0, "No session file(s) given.");
191

192
            m_filename    = m_filenames[0];
193
            m_sessionName = m_filename.substr(0, m_filename.find_last_of('.'));
194 195 196 197 198 199
            if (m_filename.size() > 3 &&
                m_filename.substr(m_filename.size() - 3, 3) == ".gz")
            {
                m_sessionName =
                    m_sessionName.substr(0, m_sessionName.find_last_of('.'));
            }
200

201
            // Create communicator
202
            CreateComm(argc, argv);
203 204 205 206 207

            // If running in parallel change the default global sys solution
            // type.
            if (m_comm->GetSize() > 1)
            {
208
                GetSolverInfoDefaults()["GLOBALSYSSOLN"] = 
209 210
                    "IterativeStaticCond";
            }
211 212 213
        }


214 215 216
        /**
         *
         */
217 218 219 220 221
        SessionReader::SessionReader(
            int                             argc, 
            char                           *argv[], 
            const std::vector<std::string> &pFilenames, 
            const CommSharedPtr            &pComm)
222 223 224
        {
            ASSERTL0(pFilenames.size() > 0, "No filenames specified.");

225
            ParseCommandLineArguments(argc, argv);
Chris Cantwell's avatar
Chris Cantwell committed
226
            m_xmlDoc      = 0;
227
            m_filenames   = pFilenames;
228

229
            m_filename    = pFilenames[0];
230
            m_sessionName = m_filename.substr(0, m_filename.find_last_of('.'));
231 232 233 234 235 236
            if (m_filename.size() > 3 &&
                m_filename.substr(m_filename.size() - 3, 3) == ".gz")
            {
                m_sessionName =
                    m_sessionName.substr(0, m_sessionName.find_last_of('.'));
            }
237

238
            // Create communicator
239 240
            if (!pComm.get())
            {
241
                CreateComm(argc, argv);
242 243 244 245
            }
            else
            {
                m_comm = pComm;
246 247 248

                if (m_comm->GetSize() > 1)
                {
249
                    GetSolverInfoDefaults()["GLOBALSYSSOLN"] = 
250 251
                        "IterativeStaticCond";
                }
252
            }
253 254 255 256 257

            // If running in parallel change the default global sys solution
            // type.
            if (m_comm->GetSize() > 1)
            {
258
                GetSolverInfoDefaults()["GLOBALSYSSOLN"] = 
259 260
                    "IterativeStaticCond";
            }
261 262 263
        }


264 265 266
        /**
         *
         */
267 268
        SessionReader::~SessionReader()
        {
269
            delete m_xmlDoc;
270 271
        }

272 273 274 275 276 277 278

        /**
         * Performs the main initialisation of the object. The XML file provided
         * on the command-line is loaded and any mesh partitioning is done. The
         * resulting process-specific XML file (containing the process's
         * geometry partition) is then reloaded and parsed.
         */
279 280
        void SessionReader::InitSession()
        {
281 282
            m_exprEvaluator.SetRandomSeed((m_comm->GetRank() + 1) * time(NULL));

283 284 285
            // Split up the communicator
            PartitionComm();

286 287 288
            // Partition mesh
            PartitionMesh();

289 290
            // Parse the XML data in #m_xmlDoc
            ParseDocument();
291 292 293 294

            // Override SOLVERINFO and parameters with any specified on the
            // command line.
            CmdLineOverride();
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

            // In verbose mode, print out parameters and solver info sections
            if (m_verbose && m_comm)
            {
                if (m_comm->GetRank() == 0 && m_parameters.size() > 0)
                {
                    cout << "Parameters:" << endl;
                    ParameterMap::iterator x;
                    for (x = m_parameters.begin(); x != m_parameters.end(); ++x)
                    {
                        cout << "\t" << x->first << " = " << x->second << endl;
                    }
                    cout << endl;
                }

                if (m_comm->GetRank() == 0 && m_solverInfo.size() > 0)
                {
                    cout << "Solver Info:" << endl;
                    SolverInfoMap::iterator x;
                    for (x = m_solverInfo.begin(); x != m_solverInfo.end(); ++x)
                    {
                        cout << "\t" << x->first << " = " << x->second << endl;
                    }
                    cout << endl;
                }
            }
321 322
        }

323

324
        /**
325 326
         * @brief Parses the command-line arguments for known options and
         * filenames.
327
         */
328 329
        std::vector<std::string> SessionReader::ParseCommandLineArguments(
            int argc, char *argv[])
330 331 332 333
        {
            // List the publically visible options (listed using --help)
            po::options_description desc("Allowed options");
            desc.add_options()
334
                ("verbose,v",    "be verbose")
335
                ("version,V",    "print version information")
336 337 338 339 340
                ("help,h",       "print this help message")
                ("solverinfo,I", po::value<vector<std::string> >(), 
                                 "override a SOLVERINFO property")
                ("parameter,P",  po::value<vector<std::string> >(),
                                 "override a parameter")
341
                ("shared-filesystem,s", "Using shared filesystem.")
342 343 344 345 346 347
                ("npx",          po::value<int>(),
                                 "number of procs in X-dir")
                ("npy",          po::value<int>(),
                                 "number of procs in Y-dir")
                ("npz",          po::value<int>(),
                                 "number of procs in Z-dir")
348
                ("part-info",    "Output partition information")
349
            ;
350
            
351
            CmdLineArgMap::const_iterator cmdIt;
352 353
            for (cmdIt  = GetCmdLineArgMap().begin();
                 cmdIt != GetCmdLineArgMap().end(); ++cmdIt)
354 355 356 357 358 359
            {
                std::string names = cmdIt->first;
                if (cmdIt->second.shortName != "")
                {
                    names += "," + cmdIt->second.shortName;
                }
360 361 362 363 364 365 366 367 368 369 370 371 372
                if (cmdIt->second.isFlag)
                {
                    desc.add_options()
                        (names.c_str(), cmdIt->second.description.c_str())
                    ;
                }
                else
                {
                    desc.add_options()
                        (names.c_str(), po::value<std::string>(),
                         cmdIt->second.description.c_str())
                    ;
                }
373
            }
374 375 376 377 378

            // List hidden options (e.g. session file arguments are not actually
            // specified using the input-file option by the user).
            po::options_description hidden("Hidden options");
            hidden.add_options()
379 380
                    ("input-file", po::value< vector<string> >(), 
                                   "input filename")
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
            ;

            // Combine all options for the parser
            po::options_description all("All options");
            all.add(desc).add(hidden);

            // Session file is a positional option
            po::positional_options_description p;
            p.add("input-file", -1);

            // Parse the command-line options
            po::parsed_options parsed = po::command_line_parser(argc, argv).
                                                options(all).
                                                positional(p).
                                                allow_unregistered().
                                                run();

            // Extract known options to map and update
            po::store(parsed, m_cmdLineOptions);
            po::notify(m_cmdLineOptions);

            // Help message
            if (m_cmdLineOptions.count("help"))
            {
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
                cout << desc;
                exit(0);
            }

            // Version information
            if (m_cmdLineOptions.count("version"))
            {
                cout << "Nektar++ version " << NEKTAR_VERSION;

                if (NekConstants::kGitSha1 != "GITDIR-NOTFOUND")
                {
                    string sha1(NekConstants::kGitSha1);
                    string branch(NekConstants::kGitBranch);
                    boost::replace_all(branch, "refs/heads/", "");

Dave Moxey's avatar
Dave Moxey committed
420 421 422 423 424 425 426 427 428 429 430 431
                    cout << " (git changeset " << sha1.substr(0, 8) << ", ";

                    if (branch == "")
                    {
                        cout << "detached head";
                    }
                    else
                    {
                        cout << "head " << branch;
                    }

                    cout << ")";
432 433 434
                }

                cout << endl;
435 436 437 438 439 440 441 442 443 444 445 446
                exit(0);
            }

            // Enable verbose mode
            if (m_cmdLineOptions.count("verbose"))
            {
                m_verbose = true;
            }
            else
            {
                m_verbose = false;
            }
447
            
448 449 450 451 452 453
            // Print a warning for unknown options
            std::vector< po::basic_option<char> >::iterator x;
            for (x = parsed.options.begin(); x != parsed.options.end(); ++x)
            {
                if (x->unregistered)
                {
454 455
                    cout << "Warning: Unknown option: " << x->string_key 
                         << endl;
456 457 458 459 460 461
                }
            }

            // Return the vector of filename(s) given as positional options
            if (m_cmdLineOptions.count("input-file"))
            {
462 463
                return m_cmdLineOptions["input-file"].as<
                    std::vector<std::string> >();
464 465 466 467 468 469 470 471
            }
            else
            {
                return std::vector<std::string>();
            }
        }


472 473 474
        /**
         *
         */
475 476
        TiXmlDocument& SessionReader::GetDocument()
        {
477
            ASSERTL1(m_xmlDoc, "XML Document not defined.");
478 479 480
            return *m_xmlDoc;
        }

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

        /**
         * The single parameter specifies a path to the requested element in a
         * similar format to the filesystem path. Given the following XML:
         * @code
         * <NEKTAR>
         *   <CONDITIONS>
         *     <PARAMETERS>
         *     ...
         *     </PARAMETERS>
         *   </CONDITIONS>
         * </NEKTAR>
         * @endcode
         * the PARAMETERS element would be retrieved by requesting the path:
         * @code
         * Nektar/Conditions/Parameters
         * @endcode
         * @note Paths are case-insensitive.
         *
         * @param   pPath       Path to requested element.
501 502
         *
         * @return Direct pointer to requested XML Element.
503
         */
504 505 506
        TiXmlElement* SessionReader::GetElement(const string& pPath)
        {
            std::string vPath = boost::to_upper_copy(pPath);
507 508 509
            std::vector<std::string> st;
            boost::split(st, vPath, boost::is_any_of("\\/ "));
            ASSERTL0(st.size() > 0, "No path given in XML element request.");
510

511
            TiXmlElement* vReturn = m_xmlDoc->FirstChildElement(st[0].c_str());
512
            ASSERTL0(vReturn, std::string("Cannot find element '")
513 514
                              + st[0] + std::string("'."));
            for (int i = 1; i < st.size(); ++i)
515
            {
516
                vReturn = vReturn->FirstChildElement(st[i].c_str());
517
                ASSERTL0(vReturn, std::string("Cannot find element '")
518
                                  + st[i] + std::string("'."));
519 520 521 522
            }
            return vReturn;
        }

523 524 525 526 527

        /**
         *
         */
        bool SessionReader::DefinesElement(const std::string &pPath) const
528 529
        {
            std::string vPath = boost::to_upper_copy(pPath);
530 531 532
            std::vector<std::string> st;
            boost::split(st, vPath, boost::is_any_of("\\/ "));
            ASSERTL0(st.size() > 0, "No path given in XML element request.");
533

534
            TiXmlElement* vReturn = m_xmlDoc->FirstChildElement(st[0].c_str());
535
            ASSERTL0(vReturn, std::string("Cannot find element '")
536 537
                              + st[0] + std::string("'."));
            for (int i = 1; i < st.size(); ++i)
538
            {
539
                vReturn = vReturn->FirstChildElement(st[i].c_str());
540 541 542 543 544
                if (!vReturn) return false;
            }
            return true;
        }

545 546 547 548

        /**
         *
         */
549
        const std::string& SessionReader::GetFilename() const
550 551 552 553
        {
            return m_filename;
        }

554 555 556 557

        /**
         *
         */
558 559 560 561 562
        const std::string& SessionReader::GetSessionName() const
        {
            return m_sessionName;
        }

563

564 565 566 567 568 569
        /**
         * Output is of the form [sessionName]_P[idx] where idx is the rank
         * of the process.
         */
        const std::string SessionReader::GetSessionNameRank() const
        {
570
            std::string  dirname = m_sessionName + "_xml"; 
571 572
            fs::path     pdirname(dirname);
            
573
            std::string vFilename = "P" + boost::lexical_cast<std::string>(m_comm->GetRowComm()->GetRank());
574
            fs::path    pFilename(vFilename);            
575

576
            fs::path fullpath = pdirname / pFilename;
577

578 579
            return PortablePath(fullpath);
        }
580

581 582 583
        /**
         *
         */
584 585 586 587 588
        CommSharedPtr& SessionReader::GetComm()
        {
            return m_comm;
        }

589 590 591 592 593 594 595

        /**
         * This routine finalises any parallel communication.
         *
         * @note This routine should be called at the very end of a users
         * application.
         */
596 597 598 599 600
        void SessionReader::Finalise()
        {
            m_comm->Finalise();
        }

601

602 603 604 605 606 607
        /**
         *
         */
        bool SessionReader::DefinesParameter(const std::string& pName) const
        {
            std::string vName = boost::to_upper_copy(pName);
608 609
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
            return (paramIter != m_parameters.end());
610 611
        }

612 613 614 615 616 617 618 619 620

        /**
         * If the parameter is not defined, termination occurs. Therefore, the
         * parameters existence should be tested for using #DefinesParameter
         * before calling this function.
         *
         * @param   pName       The name of a floating-point parameter.
         * @returns The value of the floating-point parameter.
         */
621 622
        const NekDouble& SessionReader::GetParameter(
            const std::string& pName) const
623 624
        {
            std::string vName = boost::to_upper_copy(pName);
625
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
626

627 628
            ASSERTL0(paramIter != m_parameters.end(),
                     "Unable to find requested parameter: " + pName);
629

630
            return paramIter->second;
631 632
        }

633 634 635 636

        /**
         *
         */
637 638
        void SessionReader::LoadParameter(
            const std::string &pName, int &pVar) const
639 640
        {
            std::string vName = boost::to_upper_copy(pName);
641 642 643 644
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
            ASSERTL0(paramIter != m_parameters.end(), "Required parameter '" + 
                     pName + "' not specified in session.");
            pVar = (int)floor(paramIter->second);
645 646
        }

647 648 649 650

        /**
         *
         */
651 652
        void SessionReader::LoadParameter(
            const std::string &pName, int &pVar, const int &pDefault) const
653 654
        {
            std::string vName = boost::to_upper_copy(pName);
655 656
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
            if(paramIter != m_parameters.end())
657
            {
658
                pVar = (int)floor(paramIter->second);
659 660 661 662 663 664 665
            }
            else
            {
                pVar  = pDefault;
            }
        }

666 667 668 669

        /**
         *
         */
670 671
        void SessionReader::LoadParameter(
            const std::string &pName, NekDouble& pVar) const
672 673
        {
            std::string vName = boost::to_upper_copy(pName);
674 675 676 677
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
            ASSERTL0(paramIter != m_parameters.end(), "Required parameter '" + 
                     pName + "' not specified in session.");
            pVar = paramIter->second;
678 679
        }

680 681 682 683

        /**
         *
         */
684 685 686 687
        void SessionReader::LoadParameter(
            const std::string &pName, 
                  NekDouble   &pVar, 
            const NekDouble   &pDefault) const
688 689
        {
            std::string vName = boost::to_upper_copy(pName);
690 691
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
            if(paramIter != m_parameters.end())
692
            {
693
                pVar = paramIter->second;
694 695 696
            }
            else
            {
697
                pVar = pDefault;
698 699 700
            }
        }

701

Spencer Sherwin's avatar
Spencer Sherwin committed
702 703 704 705 706 707 708 709 710 711 712 713 714 715

        /**
         *
         */
        void SessionReader::SetParameter(const std::string &pName, int &pVar) 
        {
            std::string vName = boost::to_upper_copy(pName);
            m_parameters[vName] = pVar;
        }


        /**
         *
         */
716 717
        void SessionReader::SetParameter(
            const std::string &pName, NekDouble& pVar) 
Spencer Sherwin's avatar
Spencer Sherwin committed
718 719 720 721 722 723 724
        {
            std::string vName = boost::to_upper_copy(pName);
            m_parameters[vName] = pVar;
        }



725 726 727 728
        /**
         *
         */
        bool SessionReader::DefinesSolverInfo(const std::string &pName) const
729 730
        {
            std::string vName = boost::to_upper_copy(pName);
731 732
            SolverInfoMap::const_iterator infoIter = m_solverInfo.find(vName);
            return (infoIter != m_solverInfo.end());
733 734
        }

735 736 737 738

        /**
         *
         */
739 740
        const std::string& SessionReader::GetSolverInfo(
            const std::string &pProperty) const
741 742
        {
            std::string vProperty = boost::to_upper_copy(pProperty);
743
            SolverInfoMap::const_iterator iter = m_solverInfo.find(vProperty);
744

745 746
            ASSERTL1(iter != m_solverInfo.end(),
                     "Unable to find requested property: " + pProperty);
747

748
            return iter->second;
749 750
        }

Sergey Yakovlev's avatar
Sergey Yakovlev committed
751 752 753 754 755 756 757 758 759 760 761 762 763 764
        /**
         *
         */
        void SessionReader::SetSolverInfo(
            const std::string &pProperty, const std::string &pValue) 
        {
            std::string vProperty = boost::to_upper_copy(pProperty);
            SolverInfoMap::iterator iter = m_solverInfo.find(vProperty);

            ASSERTL1(iter != m_solverInfo.end(),
                     "Unable to find requested property: " + pProperty);

            iter->second = pValue;
        }
765 766 767 768

        /**
         *
         */
769 770 771 772
        void SessionReader::LoadSolverInfo(
            const std::string &pName, 
                  std::string &pVar, 
            const std::string &pDefault) const
773 774
        {
            std::string vName = boost::to_upper_copy(pName);
775 776
            SolverInfoMap::const_iterator infoIter = m_solverInfo.find(vName);
            if(infoIter != m_solverInfo.end())
777
            {
778
                pVar = infoIter->second;
779 780 781
            }
            else
            {
782
                pVar = pDefault;
783 784 785
            }
        }

786 787 788 789

        /**
         *
         */
790 791 792 793 794
        void SessionReader::MatchSolverInfo(
            const std::string &pName,
            const std::string &pTrueVal,
                  bool        &pVar,
            const bool        &pDefault) const
795 796
        {
            std::string vName = boost::to_upper_copy(pName);
797 798
            SolverInfoMap::const_iterator infoIter = m_solverInfo.find(vName);
            if(infoIter != m_solverInfo.end())
799
            {
800
                pVar = boost::iequals(infoIter->second, pTrueVal);
801 802 803
            }
            else
            {
804
                pVar = pDefault;
805 806 807
            }
        }

808 809 810 811

        /**
         *
         */
812 813 814
        bool SessionReader::MatchSolverInfo(
            const std::string &pName,
            const std::string &pTrueVal) const
815 816 817 818
        {
            if (DefinesSolverInfo(pName))
            {
                std::string vName = boost::to_upper_copy(pName);
819 820
                SolverInfoMap::const_iterator iter = m_solverInfo.find(vName);
                if(iter != m_solverInfo.end())
821 822 823 824 825 826 827 828
                {
                    return true;
                }
            }
            return false;
        }


829 830 831 832 833 834 835
        /**
         *
         */
        bool SessionReader::DefinesGlobalSysSolnInfo(const std::string &pVariable, 
                                                     const std::string &pProperty) const
        {

836 837 838
            GloSysSolnInfoList::const_iterator iter =
                    GetGloSysSolnList().find(pVariable);
            if(iter == GetGloSysSolnList().end())
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
            {
                return false;
            }

            std::string vProperty = boost::to_upper_copy(pProperty);
            
            GloSysInfoMap::const_iterator iter1 = iter->second.find(vProperty);
            if(iter1 == iter->second.end())
            {
                return false;
            }
            
            return true;
        }

        
        /**
         *
         */
        const std::string &SessionReader::GetGlobalSysSolnInfo(const std::string &pVariable, const std::string &pProperty) const
        {
            GloSysSolnInfoList::const_iterator iter; 

862 863
            ASSERTL0( (iter = GetGloSysSolnList().find(pVariable)) !=
                              GetGloSysSolnList().end(),
864 865 866 867 868 869 870 871 872 873 874
                      "Failed to find variable in GlobalSysSolnInfoList");

            std::string vProperty = boost::to_upper_copy(pProperty);
            GloSysInfoMap::const_iterator iter1; 

            ASSERTL0( (iter1 = iter->second.find(vProperty)) != iter->second.end(),
                      "Failed to find property: " + vProperty + " in GlobalSysSolnInfoList");
            
            return iter1->second;
        }
        
875 876 877 878
        /**
         *
         */
        bool SessionReader::DefinesGeometricInfo(const std::string &pName) const
879 880
        {
            std::string vName = boost::to_upper_copy(pName);
881 882
            GeometricInfoMap::const_iterator iter = m_geometricInfo.find(vName);
            return (iter != m_geometricInfo.end());
883 884
        }

885 886 887 888

        /**
         *
         */
889 890 891 892
        void SessionReader::LoadGeometricInfo(
            const std::string &pName,
                  std::string &pVar,
            const std::string &pDefault) const
893 894
        {
            std::string vName = boost::to_upper_copy(pName);
895 896
            GeometricInfoMap::const_iterator iter = m_geometricInfo.find(vName);
            if(iter != m_geometricInfo.end())
897
            {
898
                pVar = iter->second;
899 900 901
            }
            else
            {
902
                pVar = pDefault;
903 904 905
            }
        }

906 907 908 909

        /**
         *
         */
910 911 912 913
        void SessionReader::LoadGeometricInfo(
            const std::string &pName,
                  bool        &pVar,
            const bool        &pDefault) const
914 915
        {
            std::string vName = boost::to_upper_copy(pName);
916 917
            GeometricInfoMap::const_iterator iter = m_geometricInfo.find(vName);
            if(iter != m_geometricInfo.end())
918
            {
919
                if (iter->second == "TRUE")
920 921 922 923 924 925 926 927 928 929
                {
                    pVar = true;
                }
                else
                {
                    pVar = false;
                }
            }
            else
            {
930
                pVar = pDefault;
931 932 933
            }
        }

934

935 936 937
        /**
         *
         */
938 939 940 941
        void SessionReader::LoadGeometricInfo(
            const std::string &pName,
                  NekDouble   &pVar,
            const NekDouble   &pDefault) const
942 943
        {
            std::string vName = boost::to_upper_copy(pName);
944 945
            GeometricInfoMap::const_iterator iter = m_geometricInfo.find(vName);
            if(iter != m_geometricInfo.end())
946
            {
947
                pVar = std::atoi(iter->second.c_str());
948 949 950
            }
            else
            {
951
                pVar = pDefault;
952 953 954 955
            }
        }


956 957 958
        /**
         *
         */
959 960 961 962 963
        void SessionReader::MatchGeometricInfo(
            const std::string &pName,
            const std::string &pTrueVal,
                  bool        &pVar,
            const bool        &pDefault) const
964 965
        {
            std::string vName = boost::to_upper_copy(pName);
966 967
            GeometricInfoMap::const_iterator iter = m_geometricInfo.find(vName);
            if(iter != m_geometricInfo.end())
968
            {
969
                pVar = boost::iequals(iter->second, pTrueVal);
970 971 972 973 974 975 976 977
            }
            else
            {
                pVar  = pDefault;
            }
        }


978 979 980
        /**
         *
         */
981 982
        const std::string& SessionReader::GetVariable(
            const unsigned int &idx) const
983 984 985 986 987
        {
            ASSERTL0(idx < m_variables.size(), "Variable index out of range.");
            return m_variables[idx];
        }

988

989 990 991 992 993 994 995 996 997 998 999 1000

        /**
         *
         */
        void SessionReader::SetVariable(const unsigned int &idx, 
                                        std::string newname) 
        {
            ASSERTL0(idx < m_variables.size(), "Variable index out of range.");
            m_variables[idx] = newname;
        }


1001 1002 1003
        /**
         *
         */
1004 1005 1006 1007 1008
        std::vector<std::string> SessionReader::GetVariables() const
        {
            return m_variables;
        }

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028

        /**
         *
         */
        bool SessionReader::DefinesFunction(const std::string &pName) const
        {
            FunctionMap::const_iterator it1;
            std::string vName = boost::to_upper_copy(pName);

            if ((it1 = m_functions.find(vName)) != m_functions.end())
            {
                return true;
            }
            return false;
        }


        /**
         *
         */
1029 1030
        bool SessionReader::DefinesFunction(
            const std::string &pName,
1031 1032
            const std::string &pVariable,
            const int pDomain) const
1033 1034
        {
            FunctionMap::const_iterator it1;
1035
            FunctionVariableMap::const_iterator it2;
1036 1037
            std::string vName = boost::to_upper_copy(pName);

1038 1039
            // Check function exists
            if ((it1 = m_functions.find(vName))     != m_functions.end())
1040
            {
1041 1042
                pair<std::string, int> key(pVariable,pDomain);
                pair<std::string, int> defkey("*",pDomain);
1043
                bool varExists =
1044 1045
                    (it2 = it1->second.find(key)) != it1->second.end() ||
                    (it2 = it1->second.find(defkey)) != it1->second.end();
1046
                return varExists;
1047 1048 1049 1050 1051 1052 1053 1054
            }
            return false;
        }


        /**
         *
         */
1055 1056
        EquationSharedPtr SessionReader::GetFunction(
            const std::string &pName,
1057 1058
            const std::string &pVariable,
            const int pDomain) const
1059 1060
        {
            FunctionMap::const_iterator it1;
1061
            FunctionVariableMap::const_iterator it2, it3;
1062 1063 1064 1065 1066
            std::string vName = boost::to_upper_copy(pName);

            ASSERTL0((it1 = m_functions.find(vName)) != m_functions.end(),
                     std::string("No such function '") + pName
                     + std::string("' has been defined in the session file."));
1067 1068

            // Check for specific and wildcard definitions
1069 1070 1071 1072 1073 1074
            pair<std::string,int> key(pVariable,pDomain);
            pair<std::string,int> defkey("*",pDomain);
            bool specific = (it2 = it1->second.find(key)) !=
                it1->second.end();
            bool wildcard = (it3 = it1->second.find(defkey)) !=
                it1->second.end();
1075 1076 1077

            // Check function is defined somewhere
            ASSERTL0(specific || wildcard,
1078 1079 1080 1081
                     "No such variable " + pVariable
                     + " in domain " + boost::lexical_cast<string>(pDomain) 
                     + " defined for function " + pName
                     + " in session file.");
1082 1083 1084 1085 1086 1087 1088

            // If not specific, must be wildcard
            if (!specific)
            {
                it2 = it3;
            }

1089
            ASSERTL0((it2->second.m_type == eFunctionTypeExpression),
1090
                    std::string("Function is defined by a file."));
1091
            return it2->second.m_expression;
1092 1093
        }

1094 1095 1096 1097

        /**
         *
         */
1098 1099
        EquationSharedPtr SessionReader::GetFunction(
            const std::string  &pName,
1100 1101
            const unsigned int &pVar,
            const int pDomain) const
1102 1103
        {
            ASSERTL0(pVar < m_variables.size(), "Variable index out of range.");
1104
            return GetFunction(pName, m_variables[pVar],pDomain);
1105 1106
        }

1107 1108 1109 1110

        /**
         *
         */
1111 1112
        enum FunctionType SessionReader::GetFunctionType(
            const std::string &pName,
1113 1114
            const std::string &pVariable,
            const int pDomain) const
1115 1116
        {
            FunctionMap::const_iterator it1;
1117
            FunctionVariableMap::const_iterator it2, it3;
1118 1119 1120 1121 1122 1123
            std::string vName = boost::to_upper_copy(pName);

            it1 = m_functions.find(vName);
            ASSERTL0 (it1 != m_functions.end(),
                      std::string("Function '") + pName
                      + std::string("' not found."));
1124 1125

            // Check for specific and wildcard definitions
1126 1127 1128
            pair<std::string,int> key(pVariable,pDomain);
            pair<std::string,int> defkey("*",pDomain);
            bool specific = (it2 = it1->second.find(key)) !=
1129
                            it1->second.end();
1130
            bool wildcard = (it3 = it1->second.find(defkey)) !=
1131 1132 1133 1134
                            it1->second.end();

            // Check function is defined somewhere
            ASSERTL0(specific || wildcard,
1135 1136 1137 1138
                     "No such variable " + pVariable
                     + " in domain " + boost::lexical_cast<string>(pDomain) 
                     + " defined for function " + pName
                     + " in session file.");
1139 1140 1141 1142 1143 1144 1145

            // If not specific, must be wildcard
            if (!specific)
            {
                it2 = it3;
            }

1146
            return it2->second.m_type;
1147 1148
        }

1149 1150 1151 1152

        /**
         *
         */
1153 1154
        enum FunctionType SessionReader::GetFunctionType(
            const std::string  &pName,
1155 1156
            const unsigned int &pVar,
            const int pDomain) const
1157 1158
        {
            ASSERTL0(pVar < m_variables.size(), "Variable index out of range.");
1159
            return GetFunctionType(pName, m_variables[pVar],pDomain);
1160 1161 1162 1163 1164 1165
        }


        /**
         *
         */
1166 1167
        std::string SessionReader::GetFunctionFilename(
            const std::string &pName, 
1168 1169
            const std::string &pVariable,
            const int pDomain) const
1170 1171
        {
            FunctionMap::const_iterator it1;
1172
            FunctionVariableMap::const_iterator it2, it3;
1173 1174 1175 1176 1177 1178
            std::string vName = boost::to_upper_copy(pName);

            it1 = m_functions.find(vName);
            ASSERTL0 (it1 != m_functions.end(),
                      std::string("Function '") + pName
                      + std::string("' not found."));
1179 1180

            // Check for specific and wildcard definitions
1181 1182 1183
            pair<std::string,int> key(pVariable,pDomain);
            pair<std::string,int> defkey("*",pDomain);
            bool specific = (it2 = it1->second.find(key)) !=
1184
                            it1->second.end();
1185
            bool wildcard = (it3 = it1->second.find(defkey)) !=
1186 1187 1188 1189
                            it1->second.end();

            // Check function is defined somewhere
            ASSERTL0(specific || wildcard,
1190 1191 1192 1193 1194
                     "No such variable " + pVariable
                     + " in domain " + boost::lexical_cast<string>(pDomain) 
                     + " defined for function " + pName
                     + " in session file.");
            
1195 1196 1197 1198 1199 1200
            // If not specific, must be wildcard
            if (!specific)
            {
                it2 = it3;
            }

1201 1202 1203 1204 1205 1206 1207
            return it2->second.m_filename;
        }


        /**
         *
         */
1208 1209
        std::string SessionReader::GetFunctionFilename(
            const std::string  &pName, 
1210 1211
            const unsigned int &pVar,
            const int pDomain) const
1212 1213
        {
            ASSERTL0(pVar < m_variables.size(), "Variable index out of range.");
1214
            return GetFunctionFilename(pName, m_variables[pVar],pDomain);
1215 1216 1217
        }


1218 1219 1220 1221 1222 1223 1224 1225 1226
        /**
         *
         */
        AnalyticExpressionEvaluator& SessionReader::GetExpressionEvaluator()
        {
            return m_exprEvaluator;
        }


1227 1228 1229 1230
        /**
         *
         */
        bool SessionReader::DefinesTag(const std::string &pName) const
1231 1232
        {
            std::string vName = boost::to_upper_copy(pName);
1233
            TagMap::const_iterator vTagIterator = m_tags.find(vName);
1234 1235 1236
            return (vTagIterator != m_tags.end());
        }

1237 1238 1239 1240

        /**
         *
         */
1241 1242 1243
        void SessionReader::SetTag(
            const std::string &pName, 
            const std::string &pValue)
1244 1245 1246 1247 1248
        {
            std::string vName = boost::to_upper_copy(pName);
            m_tags[vName] = pValue;
        }

1249 1250 1251 1252 1253

        /**
         *
         */
        const std::string &SessionReader::GetTag(const std::string& pName) const
1254 1255
        {
            std::string vName = boost::to_upper_copy(pName);
1256
            TagMap::const_iterator vTagIterator = m_tags.find(vName);
1257 1258 1259 1260 1261
            ASSERTL0(vTagIterator != m_tags.end(),
                     "Requested tag does not exist.");
            return vTagIterator->second;
        }

1262

1263 1264 1265 1266 1267 1268 1269 1270 1271
        /**
         *
         */
        const FilterMap &SessionReader::GetFilters() const
        {
            return m_filters;
        }


1272 1273 1274
        /**
         *
         */
1275 1276
        bool SessionReader::DefinesCmdLineArgument(
            const std::string& pName) const
1277 1278 1279 1280 1281
        {
            return (m_cmdLineOptions.find(pName) != m_cmdLineOptions.end());
        }


1282 1283 1284 1285 1286 1287
        /**
         *
         */
        void SessionReader::SubstituteExpressions(std::string& pExpr)
        {
            ExpressionMap::iterator exprIter;
1288 1289
            for (exprIter  = m_expressions.begin(); 
                 exprIter != m_expressions.end(); ++exprIter)
1290 1291 1292 1293 1294
            {
                boost::replace_all(pExpr, exprIter->first, exprIter->second);
            }
        }

1295 1296 1297 1298
        CompositeOrdering SessionReader::GetCompositeOrdering() const
        {
            return m_compOrder;
        }
1299

1300 1301 1302 1303 1304
        BndRegionOrdering SessionReader::GetBndRegionOrdering() const
        {
            return m_bndRegOrder;
        }

1305 1306 1307 1308 1309 1310 1311
        /**
         *
         */
        void SessionReader::LoadDoc(
            const std::string &pFilename,
            TiXmlDocument* pDoc) const
        {
1312 1313
            if (pFilename.size() > 3 &&
                pFilename.substr(pFilename.size() - 3, 3) == ".gz")
1314
            {
1315 1316 1317
                ifstream file(pFilename.c_str(),
                              ios_base::in | ios_base::binary);
                ASSERTL0(file.good(), "Unable to open file: " + pFilename);
1318