<commit_before>//! @file application.cpp
#include "application.h"

#include "cantera/base/ctexceptions.h"
#include "cantera/base/ctml.h"
#include "cantera/base/stringUtils.h"
#include "cantera/base/xml.h"
#include "units.h"

#include <fstream>
#include <sstream>
#include <functional>

using std::string;
using std::endl;

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _MSC_VER
#pragma comment(lib, "advapi32")
#endif

namespace Cantera
{

// If running multiple threads in a cpp application, the Application class
// is the only internal object that is single instance with static data.

#ifdef THREAD_SAFE_CANTERA
cthreadId_t getThisThreadId()
{
#if defined(BOOST_HAS_WINTHREADS)
    return ::GetCurrentThreadId();
#elif defined(BOOST_HAS_PTHREADS)
    return pthread_self();
#endif
}

#endif

//! Mutex for input directory access
static mutex_t dir_mutex;

//! Mutex for creating singletons within the application object
static mutex_t app_mutex;

//! Mutex for controlling access to XML file storage
static mutex_t xml_mutex;

Application::Messages::Messages() :
    errorMessage(0),
    errorRoutine(0),
    logwriter(0)
{
    // install a default logwriter that writes to standard
    // output / standard error
    logwriter = new Logger();
}

Application::Messages::Messages(const Messages& r) :
    errorMessage(r.errorMessage),
    errorRoutine(r.errorRoutine),
    logwriter(0)
{
    // install a default logwriter that writes to standard
    // output / standard error
    logwriter = new Logger(*(r.logwriter));
}

Application::Messages& Application::Messages::operator=(const Messages& r)
{
    if (this == &r) {
        return *this;
    }
    errorMessage = r.errorMessage;
    errorRoutine = r.errorRoutine;
    logwriter = new Logger(*(r.logwriter));
    return *this;
}

Application::Messages::~Messages()
{
    delete logwriter;
}

void Application::Messages::addError(const std::string& r, const std::string& msg)
{
    errorMessage.push_back(msg);
    errorRoutine.push_back(r);
}

int Application::Messages::getErrorCount()
{
    return static_cast<int>(errorMessage.size()) ;
}

void Application::Messages::setLogger(Logger* _logwriter)
{
    if (logwriter == _logwriter) {
        return ;
    }
    if (logwriter != 0) {
        delete logwriter;
        logwriter = 0 ;
    }
    logwriter = _logwriter;
}

void Application::Messages::logerror(const std::string& msg)
{
    Cantera::warn_deprecated("Application::Messages::logerror");
    logwriter->error(msg) ;
}

void Application::Messages::writelog(const std::string& msg)
{
    logwriter->write(msg);
}

void Application::Messages::writelogendl()
{
    logwriter->writeendl();
}

#ifdef THREAD_SAFE_CANTERA

//! Mutex for access to string messages
static mutex_t msg_mutex;

Application::Messages* Application::ThreadMessages::operator ->()
{
    ScopedLock msgLock(msg_mutex);
    cthreadId_t curId = getThisThreadId() ;
    threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
    if (iter != m_threadMsgMap.end()) {
        return iter->second.get();
    }
    pMessages_t pMsgs(new Messages()) ;
    m_threadMsgMap.insert(std::pair< cthreadId_t, pMessages_t >(curId, pMsgs)) ;
    return pMsgs.get() ;
}

void Application::ThreadMessages::removeThreadMessages()
{
    ScopedLock msgLock(msg_mutex);
    cthreadId_t curId = getThisThreadId() ;
    threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
    if (iter != m_threadMsgMap.end()) {
        m_threadMsgMap.erase(iter) ;
    }
}
#endif // THREAD_SAFE_CANTERA

Application::Application() :
    inputDirs(0),
    stop_on_error(false),
    options(),
    xmlfiles(),
    m_suppress_deprecation_warnings(false),
    pMessenger()
{
#if !defined( THREAD_SAFE_CANTERA )
    pMessenger = std::auto_ptr<Messages>(new Messages());
#endif

    // install a default logwriter that writes to standard
    // output / standard error
    setDefaultDirectories();
#if defined(THREAD_SAFE_CANTERA)
    Unit::units() ;
#endif
}

Application* Application::Instance()
{
    ScopedLock appLock(app_mutex);
    if (Application::s_app == 0) {
        Application::s_app = new Application();
    }
    return s_app;
}

Application::~Application()
{
    std::map<std::string, XML_Node*>::iterator pos;
    for (pos = xmlfiles.begin(); pos != xmlfiles.end(); ++pos) {
        pos->second->unlock();
        delete pos->second;
        pos->second = 0;
    }
}

void Application::ApplicationDestroy()
{
    ScopedLock appLock(app_mutex);
    if (Application::s_app != 0) {
        delete Application::s_app;
        Application::s_app = 0;
    }
}

void Application::warn_deprecated(const std::string& method,
                                  const std::string& extra)
{
    if (m_suppress_deprecation_warnings || warnings.count(method)) {
        return;
    }
    warnings.insert(method);
    writelog("WARNING: '" + method + "' is deprecated. " + extra);
    writelogendl();
}

void Application::thread_complete()
{
#if defined(THREAD_SAFE_CANTERA)
    pMessenger.removeThreadMessages() ;
#endif
}

XML_Node* Application::get_XML_File(const std::string& file, int debug)
{
    ScopedLock xmlLock(xml_mutex);
    std::string path = "";
    path = findInputFile(file);
#ifdef _WIN32
    // RFB: For Windows make the path POSIX compliant so code looking for directory
    // separators is simpler.  Just look for '/' not both '/' and '\\'
    std::replace_if(path.begin(), path.end(),
                    std::bind2nd(std::equal_to<char>(), '\\'), '/') ;
#endif

    string ff = path;
    if (xmlfiles.find(path)
            == xmlfiles.end()) {
        /*
         * Check whether or not the file is XML. If not, it will
         * be first processed with the preprocessor. We determine
         * whether it is an XML file by looking at the file extension.
         */
        string::size_type idot = path.rfind('.');
        string ext;
        if (idot != string::npos) {
            ext = path.substr(idot, path.size());
        } else {
            ext = "";
            idot = path.size();
        }
        if (ext != ".xml" && ext != ".ctml") {
            /*
             * We will assume that we are trying to open a cti file.
             * First, determine the name of the xml file, ff, derived from
             * the cti file.
             * In all cases, we will write the xml file to the current
             * directory.
             */
            string::size_type islash = path.rfind('/');
            if (islash != string::npos) {
                ff = string("./")+path.substr(islash+1,idot-islash - 1) + ".xml";
            } else {
                ff = string("./")+path.substr(0,idot) + ".xml";
            }
            if (debug > 0) {
                writelog("get_XML_File(): Expected location of xml file = " +
                         ff + "\n");
            }
            /*
             * Do a search of the existing XML trees to determine if we have
             * already processed this file. If we have, return a pointer to
             * the processed xml tree.
             */
            if (xmlfiles.find(ff) != xmlfiles.end()) {
                if (debug > 0) {
                    writelog("get_XML_File(): File, " + ff +
                             ", was previously read." +
                             " Retrieving the stored xml tree.\n");
                }
                return xmlfiles[ff];
            }
            /*
             * Ok, we didn't find the processed XML tree. Do the conversion from cti
             */
            string phase_xml = ctml::ct2ctml_string(path);
            XML_Node* x = new XML_Node("doc");
            std::stringstream s(phase_xml);
            x->build(s);
            x->lock();
            xmlfiles[ff] = x;
            return x;
        } else {
            ff = path;
        }
        /*
         * Take the XML file ff, open it, and process it, creating an
         * XML tree, and then adding an entry in the map. We will store
         * the absolute pathname as the key for this map.
         */
        std::ifstream s(ff.c_str());

        XML_Node* x = new XML_Node("doc");
        if (s) {
            x->build(s);
            x->lock();
            xmlfiles[ff] = x;
        } else {
            string estring = "cannot open "+ff+" for reading.";
            estring += "Note, this error indicates a possible configuration problem.";
            throw CanteraError("get_XML_File", estring);
        }
    }

    /*
     * Return the XML node pointer. At this point, we are sure that the
     * lookup operation in the return statement will return a valid
     * pointer.
     */
    return xmlfiles[ff];
}

void Application::close_XML_File(const std::string& file)
{
    ScopedLock xmlLock(xml_mutex);
    if (file == "all") {
        std::map<string, XML_Node*>::iterator
        b = xmlfiles.begin(),
        e = xmlfiles.end();
        for (; b != e; ++b) {
            b->second->unlock();
            delete b->second;
            xmlfiles.erase(b->first);
        }
    } else if (xmlfiles.find(file) != xmlfiles.end()) {
        xmlfiles[file]->unlock();
        delete xmlfiles[file];
        xmlfiles.erase(file);
    }
}

#ifdef _WIN32
long int Application::readStringRegistryKey(const std::string& keyName, const std::string& valueName,
        std::string& value, const std::string& defaultValue)
{

    HKEY key;
    long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
    if (open_error != ERROR_SUCCESS) {
        return open_error;
    }
    value = defaultValue;
    CHAR buffer[1024];
    DWORD bufferSize = sizeof(buffer);
    ULONG error;
    error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
    if (ERROR_SUCCESS == error) {
        value = buffer;
    }
    RegCloseKey(key);
    return error;
}
#endif

void Application::Messages::popError()
{
    if (!errorMessage.empty()) {
        errorRoutine.pop_back() ;
        errorMessage.pop_back() ;
    }
}

std::string Application::Messages::lastErrorMessage()
{
    if (!errorMessage.empty()) {
        string head =
            "\n\n************************************************\n"
            "                Cantera Error!                  \n"
            "************************************************\n\n";
        return head+string("\nProcedure: ")+errorRoutine.back()
               +string("\nError:   ")+errorMessage.back();
    } else  {
        return "<no Cantera error>";
    }
}

void Application::Messages::getErrors(std::ostream& f)
{
    size_t i = errorMessage.size();
    if (i == 0) {
        return;
    }
    f << endl << endl;
    f << "************************************************" << endl;
    f << "                   Cantera Error!                  " << endl;
    f << "************************************************" << endl
      << endl;
    for (size_t j = 0; j < i; j++) {
        f << endl;
        f << "Procedure: " << errorRoutine[j] << endl;
        f << "Error:     " << errorMessage[j] << endl;
    }
    f << endl << endl;
    errorMessage.clear();
    errorRoutine.clear();
}

void Application::Messages::logErrors()
{
    size_t i = errorMessage.size();
    if (i == 0) {
        return;
    }
    writelog("\n\n");
    writelog("************************************************\n");
    writelog("                   Cantera Error!                  \n");
    writelog("************************************************\n\n");
    for (size_t j = 0; j < i; j++) {
        writelog("\n");
        writelog(string("Procedure: ")+ errorRoutine[j]+" \n");
        writelog(string("Error:     ")+ errorMessage[j]+" \n");
    }
    writelog("\n\n");
    errorMessage.clear();
    errorRoutine.clear();
}

void Application::setDefaultDirectories()
{
    std::vector<string>& dirs = inputDirs;

    // always look in the local directory first
    dirs.push_back(".");

#ifdef _WIN32
    // Under Windows, the Cantera setup utility records the installation
    // directory in the registry. Data files are stored in the 'data' and
    // 'templates' subdirectories of the main installation directory.

    std::string installDir;
    readStringRegistryKey("SOFTWARE\\Cantera\\Cantera 2.0",
                          "InstallDir", installDir, "");
    if (installDir != "") {
        dirs.push_back(installDir + "data");
        dirs.push_back(installDir + "templates");

        // Scripts for converting mechanisms to CTI and CMTL are installed in
        // the 'bin' subdirectory. Add that directory to the PYTHONPATH.
        const char* old_pythonpath = getenv("PYTHONPATH");
        std::string pythonpath = "PYTHONPATH=" + installDir + "\\bin";
        if (old_pythonpath) {
            pythonpath += ";";
            pythonpath.append(old_pythonpath);
        }
        putenv(pythonpath.c_str());
    }

#endif

#ifdef DARWIN
    //
    // add a default data location for Mac OS X
    //
    dirs.push_back("/Applications/Cantera/data");
#endif

    //
    // if environment variable CANTERA_DATA is defined, then add
    // it to the search path
    //
    if (getenv("CANTERA_DATA") != 0) {
        string datadir = string(getenv("CANTERA_DATA"));
        dirs.push_back(datadir);
    }

    // CANTERA_DATA is defined in file config.h. This file is written
    // during the build process (unix), and points to the directory
    // specified by the 'prefix' option to 'configure', or else to
    // /usr/local/cantera.
#ifdef CANTERA_DATA
    string datadir = string(CANTERA_DATA);
    dirs.push_back(datadir);
#endif
}

void Application::addDataDirectory(const std::string& dir)
{
    ScopedLock dirLock(dir_mutex);
    if (inputDirs.size() == 0) {
        setDefaultDirectories();
    }
    string d = stripnonprint(dir);
    size_t m, n = inputDirs.size();

    // don't add if already present
    for (m = 0; m < n; m++) {
        if (d == inputDirs[m]) {
            return;
        }
    }

    inputDirs.push_back(d);
}

std::string Application::findInputFile(const std::string& name)
{
    ScopedLock dirLock(dir_mutex);
    string::size_type islash = name.find('/');
    string::size_type ibslash = name.find('\\');
    string inname;
    std::vector<string>& dirs = inputDirs;

    // Expand "~/" to user's home directory, if possible
    if (name.find("~/") == 0) {
        char* home = getenv("HOME"); // POSIX systems
        if (!home) {
            home = getenv("USERPROFILE"); // Windows systems
        }
        if (home) {
            return home + name.substr(1, npos);
        }
    }

    if (islash == string::npos && ibslash == string::npos) {
        size_t nd = dirs.size();
        inname = "";
        for (size_t i = 0; i < nd; i++) {
            inname = dirs[i] + "/" + name;
            std::ifstream fin(inname.c_str());
            if (fin) {
                fin.close();
                return inname;
            }
        }
        string msg;
        msg = "\nInput file " + name
              + " not found in director";
        msg += (nd == 1 ? "y " : "ies ");
        for (size_t i = 0; i < nd; i++) {
            msg += "\n'" + dirs[i] + "'";
            if (i+1 < nd) {
                msg += ", ";
            }
        }
        msg += "\n\n";
        msg += "To fix this problem, either:\n";
        msg += "    a) move the missing files into the local directory;\n";
        msg += "    b) define environment variable CANTERA_DATA to\n";
        msg += "         point to the directory containing the file.";
        throw CanteraError("findInputFile", msg);
    }

    return name;
}

Application* Application::s_app = 0;

} // namespace Cantera
<commit_msg>Simplify implementation of get_XML_File<commit_after>//! @file application.cpp
#include "application.h"

