Cantera  2.1.2
application.cpp
Go to the documentation of this file.
1 //! @file application.cpp
2 #include "application.h"
3 
5 #include "cantera/base/ctml.h"
7 #include "cantera/base/xml.h"
8 #include "units.h"
9 
10 #include <fstream>
11 #include <functional>
12 
13 using std::string;
14 using std::endl;
15 
16 #ifdef _WIN32
17 #include <windows.h>
18 #endif
19 
20 #ifdef _MSC_VER
21 #pragma comment(lib, "advapi32")
22 #endif
23 
24 namespace Cantera
25 {
26 
27 
28 // If running multiple threads in a cpp application, the Application class
29 // is the only internal object that is single instance with static data.
30 
31 #ifdef THREAD_SAFE_CANTERA
32 cthreadId_t getThisThreadId()
33 {
34 #if defined(BOOST_HAS_WINTHREADS)
35  return ::GetCurrentThreadId();
36 #elif defined(BOOST_HAS_PTHREADS)
37  return pthread_self();
38 #endif
39 }
40 
41 #endif
42 
43 //! Mutex for input directory access
44 static mutex_t dir_mutex;
45 
46 //! Mutex for creating singletons within the application object
47 static mutex_t app_mutex;
48 
49 //! Mutex for controlling access to XML file storage
50 static mutex_t xml_mutex;
51 
52 
54  errorMessage(0),
55  errorRoutine(0),
56  logwriter(0)
57 #ifdef WITH_HTML_LOGS
58  ,xmllog(0),
59  current(0),
60  loglevel(0),
61  loglevels(0),
62  loggroups(0)
63 #endif
64 {
65  // install a default logwriter that writes to standard
66  // output / standard error
67  logwriter = new Logger();
68 }
69 
71  errorMessage(r.errorMessage),
72  errorRoutine(r.errorRoutine),
73  logwriter(0)
74 #ifdef WITH_HTML_LOGS
75  , xmllog(r.xmllog),
76  current(r.current),
77  loglevel(r.loglevel),
78  loglevels(r.loglevels),
79  loggroups(r.loggroups)
80 #endif
81 {
82  // install a default logwriter that writes to standard
83  // output / standard error
84  logwriter = new Logger(*(r.logwriter));
85 }
86 
87 Application::Messages& Application::Messages::operator=(const Messages& r)
88 {
89  if (this == &r) {
90  return *this;
91  }
92  errorMessage = r.errorMessage;
93  errorRoutine = r.errorRoutine;
94  logwriter = new Logger(*(r.logwriter));
95 #ifdef WITH_HTML_LOGS
96  xmllog = r.xmllog;
97  current = r.current;
98  loglevel = r.loglevel;
99  loglevels = r.loglevels;
100  loggroups = r.loggroups;
101 #endif
102  return *this;
103 }
104 
105 Application::Messages::~Messages()
106 {
107  delete logwriter;
108 #ifdef WITH_HTML_LOGS
109  if (xmllog) {
110  write_logfile("orphan");
111  }
112 #endif
113 }
114 
115 void Application::Messages::addError(const std::string& r, const std::string& msg)
116 {
117  errorMessage.push_back(msg);
118  errorRoutine.push_back(r);
119 }
120 
122 {
123  return static_cast<int>(errorMessage.size()) ;
124 }
125 
127 {
128  if (logwriter == _logwriter) {
129  return ;
130  }
131  if (logwriter != 0) {
132  delete logwriter;
133  logwriter = 0 ;
134  }
135  logwriter = _logwriter;
136 }
137 
138 void Application::Messages::logerror(const std::string& msg)
139 {
140  logwriter->error(msg) ;
141 }
142 
143 void Application::Messages::writelog(const std::string& msg)
144 {
145  logwriter->write(msg);
146 }
147 
149 {
150  logwriter->writeendl();
151 }
152 
153 #ifdef WITH_HTML_LOGS
154 
155 void Application::Messages::beginLogGroup(const std::string& title, int _loglevel /*=-99*/)
156 {
157  Cantera::warn_deprecated("Application::Messages::beginLogGroup",
158  "HTML Logs will be removed in Cantera 2.2");
159  // Add the current loglevel to the vector of loglevels
160  loglevels.push_back(loglevel);
161 
162  // loglevel is a member of the Messages class.
163  if (_loglevel != -99) {
164  loglevel = _loglevel;
165  } else {
166  loglevel--;
167  }
168 
169  // Add the title of the current logLevel to the vector of titles
170  loggroups.push_back(title);
171 
172  if (loglevel <= 0) {
173  return;
174  }
175 
176  // If we haven't started an XML tree for the log file, do so here
177  if (xmllog == 0) {
178  // The top of this tree will have a zero pointer.
179  xmllog = new XML_Node("html");
180  current = &xmllog->addChild("ul");
181  }
182  // Add two children to the XML tree.
183  current = &current->addChild("li","<b>"+title+"</b>");
184  current = &current->addChild("ul");
185 }
186 
187 void Application::Messages::addLogEntry(const std::string& tag, const std::string& value)
188 {
189  if (loglevel > 0 && current) {
190  current->addChild("li",tag+": "+value);
191  }
192 }
193 
194 void Application::Messages::addLogEntry(const std::string& tag, doublereal value)
195 {
196  if (loglevel > 0 && current) {
197  current->addChild("li",tag+": "+fp2str(value));
198  }
199 }
200 
201 void Application::Messages::addLogEntry(const std::string& tag, int value)
202 {
203  if (loglevel > 0 && current) {
204  current->addChild("li",tag+": "+int2str(value));
205  }
206 }
207 
208 void Application::Messages::addLogEntry(const std::string& msg)
209 {
210  if (loglevel > 0 && current) {
211  current->addChild("li",msg);
212  }
213 }
214 
215 void Application::Messages::endLogGroup(const std::string& title)
216 {
217  if (title != "" && title != loggroups.back()) {
218  writelog("Logfile error."
219  "\n beginLogGroup: "+ loggroups.back()+
220  "\n endLogGroup: "+title+"\n");
221  write_logfile("logerror");
222  }
223 
224  if (loggroups.size() == 1) {
225  write_logfile(loggroups.back()+"_log");
226  } else if (loglevel > 0) {
227  AssertThrowMsg(current, "Application::Messages::endLogGroup",
228  "Error while ending a LogGroup. This is probably due to an unmatched"
229  " beginning and ending group");
230  current = current->parent();
231  AssertThrowMsg(current, "Application::Messages::endLogGroup",
232  "Error while ending a LogGroup. This is probably due to an unmatched"
233  " beginning and ending group");
234  current = current->parent();
235  // Get the loglevel of the previous level and get rid of
236  // vector entry in loglevels.
237  }
238 
239  loggroups.pop_back();
240  loglevel = loglevels.back();
241  loglevels.pop_back();
242 }
243 
244 void Application::Messages::write_logfile(const std::string& file)
245 {
246  Cantera::warn_deprecated("Application::Messages::write_logfile",
247  "HTML Logs will be removed in Cantera 2.2");
248 
249  if (!xmllog) {
250  return;
251  }
252  std::string::size_type idot = file.rfind('.');
253  std::string ext = "";
254  std::string nm = file;
255  if (idot != std::string::npos) {
256  ext = file.substr(idot, file.size());
257  nm = file.substr(0,idot);
258  } else {
259  ext = ".html";
260  nm = file;
261  }
262 
263  // see if file exists. If it does, find an integer that
264  // can be appended to the name to create the name of a file
265  // that does not exist.
266  std::string fname = nm + ext;
267  int n = 0;
268  while (std::ifstream(fname.c_str())) {
269  n++;
270  fname = nm + int2str(n) + ext;
271  }
272 
273  // Now we have a file name that does not correspond to any
274  // existing file. Open it as an output stream, and dump the
275  // XML (HTML) tree to it.
276 
277  if (xmllog) {
278  std::ofstream f(fname.c_str());
279  // go to the top of the tree, and write it all.
280  xmllog->root().write(f);
281  f.close();
282  writelog("Log file " + fname + " written.\n");
283  delete xmllog;
284  xmllog = 0;
285  current = 0;
286  }
287 }
288 
289 #endif // WITH_HTML_LOGS
290 
291 #ifdef THREAD_SAFE_CANTERA
292 
293 //! Mutex for access to string messages
294 static mutex_t msg_mutex;
295 
297 {
298  ScopedLock msgLock(msg_mutex);
299  cthreadId_t curId = getThisThreadId() ;
300  threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
301  if (iter != m_threadMsgMap.end()) {
302  return iter->second.get();
303  }
304  pMessages_t pMsgs(new Messages()) ;
305  m_threadMsgMap.insert(std::pair< cthreadId_t, pMessages_t >(curId, pMsgs)) ;
306  return pMsgs.get() ;
307 }
308 
310 {
311  ScopedLock msgLock(msg_mutex);
312  cthreadId_t curId = getThisThreadId() ;
313  threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
314  if (iter != m_threadMsgMap.end()) {
315  m_threadMsgMap.erase(iter) ;
316  }
317 }
318 #endif // THREAD_SAFE_CANTERA
319 
321  inputDirs(0),
322  stop_on_error(false),
323  options(),
324  xmlfiles(),
325  m_suppress_deprecation_warnings(false),
326  pMessenger()
327 {
328 #if !defined( THREAD_SAFE_CANTERA )
329  pMessenger = std::auto_ptr<Messages>(new Messages());
330 #endif
331 
332  // install a default logwriter that writes to standard
333  // output / standard error
334  // logwriter = new Logger();
335  //#ifdef WITH_HTML_LOGS
336  // // HTML log files
337  // xmllog = 0;
338  // current = 0;
339  // loglevel = 0;
340  //#endif
342 #if defined(THREAD_SAFE_CANTERA)
343  Unit::units() ;
344 #endif
345 }
346 
348 {
349  ScopedLock appLock(app_mutex);
350  if (Application::s_app == 0) {
352  }
353  return s_app;
354 }
355 
357 {
358  std::map<std::string, XML_Node*>::iterator pos;
359  for (pos = xmlfiles.begin(); pos != xmlfiles.end(); ++pos) {
360  pos->second->unlock();
361  delete pos->second;
362  pos->second = 0;
363  }
364 }
365 
367 {
368  ScopedLock appLock(app_mutex);
369  if (Application::s_app != 0) {
370  delete Application::s_app;
371  Application::s_app = 0;
372  }
373 }
374 
375 void Application::warn_deprecated(const std::string& method,
376  const std::string& extra)
377 {
378  if (m_suppress_deprecation_warnings || warnings.count(method)) {
379  return;
380  }
381  warnings.insert(method);
382  writelog("WARNING: '" + method + "' is deprecated. " + extra);
383  writelogendl();
384 }
385 
387 {
388 #if defined(THREAD_SAFE_CANTERA)
390 #endif
391 }
392 
393 
394 XML_Node* Application::get_XML_File(const std::string& file, int debug)
395 {
396  ScopedLock xmlLock(xml_mutex);
397  std::string path = "";
398  path = findInputFile(file);
399 #ifdef _WIN32
400  // RFB: For Windows make the path POSIX compliant so code looking for directory
401  // separators is simpler. Just look for '/' not both '/' and '\\'
402  std::replace_if(path.begin(), path.end(),
403  std::bind2nd(std::equal_to<char>(), '\\'), '/') ;
404 #endif
405 
406  string ff = path;
407  if (xmlfiles.find(path)
408  == xmlfiles.end()) {
409  /*
410  * Check whether or not the file is XML. If not, it will
411  * be first processed with the preprocessor. We determine
412  * whether it is an XML file by looking at the file extension.
413  */
414  string::size_type idot = path.rfind('.');
415  string ext;
416  if (idot != string::npos) {
417  ext = path.substr(idot, path.size());
418  } else {
419  ext = "";
420  idot = path.size();
421  }
422  if (ext != ".xml" && ext != ".ctml") {
423  /*
424  * We will assume that we are trying to open a cti file.
425  * First, determine the name of the xml file, ff, derived from
426  * the cti file.
427  * In all cases, we will write the xml file to the current
428  * directory.
429  */
430  string::size_type islash = path.rfind('/');
431  if (islash != string::npos) {
432  ff = string("./")+path.substr(islash+1,idot-islash - 1) + ".xml";
433  } else {
434  ff = string("./")+path.substr(0,idot) + ".xml";
435  }
436  if (debug > 0) {
437  writelog("get_XML_File(): Expected location of xml file = " +
438  ff + "\n");
439  }
440  /*
441  * Do a search of the existing XML trees to determine if we have
442  * already processed this file. If we have, return a pointer to
443  * the processed xml tree.
444  */
445  if (xmlfiles.find(ff) != xmlfiles.end()) {
446  if (debug > 0) {
447  writelog("get_XML_File(): File, " + ff +
448  ", was previously read." +
449  " Retrieving the stored xml tree.\n");
450  }
451  return xmlfiles[ff];
452  }
453  /*
454  * Ok, we didn't find the processed XML tree. Do the conversion
455  * to xml, possibly overwriting the file, ff, in the process.
456  */
457  ctml::ct2ctml(path.c_str(),debug);
458  } else {
459  ff = path;
460  }
461  /*
462  * Take the XML file ff, open it, and process it, creating an
463  * XML tree, and then adding an entry in the map. We will store
464  * the absolute pathname as the key for this map.
465  */
466  std::ifstream s(ff.c_str());
467 
468  XML_Node* x = new XML_Node("doc");
469  if (s) {
470  x->build(s);
471  x->lock();
472  xmlfiles[ff] = x;
473  } else {
474  string estring = "cannot open "+ff+" for reading.";
475  estring += "Note, this error indicates a possible configuration problem.";
476  throw CanteraError("get_XML_File", estring);
477  }
478  }
479 
480  /*
481  * Return the XML node pointer. At this point, we are sure that the
482  * lookup operation in the return statement will return a valid
483  * pointer.
484  */
485  return xmlfiles[ff];
486 }
487 
488 
489 void Application::close_XML_File(const std::string& file)
490 {
491  ScopedLock xmlLock(xml_mutex);
492  if (file == "all") {
493  std::map<string, XML_Node*>::iterator
494  b = xmlfiles.begin(),
495  e = xmlfiles.end();
496  for (; b != e; ++b) {
497  b->second->unlock();
498  delete b->second;
499  xmlfiles.erase(b->first);
500  }
501  } else if (xmlfiles.find(file) != xmlfiles.end()) {
502  xmlfiles[file]->unlock();
503  delete xmlfiles[file];
504  xmlfiles.erase(file);
505  }
506 }
507 
508 #ifdef _WIN32
509 long int Application::readStringRegistryKey(const std::string& keyName, const std::string& valueName,
510  std::string& value, const std::string& defaultValue)
511 {
512 
513  HKEY key;
514  long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
515  if (open_error != ERROR_SUCCESS) {
516  return open_error;
517  }
518  value = defaultValue;
519  CHAR buffer[1024];
520  DWORD bufferSize = sizeof(buffer);
521  ULONG error;
522  error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
523  if (ERROR_SUCCESS == error) {
524  value = buffer;
525  }
526  RegCloseKey(key);
527  return error;
528 }
529 #endif
530 
532 {
533  if (static_cast<int>(errorMessage.size()) > 0) {
534  errorRoutine.pop_back() ;
535  errorMessage.pop_back() ;
536  }
537 }
538 
540 {
541  if (static_cast<int>(errorMessage.size()) > 0) {
542  string head =
543  "\n\n************************************************\n"
544  " Cantera Error! \n"
545  "************************************************\n\n";
546  return head+string("\nProcedure: ")+errorRoutine.back()
547  +string("\nError: ")+errorMessage.back();
548  } else {
549  return "<no Cantera error>";
550  }
551 }
552 
553 void Application::Messages::getErrors(std::ostream& f)
554 {
555  int i = static_cast<int>(errorMessage.size());
556  if (i == 0) {
557  return;
558  }
559  f << endl << endl;
560  f << "************************************************" << endl;
561  f << " Cantera Error! " << endl;
562  f << "************************************************" << endl
563  << endl;
564  int j;
565  for (j = 0; j < i; j++) {
566  f << endl;
567  f << "Procedure: " << errorRoutine[j] << endl;
568  f << "Error: " << errorMessage[j] << endl;
569  }
570  f << endl << endl;
571  errorMessage.clear();
572  errorRoutine.clear();
573 }
574 
576 {
577  int i = static_cast<int>(errorMessage.size());
578  if (i == 0) {
579  return;
580  }
581  writelog("\n\n");
582  writelog("************************************************\n");
583  writelog(" Cantera Error! \n");
584  writelog("************************************************\n\n");
585  int j;
586  for (j = 0; j < i; j++) {
587  writelog("\n");
588  writelog(string("Procedure: ")+ errorRoutine[j]+" \n");
589  writelog(string("Error: ")+ errorMessage[j]+" \n");
590  }
591  writelog("\n\n");
592  errorMessage.clear();
593  errorRoutine.clear();
594 }
595 
596 
597 
599 {
600  std::vector<string>& dirs = inputDirs;
601 
602  // always look in the local directory first
603  dirs.push_back(".");
604 
605 #ifdef _WIN32
606  // Under Windows, the Cantera setup utility records the installation
607  // directory in the registry. Data files are stored in the 'data' and
608  // 'templates' subdirectories of the main installation directory.
609 
610  std::string installDir;
611  readStringRegistryKey("SOFTWARE\\Cantera\\Cantera 2.0",
612  "InstallDir", installDir, "");
613  if (installDir != "") {
614  dirs.push_back(installDir + "data");
615  dirs.push_back(installDir + "templates");
616 
617  // Scripts for converting mechanisms to CTI and CMTL are installed in
618  // the 'bin' subdirectory. Add that directory to the PYTHONPATH.
619  const char* old_pythonpath = getenv("PYTHONPATH");
620  std::string pythonpath = "PYTHONPATH=" + installDir + "\\bin";
621  if (old_pythonpath) {
622  pythonpath += ";";
623  pythonpath.append(old_pythonpath);
624  }
625  putenv(pythonpath.c_str());
626  }
627 
628 #endif
629 
630 #ifdef DARWIN
631  //
632  // add a default data location for Mac OS X
633  //
634  dirs.push_back("/Applications/Cantera/data");
635 #endif
636 
637  //
638  // if environment variable CANTERA_DATA is defined, then add
639  // it to the search path
640  //
641  if (getenv("CANTERA_DATA") != 0) {
642  string datadir = string(getenv("CANTERA_DATA"));
643  dirs.push_back(datadir);
644  }
645 
646  // CANTERA_DATA is defined in file config.h. This file is written
647  // during the build process (unix), and points to the directory
648  // specified by the 'prefix' option to 'configure', or else to
649  // /usr/local/cantera.
650 #ifdef CANTERA_DATA
651  string datadir = string(CANTERA_DATA);
652  dirs.push_back(datadir);
653 #endif
654 }
655 
656 void Application::addDataDirectory(const std::string& dir)
657 {
658  ScopedLock dirLock(dir_mutex);
659  if (inputDirs.size() == 0) {
661  }
662  string d = stripnonprint(dir);
663  size_t m, n = inputDirs.size();
664 
665  // don't add if already present
666  for (m = 0; m < n; m++) {
667  if (d == inputDirs[m]) {
668  return;
669  }
670  }
671 
672  inputDirs.push_back(d);
673 }
674 
675 std::string Application::findInputFile(const std::string& name)
676 {
677  ScopedLock dirLock(dir_mutex);
678  string::size_type islash = name.find('/');
679  string::size_type ibslash = name.find('\\');
680  string inname;
681  std::vector<string>& dirs = inputDirs;
682 
683  int nd;
684  if (islash == string::npos && ibslash == string::npos) {
685  nd = static_cast<int>(dirs.size());
686  int i;
687  inname = "";
688  for (i = 0; i < nd; i++) {
689  inname = dirs[i] + "/" + name;
690  std::ifstream fin(inname.c_str());
691  if (fin) {
692  fin.close();
693  return inname;
694  }
695  }
696  string msg;
697  msg = "\nInput file " + name
698  + " not found in director";
699  msg += (nd == 1 ? "y " : "ies ");
700  for (i = 0; i < nd; i++) {
701  msg += "\n'" + dirs[i] + "'";
702  if (i < nd-1) {
703  msg += ", ";
704  }
705  }
706  msg += "\n\n";
707  msg += "To fix this problem, either:\n";
708  msg += " a) move the missing files into the local directory;\n";
709  msg += " b) define environment variable CANTERA_DATA to\n";
710  msg += " point to the directory containing the file.";
711  throw CanteraError("findInputFile", msg);
712  }
713 
714  return name;
715 }
716 
718 
719 } // namespace Cantera
void popError()
Discard the last error message.
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:40
void writelogendl()
Write an end of line character to the screen and flush output.
std::map< std::string, XML_Node * > xmlfiles
Current vector of xml file trees that have been previously parsed.
Definition: application.h:555
void writelogendl()
Write an endl to the screen and flush output.
Definition: application.h:435
Base class for 'loggers' that write text messages to log files.
Definition: logger.h:39
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
Class to hold global data.
Definition: application.h:41
int getErrorCount()
Return the number of errors that have been encountered so far.
ThreadMessages pMessenger
Current pointer to the logwriter.
Definition: application.h:577
virtual ~Application()
Destructor for class deletes global data.
Messages()
Constructor for the Messages class.
Definition: application.cpp:53
std::string findInputFile(const std::string &name)
Find an input file.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:173
void beginLogGroup(const std::string &title, int loglevel)
Create a new group for log messages.
static Application * s_app
Pointer to the single Application instance.
Definition: application.h:584
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
void logerror(const std::string &msg)
Write an error message and quit.
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:76
void addError(const std::string &r, const std::string &msg)
Set an error condition in the application class without throwing an exception.
void writelog(const std::string &msg)
Write a message to the screen.
Definition: application.h:430
boost::shared_ptr< Messages > pMessages_t
Typedef for thread specific messages.
Definition: application.h:288
std::vector< std::string > inputDirs
Current vector of input directories to search for input files.
Definition: application.h:537
#define AssertThrowMsg(expr, procedure, message)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:247
std::string lastErrorMessage()
Retrieve the last error message in a string.
void ct2ctml(const char *file, const int debug)
Convert a cti file into a ctml file.
Definition: ct2ctml.cpp:55
void addLogEntry(const std::string &tag, const std::string &value)
Add an entry to an HTML log file.
static mutex_t msg_mutex
Mutex for access to string messages.
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Definition: stringUtils.cpp:29
static Unit * units()
Initialize the static Unit class.
Definition: units.h:29
void error(const std::string &msg)
Write an error message and quit.
Definition: global.cpp:71
Classes providing support for XML data files.
void setDefaultDirectories()
Set the default directories for input files.
static mutex_t app_mutex
Mutex for creating singletons within the application object.
Definition: application.cpp:47
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
void setLogger(Logger *logwriter)
Install a logger.
void warn_deprecated(const std::string &method, const std::string &extra="")
Print a warning indicating that method is deprecated.
Header for units conversion utilities, which are used to translate user input from input files (See I...
std::set< std::string > warnings
Vector of deprecation warnings that have been emitted (to suppress duplicates)
Definition: application.h:557
void write_logfile(const std::string &file)
Write the HTML log file.
XML_Node * get_XML_File(const std::string &file, int debug=0)
Return a pointer to the XML tree for a Cantera input file.
void endLogGroup(const std::string &title)
Close the current group of log messages.
Application()
Constructor for class sets up the initial conditions Protected ctor access thru static member functio...
void thread_complete()
Delete and free memory allocated per thread in multithreaded applications.
static Application * Instance()
Return a pointer to the one and only instance of class Application.
void removeThreadMessages()
Remove a local thread message.
Class to carry out messages.
Definition: application.h:48
std::vector< std::string > errorMessage
Current list of error messages.
Definition: application.h:261
static mutex_t xml_mutex
Mutex for controlling access to XML file storage.
Definition: application.cpp:50
Contains declarations for string manipulation functions within Cantera.
void write_logfile(const std::string &file)
Write the HTML log file.
Definition: application.h:502
std::vector< std::string > errorRoutine
Current error Routine.
Definition: application.h:264
void addDataDirectory(const std::string &dir)
Add a directory to the data file search path.
static mutex_t dir_mutex
Mutex for input directory access.
Definition: application.cpp:44
static void ApplicationDestroy()
Static function that destroys the application class's data.
Logger * logwriter
Current pointer to the logwriter.
Definition: application.h:267
void writelog(const std::string &msg)
Write a message to the screen.
std::string stripnonprint(const std::string &s)
Strip non-printing characters wherever they are.
Messages * operator->()
Provide a pointer dereferencing overloaded operator.
void logErrors()
Prints all of the error messages using writelog.
bool stop_on_error
Current list of error messages.
Definition: application.h:549
void getErrors(std::ostream &f)
Prints all of the error messages to an ostream.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
void close_XML_File(const std::string &file)
Close an XML File.
std::map< std::string, std::string > options
Current map of options.
Definition: application.h:551