Cantera  2.0
application.h
1 #ifndef CT_BASE_APPLICATION_H
2 #define CT_BASE_APPLICATION_H
3 
4 #include "cantera/base/config.h"
6 #include "cantera/base/logger.h"
7 
8 #include <map>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 namespace Cantera {
14 
15 class XML_Node;
16 
17 /*!
18  * @defgroup globalData Global Data
19  *
20  * Global data are available anywhere. There are two kinds.
21  * Cantera has an assortment of constant values for physical parameters.
22  * Also, Cantera maintains a collection of global data which is specific
23  * to each process that invokes Cantera functions. This process-specific
24  * data is stored in the class Application.
25  */
26 
27 
28 //! Class to hold global data.
29 /*!
30  * Class Application is the top-level
31  * class that stores data that should persist for the duration of
32  * the process. The class should not be instantiated directly;
33  * instead, it is instantiated as needed by the functions declared
34  * here. At most one instance is created, and it is not destroyed
35  * until the process terminates.
36  *
37  * @ingroup HTML_logs
38  * @ingroup textlogs
39  * @ingroup globalData
40  */
42 {
43 protected:
44  //! Class to carry out messages
45  /*!
46  * @ingroup HTML_logs
47  */
48  class Messages
49  {
50  public:
51  //! Constructor for the Messages class
52  /*! Constructor for the Messages class which is a subclass
53  * of the Application class.
54  */
55  Messages();
56 
57  //! Copy Constructor for the Messages class
58  /*! Constructor for the Messages class which is a subclass
59  * of the Application class.
60  * @param r Message to be copied
61  */
62  Messages(const Messages& r);
63 
64  //! Assignment operator
65  /*!
66  * @param r Message to be copied
67  */
68  Messages& operator=(const Messages& r);
69 
70  //! Destructor for the Messages class
71  ~Messages();
72 
73  //! Set an error condition in the application class without
74  //! throwing an exception.
75  /*!
76  * This routine adds an error message to the end of the stack
77  * of errors that Cantera accumulates in the Application
78  * class.
79  * @param r location
80  * @param msg Description of the error
81  * @ingroup errorhandling
82  */
83  void addError(std::string r, std::string msg);
84 
85  //! Return the number of errors that have been encountered so far.
86  /*!
87  * @ingroup errorhandling
88  */
89  int getErrorCount() ;
90 
91  //! Discard the last error message
92  /*!
93  * %Cantera saves a stack of exceptions that it
94  * has caught in the Application class. This routine eliminates
95  * the last exception to be added to that stack.
96  *
97  * @ingroup errorhandling
98  */
99  void popError() ;
100 
101  //! Retrieve the last error message in a string
102  /*!
103  * This routine will retrieve the last error message and return
104  * it in the return string.
105  *
106  * @ingroup errorhandling
107  */
108  std::string lastErrorMessage() ;
109 
110  //! Prints all of the error messages to an ostream
111  /*!
112  * Print all of the error messages using function writelog.
113  * Write out all of the saved error messages to the ostream f
114  * Cantera saves a stack of exceptions that it
115  * has caught in the Application class. This routine writes
116  * out all of the error messages to the ostream
117  * and then clears them from internal storage.
118  *
119  * @param f ostream which will receive the error messages
120  *
121  * @ingroup errorhandling
122  */
123  void getErrors(std::ostream& f) ;
124 
125  //! Prints all of the error messages using writelog
126  /*!
127  * Print all of the error messages using function writelog.
128  * Cantera saves a stack of exceptions that it
129  * has caught in the Application class. This routine writes
130  * out all of the error messages
131  * and then clears them from internal storage.
132  *
133  * @ingroup errorhandling
134  */
135  void logErrors();
136 
137  //! Write a message to the screen.
138  /*!
139  * The string may be of any
140  * length, and may contain end-of-line characters. This method is
141  * used throughout %Cantera to write log messages.
142  *
143  * @param msg c++ string to be written to the screen
144  * @ingroup textlogs
145  */
146  void writelog(const std::string& msg);
147 
148  //! Write an end of line and flush output
149  void writelogendl();
150 
151  //! Write a message to the screen.
152  /*!
153  * The string may be of any
154  * length, and may contain end-of-line characters. This method is
155  * used throughout %Cantera to write log messages.
156  *
157  * @param pszmsg c character string to be written to the screen
158  * @ingroup textlogs
159  */
160  void writelog(const char* pszmsg) ;
161 
162  //! Write an error message and quit.
163  /*!
164  * The default behavior is
165  * to write to the standard error stream, and then call
166  * exit(). Note that no end-of-line character is appended to
167  * the message, and so if one is desired it must be included
168  * in the string. Note that this default behavior will
169  * terminate the application Cantera is invoked from (MATLAB,
170  * Excel, etc.) If this is not desired, then derive a class
171  * and reimplement this method.
172  *
173  * @param msg Error message to be written to cerr.
174  */
175  void logerror(const std::string& msg) ;
176 
177  //! Returns an integer specifying the application environment
178  //! @deprecated
179  DEPRECATED(int getUserEnv()) ;
180 
181  //! Install a logger.
182  /*!
183  * Called by the language interfaces to install an appropriate logger.
184  * The logger is used for the writelog() function
185  *
186  * @param logwriter Pointer to a logger object
187  * @see Logger.
188  * @ingroup textlogs
189  */
190  void setLogger(Logger* logwriter) ;
191 
192 #ifdef WITH_HTML_LOGS
193 
194  //!Create a new group for log messages.
195  /*!
196  * Usually this is called
197  * upon entering the function, with the title parameter equal to
198  * the name of the function or method. Subsequent messages
199  * written with addLogEntry will appear grouped under this
200  * heading, until endLogGroup() is called.
201  *
202  * @param title String name of the LogGroup
203  * @param loglevel loglevel of the group.
204  * @ingroup HTML_logs
205  */
206  void beginLogGroup(std::string title, int loglevel) ;
207 
208  //! Add an entry to an HTML log file.
209  /*!
210  * Entries appear in the form "tag:value".
211  *
212  * @param tag tag
213  * @param value double value
214  *
215  * @ingroup HTML_logs
216  */
217  void addLogEntry(std::string tag, std::string value) ;
218 
219  //! Add an entry to an HTML log file.
220  /*!
221  * Entries appear in the form "tag:value".
222  *
223  * @param tag tag
224  * @param value double value
225  *
226  * @ingroup HTML_logs
227  */
228  void addLogEntry(std::string tag, doublereal value) ;
229 
230  //! Add an entry to an HTML log file.
231  /*!
232  * Entries appear in the form "tag:value".
233  *
234  * @param tag tag
235  * @param value double value
236  *
237  * @ingroup HTML_logs
238  */
239  void addLogEntry(std::string tag, int value) ;
240 
241  //! Add an entry to an HTML log file.
242  /*!
243  * Entries appear in the form "msg".
244  *
245  * @param msg Message to be added
246  *
247  * @ingroup HTML_logs
248  */
249  void addLogEntry(std::string msg) ;
250 
251  //! Close the current group of log messages.
252  /*!
253  * This is typically
254  * called just before leaving a function or method, to close the
255  * group of messages that were output from this
256  * function. Subsequent messages written with addLogEntry() will
257  * appear at the next-higher level in the outline, unless
258  * beginLogGroup() is called first to create a new group.
259  *
260  * @param title Name of the log group. It defaults to the most recent
261  * log group created.
262  */
263  void endLogGroup(std::string title) ;
264 
265  //! Write the HTML log file.
266  /*!
267  * Log entries are stored in memory in
268  * an XML tree until this function is called, which writes the
269  * tree to a file and clears the entries stored in memory. The
270  * output file will have the name specified in the 'file'
271  * argument. If this argument has no extension, the extension
272  * '.html' will be appended. Also, if the file already exists, an
273  * integer will be appended to the name so that no existing log
274  * file will be overwritten.
275  * WITH_HTML_LOGS must be defined.
276  *
277  * @param file Name of the file to be written
278  */
279  void write_logfile(std::string file);
280 #endif
281 
282  protected:
283  //! Current list of error messages
284  std::vector<std::string> errorMessage;
285 
286  //! Current error Routine
287  std::vector<std::string> errorRoutine;
288 
289  //! Current pointer to the logwriter
291 #ifdef WITH_HTML_LOGS
292  //! Current pointer to the top of the XML_Node tree for the current HTML log
294 
295  //! Pointer to the last current position in the XML_Node tree for the current HTML log
297 
298  //! Current value of the loglevel
299  int loglevel;
300 
301  //! Vector of loglevels for loggroups that are open
302  std::vector<int> loglevels;
303 
304  //! Current vector of loggroups that are open
305  std::vector<std::string> loggroups;
306 #endif
307  } ;
308 
309 #ifdef THREAD_SAFE_CANTERA
310  //! Typedef for thread specific messages
311  typedef boost::shared_ptr< Messages > pMessages_t ;
312 
313  //! Class that stores thread messages for each thread, and retrieves them
314  //! based on the thread id.
316  {
317  public:
318  //! Constructor
320 
321  //! Provide a pointer dereferencing overloaded operator
322  /*!
323  * @return returns a pointer to Messages
324  */
325  Messages* operator->();
326 
327  //! Remove a local thread message
328  void removeThreadMessages();
329 
330  //! Typedef for map between a thread and the message
331  typedef std::map< cthreadId_t, pMessages_t > threadMsgMap_t ;
332 
333  private:
334  //! Thread Msg Map
336  } ;
337 #endif
338 
339 
340 protected:
341  //! Constructor for class sets up the initial conditions
342  //! Protected ctor access thru static member function Instance
343  Application();
344 
345 public:
346  //! Return a pointer to the one and only instance of class Application
347  /*!
348  * If the an Application object has not yet been created it is created
349  */
350  static Application* Instance();
351 
352  //! Destructor for class deletes global data
353  /*!
354  * Delete any open XML trees, the logwriter, and
355  * the XML log, if any.
356  */
357  virtual ~Application();
358 
359  //! Static function that destroys the application class's data
360  static void ApplicationDestroy();
361 
362  //! Set an error condition in the application class without
363  //! throwing an exception.
364  /*!
365  * This routine adds an error message to the end of the stack
366  * of errors that Cantera accumulates in the Application
367  * class.
368  * @param r location
369  * @param msg Description of the error
370  * @ingroup errorhandling
371  */
372  void addError(std::string r, std::string msg) {
373  pMessenger->addError(r, msg) ;
374  }
375 
376  //! Return the number of errors that have been encountered so far.
377  /*!
378  * @ingroup error handling
379  */
381  return pMessenger->getErrorCount() ;
382  }
383 
384  //! Discard the last error message
385  /*!
386  * %Cantera saves a stack of exceptions that it
387  * has caught in the Application class. This routine eliminates
388  * the last exception to be added to that stack.
389  *
390  * @ingroup errorhandling
391  */
392  void popError() {
393  pMessenger->popError() ;
394  }
395 
396  //! Retrieve the last error message in a string
397  /*!
398  * This routine will retrieve the last error message and return
399  * it in the return string.
400  *
401  * @ingroup errorhandling
402  */
403  std::string lastErrorMessage() {
404  return pMessenger->lastErrorMessage() ;
405  }
406 
407  //! Prints all of the error messages to an ostream
408  /*!
409  * Print all of the error messages using function writelog.
410  * Write out all of the saved error messages to the ostream f
411  * Cantera saves a stack of exceptions that it
412  * has caught in the Application class. This routine writes
413  * out all of the error messages to the ostream
414  * and then clears them from internal storage.
415  *
416  * @param f ostream which will receive the error messages
417  *
418  * @ingroup errorhandling
419  */
420  void getErrors(std::ostream& f) {
421  pMessenger->getErrors(f) ;
422  }
423 
424  //! Prints all of the error messages using writelog
425  /*!
426  * Print all of the error messages using function writelog.
427  * Cantera saves a stack of exceptions that it
428  * has caught in the Application class. This routine writes
429  * out all of the error messages
430  * and then clears them from internal storage.
431  *
432  * @ingroup errorhandling
433  */
434  void logErrors() {
435  pMessenger->logErrors() ;
436  }
437 
438  //! Add a directory to the data file search path.
439  /*!
440  * @ingroup inputfiles
441  *
442  * @param dir String name for the directory to be added to the search path
443  */
444  void addDataDirectory(std::string dir) ;
445 
446  //! Find an input file.
447  /*!
448  * This routine will search for a file in the default
449  * locations specified for the application.
450  * See the routine setDefaultDirectories() listed above.
451  *
452  * The default set of directories specified for the application
453  * will be searched if a '/' or an '\\' is found in the
454  * name. If either is found then a relative path name is
455  * presumed, and the default directories are not searched.
456  *
457  * The presence of the file is determined by whether the file
458  * can be opened for reading by the current user.
459  *
460  * @param name Name of the input file to be searched for
461  *
462  * @return
463  *
464  * The absolute path name of the first matching
465  * file is returned. If a relative path name
466  * is indicated, the relative path name is returned.
467  *
468  * If the file is not found, a message is written to
469  * stdout and a CanteraError exception is thrown.
470  *
471  * @ingroup inputfiles
472  */
473  std::string findInputFile(std::string name) ;
474 
475  //! Return a pointer to the XML tree for a Cantera input file.
476  /*!
477  * This routine will find the file and read the XML file into an
478  * XML tree structure. Then, a pointer will be returned. If the
479  * file has already been processed, then just the pointer will
480  * be returned.
481  *
482  * @param file String containing the relative or absolute file name
483  * @param debug Debug flag
484  */
485  XML_Node* get_XML_File(std::string file, int debug=0) ;
486 
487  //! Close an XML File
488  /*!
489  * Close a file that is opened by this application object
490  *
491  * @param file String containing the relative or absolute file name
492  */
493  void close_XML_File(std::string file) ;
494 
495  //! Write a message to the screen.
496  /*!
497  * The string may be of any
498  * length, and may contain end-of-line characters. This method is
499  * used throughout %Cantera to write log messages.
500  *
501  * @param msg c++ string to be written to the screen
502  * @ingroup textlogs
503  */
504 #ifdef _WIN32
505  long int readStringRegistryKey(const std::string& keyName, const std::string& valueName,
506  std::string& value, const std::string& defaultValue);
507 #endif
508 
509  void writelog(const std::string& msg) {
510  pMessenger->writelog(msg);
511  }
512 
513 
514  //! Write an endl to the screen and flush output
515  /*!
516  * @ingroup textlogs
517  */
518  void writelogendl() {
520  }
521 
522  //! Write a message to the screen.
523  /*!
524  * The string may be of any
525  * length, and may contain end-of-line characters. This method is
526  * used throughout %Cantera to write log messages.
527  *
528  * @param pszmsg c null terminated string to be written to the screen
529  * @ingroup textlogs
530  */
531  void writelog(const char* pszmsg) {
532  pMessenger->writelog(pszmsg);
533  }
534 
535  //! Write an error message and quit.
536  /*!
537  * The default behavior is
538  * to write to the standard error stream, and then call
539  * exit(). Note that no end-of-line character is appended to
540  * the message, and so if one is desired it must be included
541  * in the string. Note that this default behavior will
542  * terminate the application Cantera is invoked from (MATLAB,
543  * Excel, etc.) If this is not desired, then derive a class
544  * and reimplement this method.
545  *
546  * @param msg Error message to be written to cerr.
547  */
548  void logerror(const std::string& msg) {
549  pMessenger->logerror(msg);
550  }
551 
552  //! Returns an integer specifying the application environment.
553  //! @deprecated
554  DEPRECATED(int getUserEnv()) {
555  return pMessenger->getUserEnv() ;
556  }
557 
558  //! Install a logger - Called by the language interfaces to install an
559  //! appropriate logger.
560  /*!
561  * @param logwriter Pointer to a logger object
562  * @see Logger.
563  * @ingroup textlogs
564  */
565  void setLogger(Logger* logwriter) {
566  pMessenger->setLogger(logwriter);
567  }
568 
569  //! Delete Messenger object allocated per thread.
570  void thread_complete() ;
571 
572 #ifdef WITH_HTML_LOGS
573  //!Create a new group for log messages.
574  /*!
575  * Usually this is called
576  * upon entering the function, with the title parameter equal to
577  * the name of the function or method. Subsequent messages
578  * written with addLogEntry will appear grouped under this
579  * heading, until endLogGroup() is called.
580  *
581  * @param title String name of the LogGroup
582  * @param loglevel loglevel of the group.
583  * @ingroup HTML_logs
584  */
585  void beginLogGroup(std::string title, int loglevel) {
586  pMessenger->beginLogGroup(title,loglevel);
587  }
588 
589  //! Add an entry to an HTML log file.
590  /*!
591  * Entries appear in the form "tag:value".
592  *
593  * @param tag tag
594  * @param value double value
595  *
596  * @ingroup HTML_logs
597  */
598  void addLogEntry(std::string tag, std::string value) {
599  pMessenger->addLogEntry(tag, value);
600  }
601 
602  //! Add an entry to an HTML log file.
603  /*!
604  * Entries appear in the form "tag:value".
605  *
606  * @param tag tag
607  * @param value double value
608  *
609  * @ingroup HTML_logs
610  */
611  void addLogEntry(std::string tag, doublereal value) {
612  pMessenger->addLogEntry(tag, value);
613  }
614 
615  //! Add an entry to an HTML log file.
616  /*!
617  * Entries appear in the form "tag:value".
618  *
619  * @param tag tag
620  * @param value double value
621  *
622  * @ingroup HTML_logs
623  */
624  void addLogEntry(std::string tag, int value) {
625  pMessenger->addLogEntry(tag, value);
626  }
627 
628  //! Add an entry to an HTML log file.
629  /*!
630  * Entries appear in the form "msg".
631  *
632  * @param msg Message to be added to file
633  *
634  * @ingroup HTML_logs
635  */
636  void addLogEntry(std::string msg) {
637  pMessenger->addLogEntry(msg);
638  }
639 
640  //! Close the current group of log messages.
641  /*!
642  * This is typically
643  * called just before leaving a function or method, to close the
644  * group of messages that were output from this
645  * function. Subsequent messages written with addLogEntry() will
646  * appear at the next-higher level in the outline, unless
647  * beginLogGroup() is called first to create a new group.
648  *
649  * @param title Name of the log group. It defaults to the most recent
650  * log group created.
651  * @ingroup HTML_logs
652  */
653  void endLogGroup(std::string title) {
654  pMessenger->endLogGroup(title) ;
655  }
656 
657  //! Write the HTML log file.
658  /*!
659  * Log entries are stored in memory in
660  * an XML tree until this function is called, which writes the
661  * tree to a file and clears the entries stored in memory. The
662  * output file will have the name specified in the 'file'
663  * argument. If this argument has no extension, the extension
664  * '.html' will be appended. Also, if the file already exists, an
665  * integer will be appended to the name so that no existing log
666  * file will be overwritten.
667  * WITH_HTML_LOGS must be defined.
668  *
669  * @param file Name of the file to be written
670  */
671  void write_logfile(std::string file) {
672  pMessenger->write_logfile(file) ;
673  }
674 #endif
675 
676 protected:
677  //! Set the default directories for input files.
678  /*!
679  * %Cantera searches
680  * for input files along a path that includes platform-specific
681  * default locations, and possibly user-specified locations. This
682  * function installs the platform-specific directories on the
683  * search path. It is invoked at startup by appinit(), and never
684  * should need to be called by user programs.
685  *
686  * The current directory (".") is always searched first. Then, on
687  * Windows platforms, if environment variable COMMONPROGRAMFILES
688  * is set (which it should be on Win XP or Win 2000), then
689  * directories under this one will be added to the search
690  * path. The %Cantera Windows installer installs data files to this
691  * location.
692  *
693  * On the Mac, directory '/Applications/Cantera/data' is added to the
694  * search path.
695  *
696  * On any platform, if environment variable CANTERA_DATA is set to a
697  * directory name, then this directory is added to the search path.
698  *
699  * Finally, the location where the data files were installed when
700  * %Cantera was built is added to the search path.
701  *
702  * Additional directories may be added by calling function addDirectory.
703  * @ingroup inputfiles
704  */
705  void setDefaultDirectories();
706 
707  //! Current vector of input directories to search for input files
708  std::vector<std::string> inputDirs;
709  //! Current list of error messages
710  //vector<string> errorMessage;
711  //! Current list of warning messages
712  //vector<string> warning;
713  //! Current error Routine
714  //vector<string> errorRoutine;
715  //! Last error message
716  //string msglog;
717  //! Current line length
718  // size_t linelen;
719  //! Current value of stop_on_error
721  //! Current map of options
722  std::map<std::string, std::string> options;
723  //! Current value of tmp_dir
724  std::string tmp_dir;
725  //! Current vector of xml file trees that have been previously parsed
726  std::map<std::string, XML_Node*> xmlfiles;
727  //! Current pointer to the logwriter
728  //Logger* logwriter;
729 #ifdef WITH_HTML_LOGS
730  //! Current pointer to the top of the XML_Node tree for the current HTML log
731  //XML_Node *xmllog;
732  //! Pointer to the last current position in the XML_Node tree for the current HTML log
733  //XML_Node *current;
734  //! Current value of loglevel
735  //int loglevel;
736  //! Vector of loglevels for loggroups that are open
737  //vector<int> loglevels;
738  //! Current vector of loggroups that are open
739  //vector<string> loggroups;
740 #endif
741 
742 #if defined(THREAD_SAFE_CANTERA)
744 #else
745  std::auto_ptr<Messages> pMessenger ;
746 #endif
747 
748 private:
749  //! Pointer to the single Application instance
750  static Application* s_app ;
751 };
752 
753 }
754 
755 #endif