#include "cantera/base/ctexceptions.h"
#include "cantera/base/ctml.h"
#include "cantera/base/stringUtils.h"
#include "cantera/base/xml.h"
#include "units.h"

#include <fstream>
#include <sstream>
#include <functional>

using std::string;
using std::endl;

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _MSC_VER
#pragma comment(lib, "advapi32")
#endif

namespace Cantera
{

// If running multiple threads in a cpp application, the Application class
// is the only internal object that is single instance with static data.

#ifdef THREAD_SAFE_CANTERA
cthreadId_t getThisThreadId()
{
#if defined(BOOST_HAS_WINTHREADS)
    return ::GetCurrentThreadId();
#elif defined(BOOST_HAS_PTHREADS)
    return pthread_self();
#endif
}

#endif

//! Mutex for input directory access
static mutex_t dir_mutex;

//! Mutex for creating singletons within the application object
static mutex_t app_mutex;

//! Mutex for controlling access to XML file storage
static mutex_t xml_mutex;

Application::Messages::Messages() :
    errorMessage(0),
    errorRoutine(0),
    logwriter(0)
{
    // install a default logwriter that writes to standard
    // output / standard error
    logwriter = new Logger();
}

Application::Messages::Messages(const Messages& r) :
    errorMessage(r.errorMessage),
    errorRoutine(r.errorRoutine),
    logwriter(0)
{
    // install a default logwriter that writes to standard
    // output / standard error
    logwriter = new Logger(*(r.logwriter));
}

Application::Messages& Application::Messages::operator=(const Messages& r)
{
    if (this == &r) {
        return *this;
    }
    errorMessage = r.errorMessage;
    errorRoutine = r.errorRoutine;
    logwriter = new Logger(*(r.logwriter));
    return *this;
}

Application::Messages::~Messages()
{
    delete logwriter;
}

void Application::Messages::addError(const std::string& r, const std::string& msg)
{
    errorMessage.push_back(msg);
    errorRoutine.push_back(r);
}

int Application::Messages::getErrorCount()
{
    return static_cast<int>(errorMessage.size()) ;
}

void Application::Messages::setLogger(Logger* _logwriter)
{
    if (logwriter == _logwriter) {
        return ;
    }
    if (logwriter != 0) {
        delete logwriter;
        logwriter = 0 ;
    }
    logwriter = _logwriter;
}

void Application::Messages::logerror(const std::string& msg)
{
    Cantera::warn_deprecated("Application::Messages::logerror");
    logwriter->error(msg) ;
}

void Application::Messages::writelog(const std::string& msg)
{
    logwriter->write(msg);
}

void Application::Messages::writelogendl()
{
    logwriter->writeendl();
}

#ifdef THREAD_SAFE_CANTERA

//! Mutex for access to string messages
static mutex_t msg_mutex;

Application::Messages* Application::ThreadMessages::operator ->()
{
    ScopedLock msgLock(msg_mutex);
    cthreadId_t curId = getThisThreadId() ;
    threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
    if (iter != m_threadMsgMap.end()) {
        return iter->second.get();
    }
    pMessages_t pMsgs(new Messages()) ;
    m_threadMsgMap.insert(std::pair< cthreadId_t, pMessages_t >(curId, pMsgs)) ;
    return pMsgs.get() ;
}

void Application::ThreadMessages::removeThreadMessages()
{
    ScopedLock msgLock(msg_mutex);
    cthreadId_t curId = getThisThreadId() ;
    threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
    if (iter != m_threadMsgMap.end()) {
        m_threadMsgMap.erase(iter) ;
    }
}
#endif // THREAD_SAFE_CANTERA

Application::Application() :
    inputDirs(0),
    stop_on_error(false),
    options(),
    xmlfiles(),
    m_suppress_deprecation_warnings(false),
    pMessenger()
{
#if !defined( THREAD_SAFE_CANTERA )
    pMessenger = std::auto_ptr<Messages>(new Messages());
#endif

    // install a default logwriter that writes to standard
    // output / standard error
    setDefaultDirectories();
#if defined(THREAD_SAFE_CANTERA)
    Unit::units() ;
#endif
}

Application* Application::Instance()
{
    ScopedLock appLock(app_mutex);
    if (Application::s_app == 0) {
        Application::s_app = new Application();
    }
    return s_app;
}

Application::~Application()
{
    std::map<std::string, XML_Node*>::iterator pos;
    for (pos = xmlfiles.begin(); pos != xmlfiles.end(); ++pos) {
        pos->second->unlock();
        delete pos->second;
        pos->second = 0;
    }
}

void Application::ApplicationDestroy()
{
    ScopedLock appLock(app_mutex);
    if (Application::s_app != 0) {
        delete Application::s_app;
        Application::s_app = 0;
    }
}

void Application::warn_deprecated(const std::string& method,
                                  const std::string& extra)
{
    if (m_suppress_deprecation_warnings || warnings.count(method)) {
        return;
    }
    warnings.insert(method);
    writelog("WARNING: '" + method + "' is deprecated. " + extra);
    writelogendl();
}

void Application::thread_complete()
{
#if defined(THREAD_SAFE_CANTERA)
    pMessenger.removeThreadMessages() ;
#endif
}

XML_Node* Application::get_XML_File(const std::string& file, int debug)
{
    ScopedLock xmlLock(xml_mutex);
    std::string path = "";
    path = findInputFile(file);

    if (xmlfiles.find(path) != xmlfiles.end()) {
        // Already have the parsed XML tree for this file cached, so just return
        // that.
        return xmlfiles[path];
    }
    /*
     * Check whether or not the file is XML (based on the file extension). If
     * not, it will be first processed with the preprocessor.
     */
    string::size_type idot = path.rfind('.');
    string ext;
    if (idot != string::npos) {
        ext = path.substr(idot, path.size());
    } else {
        ext = "";
    }
    XML_Node* x = new XML_Node("doc");
    if (ext != ".xml" && ext != ".ctml") {
        // Assume that we are trying to open a cti file. Do the conversion to XML.
        std::stringstream phase_xml(ctml::ct2ctml_string(path));
        x->build(phase_xml);
    } else {
        std::ifstream s(path.c_str());
        if (s) {
            x->build(s);
        } else {
            throw CanteraError("get_XML_File",
                "cannot open "+file+" for reading.\n"
                "Note, this error indicates a possible configuration problem.");
        }
    }
    x->lock();
    xmlfiles[path] = x;
    return x;
}

void Application::close_XML_File(const std::string& file)
{
    ScopedLock xmlLock(xml_mutex);
    if (file == "all") {
        std::map<string, XML_Node*>::iterator
        b = xmlfiles.begin(),
        e = xmlfiles.end();
        for (; b != e; ++b) {
            b->second->unlock();
            delete b->second;
            xmlfiles.erase(b->first);
        }
    } else if (xmlfiles.find(file) != xmlfiles.end()) {
        xmlfiles[file]->unlock();
        delete xmlfiles[file];
        xmlfiles.erase(file);
    }
}

#ifdef _WIN32
long int Application::readStringRegistryKey(const std::string& keyName, const std::string& valueName,
        std::string& value, const std::string& defaultValue)
{

    HKEY key;
    long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
    if (open_error != ERROR_SUCCESS) {
        return open_error;
    }
    value = defaultValue;
    CHAR buffer[1024];
    DWORD bufferSize = sizeof(buffer);
    ULONG error;
    error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
    if (ERROR_SUCCESS == error) {
        value = buffer;
    }
    RegCloseKey(key);
    return error;
}
#endif

void Application::Messages::popError()
{
    if (!errorMessage.empty()) {
        errorRoutine.pop_back() ;
        errorMessage.pop_back() ;
    }
}

std::string Application::Messages::lastErrorMessage()
{
    if (!errorMessage.empty()) {
        string head =
            "\n\n************************************************\n"
            "                Cantera Error!                  \n"
            "************************************************\n\n";
        return head+string("\nProcedure: ")+errorRoutine.back()
               +string("\nError:   ")+errorMessage.back();
    } else  {
        return "<no Cantera error>";
    }
}

void Application::Messages::getErrors(std::ostream& f)
{
    size_t i = errorMessage.size();
    if (i == 0) {
        return;
    }
    f << endl << endl;
    f << "************************************************" << endl;
    f << "                   Cantera Error!                  " << endl;
    f << "************************************************" << endl
      << endl;
    for (size_t j = 0; j < i; j++) {
        f << endl;
        f << "Procedure: " << errorRoutine[j] << endl;
        f << "Error:     " << errorMessage[j] << endl;
    }
    f << endl << endl;
    errorMessage.clear();
    errorRoutine.clear();
}

void Application::Messages::logErrors()
{
    size_t i = errorMessage.size();
    if (i == 0) {
        return;
    }
    writelog("\n\n");
    writelog("************************************************\n");
    writelog("                   Cantera Error!                  \n");
    writelog("************************************************\n\n");
    for (size_t j = 0; j < i; j++) {
        writelog("\n");
        writelog(string("Procedure: ")+ errorRoutine[j]+" \n");
        writelog(string("Error:     ")+ errorMessage[j]+" \n");
    }
    writelog("\n\n");
    errorMessage.clear();
    errorRoutine.clear();
}

void Application::setDefaultDirectories()
{
    std::vector<string>& dirs = inputDirs;

    // always look in the local directory first
    dirs.push_back(".");

#ifdef _WIN32
    // Under Windows, the Cantera setup utility records the installation
    // directory in the registry. Data files are stored in the 'data' and
    // 'templates' subdirectories of the main installation directory.

    std::string installDir;
    readStringRegistryKey("SOFTWARE\\Cantera\\Cantera 2.0",
                          "InstallDir", installDir, "");
    if (installDir != "") {
        dirs.push_back(installDir + "data");
        dirs.push_back(installDir + "templates");

        // Scripts for converting mechanisms to CTI and CMTL are installed in
        // the 'bin' subdirectory. Add that directory to the PYTHONPATH.
        const char* old_pythonpath = getenv("PYTHONPATH");
        std::string pythonpath = "PYTHONPATH=" + installDir + "\\bin";
        if (old_pythonpath) {
            pythonpath += ";";
            pythonpath.append(old_pythonpath);
        }
        putenv(pythonpath.c_str());
    }

#endif

#ifdef DARWIN
    //
    // add a default data location for Mac OS X
    //
    dirs.push_back("/Applications/Cantera/data");
#endif

    //
    // if environment variable CANTERA_DATA is defined, then add
    // it to the search path
    //
    if (getenv("CANTERA_DATA") != 0) {
        string datadir = string(getenv("CANTERA_DATA"));
        dirs.push_back(datadir);
    }

    // CANTERA_DATA is defined in file config.h. This file is written
    // during the build process (unix), and points to the directory
    // specified by the 'prefix' option to 'configure', or else to
    // /usr/local/cantera.
#ifdef CANTERA_DATA
    string datadir = string(CANTERA_DATA);
    dirs.push_back(datadir);
#endif
}

void Application::addDataDirectory(const std::string& dir)
{
    ScopedLock dirLock(dir_mutex);
    if (inputDirs.size() == 0) {
        setDefaultDirectories();
    }
    string d = stripnonprint(dir);
    size_t m, n = inputDirs.size();

    // don't add if already present
    for (m = 0; m < n; m++) {
        if (d == inputDirs[m]) {
            return;
        }
    }

    inputDirs.push_back(d);
}

std::string Application::findInputFile(const std::string& name)
{
    ScopedLock dirLock(dir_mutex);
    string::size_type islash = name.find('/');
    string::size_type ibslash = name.find('\\');
    string inname;
    std::vector<string>& dirs = inputDirs;

    // Expand "~/" to user's home directory, if possible
    if (name.find("~/") == 0) {
        char* home = getenv("HOME"); // POSIX systems
        if (!home) {
            home = getenv("USERPROFILE"); // Windows systems
        }
        if (home) {
            return home + name.substr(1, npos);
        }
    }

    if (islash == string::npos && ibslash == string::npos) {
        size_t nd = dirs.size();
        inname = "";
        for (size_t i = 0; i < nd; i++) {
            inname = dirs[i] + "/" + name;
            std::ifstream fin(inname.c_str());
            if (fin) {
                fin.close();
                return inname;
            }
        }
        string msg;
        msg = "\nInput file " + name
              + " not found in director";
        msg += (nd == 1 ? "y " : "ies ");
        for (size_t i = 0; i < nd; i++) {
            msg += "\n'" + dirs[i] + "'";
            if (i+1 < nd) {
                msg += ", ";
            }
        }
        msg += "\n\n";
        msg += "To fix this problem, either:\n";
        msg += "    a) move the missing files into the local directory;\n";
        msg += "    b) define environment variable CANTERA_DATA to\n";
        msg += "         point to the directory containing the file.";
        throw CanteraError("findInputFile", msg);
    }

    return name;
}

Application* Application::s_app = 0;

} // namespace Cantera
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CG_PDELAB_HH
#define DUNE_GDT_SPACES_CG_PDELAB_HH

