SessionReader.cpp 93.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
///////////////////////////////////////////////////////////////////////////////
//
// 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
Dave Moxey's avatar
Dave Moxey committed
22
// in all copies or substantial portions of the Software.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
//
// 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
                    "IterativeStaticCond";
260
            }
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 349
                ("nsz",          po::value<int>(),
                                 "number of slics in Z-dir")
350 351
                ("part-only",    po::value<int>(),
                                 "only partition mesh into N partitions.")
352
                ("part-info",    "Output partition information")
353
            ;
354
            
355
            CmdLineArgMap::const_iterator cmdIt;
356 357
            for (cmdIt  = GetCmdLineArgMap().begin();
                 cmdIt != GetCmdLineArgMap().end(); ++cmdIt)
358 359 360 361 362 363
            {
                std::string names = cmdIt->first;
                if (cmdIt->second.shortName != "")
                {
                    names += "," + cmdIt->second.shortName;
                }
364 365 366 367 368 369 370 371 372 373 374 375 376
                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())
                    ;
                }
377
            }
378 379 380 381 382

            // 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()
383 384
                    ("input-file", po::value< vector<string> >(), 
                                   "input filename")
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
            ;

            // 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"))
            {
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
                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
424 425 426 427 428 429 430 431 432 433 434 435
                    cout << " (git changeset " << sha1.substr(0, 8) << ", ";

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

                    cout << ")";
436 437 438
                }

                cout << endl;
439 440 441 442 443 444 445 446 447 448 449 450
                exit(0);
            }

            // Enable verbose mode
            if (m_cmdLineOptions.count("verbose"))
            {
                m_verbose = true;
            }
            else
            {
                m_verbose = false;
            }
451
            
452 453 454 455 456 457
            // 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)
                {
458 459
                    cout << "Warning: Unknown option: " << x->string_key 
                         << endl;
460 461 462 463 464 465
                }
            }

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


476 477 478
        /**
         *
         */
479 480
        TiXmlDocument& SessionReader::GetDocument()
        {
481
            ASSERTL1(m_xmlDoc, "XML Document not defined.");
482 483 484
            return *m_xmlDoc;
        }

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504

        /**
         * 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.
505 506
         *
         * @return Direct pointer to requested XML Element.
507
         */
508 509 510
        TiXmlElement* SessionReader::GetElement(const string& pPath)
        {
            std::string vPath = boost::to_upper_copy(pPath);
511 512 513
            std::vector<std::string> st;
            boost::split(st, vPath, boost::is_any_of("\\/ "));
            ASSERTL0(st.size() > 0, "No path given in XML element request.");
514

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

527 528 529 530 531

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

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

549 550 551 552

        /**
         *
         */
553
        const std::string& SessionReader::GetFilename() const
554 555 556 557
        {
            return m_filename;
        }

558 559 560 561

        /**
         *
         */
562 563 564 565 566
        const std::string& SessionReader::GetSessionName() const
        {
            return m_sessionName;
        }

567

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

580 581 582 583
            fs::path fullpath = pdirname / pFilename;

            return PortablePath(fullpath);
        }
584

585 586 587
        /**
         *
         */
588 589 590 591 592
        CommSharedPtr& SessionReader::GetComm()
        {
            return m_comm;
        }

593 594 595 596 597 598 599

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

605

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

616 617 618 619 620 621 622 623 624

        /**
         * 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.
         */
625 626
        const NekDouble& SessionReader::GetParameter(
            const std::string& pName) const
627 628
        {
            std::string vName = boost::to_upper_copy(pName);
629
            ParameterMap::const_iterator paramIter = m_parameters.find(vName);
630

631 632
            ASSERTL0(paramIter != m_parameters.end(),
                     "Unable to find requested parameter: " + pName);
633

634
            return paramIter->second;
635 636
        }

637 638 639 640

        /**
         *
         */
641 642
        void SessionReader::LoadParameter(
            const std::string &pName, int &pVar) const
643 644
        {
            std::string vName = boost::to_upper_copy(pName);
645 646 647 648
            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);
649 650
        }

651 652 653 654

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

670 671 672 673

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

684 685 686 687

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

705

Spencer Sherwin's avatar
Spencer Sherwin committed
706 707 708 709 710 711 712 713 714 715 716 717 718 719

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


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



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

739 740 741 742

        /**
         *
         */
743 744
        const std::string& SessionReader::GetSolverInfo(
            const std::string &pProperty) const
745 746
        {
            std::string vProperty = boost::to_upper_copy(pProperty);
747
            SolverInfoMap::const_iterator iter = m_solverInfo.find(vProperty);
748

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

752
            return iter->second;
753 754
        }

Sergey Yakovlev's avatar
Sergey Yakovlev committed
755 756 757 758 759 760 761 762 763 764 765 766 767 768
        /**
         *
         */
        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;
        }
769 770 771 772

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

790 791 792 793

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

812 813 814 815

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


