diff --git a/Cantera/README.txt b/Cantera/README.txt new file mode 100644 index 000000000..06aaa8f6e --- /dev/null +++ b/Cantera/README.txt @@ -0,0 +1,9 @@ + +This directory contains the source for Cantera and its various language interfaces. + +clib - the library of C-callable functions used by the Python and Matlab interfaces. +cxx - files that are only required for C++ application programs. +matlab - the Cantera Matlab toolbox +python - the Cantera Python package +src - the Cantera kernel + diff --git a/Cantera/clib/README.txt b/Cantera/clib/README.txt new file mode 100644 index 000000000..749a905c9 --- /dev/null +++ b/Cantera/clib/README.txt @@ -0,0 +1,5 @@ + +This directory contains code that implements C-callable functions that +can be used to create and use Cantera objects from languages other +than C++. It is used by both the Python and Matlab interface packages. + diff --git a/Cantera/clib/src/ct.cpp b/Cantera/clib/src/ct.cpp index ec1617df6..ae9f65d65 100755 --- a/Cantera/clib/src/ct.cpp +++ b/Cantera/clib/src/ct.cpp @@ -831,14 +831,15 @@ extern "C" { int DLL_EXPORT readlog(int n, char* buf) { string s; - getlog(s); + writelog("function readlog is deprecated!"); + //getlog(s); int nlog = s.size(); if (n < 0) return nlog; int nn = min(n-1, nlog); copy(s.begin(), s.begin() + nn, buf); buf[min(nlog, n-1)] = '\0'; - clearlog(); + //clearlog(); return 0; } diff --git a/Cantera/cxx/writelog.cpp b/Cantera/cxx/writelog.cpp index 874d28f54..e51c8f6ab 100644 --- a/Cantera/cxx/writelog.cpp +++ b/Cantera/cxx/writelog.cpp @@ -3,7 +3,7 @@ using namespace std; namespace Cantera { - + void writelog(const string& s) { cout << s; } diff --git a/Cantera/matlab/cantera/private/ctmethods.cpp b/Cantera/matlab/cantera/private/ctmethods.cpp index 02399690b..40f17af8e 100644 --- a/Cantera/matlab/cantera/private/ctmethods.cpp +++ b/Cantera/matlab/cantera/private/ctmethods.cpp @@ -69,7 +69,7 @@ extern "C" { int iclass = getInt(prhs[0]); // specifies that function writelog should write to MATLAB - Cantera::setMatlabMode(true); + //Cantera::setMatlabMode(true); // Hand off to the appropriate routine, based on the // value of the first parameter diff --git a/Cantera/python/Cantera/ctml_writer.py b/Cantera/python/Cantera/ctml_writer.py index 9b09f3b4d..d73d316a4 100644 --- a/Cantera/python/Cantera/ctml_writer.py +++ b/Cantera/python/Cantera/ctml_writer.py @@ -1,8 +1,15 @@ - # # Cantera input file processor # - +# The functions and classes in this module process Cantera .cti input files and produce CTML files. # +# usage: +# +# from Cantera import * +# from Cantera.ctml_writer import * +# execfile('infile.cti') +# write() +# +from Cantera import CanteraError from Cantera import GasConstant from Cantera.XML import XML_Node import types, math @@ -17,6 +24,12 @@ SKIP_UNDECLARED_ELEMENTS = 20 SKIP_UNDECLARED_SPECIES = 30 STOP = 0 +_EXCEPT = 10 +_WARN = 2 +_SKIP = 1 +_handle_undeclared_element = _EXCEPT +_handle_undeclared_species = _EXCEPT + # default units _ulen = 'm' _umol = 'kmol' @@ -30,18 +43,26 @@ _pref = 1.0e5 # 1 bar _name = 'noname' _species = [] +_speciesnames = [] _phases = [] _reactions = [] _atw = {} _mw = {} def isnum(a): + """True if a is an integer or floating-point number.""" if type(a) == types.IntType or type(a) == types.FloatType: return 1 else: return 0 - + +def is_local_species(name): + if name in _speciesnames: + return 1 + return 0 + def dataset(nm): + "Set the dataset name" global _name _name = nm @@ -49,6 +70,15 @@ def standard_pressure(p0): """Set the default standard-state pressure.""" global _pref _pref = p0 + +def on_error(undeclared_element = '', undeclared_species = ''): + global _handle_undeclared_species + global _handle_undeclared_element + + _handle_undeclared_species = undeclared_species + _handle_undeclared_element = undeclared_element + + def get_atomic_wts(): global _atw @@ -216,6 +246,8 @@ class species(writer): global _species _species.append(self) + global _speciesnames + _speciesnames.append(name) def build(self, p): @@ -417,22 +449,13 @@ class reaction(writer): else: nstr = `self._num` id = nstr - p.addComment(" reaction "+id+" ") - r = p.addChild('reaction') - r['id'] = id - if self.rev: - r['reversible'] = 'yes' - else: - r['reversible'] = 'no' - ee = self._e.replace('<','[') - ee = ee.replace('>',']') - r.addChild('equation',ee) mdim = 0 ldim = 0 str = '' + for s in self._r.keys(): ns = self._r[s] nm = -999 @@ -446,12 +469,49 @@ class reaction(writer): if ph.is_ideal_gas(): self._igspecies.append(s) break - if nm < 0: - print self._r - raise 'undeclared species '+s - else: - mdim += nm*ns - ldim += nl*ns +## if nm < 0: +## if _handle_undeclared_species == _WARN: +## print 'Warning... skipping reaction '+self._e +## print 'because species '+s+' is undeclared' +## if _handle_undeclared_species <= _WARN: +## return 0 +## else: +## raise CanteraError('undeclared species '+s+' in reaction '+self._e) + +## else: + mdim += nm*ns + ldim += nl*ns + +## for s in self._p.keys(): +## ns = self._p[s] +## ok = 0 +## for ph in _phases: +## if ph.has_species(s): +## ok = 1 +## break + +## if not ok: +## if _handle_undeclared_species == _WARN: +## print 'Warning... skipping reaction '+self._e +## print 'because species '+s+' is undeclared' +## if _handle_undeclared_species <= _WARN: +## return 0 +## else: +## raise CanteraError('undeclared species '+s+' in reaction '+self._e) + + + p.addComment(" reaction "+id+" ") + r = p.addChild('reaction') + r['id'] = id + if self.rev: + r['reversible'] = 'yes' + else: + r['reversible'] = 'no' + + ee = self._e.replace('<','[') + ee = ee.replace('>',']') + r.addChild('equation',ee) + # adjust the moles and length powers based on the dimensions of # the rate of progress (moles/length^2 or moles/length^3) @@ -537,6 +597,7 @@ class three_body_reaction(reaction): def build(self, p): r = reaction.build(self, p) + if r == 0: return kfnode = r.child('rateCoeff') if self._eff: @@ -591,7 +652,7 @@ class falloff_reaction(reaction): def build(self, p): r = reaction.build(self, p) - + if r == 0: return kfnode = r.child('rateCoeff') if self._eff and self._effm >= 0.0: @@ -748,6 +809,10 @@ class phase(writer): datasrc = r[0] ra = p.addChild('reactionArray') ra['datasrc'] = datasrc+'#reaction_data' + if _handle_undeclared_species == 'skip': + rk = ra.addChild('skip') + rk['species'] = 'undeclared' + rtoks = r[1].split() if rtoks[0] <> 'all': i = ra.addChild('include') @@ -770,10 +835,10 @@ class phase(writer): datasrc, names = s sa = ph.addChild('speciesArray',names) sa['datasrc'] = datasrc+'#species_data' - - if self._skip: - sk = sa.addChild('skip') - sk['element'] = 'undeclared' + + if _handle_undeclared_element == 'skip': + sk = sa.addChild('skip') + sk['element'] = 'undeclared' if self._rxns <> 'none': self.buildrxns(ph) diff --git a/Cantera/python/Cantera/exceptions.py b/Cantera/python/Cantera/exceptions.py index d97b130cd..81db707f6 100755 --- a/Cantera/python/Cantera/exceptions.py +++ b/Cantera/python/Cantera/exceptions.py @@ -9,9 +9,9 @@ class CanteraError(Exception): msg = _cantera.get_Cantera_Error() self.msg = msg def __str__(self): - print '\n\n\n############# CANTERA ERROR ############\n' + print '\n\n\n####################### CANTERA ERROR ######################\n' print ' ',self.msg - print '\n##########################################\n' + print '\n##############################################################\n' class OptionError(CanteraError): diff --git a/Cantera/python/src/writelog.cpp b/Cantera/python/src/writelog.cpp index 5c36f3341..415a90579 100644 --- a/Cantera/python/src/writelog.cpp +++ b/Cantera/python/src/writelog.cpp @@ -2,7 +2,7 @@ #include using namespace std; -static std::string ss = "print \""; +static std::string ss = "print \"\"\" "; namespace Cantera { @@ -11,9 +11,9 @@ namespace Cantera { int n = 0; while (ch != '\0') { if (ch =='\n') { - ss += "\""; + ss += "\"\"\""; PyRun_SimpleString((char *)ss.c_str()); - ss = "print \""; + ss = "print \"\"\""; } else ss += ch; diff --git a/Cantera/src/ChemEquil.h b/Cantera/src/ChemEquil.h index b8087ca5b..3b02f6016 100755 --- a/Cantera/src/ChemEquil.h +++ b/Cantera/src/ChemEquil.h @@ -26,7 +26,7 @@ using namespace std; #include "ct_defs.h" #include "vec_functions.h" #include "ctexceptions.h" -#include "Thermo.h" +#include "ThermoPhase.h" #include "PropertyCalculator.h" #include "DenseMatrix.h" diff --git a/Cantera/src/ConstDensityThermo.h b/Cantera/src/ConstDensityThermo.h index 1438ee5e9..846687310 100755 --- a/Cantera/src/ConstDensityThermo.h +++ b/Cantera/src/ConstDensityThermo.h @@ -17,7 +17,7 @@ #include "ct_defs.h" #include "mix_defs.h" -#include "Thermo.h" +#include "ThermoPhase.h" #include "SpeciesThermo.h" namespace Cantera { diff --git a/Cantera/src/ct2ctml.cpp b/Cantera/src/ct2ctml.cpp index 2a97448a3..e9a5682d5 100644 --- a/Cantera/src/ct2ctml.cpp +++ b/Cantera/src/ct2ctml.cpp @@ -39,20 +39,26 @@ namespace ctml { } f << "from Cantera import *\n"; f.close(); + int ierr = 0; string cmd = pypath() + " " + path + " &> " + tmpDir() + "/log"; - int ierr = system(cmd.c_str()); - if (ierr != 0) { - string msg; - msg = cmd + "\n\n########################################################################\n\n" - "The Cantera Python interface is required in order to process\n" - "Cantera input files, but it does not seem to be correctly installed.\n\n" - "Check that you can invoke the Python interpreter with \n" - "the command \"python\", and that typing \"from Cantera import *\"\n" - "at the Python prompt does not produce an error. If Python on your system\n" - "is invoked with some other command, set environment variable PYTHON_CMD\n" - "to the full path to the Python interpreter. \n\n" - "#########################################################################\n\n"; - writelog(msg); + try { + ierr = system(cmd.c_str()); + if (ierr != 0) { + string msg; + msg = cmd + "\n\n########################################################################\n\n" + "The Cantera Python interface is required in order to process\n" + "Cantera input files, but it does not seem to be correctly installed.\n\n" + "Check that you can invoke the Python interpreter with \n" + "the command \"python\", and that typing \"from Cantera import *\"\n" + "at the Python prompt does not produce an error. If Python on your system\n" + "is invoked with some other command, set environment variable PYTHON_CMD\n" + "to the full path to the Python interpreter. \n\n" + "#########################################################################\n\n"; + writelog(msg); + return false; + } + } + catch (...) { return false; } return true; @@ -76,19 +82,37 @@ namespace ctml { << "write()\n"; f.close(); string cmd = pypath() + " " + path + " &> ct2ctml.log"; - int ierr = system(cmd.c_str()); - if (ierr != 0) { - string msg = cmd; + int ierr; + try { + ierr = system(cmd.c_str()); + } + catch (...) { + ierr = -10; + } + char line[90]; + //if (ierr != 0) { + try { + char ch; + string s = ""; ifstream ferr("ct2ctml.log"); if (ferr) { - char line[80]; while (!ferr.eof()) { //msg += "\n"; - ferr.getline(line, 80); - writelog(string(line)+"\n"); + ferr.get(ch); + s += ch; + if (ch == '\n') { + writelog(s); + s = ""; + } } ferr.close(); } + } + catch (...) { + ; //writelog("could not print error message.\n"); + } + if (ierr != 0) { + string msg = cmd; bool pyok = checkPython(); if (!pyok) msg += "\nError in Python installation."; diff --git a/Cantera/src/ctml.cpp b/Cantera/src/ctml.cpp index d4a97efe8..0c3b0434e 100755 --- a/Cantera/src/ctml.cpp +++ b/Cantera/src/ctml.cpp @@ -191,14 +191,14 @@ namespace ctml { if (vmin != "") { x0 = atof(vmin.c_str()); if (x < x0 - Tiny) { - write("\nWarning: value "+fi()+" is below lower limit of " + writelog("\nWarning: value "+fi()+" is below lower limit of " +vmin+".\n"); } } if (fi["max"] != "") { x1 = atof(vmax.c_str()); if (x > x1 + Tiny) { - write("\nWarning: value "+fi()+" is above upper limit of " + writelog("\nWarning: value "+fi()+" is above upper limit of " +vmax+".\n"); } } @@ -232,14 +232,14 @@ namespace ctml { if (vmin != "") { x0 = atof(vmin.c_str()); if (x < x0 - Tiny) { - write("\nWarning: value "+node()+" is below lower limit of " + writelog("\nWarning: value "+node()+" is below lower limit of " +vmin+".\n"); } } if (node["max"] != "") { x1 = atof(vmax.c_str()); if (x > x1 + Tiny) { - write("\nWarning: value "+node()+" is above upper limit of " + writelog("\nWarning: value "+node()+" is above upper limit of " +vmax+".\n"); } } @@ -286,11 +286,11 @@ namespace ctml { } vv = v.back(); if (vmin != Undef && vv < vmin - Tiny) { - write("\nWarning: value "+fp2str(vv)+ + writelog("\nWarning: value "+fp2str(vv)+ " is below lower limit of " +fp2str(vmin)+".\n"); } if (vmax != Undef && vv > vmax + Tiny) { - write("\nWarning: value "+fp2str(vv)+ + writelog("\nWarning: value "+fp2str(vv)+ " is above upper limit of " +fp2str(vmin)+".\n"); } } diff --git a/Cantera/src/global.h b/Cantera/src/global.h index c67c3ddce..5de4d01e8 100755 --- a/Cantera/src/global.h +++ b/Cantera/src/global.h @@ -1,5 +1,9 @@ /** * @file global.h + * + * These functions handle various utility functions, and store some parameters in + * global storage that are accessible at all times. +8 */ /* $Author$ @@ -17,7 +21,7 @@ namespace Cantera { - /// Number of errors that have been encountered + /// Number of errors that have been encountered so far int nErrors(); /// The last error message @@ -26,7 +30,7 @@ namespace Cantera { /// Add an error message void setError(string r, string msg); - /// Print the error messages to f + /// Print the error messages to stream f void showErrors(ostream& f); /// Discard the last error message @@ -38,26 +42,53 @@ namespace Cantera { /// Add a directory to the search path void addDirectory(string dir); - /// Write a message - void write(const string& msg); + // Write a message (deprecated; use writelog) + //void write(const string& msg); - /// Write a message - void write(const char* msg); + // Write a message (deprecated; use writelog) + //void write(const char* msg); + /// The root directory where Cantera is installed string canteraRoot(); + /// Set the temporary file directory. Default: /tmp. void setTmpDir(string tmp); + + /// The directory where temporary files may be created string tmpDir(); + /** - * Write a diagnostic message to an internal buffer. - */ + * Write a diagnostic message to standard output. + * + * There are several versions of function writelog, each designed + * for a particular environment. One version is designed for use + * in C++ programs, or in any environment where messages can be + * written to the standard output stream. Other versions are + * written specifically for Matlab and for Python, which call + * Matlab or Python functions, respectively, to display the + * message. This is particularly important for Matlab, since + * everything written to the standard output simply + * disappears. For Python, the messages show up, but are not in + * the right order if Python scripts also print output. Hence the + * need for separate versions. + * + * The C++ version may be linked to an application by linking in + * the library libctcxx.a (-lctcxx). The Python and Matlab + * interfaces do not link this library, and instead link to their + * own versions of writelog. + */ + void writelog(const string& msg); void writelog(const char* msg); - void getlog(string& s); - void clearlog(); + //void getlog(string& s); + //void clearlog(); + + /** + * Return the conversion factor to convert unit string 'unit' to SI units. + */ doublereal toSI(string unit); doublereal actEnergyToSI(string unit); // diff --git a/Cantera/src/misc.cpp b/Cantera/src/misc.cpp index a1f86dbcd..8a724a28b 100755 --- a/Cantera/src/misc.cpp +++ b/Cantera/src/misc.cpp @@ -33,7 +33,7 @@ namespace Cantera { class Application { public: Application() : linelen(0), stop_on_error(false), - write_log_to_cout(true), matlab(false), tmp_dir("/tmp") {} + tmp_dir("/tmp") {} virtual ~Application(){} vector inputDirs; vector errorMessage; @@ -42,8 +42,8 @@ namespace Cantera { string msglog; size_t linelen; bool stop_on_error; - bool write_log_to_cout; - bool matlab; + //bool write_log_to_cout; + //bool matlab; map options; string tmp_dir; }; @@ -69,10 +69,10 @@ namespace Cantera { return __app; } - void setTmpDir(string tmp) { appinit(); __app->tmp_dir = tmp; } - string tmpDir() { appinit(); return __app->tmp_dir; } + void setTmpDir(string tmp) { app()->tmp_dir = tmp; } + string tmpDir() { appinit(); return app()->tmp_dir; } - int nErrors() {return __app->errorMessage.size();} + int nErrors() {return app()->errorMessage.size();} void popError() { appinit(); @@ -256,22 +256,23 @@ namespace Cantera { } } - void setMatlabMode(bool m) { - appinit(); - __app->matlab = m; - } + //void setMatlabMode(bool m) { + // appinit(); + // __app->matlab = m; + //} + + //void write(const string& msg) {cout << msg;} + //void write(const char* msg) {cout << msg;} - void write(const string& msg) {cout << msg;} - void write(const char* msg) {cout << msg;} void writelog(const char* msg) {writelog(string(msg));} - void getlog(string& s) { - appinit(); - s = __app->msglog; - //__app->msglog = ""; - } - void clearlog() { - __app->msglog = ""; - } + //void getlog(string& s) { + // appinit(); + // s = __app->msglog; + // //__app->msglog = ""; + //} + //void clearlog() { + // __app->msglog = ""; + //} doublereal toSI(string unit) { doublereal f = Unit::units()->toSI(unit);