#include <memory>

#include <dune/common/fvector.hh>
#include <dune/common/deprecated.hh>

#include <dune/geometry/genericgeometry/topologytypes.hh>

#if HAVE_DUNE_ISTL
# include <dune/istl/paamg/pinfo.hh>
# include <dune/stuff/la/solver/istl_amg.hh>
#endif

#if HAVE_DUNE_PDELAB
# include <dune/pdelab/finiteelementmap/pkfem.hh>
# include <dune/pdelab/finiteelementmap/qkfem.hh>
# include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>
# include <dune/pdelab/constraints/conforming.hh>
#endif // HAVE_DUNE_PDELAB

#include <dune/stuff/common/type_utils.hh>

#include <dune/gdt/spaces/parallel.hh>

#include "../../mapper/pdelab.hh"
#include "../../basefunctionset/pdelab.hh"

#include "interface.hh"

namespace Dune {

namespace GDT {
namespace Spaces {
namespace CG {

#if HAVE_DUNE_PDELAB

// forward, to be used in the traits and to allow for specialization
template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class PdelabBased
{
  static_assert(Dune::AlwaysFalse< GridViewImp >::value, "Untested for this combination of dimensions!");
};

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class PdelabBasedTraits
{
public:
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  typedef GridViewImp                   GridViewType;
  static const int                      polOrder = polynomialOrder;
  static_assert(polOrder >= 1, "Wrong polOrder given!");
private:
  typedef typename GridViewType::ctype  DomainFieldType;
  static const size_t                   dimDomain = GridViewType::dimension;
public:
  typedef RangeFieldImp                 RangeFieldType;
private:
  template< class G, bool single_geom, bool is_simplex, bool is_cube >
  struct FeMap
  {
    static_assert(Dune::AlwaysFalse< G >::value,
                  "This space is only implemented for either fully simplicial or fully cubic grids!");
  };
  template< class G >
  struct FeMap< G, true, true, false >
  {
    typedef PDELab::PkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  template< class G >
  struct FeMap< G, true, false, true >
  {
    typedef PDELab::QkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  typedef typename GridViewType::Grid GridType;
  static const bool single_geom_ = Dune::Capabilities::hasSingleGeometryType< GridType >::v;
  static const bool simplicial_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                                   == GenericGeometry::SimplexTopology< dimDomain >::type::id);
  static const bool cubic_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                              == GenericGeometry::CubeTopology< dimDomain >::type::id);
  typedef typename FeMap< GridType, single_geom_, simplicial_, cubic_ >::Type FEMapType;
public:
  typedef PDELab::GridFunctionSpace< GridViewType, FEMapType, PDELab::OverlappingConformingDirichletConstraints > BackendType;
  typedef Mapper::ContinuousPdelabWrapper< BackendType > MapperType;
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;
  typedef BaseFunctionSet::PdelabWrapper
      < BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, rangeDim, rangeDimCols >
    BaseFunctionSetType;
  static const Stuff::Grid::ChoosePartView part_view_type = Stuff::Grid::ChoosePartView::view;
  static const bool needs_grid_view = true;

  typedef typename CommunicationChooser<GridViewType>::Type CommunicatorType;
private:
  friend class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols >;
}; // class PdelabBasedTraits

template< class GridViewImp, int polynomialOrder, class RangeFieldImp >
class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
  : public Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >,
                                GridViewImp::dimension, 1, 1 >
{
  typedef Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >,
                               GridViewImp::dimension, 1, 1 >                    BaseType;
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >       ThisType;
public:
  typedef PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 > Traits;

  static const int    polOrder = Traits::polOrder;
  static const size_t dimDomain = BaseType::dimDomain;
  static const size_t dimRange = BaseType::dimRange;
  static const size_t dimRangeCols = BaseType::dimRangeCols;

  typedef typename Traits::GridViewType         GridViewType;
  typedef typename Traits::RangeFieldType       RangeFieldType;
  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;

  typedef typename GridViewType::ctype              DomainFieldType;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;
  typedef CommunicationChooser< GridViewType >      CommunicationChooserType;
  typedef typename CommunicationChooserType::Type   CommunicatorType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef typename BaseType::IntersectionType  IntersectionType;
  typedef typename BaseType::EntityType        EntityType;
  typedef typename BaseType::PatternType       PatternType;
  typedef typename BaseType::BoundaryInfoType  BoundaryInfoType;

  explicit PdelabBased(GridViewType gV)
    : gridView_(gV)
    , fe_map_(gridView_)
    , backend_(gridView_, fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser< GridViewImp >::create(gridView_))
    , communicator_prepared_(false)
  {}

  /**
   * \brief Copy ctor.
   * \note  Manually implemented bc of the std::mutex + communicator_ unique_ptr
   */
  PdelabBased(const ThisType& other)
    : gridView_(other.gridView_)
    , fe_map_(gridView_)
    , backend_(gridView_, fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser< GridViewImp >::create(gridView_))
    , communicator_prepared_(false)
  {
    // make sure our new communicator is prepared if other's was
    if (other.communicator_prepared_)
      const auto& DUNE_UNUSED(comm) = this->communicator();
  }

  /**
   * \brief Move ctor.
   * \note  Manually implemented bc of the std::mutex.
   */
  PdelabBased(ThisType&& source)
    : gridView_(source.gridView_)
    , fe_map_(source.fe_map_)
    , backend_(source.backend_)
    , mapper_(source.mapper_)
    , communicator_(std::move(source.communicator_))
    , communicator_prepared_(source.communicator_prepared_)
  {}

  ThisType& operator=(const ThisType& other) = delete;

  ThisType& operator=(ThisType&& source) = delete;

  const GridViewType& grid_view() const
  {
    return gridView_;
  }

  const BackendType& backend() const
  {
    return backend_;
  }

  const MapperType& mapper() const
  {
    return mapper_;
  }

  std::vector< DomainType > lagrange_points(const EntityType& entity) const
  {
    return BaseType::lagrange_points_order_1(entity);
  }

  std::set< size_t > local_dirichlet_DoFs(const EntityType& entity,
                                          const BoundaryInfoType& boundaryInfo) const
  {
    return BaseType::local_dirichlet_DoFs_order_1(entity, boundaryInfo);
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(backend_, entity);
  }

  CommunicatorType& communicator() const
  {
    std::lock_guard< std::mutex > DUNE_UNUSED(gg)(communicator_mutex_);
    if (!communicator_prepared_)
      communicator_prepared_ = CommunicationChooserType::prepare(*this, *communicator_);
    return *communicator_;
  } // ... communicator(...)

private:
  GridViewType gridView_;
  const FEMapType fe_map_;
  const BackendType backend_;
  const MapperType mapper_;
  mutable std::unique_ptr<CommunicatorType> communicator_;
  mutable bool communicator_prepared_;
  mutable std::mutex communicator_mutex_;
}; // class PdelabBased< ..., 1 >

#else // HAVE_DUNE_PDELAB

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class PdelabBased
{
  static_assert(Dune::AlwaysFalse< GridViewImp >::value, "You are missing dune-pdelab!");
};

#endif // HAVE_DUNE_PDELAB

} // namespace CG
} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CG_PDELAB_HH
<commit_msg>[spaces.cg.pedelab] add vector-valued case, not all methods have been implemented yet<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CG_PDELAB_HH
#define DUNE_GDT_SPACES_CG_PDELAB_HH

#include <memory>

#include <dune/common/fvector.hh>
#include <dune/common/deprecated.hh>

#include <dune/geometry/genericgeometry/topologytypes.hh>

#if HAVE_DUNE_ISTL
# include <dune/istl/paamg/pinfo.hh>
# include <dune/stuff/la/solver/istl_amg.hh>
#endif

#if HAVE_DUNE_PDELAB
# include <dune/pdelab/finiteelementmap/pkfem.hh>
# include <dune/pdelab/finiteelementmap/qkfem.hh>
# include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>
# include <dune/pdelab/gridfunctionspace/vectorgridfunctionspace.hh>
# include <dune/pdelab/constraints/conforming.hh>
#endif // HAVE_DUNE_PDELAB

#include <dune/stuff/common/type_utils.hh>

#include <dune/gdt/spaces/parallel.hh>

#include "../../mapper/pdelab.hh"
#include "../../basefunctionset/pdelab.hh"

#include "interface.hh"

namespace Dune {

namespace GDT {
namespace Spaces {
namespace CG {

#if HAVE_DUNE_PDELAB

// forward, to be used in the traits and to allow for specialization
template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class PdelabBased
{
  static_assert(Dune::AlwaysFalse< GridViewImp >::value, "Untested for this combination of dimensions!");
};

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class PdelabBasedTraits
{
public:
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  typedef GridViewImp                   GridViewType;
  static const int                      polOrder = polynomialOrder;
  static_assert(polOrder >= 1, "Wrong polOrder given!");
private:
  typedef typename GridViewType::ctype  DomainFieldType;
  static const size_t                   dimDomain = GridViewType::dimension;
public:
  typedef RangeFieldImp                 RangeFieldType;
private:
  template< class G, bool single_geom, bool is_simplex, bool is_cube >
  struct FeMap
  {
    static_assert(Dune::AlwaysFalse< G >::value,
                  "This space is only implemented for either fully simplicial or fully cubic grids!");
  };
  template< class G >
  struct FeMap< G, true, true, false >
  {
    typedef PDELab::PkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  template< class G >
  struct FeMap< G, true, false, true >
  {
    typedef PDELab::QkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  typedef typename GridViewType::Grid GridType;
  static const bool single_geom_ = Dune::Capabilities::hasSingleGeometryType< GridType >::v;
  static const bool simplicial_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                                   == GenericGeometry::SimplexTopology< dimDomain >::type::id);
  static const bool cubic_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                              == GenericGeometry::CubeTopology< dimDomain >::type::id);
  typedef typename FeMap< GridType, single_geom_, simplicial_, cubic_ >::Type FEMapType;
public:
  template< class G, size_t dimRange >
  struct BackendMapper
  {
    typedef PDELab::VectorGridFunctionSpace< GridViewType, FEMapType, dimRange, PDELab::ISTLVectorBackend<>,
                                             PDELab::ISTLVectorBackend<>, PDELab::OverlappingConformingDirichletConstraints > Type;
    typedef Mapper::ContinuousPowerPdelabWrapper< Type > MapType;
  };
  template< class G >
  struct BackendMapper< G, 1 >
  {
    typedef PDELab::GridFunctionSpace< GridViewType, FEMapType, PDELab::OverlappingConformingDirichletConstraints > Type;
    typedef Mapper::ContinuousPdelabWrapper< Type > MapType;
  };
  typedef typename BackendMapper< GridType, rangeDim >::Type BackendType;
  typedef typename BackendMapper< GridType, rangeDim >::MapType MapperType;
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;
 /* template< class G, size_t dimRange >
  struct BasefunctionSet
  {
    typedef BaseFunctionSet::PdelabWrapper< PDELab::GridFunctionSpace< GridViewType, FEMapType, PDELab::OverlappingConformingDirichletConstraints >,
                                            EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, rangeDimCols > Type;
  };
  template< class G >
  struct BasefunctionSet< G, 1 >
  {
    typedef BaseFunctionSet::PdelabWrapper< BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, rangeDimCols > Type;
  };
  typedef typename BasefunctionSet< GridType, rangeDim >::Type BaseFunctionSetType;*/
  typedef BaseFunctionSet::PdelabWrapper< BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, rangeDim, rangeDimCols > BaseFunctionSetType;
  static const Stuff::Grid::ChoosePartView part_view_type = Stuff::Grid::ChoosePartView::view;
  static const bool needs_grid_view = true;

  typedef typename CommunicationChooser<GridViewType>::Type CommunicatorType;
private:
  friend class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols >;
}; // class PdelabBasedTraits

template< class GridViewImp, int polynomialOrder, class RangeFieldImp >
class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
  : public Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >,
                                GridViewImp::dimension, 1, 1 >
{
  typedef Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >,
                               GridViewImp::dimension, 1, 1 >                    BaseType;
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >       ThisType;
public:
  typedef PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 > Traits;

  static const int    polOrder = Traits::polOrder;
  static const size_t dimDomain = BaseType::dimDomain;
  static const size_t dimRange = BaseType::dimRange;
  static const size_t dimRangeCols = BaseType::dimRangeCols;

  typedef typename Traits::GridViewType         GridViewType;
  typedef typename Traits::RangeFieldType       RangeFieldType;
  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;

  typedef typename GridViewType::ctype              DomainFieldType;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;
  typedef CommunicationChooser< GridViewType >      CommunicationChooserType;
  typedef typename CommunicationChooserType::Type   CommunicatorType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef typename BaseType::IntersectionType  IntersectionType;
  typedef typename BaseType::EntityType        EntityType;
  typedef typename BaseType::PatternType       PatternType;
  typedef typename BaseType::BoundaryInfoType  BoundaryInfoType;

  explicit PdelabBased(GridViewType gV)
    : gridView_(gV)
    , fe_map_(gridView_)
    , backend_(gridView_, fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser< GridViewImp >::create(gridView_))
    , communicator_prepared_(false)
  {}

  /**
   * \brief Copy ctor.
   * \note  Manually implemented bc of the std::mutex + communicator_ unique_ptr
   */
  PdelabBased(const ThisType& other)
    : gridView_(other.gridView_)
    , fe_map_(gridView_)
    , backend_(gridView_, fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser< GridViewImp >::create(gridView_))
    , communicator_prepared_(false)
  {
    // make sure our new communicator is prepared if other's was
    if (other.communicator_prepared_)
      const auto& DUNE_UNUSED(comm) = this->communicator();
  }

  /**
   * \brief Move ctor.
   * \note  Manually implemented bc of the std::mutex.
   */
  PdelabBased(ThisType&& source)
    : gridView_(source.gridView_)
    , fe_map_(source.fe_map_)
    , backend_(source.backend_)
    , mapper_(source.mapper_)
    , communicator_(std::move(source.communicator_))
    , communicator_prepared_(source.communicator_prepared_)
  {}

  ThisType& operator=(const ThisType& other) = delete;

  ThisType& operator=(ThisType&& source) = delete;

  const GridViewType& grid_view() const
  {
    return gridView_;
  }

  const BackendType& backend() const
  {
    return backend_;
  }

  const MapperType& mapper() const
  {
    return mapper_;
  }

  std::vector< DomainType > lagrange_points(const EntityType& entity) const
  {
    return BaseType::lagrange_points_order_1(entity);
  }

  std::set< size_t > local_dirichlet_DoFs(const EntityType& entity,
                                          const BoundaryInfoType& boundaryInfo) const
  {
    return BaseType::local_dirichlet_DoFs_order_1(entity, boundaryInfo);
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(backend_, entity);
  }

  CommunicatorType& communicator() const
  {
    std::lock_guard< std::mutex > DUNE_UNUSED(gg)(communicator_mutex_);
    if (!communicator_prepared_)
      communicator_prepared_ = CommunicationChooserType::prepare(*this, *communicator_);
    return *communicator_;
  } // ... communicator(...)

private:
  GridViewType gridView_;
  const FEMapType fe_map_;
  const BackendType backend_;
  const MapperType mapper_;
  mutable std::unique_ptr<CommunicatorType> communicator_;
  mutable bool communicator_prepared_;
  mutable std::mutex communicator_mutex_;
}; // class PdelabBased< ..., 1 >

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim >
class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, 1 >
  : public Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, 1 >,
                                GridViewImp::dimension, rangeDim, 1 >
{
  typedef Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, 1 >,
                               GridViewImp::dimension, rangeDim, 1 >              BaseType;
  typedef Spaces::CGInterface< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >,
                               GridViewImp::dimension, 1, 1 >                     ScalarBaseType;
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, 1 > ThisType;
public:
  typedef PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, 1 > Traits;

  static const int    polOrder = Traits::polOrder;
  static const size_t dimDomain = BaseType::dimDomain;
  static const size_t dimRange = BaseType::dimRange;
  static const size_t dimRangeCols = BaseType::dimRangeCols;

  typedef typename Traits::GridViewType         GridViewType;
  typedef typename Traits::RangeFieldType       RangeFieldType;
  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;

  typedef typename GridViewType::ctype              DomainFieldType;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;
  typedef CommunicationChooser< GridViewType >      CommunicationChooserType;
  typedef typename CommunicationChooserType::Type   CommunicatorType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef typename BaseType::IntersectionType  IntersectionType;
  typedef typename BaseType::EntityType        EntityType;
  typedef typename BaseType::PatternType       PatternType;
  typedef typename BaseType::BoundaryInfoType  BoundaryInfoType;

  explicit PdelabBased(GridViewType gV)
    : gridView_(gV)
    , fe_map_(gridView_)
    , backend_(gridView_, fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser< GridViewImp >::create(gridView_))
    , communicator_prepared_(false)
  {}

  /**
   * \brief Copy ctor.
   * \note  Manually implemented bc of the std::mutex + communicator_ unique_ptr
   */
  PdelabBased(const ThisType& other)
    : gridView_(other.gridView_)
    , fe_map_(gridView_)
    , backend_(gridView_, fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser< GridViewImp >::create(gridView_))
    , communicator_prepared_(false)
  {
    // make sure our new communicator is prepared if other's was
    if (other.communicator_prepared_)
      const auto& DUNE_UNUSED(comm) = this->communicator();
  }

  /**
   * \brief Move ctor.
   * \note  Manually implemented bc of the std::mutex.
   */
  PdelabBased(ThisType&& source)
    : gridView_(source.gridView_)
    , fe_map_(source.fe_map_)
    , backend_(source.backend_)
    , mapper_(source.mapper_)
    , communicator_(std::move(source.communicator_))
    , communicator_prepared_(source.communicator_prepared_)
  {}

  ThisType& operator=(const ThisType& other) = delete;

  ThisType& operator=(ThisType&& source) = delete;

  const GridViewType& grid_view() const
  {
    return gridView_;
  }

  const BackendType& backend() const
  {
    return backend_;
  }

  const MapperType& mapper() const
  {
    return mapper_;
  }

  std::vector< DomainType > lagrange_points(const EntityType& entity) const
  {
    return ScalarBaseType::lagrange_points_order_1(entity);  //should do the right thing
  }

  std::set< size_t > local_dirichlet_DoFs(const EntityType& entity,
                                          const BoundaryInfoType& boundaryInfo) const
  {
    return BaseType::local_dirichlet_DoFs_order_1(entity, boundaryInfo);  //throws a Dune_Not_Implemented atm
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(backend_, entity);
  }

  CommunicatorType& communicator() const
  {
    std::lock_guard< std::mutex > DUNE_UNUSED(gg)(communicator_mutex_);
    if (!communicator_prepared_)
      communicator_prepared_ = CommunicationChooserType::prepare(*this, *communicator_);
    return *communicator_;
  } // ... communicator(...)

private:
  GridViewType gridView_;
  const FEMapType fe_map_;
  const BackendType backend_;
  const MapperType mapper_;
  mutable std::unique_ptr<CommunicatorType> communicator_;
  mutable bool communicator_prepared_;
  mutable std::mutex communicator_mutex_;
}; // class PdelabBased< ..., dimRange, 1 >

#else // HAVE_DUNE_PDELAB

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, size_t rangeDim, size_t rangeDimCols = 1 >
class PdelabBased
{
  static_assert(Dune::AlwaysFalse< GridViewImp >::value, "You are missing dune-pdelab!");
};

#endif // HAVE_DUNE_PDELAB

} // namespace CG
} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CG_PDELAB_HH
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIOpenGL3Renderer.cpp
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#include <GL/glew.h>

#include "CEGUI/RendererModules/OpenGL/ShaderManager.h"
#include "CEGUI/RendererModules/OpenGL/GL3Renderer.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/RendererModules/OpenGL/Shader.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/ImageCodec.h"
#include "CEGUI/DynamicModule.h"
#include "CEGUI/RendererModules/OpenGL/ViewportTarget.h"
#include "CEGUI/RendererModules/OpenGL/GL3GeometryBuffer.h"
#include "CEGUI/GUIContext.h"
#include "CEGUI/RendererModules/OpenGL/GL3FBOTextureTarget.h"
#include "CEGUI/System.h"
#include "CEGUI/DefaultResourceProvider.h"
#include "CEGUI/Logger.h"
#include "CEGUI/RendererModules/OpenGL/StateChangeWrapper.h"
#include "CEGUI/RenderMaterial.h"
#include "CEGUI/RendererModules/OpenGL/GL3ShaderWrapper.h"

#include <sstream>
#include <algorithm>
#include <cstring>

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
// The following are some GL extension / version dependant related items.
// This is all done totally internally here; no need for external interface
// to show any of this.
//----------------------------------------------------------------------------//
// we only really need this with MSVC / Windows(?) and by now it should already
// be defined on that platform, so we just define it as empty macro so the
// compile does not break on other systems.
#ifndef APIENTRY
#   define APIENTRY
#endif
//! Dummy function for if real ones are not present (saves testing each render)
static void APIENTRY activeTextureDummy(GLenum) {}

//----------------------------------------------------------------------------//
// template specialised class that does the real work for us
template<typename T>
class OGLTemplateTargetFactory : public OGLTextureTargetFactory
{
    TextureTarget* create(OpenGLRendererBase& r) const
        { return CEGUI_NEW_AO T(static_cast<OpenGL3Renderer&>(r)); }
};

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::bootstrapSystem(const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    if (System::getSingletonPtr())
        CEGUI_THROW(InvalidRequestException(
            "CEGUI::System object is already initialised."));

    OpenGL3Renderer& renderer(create());
    DefaultResourceProvider* rp = CEGUI_NEW_AO CEGUI::DefaultResourceProvider();
    System::create(renderer, rp);

    return renderer;
}

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::bootstrapSystem(const Sizef& display_size,
                                                  const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    if (System::getSingletonPtr())
        CEGUI_THROW(InvalidRequestException(
            "CEGUI::System object is already initialised."));

    OpenGL3Renderer& renderer(create(display_size));
    DefaultResourceProvider* rp = CEGUI_NEW_AO CEGUI::DefaultResourceProvider();
    System::create(renderer, rp);

    return renderer;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::destroySystem()
{
    System* sys;
    if (!(sys = System::getSingletonPtr()))
        CEGUI_THROW(InvalidRequestException(
            "CEGUI::System object is not created or was already destroyed."));

    OpenGL3Renderer* renderer = static_cast<OpenGL3Renderer*>(sys->getRenderer());
    DefaultResourceProvider* rp =
        static_cast<DefaultResourceProvider*>(sys->getResourceProvider());

    System::destroy();
    CEGUI_DELETE_AO rp;
    destroy(*renderer);
}

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::create(const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    return *CEGUI_NEW_AO OpenGL3Renderer();
}

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::create(const Sizef& display_size,
                                         const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    return *CEGUI_NEW_AO OpenGL3Renderer(display_size);
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::destroy(OpenGL3Renderer& renderer)
{
    CEGUI_DELETE_AO &renderer;
}

//----------------------------------------------------------------------------//
OpenGL3Renderer::OpenGL3Renderer() :
    d_shaderWrapperTextured(0),
    d_openGLStateChanger(0),
    d_shaderManager(0)
{
    initialiseRendererIDString();
    initialiseGLExtensions();
    d_openGLStateChanger = CEGUI_NEW_AO OpenGL3StateChangeWrapper(*this);
    initialiseTextureTargetFactory();
    initialiseOpenGLShaders();
}

//----------------------------------------------------------------------------//
OpenGL3Renderer::OpenGL3Renderer(const Sizef& display_size) :
    OpenGLRendererBase(display_size),
    d_shaderWrapperTextured(0),
    d_openGLStateChanger(0),
    d_shaderManager(0)
{
    initialiseRendererIDString();
    initialiseGLExtensions();
    d_openGLStateChanger = CEGUI_NEW_AO OpenGL3StateChangeWrapper(*this);
    initialiseTextureTargetFactory();
    initialiseOpenGLShaders();
}

//----------------------------------------------------------------------------//
OpenGL3Renderer::~OpenGL3Renderer()
{
    CEGUI_DELETE_AO d_textureTargetFactory;
    CEGUI_DELETE_AO d_openGLStateChanger;
    CEGUI_DELETE_AO d_shaderManager;

    delete d_shaderWrapperTextured;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseRendererIDString()
{
    d_rendererID =
        "CEGUI::OpenGL3Renderer - Official OpenGL 3.2 core based "
        "renderer module.";
}
//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase* OpenGL3Renderer::createGeometryBuffer_impl(CEGUI::RefCounted<RenderMaterial> renderMaterial)
{
    return CEGUI_NEW_AO OpenGL3GeometryBuffer(*this, renderMaterial);
}

//----------------------------------------------------------------------------//
TextureTarget* OpenGL3Renderer::createTextureTarget_impl()
{
    return d_textureTargetFactory->create(*this);
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::beginRendering()
{
    // do required set-up.  yes, it really is this minimal ;)
    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_BLEND);

    // force set blending ops to get to a known state.
    setupRenderingBlendMode(BM_NORMAL, true);

    // if enabled, restores a subset of the GL state back to default values.
    if (d_initExtraStates)
        setupExtraStates();

    d_openGLStateChanger->reset();
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::endRendering()
{
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::setupExtraStates()
{
    glActiveTexture(GL_TEXTURE0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseTextureTargetFactory()
{
    //Use OGL core implementation for FBOs
    d_rendererID += "  TextureTarget support enabled via FBO OGL 3.2 core implementation.";
    d_textureTargetFactory = CEGUI_NEW_AO OGLTemplateTargetFactory<OpenGL3FBOTextureTarget>;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::setupRenderingBlendMode(const BlendMode mode,
                                             const bool force)
{
    // exit if mode is already set up (and update not forced)
    if ((d_activeBlendMode == mode) && !force)
        return;

    d_activeBlendMode = mode;

    if (d_activeBlendMode == BM_RTT_PREMULTIPLIED)
    {
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    }
    else
    {
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
    }
}

//----------------------------------------------------------------------------//
Sizef OpenGL3Renderer::getAdjustedTextureSize(const Sizef& sz) const
{
    return Sizef(sz);
}

//----------------------------------------------------------------------------//
OpenGL3StateChangeWrapper* OpenGL3Renderer::getOpenGLStateChanger()
{
    return d_openGLStateChanger;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseOpenGLShaders()
{
    checkGLErrors();
    d_shaderManager = CEGUI_NEW_AO OpenGL3ShaderManager(d_openGLStateChanger);
    d_shaderManager->initialiseShaders();

    initialiseStandardTexturedShaderWrapper();
    initialiseStandardSolidShaderWrapper();
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseGLExtensions()
{
    glewExperimental = GL_TRUE;

    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        std::ostringstream err_string;
        //Problem: glewInit failed, something is seriously wrong.
        err_string << "failed to initialise the GLEW library. "
            << glewGetErrorString(err);

        CEGUI_THROW(RendererException(err_string.str().c_str()));
    }
    //Clear the useless error glew produces as of version 1.7.0, when using OGL3.2 Core Profile
    glGetError();

    // Why do we do this and not use GLEW_EXT_texture_compression_s3tc?
    // Because of glewExperimental, of course!
    int ext_count;
    glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
    for(int i = 0; i < ext_count; ++i)
    {
        if (!std::strcmp(
                reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)),
                                              "GL_EXT_texture_compression_s3tc"))
        {
            d_s3tcSupported = true;
            break;
        }
    }
}

//----------------------------------------------------------------------------//
bool OpenGL3Renderer::isS3TCSupported() const
{
    return d_s3tcSupported;
}

//----------------------------------------------------------------------------//
RefCounted<RenderMaterial> OpenGL3Renderer::createRenderMaterial(const DefaultShaderType shaderType) const
{
    if(shaderType == DS_TEXTURED)
    {
        RefCounted<RenderMaterial> render_material(CEGUI_NEW_AO RenderMaterial(d_shaderWrapperTextured));

        return render_material;
    }
    else if(shaderType == DS_SOLID)
    {
        RefCounted<RenderMaterial> render_material(CEGUI_NEW_AO RenderMaterial(d_shaderWrapperSolid));

        return render_material;
    }
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseStandardTexturedShaderWrapper()
{
    OpenGL3Shader* shader_standard_textured =  d_shaderManager->getShader(SHADER_ID_STANDARD_TEXTURED);
    d_shaderWrapperTextured = new OpenGL3ShaderWrapper(*shader_standard_textured);

    d_shaderWrapperTextured->addTextureUniformVariable("texture0", 0);

    d_shaderWrapperTextured->addUniformVariable("modelViewPerspMatrix");

    d_shaderWrapperTextured->addAttributeVariable("inPosition");
    d_shaderWrapperTextured->addAttributeVariable("inTexCoord");
    d_shaderWrapperTextured->addAttributeVariable("inColour");
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseStandardSolidShaderWrapper()
{
    OpenGL3Shader* shader_standard_solid =  d_shaderManager->getShader(SHADER_ID_STANDARD_SOLID);
    d_shaderWrapperSolid = new OpenGL3ShaderWrapper(*shader_standard_solid);

    d_shaderWrapperSolid->addTextureUniformVariable("texture0", 0);

    d_shaderWrapperSolid->addUniformVariable("modelViewPerspMatrix");

    d_shaderWrapperSolid->addAttributeVariable("inPosition");
    d_shaderWrapperSolid->addAttributeVariable("inColour");
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<commit_msg>MOD: Added exception throwing to RenderMaterial getter<commit_after>/***********************************************************************
    filename:   CEGUIOpenGL3Renderer.cpp
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#include <GL/glew.h>

#include "CEGUI/RendererModules/OpenGL/ShaderManager.h"
#include "CEGUI/RendererModules/OpenGL/GL3Renderer.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/RendererModules/OpenGL/Shader.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/ImageCodec.h"
#include "CEGUI/DynamicModule.h"
#include "CEGUI/RendererModules/OpenGL/ViewportTarget.h"
#include "CEGUI/RendererModules/OpenGL/GL3GeometryBuffer.h"
#include "CEGUI/GUIContext.h"
#include "CEGUI/RendererModules/OpenGL/GL3FBOTextureTarget.h"
#include "CEGUI/System.h"
#include "CEGUI/DefaultResourceProvider.h"
#include "CEGUI/Logger.h"
#include "CEGUI/RendererModules/OpenGL/StateChangeWrapper.h"
#include "CEGUI/RenderMaterial.h"
#include "CEGUI/RendererModules/OpenGL/GL3ShaderWrapper.h"

#include <sstream>
#include <algorithm>
#include <cstring>

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
// The following are some GL extension / version dependant related items.
// This is all done totally internally here; no need for external interface
// to show any of this.
//----------------------------------------------------------------------------//
// we only really need this with MSVC / Windows(?) and by now it should already
// be defined on that platform, so we just define it as empty macro so the
// compile does not break on other systems.
#ifndef APIENTRY
#   define APIENTRY
#endif
//! Dummy function for if real ones are not present (saves testing each render)
static void APIENTRY activeTextureDummy(GLenum) {}

//----------------------------------------------------------------------------//
// template specialised class that does the real work for us
template<typename T>
class OGLTemplateTargetFactory : public OGLTextureTargetFactory
{
    TextureTarget* create(OpenGLRendererBase& r) const
        { return CEGUI_NEW_AO T(static_cast<OpenGL3Renderer&>(r)); }
};

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::bootstrapSystem(const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    if (System::getSingletonPtr())
        CEGUI_THROW(InvalidRequestException(
            "CEGUI::System object is already initialised."));

    OpenGL3Renderer& renderer(create());
    DefaultResourceProvider* rp = CEGUI_NEW_AO CEGUI::DefaultResourceProvider();
    System::create(renderer, rp);

    return renderer;
}

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::bootstrapSystem(const Sizef& display_size,
                                                  const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    if (System::getSingletonPtr())
        CEGUI_THROW(InvalidRequestException(
            "CEGUI::System object is already initialised."));

    OpenGL3Renderer& renderer(create(display_size));
    DefaultResourceProvider* rp = CEGUI_NEW_AO CEGUI::DefaultResourceProvider();
    System::create(renderer, rp);

    return renderer;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::destroySystem()
{
    System* sys;
    if (!(sys = System::getSingletonPtr()))
        CEGUI_THROW(InvalidRequestException(
            "CEGUI::System object is not created or was already destroyed."));

    OpenGL3Renderer* renderer = static_cast<OpenGL3Renderer*>(sys->getRenderer());
    DefaultResourceProvider* rp =
        static_cast<DefaultResourceProvider*>(sys->getResourceProvider());

    System::destroy();
    CEGUI_DELETE_AO rp;
    destroy(*renderer);
}

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::create(const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    return *CEGUI_NEW_AO OpenGL3Renderer();
}

//----------------------------------------------------------------------------//
OpenGL3Renderer& OpenGL3Renderer::create(const Sizef& display_size,
                                         const int abi)
{
    System::performVersionTest(CEGUI_VERSION_ABI, abi, CEGUI_FUNCTION_NAME);

    return *CEGUI_NEW_AO OpenGL3Renderer(display_size);
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::destroy(OpenGL3Renderer& renderer)
{
    CEGUI_DELETE_AO &renderer;
}

//----------------------------------------------------------------------------//
OpenGL3Renderer::OpenGL3Renderer() :
    d_shaderWrapperTextured(0),
    d_openGLStateChanger(0),
    d_shaderManager(0)
{
    initialiseRendererIDString();
    initialiseGLExtensions();
    d_openGLStateChanger = CEGUI_NEW_AO OpenGL3StateChangeWrapper(*this);
    initialiseTextureTargetFactory();
    initialiseOpenGLShaders();
}

//----------------------------------------------------------------------------//
OpenGL3Renderer::OpenGL3Renderer(const Sizef& display_size) :
    OpenGLRendererBase(display_size),
    d_shaderWrapperTextured(0),
    d_openGLStateChanger(0),
    d_shaderManager(0)
{
    initialiseRendererIDString();
    initialiseGLExtensions();
    d_openGLStateChanger = CEGUI_NEW_AO OpenGL3StateChangeWrapper(*this);
    initialiseTextureTargetFactory();
    initialiseOpenGLShaders();
}

//----------------------------------------------------------------------------//
OpenGL3Renderer::~OpenGL3Renderer()
{
    CEGUI_DELETE_AO d_textureTargetFactory;
    CEGUI_DELETE_AO d_openGLStateChanger;
    CEGUI_DELETE_AO d_shaderManager;

    delete d_shaderWrapperTextured;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseRendererIDString()
{
    d_rendererID =
        "CEGUI::OpenGL3Renderer - Official OpenGL 3.2 core based "
        "renderer module.";
}
//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase* OpenGL3Renderer::createGeometryBuffer_impl(CEGUI::RefCounted<RenderMaterial> renderMaterial)
{
    return CEGUI_NEW_AO OpenGL3GeometryBuffer(*this, renderMaterial);
}

//----------------------------------------------------------------------------//
TextureTarget* OpenGL3Renderer::createTextureTarget_impl()
{
    return d_textureTargetFactory->create(*this);
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::beginRendering()
{
    // do required set-up.  yes, it really is this minimal ;)
    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_BLEND);

    // force set blending ops to get to a known state.
    setupRenderingBlendMode(BM_NORMAL, true);

    // if enabled, restores a subset of the GL state back to default values.
    if (d_initExtraStates)
        setupExtraStates();

    d_openGLStateChanger->reset();
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::endRendering()
{
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::setupExtraStates()
{
    glActiveTexture(GL_TEXTURE0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseTextureTargetFactory()
{
    //Use OGL core implementation for FBOs
    d_rendererID += "  TextureTarget support enabled via FBO OGL 3.2 core implementation.";
    d_textureTargetFactory = CEGUI_NEW_AO OGLTemplateTargetFactory<OpenGL3FBOTextureTarget>;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::setupRenderingBlendMode(const BlendMode mode,
                                             const bool force)
{
    // exit if mode is already set up (and update not forced)
    if ((d_activeBlendMode == mode) && !force)
        return;

    d_activeBlendMode = mode;

    if (d_activeBlendMode == BM_RTT_PREMULTIPLIED)
    {
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    }
    else
    {
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
    }
}

//----------------------------------------------------------------------------//
Sizef OpenGL3Renderer::getAdjustedTextureSize(const Sizef& sz) const
{
    return Sizef(sz);
}

//----------------------------------------------------------------------------//
OpenGL3StateChangeWrapper* OpenGL3Renderer::getOpenGLStateChanger()
{
    return d_openGLStateChanger;
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseOpenGLShaders()
{
    checkGLErrors();
    d_shaderManager = CEGUI_NEW_AO OpenGL3ShaderManager(d_openGLStateChanger);
    d_shaderManager->initialiseShaders();

    initialiseStandardTexturedShaderWrapper();
    initialiseStandardSolidShaderWrapper();
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseGLExtensions()
{
    glewExperimental = GL_TRUE;

    GLenum err = glewInit();
    if(err != GLEW_OK)
    {
        std::ostringstream err_string;
        //Problem: glewInit failed, something is seriously wrong.
        err_string << "failed to initialise the GLEW library. "
            << glewGetErrorString(err);

        CEGUI_THROW(RendererException(err_string.str().c_str()));
    }
    //Clear the useless error glew produces as of version 1.7.0, when using OGL3.2 Core Profile
    glGetError();

    // Why do we do this and not use GLEW_EXT_texture_compression_s3tc?
    // Because of glewExperimental, of course!
    int ext_count;
    glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count);
    for(int i = 0; i < ext_count; ++i)
    {
        if (!std::strcmp(
                reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)),
                                              "GL_EXT_texture_compression_s3tc"))
        {
            d_s3tcSupported = true;
            break;
        }
    }
}

//----------------------------------------------------------------------------//
bool OpenGL3Renderer::isS3TCSupported() const
{
    return d_s3tcSupported;
}

//----------------------------------------------------------------------------//
RefCounted<RenderMaterial> OpenGL3Renderer::createRenderMaterial(const DefaultShaderType shaderType) const
{
    if(shaderType == DS_TEXTURED)
    {
        RefCounted<RenderMaterial> render_material(CEGUI_NEW_AO RenderMaterial(d_shaderWrapperTextured));

        return render_material;
    }
    else if(shaderType == DS_SOLID)
    {
        RefCounted<RenderMaterial> render_material(CEGUI_NEW_AO RenderMaterial(d_shaderWrapperSolid));

        return render_material;
    }
    else
    {
        CEGUI_THROW(RendererException(
            "A default shader of this type does not exist."));

        return RefCounted<RenderMaterial>();
    }
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseStandardTexturedShaderWrapper()
{
    OpenGL3Shader* shader_standard_textured =  d_shaderManager->getShader(SHADER_ID_STANDARD_TEXTURED);
    d_shaderWrapperTextured = new OpenGL3ShaderWrapper(*shader_standard_textured);

    d_shaderWrapperTextured->addTextureUniformVariable("texture0", 0);

    d_shaderWrapperTextured->addUniformVariable("modelViewPerspMatrix");

    d_shaderWrapperTextured->addAttributeVariable("inPosition");
    d_shaderWrapperTextured->addAttributeVariable("inTexCoord");
    d_shaderWrapperTextured->addAttributeVariable("inColour");
}

//----------------------------------------------------------------------------//
void OpenGL3Renderer::initialiseStandardSolidShaderWrapper()
{
    OpenGL3Shader* shader_standard_solid =  d_shaderManager->getShader(SHADER_ID_STANDARD_SOLID);
    d_shaderWrapperSolid = new OpenGL3ShaderWrapper(*shader_standard_solid);

    d_shaderWrapperSolid->addTextureUniformVariable("texture0", 0);

    d_shaderWrapperSolid->addUniformVariable("modelViewPerspMatrix");

    d_shaderWrapperSolid->addAttributeVariable("inPosition");
    d_shaderWrapperSolid->addAttributeVariable("inColour");
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "base/time_support.h"

#if !defined(_MSC_VER)
#include <sys/time.h>
#else
#include <windows.h>
#endif
#if defined(__APPLE__) && defined(__GNUC__)
#include <mach/mach_time.h>
#endif
#include <ctime>

namespace operations_research {
namespace base {

int64 GetCurrentTimeNanos() {
#if defined(_MSC_VER)
  const int64 kSecInNanoSeconds = 1000000000LL;
  LARGE_INTEGER now;
  LARGE_INTEGER freq;

  QueryPerformanceCounter(&now);
  QueryPerformanceFrequency(&freq);
  return now.QuadPart * kSecInNanoSeconds / freq.QuadPart;
#elif defined(__APPLE__) && defined(__GNUC__)
  int64 time = mach_absolute_time();
  mach_timebase_info_data_t info;
  kern_return_t err = mach_timebase_info(&info);
  return err == 0 ? time * info.numer / info.denom : 0;
#elif defined(__GNUC__)  // Linux
  const int64 kSecondInNanoSeconds = 1000000000;
  struct timespec current;
  clock_gettime(CLOCK_REALTIME, &current);
  return current.tv_sec * kSecondInNanoSeconds + current.tv_nsec;
#endif
}

}  // namespace base
}  // namespace operations_research
<commit_msg>fix for negative time limit?<commit_after>// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "base/time_support.h"

#if !defined(_MSC_VER)
#include <sys/time.h>
#else
#include <windows.h>
#endif
#if defined(__APPLE__) && defined(__GNUC__)
#include <mach/mach_time.h>
#endif
#include <ctime>

namespace operations_research {
namespace base {

int64 GetCurrentTimeNanos() {
#if defined(_MSC_VER)
  const double kSecInNanoSeconds = 1000000000.0;
  LARGE_INTEGER l_freq;
  if (!QueryPerformanceFrequency(&l_freq)) {
    return 0;
  }
  const double freq = static_cast<double>(l_freq.QuadPart)/kSecInNanoSeconds;
  LARGE_INTEGER now;
  QueryPerformanceCounter(&now);
  return static_cast<int64>(now.QuadPart / freq);
#elif defined(__APPLE__) && defined(__GNUC__)
  int64 time = mach_absolute_time();
  mach_timebase_info_data_t info;
  kern_return_t err = mach_timebase_info(&info);
  return err == 0 ? time * info.numer / info.denom : 0;
#elif defined(__GNUC__)  // Linux
  const int64 kSecondInNanoSeconds = 1000000000;
  struct timespec current;
  clock_gettime(CLOCK_REALTIME, &current);
  return current.tv_sec * kSecondInNanoSeconds + current.tv_nsec;
#endif
}

}  // namespace base
}  // namespace operations_research
<|endoftext|>