833 834 835 836 837 838 839
        /**
         *
         */
        bool SessionReader::DefinesGlobalSysSolnInfo(const std::string &pVariable, 
                                                     const std::string &pProperty) const
        {

840 841 842
            GloSysSolnInfoList::const_iterator iter =
                    GetGloSysSolnList().find(pVariable);
            if(iter == GetGloSysSolnList().end())
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
            {
                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; 

866 867
            ASSERTL0( (iter = GetGloSysSolnList().find(pVariable)) !=
                              GetGloSysSolnList().end(),
868 869 870 871 872 873 874 875 876 877 878
                      "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;
        }
        
879 880 881 882
        /**
         *
         */
        bool SessionReader::DefinesGeometricInfo(const std::string &pName) const
883 884
        {
            std::string vName = boost::to_upper_copy(pName);
885 886
            GeometricInfoMap::const_iterator iter = m_geometricInfo.find(vName);
            return (iter != m_geometricInfo.end());
887 888
        }

889 890 891 892

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

910 911 912 913

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

938

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


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


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

992

993 994 995 996 997 998 999 1000 1001 1002 1003 1004

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


1005 1006 1007
        /**
         *
         */
1008 1009 1010 1011 1012
        std::vector<std::string> SessionReader::GetVariables() const
        {
            return m_variables;
        }

1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

        /**
         *
         */
        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;
        }


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

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


        /**
         *
         */
1059 1060
        EquationSharedPtr SessionReader::GetFunction(
            const std::string &pName,
1061 1062
            const std::string &pVariable,
            const int pDomain) const
1063 1064
        {
            FunctionMap::const_iterator it1;
1065
            FunctionVariableMap::const_iterator it2, it3;
1066 1067 1068 1069 1070
            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."));
1071 1072

            // Check for specific and wildcard definitions
1073 1074 1075 1076 1077 1078
            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();
1079 1080 1081

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

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

1093
            ASSERTL0((it2->second.m_type == eFunctionTypeExpression),
1094
                    std::string("Function is defined by a file."));
1095
            return it2->second.m_expression;
1096 1097
        }

1098 1099 1100 1101

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

1111 1112 1113 1114

        /**
         *
         */
1115 1116
        enum FunctionType SessionReader::GetFunctionType(
            const std::string &pName,
1117 1118
            const std::string &pVariable,
            const int pDomain) const
1119 1120
        {
            FunctionMap::const_iterator it1;
1121
            FunctionVariableMap::const_iterator it2, it3;
1122 1123 1124 1125 1126 1127
            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."));
1128 1129

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

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

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

1150
            return it2->second.m_type;
1151 1152
        }

1153 1154 1155 1156

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


        /**
         *
         */
1170 1171
        std::string SessionReader::GetFunctionFilename(
            const std::string &pName, 
1172 1173
            const std::string &pVariable,
            const int pDomain) const
1174 1175
        {
            FunctionMap::const_iterator it1;
1176
            FunctionVariableMap::const_iterator it2, it3;
1177 1178 1179 1180 1181 1182
            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."));
1183 1184

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

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

1205 1206 1207 1208 1209 1210 1211
            return it2->second.m_filename;
        }


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


1222 1223 1224 1225 1226 1227 1228 1229 1230
        /**
         *
         */
        AnalyticExpressionEvaluator& SessionReader::GetExpressionEvaluator()
        {
            return m_exprEvaluator;
        }


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

1241 1242 1243 1244

        /**
         *
         */
1245 1246 1247
        void SessionReader::SetTag(
            const std::string &pName, 
            const std::string &pValue)
1248 1249 1250 1251 1252
        {
            std::string vName = boost::to_upper_copy(pName);
            m_tags[vName] = pValue;
        }

1253 1254 1255 1256 1257

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

1266

1267 1268 1269 1270 1271 1272 1273 1274 1275
        /**
         *
         */
        const FilterMap &SessionReader::GetFilters() const
        {
            return m_filters;
        }


1276 1277 1278
        /**
         *
         */
1279 1280
        bool SessionReader::DefinesCmdLineArgument(
            const std::string& pName) const
1281 1282 1283 1284 1285
        {
            return (m_cmdLineOptions.find(pName) != m_cmdLineOptions.end());
        }


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

1299 1300 1301 1302
        CompositeOrdering SessionReader::GetCompositeOrdering() const
        {
            return m_compOrder;
        }
1303

1304 1305 1306 1307 1308
        BndRegionOrdering SessionReader::GetBndRegionOrdering() const
        {
            return m_bndRegOrder;
        }

1309 1310 1311 1312 1313 1314 1315
        /**
         *
         */
        void SessionReader::LoadDoc(
            const std::string &pFilename,
            TiXmlDocument* pDoc) const
        {
1316 1317
            if (pFilename.size() > 3 &&
                pFilename.substr(pFilename.size() - 3, 3) == ".gz")
Chris Cantwell's avatar