11#define BOOST_DLL_USE_STD_FS 
   12#include <boost/dll/import.hpp> 
   13#include <boost/algorithm/string.hpp> 
   19namespace ba = boost::algorithm;
 
   26#pragma comment(lib, "advapi32")
 
   40    if (msg.size() != 0) {
 
   42            "\n\n************************************************\n" 
   44            "************************************************\n\n" 
   46            "\nError:     " + msg + 
"\n");
 
   54    return static_cast<int>(errorMessage.size());
 
   62    std::unique_lock<std::mutex> msgLock(
msg_mutex);
 
   63    std::thread::id curId = std::this_thread::get_id();
 
   64    auto iter = m_threadMsgMap.find(curId);
 
   65    if (iter != m_threadMsgMap.end()) {
 
   66        return iter->second.get();
 
   69    m_threadMsgMap.insert({curId, pMsgs});
 
   75    std::unique_lock<std::mutex> msgLock(
msg_mutex);
 
   76    std::thread::id curId = std::this_thread::get_id();
 
   77    auto iter = m_threadMsgMap.find(curId);
 
   78    if (iter != m_threadMsgMap.end()) {
 
   79        m_threadMsgMap.erase(iter);
 
   92    std::unique_lock<std::mutex> appLock(
app_mutex);
 
  101    std::unique_lock<std::mutex> appLock(
app_mutex);
 
  110    if (m_fatal_deprecation_warnings) {
 
  112    } 
else if (m_suppress_deprecation_warnings || 
warnings.count(method)) {
 
  116    warnlog(
"Deprecation", fmt::format(
"{}: {}", method, extra));
 
  121    if (m_fatal_warnings) {
 
  123    } 
else if (m_suppress_warnings) {
 
  126    warnlog(warning, fmt::format(
"{}: {}", method, extra));
 
  135long int Application::readStringRegistryKey(
const string& keyName, 
const string& valueName,
 
  136        string& value, 
const string& defaultValue)
 
  139    long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
 
  140    if (open_error != ERROR_SUCCESS) {
 
  143    value = defaultValue;
 
  145    DWORD bufferSize = 
sizeof(buffer);
 
  147    error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
 
  148    if (ERROR_SUCCESS == error) {
 
  158    if (!errorMessage.empty()) {
 
  159        errorMessage.pop_back();
 
  165    if (!errorMessage.empty()) {
 
  166        return errorMessage.back();
 
  168        return "<no Cantera error>";
 
  174    for (
size_t j = 0; j < errorMessage.size(); j++) {
 
  175        f << errorMessage[j] << std::endl;
 
  177    errorMessage.clear();
 
  182    for (
size_t j = 0; j < errorMessage.size(); j++) {
 
  186    errorMessage.clear();
 
  226    string pathsep = 
";";
 
  227    string dirsep = 
"\\";
 
  229    string pathsep = 
":";
 
  233    if (getenv(
"CANTERA_DATA") != 
nullptr) {
 
  234        string s(getenv(
"CANTERA_DATA"));
 
  236        size_t end = s.find(pathsep);
 
  237        while (end != 
npos) {
 
  238            inputDirs.push_back(s.substr(start, end-start));
 
  240            end = s.find(pathsep, start);
 
  242        inputDirs.push_back(s.substr(start,end));
 
  247    if (getenv(
"CONDA_PREFIX") != 
nullptr) {
 
  248        string s(getenv(
"CONDA_PREFIX"));
 
  249        inputDirs.push_back(s + dirsep + 
"share" + dirsep + 
"cantera" + dirsep + 
"data");
 
  257    readStringRegistryKey(
"SOFTWARE\\Cantera\\Cantera " CANTERA_SHORT_VERSION,
 
  258                          "InstallDir", installDir, 
"");
 
  259    if (installDir != 
"") {
 
  260        inputDirs.push_back(installDir + 
"data");
 
  264        const char* old_pythonpath = getenv(
"PYTHONPATH");
 
  265        string pythonpath = 
"PYTHONPATH=" + installDir + 
"\\bin";
 
  266        if (old_pythonpath) {
 
  268            pythonpath.append(old_pythonpath);
 
  270        _putenv(pythonpath.c_str());
 
  286    std::unique_lock<std::mutex> dirLock(
dir_mutex);
 
  293    if (d.find(
"~/") == 0 || d.find(
"~\\") == 0) {
 
  294        char* home = getenv(
"HOME"); 
 
  296            home = getenv(
"USERPROFILE"); 
 
  299            d = home + d.substr(1, 
npos);
 
  315    std::unique_lock<std::mutex> dirLock(
dir_mutex);
 
  316    string::size_type islash = name.find(
'/');
 
  317    string::size_type ibslash = name.find(
'\\');
 
  318    string::size_type icolon = name.find(
':');
 
  322    if (name.find(
"~/") == 0 || name.find(
"~\\") == 0) {
 
  323        char* home = getenv(
"HOME"); 
 
  325            home = getenv(
"USERPROFILE"); 
 
  328            string full_name = home + name.substr(1, 
npos);
 
  329            std::ifstream fin(full_name);
 
  334                                   "Input file '{}' not found", name);
 
  340    if (islash == 0 || ibslash == 0
 
  341        || (icolon == 1 && (ibslash == 2 || islash == 2)))
 
  343        std::ifstream fin(name);
 
  348                               "Input file '{}' not found", name);
 
  354    size_t nd = dirs.size();
 
  355    for (
size_t i = 0; i < nd; i++) {
 
  356        string full_name = dirs[i] + 
"/" + name;
 
  357        std::ifstream fin(full_name);
 
  362    string msg = 
"\nInput file " + name + 
" not found in director";
 
  363    msg += (nd == 1 ? 
"y " : 
"ies ");
 
  364    for (
size_t i = 0; i < nd; i++) {
 
  365        msg += 
"\n'" + dirs[i] + 
"'";
 
  371    msg += 
"To fix this problem, either:\n";
 
  372    msg += 
"    a) move the missing files into the local directory;\n";
 
  373    msg += 
"    b) define environment variable CANTERA_DATA to\n";
 
  374    msg += 
"         point to the directory containing the file.";
 
  382            "Loading extensions requires linking to the Cantera shared library\n" 
  383            "rather than the static library");
 
  385    if (m_loaded_extensions.count({extType, name})) {
 
  393        typedef void (loader_t)();
 
  397        static function<loader_t> loader;
 
  401            string py_ver_underscore = ba::replace_all_copy(py_ver, 
".", 
"_");
 
  403                loader = boost::dll::import_alias<loader_t>(
 
  404                    "cantera_python" + py_ver_underscore, 
 
  405                    "registerPythonExtensionManager", 
 
  408                    boost::dll::load_mode::search_system_folders
 
  409                    | boost::dll::load_mode::append_decorations
 
  410                    | boost::dll::load_mode::rtld_global
 
  415            } 
catch (std::exception& err) {
 
  416                errors += fmt::format(
"\nPython {}: {}\n", py_ver, err.what());
 
  421                "Error loading Python extension support. Tried the following:{}",
 
  426    m_loaded_extensions.insert({extType, name});
 
Class to carry out messages.
 
vector< string > errorMessage
Current list of error messages.
 
Messages * operator->()
Provide a pointer dereferencing overloaded operator.
 
void removeThreadMessages()
Remove a local thread message.
 
Class to hold global data.
 
static Application * s_app
Pointer to the single Application instance.
 
vector< string > m_pythonSearchVersions
Versions of Python to consider when attempting to load user extensions.
 
unique_ptr< Logger > m_logwriter
Current log writer.
 
static Application * Instance()
Return a pointer to the one and only instance of class Application.
 
void loadExtension(const string &extType, const string &name)
Load an extension implementing user-defined models.
 
void warn_deprecated(const string &method, const string &extra="")
Print a warning indicating that method is deprecated.
 
void searchPythonVersions(const string &versions)
Set the versions of Python to try when loading user-defined extensions, in order of preference.
 
vector< string > inputDirs
Current vector of input directories to search for input files.
 
void thread_complete()
Delete and free memory allocated per thread in multithreaded applications.
 
set< string > warnings
Set of deprecation warnings that have been emitted (to suppress duplicates)
 
shared_ptr< Messages > pMessages_t
Typedef for thread specific messages.
 
Application()
Constructor for class sets up the initial conditions Protected ctor access thru static member functio...
 
void writelogendl()
Write an end of line character to the logger and flush output.
 
static void ApplicationDestroy()
Static function that destroys the application class's data.
 
void warn(const string &warning, const string &method, const string &extra="")
Generate a general purpose warning; repeated warnings are not suppressed.
 
Base class for exceptions thrown by Cantera classes.
 
static shared_ptr< ExtensionManager > build(const string &extensionType)
Create a new ExtensionManager.
 
static ExtensionManagerFactory & factory()
Static function that returns the static instance of the factory, creating it if necessary.
 
Base class for 'loggers' that write text messages to log files.
 
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
 
string stripnonprint(const string &s)
Strip non-printing characters wherever they are.
 
void addError(const string &r, const string &msg="")
Set an error condition in the application class without throwing an exception.
 
void logErrors()
Prints all of the error messages using writelog.
 
void getErrors(std::ostream &f)
Prints all of the error messages to an ostream.
 
string lastErrorMessage()
Retrieve the last error message in a string.
 
int getErrorCount()
Return the number of errors that have been encountered so far.
 
void popError()
Discard the last error message.
 
bool usingSharedLibrary()
Returns true if Cantera was loaded as a shared library in the current application.
 
void warnlog(const string &warning, const string &msg)
Write a warning message to the logger.
 
void setLogger(Logger *logwriter)
Install a logger.
 
void writelog(const string &msg)
Write a message to the logger.
 
void writelog(const string &fmt, const Args &... args)
Write a formatted message to the screen.
 
void writelogendl()
Write an end of line character to the screen and flush output.
 
Namespace for the Cantera kernel.
 
const size_t npos
index returned by functions to indicate "no position"
 
static std::mutex app_mutex
Mutex for creating singletons within the application object.
 
static std::mutex dir_mutex
Mutex for input directory access.
 
static std::mutex msg_mutex
Mutex for access to string messages.
 
Contains declarations for string manipulation functions within Cantera.