ct2ctml.cpp

Go to the documentation of this file.
00001 /**
00002  * @file ct2ctml.cpp
00003  * Driver for the system call to the python executable that converts
00004  * cti files to ctml files (see \ref inputfiles).
00005  */
00006 
00007 /*
00008  * $Revision: 368 $
00009  * $Date: 2010-01-03 19:46:26 -0500 (Sun, 03 Jan 2010) $
00010  */
00011 
00012 // Copyright 2001-2005  California Institute of Technology
00013 
00014 // turn off warnings under Windows
00015 #ifdef WIN32
00016 #pragma warning(disable:4786)
00017 #pragma warning(disable:4503)
00018 #pragma warning(disable:4996)
00019 #endif
00020 
00021 #include "ct_defs.h"
00022 #include "ctexceptions.h"
00023 #include "ctml.h"
00024 #include "global.h"
00025 #include "stringUtils.h"
00026 
00027 #include <fstream>
00028 #include <string>
00029 #include <cstdlib>
00030 #include <ctime>
00031 
00032 
00033 // These defines are needed for the windows Sleep() function
00034 // - comment them out if you don't want the Sleep function.
00035 //#ifdef WIN32
00036 //#include "Windows.h"
00037 //#include "Winbase.h"
00038 //#endif
00039 
00040 using namespace Cantera;
00041 using namespace std;
00042 
00043 namespace ctml {
00044 
00045   //! return the full path to the Python interpreter. 
00046   /*!
00047    * Use the environment variable PYTHON_CMD if it is set. If not, return
00048    * the string 'python'.
00049    * 
00050    * Note, there are hidden problems here that really direct us to use
00051    * a full pathname for the location of python. Basically the system
00052    * call will use the shell /bin/sh, in order to launch python.
00053    * This default shell may not be the shell that the user is employing.
00054    * Therefore, the default path to python may be different during 
00055    * a system call than during the default user shell environment.
00056    * This is quite a headache. The answer is to always set the 
00057    * PYTHON_CMD environmental variable in the user environment to 
00058    * an absolute path to locate the python executable. Then this 
00059    * issue goes away. 
00060    */
00061   static string pypath() {
00062     string s = "python";
00063     const char* py = getenv("PYTHON_CMD");
00064     if (!py) {
00065       const char* hm = getenv("HOME");
00066       string home = stripws(string(hm));
00067       string cmd = string("source ")+home
00068         +string("/setup_cantera &> /dev/null");
00069       system(cmd.c_str());
00070       py = getenv("PYTHON_CMD");
00071     }        
00072     if (py) {
00073       string sp = stripws(string(py));
00074       if (sp.size() > 0) {
00075         s = sp;
00076       }
00077     }
00078     //else {
00079     //    throw CanteraError("ct2ctml", 
00080     //        "set environment variable PYTHON_CMD");
00081     //}
00082     return s;
00083   }
00084 
00085   // Convert a cti file into a ctml file
00086   /*
00087    *
00088    *  @param   file    Pointer to the file
00089    *  @param   debug   Turn on debug printing
00090    *
00091    *  @ingroup inputfiles
00092    */
00093   void ct2ctml(const char* file, const int debug) {
00094 
00095 #ifdef HAS_NO_PYTHON
00096     /*
00097      *  Section to bomb out if python is not
00098      *  present in the computation environment.
00099      */
00100     string ppath = file;
00101     throw CanteraError("ct2ctml", 
00102                        "python cti to ctml conversion requested for file, " + ppath +
00103                        ", but not available in this computational environment");
00104 #endif
00105 
00106     time_t aclock;
00107     time( &aclock );
00108     int ia = static_cast<int>(aclock);
00109     string path =  tmpDir()+"/.cttmp"+int2str(ia)+".pyw";
00110     ofstream f(path.c_str());
00111     if (!f) {
00112       throw CanteraError("ct2ctml","cannot open "+path+" for writing.");
00113     }
00114 
00115     f << "from ctml_writer import *\n"
00116       << "import sys, os, os.path\n"
00117       << "file = \"" << file << "\"\n"
00118       << "base = os.path.basename(file)\n"
00119       << "root, ext = os.path.splitext(base)\n"
00120       << "dataset(root)\n"
00121       << "execfile(file)\n"
00122       << "write()\n";
00123     f.close();
00124     string logfile = tmpDir()+"/ct2ctml.log";
00125 #ifdef WIN32
00126     string cmd = pypath() + " " + "\"" + path + "\"" + "> " + logfile + " 2>&1";
00127 #else
00128     string cmd = "sleep " + sleep() + "; " + "\"" + pypath() + "\"" + 
00129       " " + "\"" + path + "\"" + " &> " + logfile;
00130 #endif
00131 #ifdef DEBUG_PATHS
00132     writelog("ct2ctml: executing the command " + cmd + "\n");
00133 #endif
00134     if (debug > 0) {
00135       writelog("ct2ctml: executing the command " + cmd + "\n");
00136       writelog("ct2ctml: the Python command is: " + pypath() + "\n");
00137     }
00138 
00139     int ierr = 0;
00140     try {
00141       ierr = system(cmd.c_str());
00142     }
00143     catch (...) {
00144       ierr = -10;
00145           if (debug > 0) {
00146             writelog("ct2ctml: command execution failed.\n");
00147           }
00148     }
00149 
00150     /*
00151      * This next section may seem a bit weird. However, it is in
00152      * response to an issue that arises when running cantera with
00153      * cygwin, using cygwin's python intepreter. Basically, the
00154      * xml file is written to the local directory by the last
00155      * system command. Then, the xml file is read immediately
00156      * after by an ifstream() c++ command. Unfortunately, it seems
00157      * that the directory info is not being synched fast enough so
00158      * that the ifstream() read fails, even though the file is
00159      * actually there. Putting in a sleep system call here fixes
00160      * this problem. Also, having the xml file pre-existing fixes
00161      * the problem as well. There may be more direct ways to fix
00162      * this bug; however, I am not aware of them.
00163      * HKM -> During the solaris port, I found the same thing.
00164      *        It probably has to do with NFS syncing problems.
00165      *        3/3/06
00166      */
00167 #ifndef WIN32
00168     string sss = sleep();
00169     if (debug > 0) {
00170       writelog("sleeping for " + sss + " secs+\n");
00171     }
00172     cmd = "sleep " + sss;
00173     try {
00174       ierr = system(cmd.c_str());
00175     }
00176     catch (...) {
00177       ierr = -10;
00178       writelog("ct2ctml: command execution failed.\n");
00179     }
00180 #else
00181     // This command works on windows machines if Windows.h and Winbase.h are included
00182     // Sleep(5000);
00183 #endif
00184     // show the contents of the log file on the screen
00185     try {
00186       char ch=0;
00187       string s = "";
00188       ifstream ferr("ct2ctml.log");
00189       if (ferr) {
00190             while (!ferr.eof()) {
00191               ferr.get(ch);
00192               s += ch;
00193               if (ch == '\n') {
00194                 writelog(s);
00195                 s = "";
00196               }
00197             }
00198             ferr.close();
00199       }
00200       else {
00201             if (debug > 0) {
00202               writelog("cannot open ct2ctml.log for reading.\n");
00203             }
00204       }
00205     }
00206     catch (...) {
00207       writelog("ct2ctml: caught something \n");; 
00208     }
00209     if (ierr != 0) {
00210       string msg = cmd;
00211           writelog("ct2ctml: throw cantera error \n");; 
00212       throw CanteraError("ct2ctml", 
00213                          "could not convert input file to CTML.\n "
00214                          "Command line was: \n" + msg);
00215     }
00216 
00217     // if the conversion succeeded and DEBUG_PATHS is not defined,
00218     // then clean up by deleting the temporary Python file.
00219 #ifndef DEBUG_PATHS
00220     //#ifdef WIN32
00221     //cmd = "cmd /C rm " + path;
00222     if (debug == 0)
00223       remove(path.c_str());
00224     else {
00225       writelog("ct2ctml: retaining temporary file "+path+"\n");
00226     }
00227 #else
00228     if (debug > 0) {
00229       writelog("ct2ctml: retaining temporary file "+path+"\n");
00230     }
00231 #endif
00232   }
00233 
00234 
00235   // Read an ctml file from a file and fill up an XML tree
00236   /*
00237    *  This is the main routine that reads a ctml file and puts it into
00238    *  an XML_Node tree
00239    *
00240    *  @param node    Root of the tree
00241    *  @param file    Name of the file
00242    *  @param debug   Turn on debugging printing
00243    */
00244   void get_CTML_Tree(Cantera::XML_Node* rootPtr, const std::string file, const int debug) {
00245 
00246     std::string ff, ext = "";
00247 
00248     // find the input file on the Cantera search path
00249     std::string inname = findInputFile(file);
00250 #ifdef DEBUG_PATHS
00251     writelog("Found file: "+inname+"\n");
00252 #endif
00253     if (debug > 0)
00254       writelog("Found file: "+inname+"\n");
00255 
00256     if (inname == "") {
00257       throw CanteraError("get_CTML_Tree", "file "+file+" not found");
00258     }
00259 
00260     /* 
00261      * Check whether or not the file is XML. If not, it will be first
00262      * processed with the preprocessor.
00263      */
00264         std::string::size_type idot = inname.rfind('.');
00265     if (idot != string::npos) {
00266       ext = inname.substr(idot, inname.size());
00267     }
00268     if (ext != ".xml" && ext != ".ctml") {
00269         try {
00270           ctml::ct2ctml(inname.c_str(), debug);
00271         }
00272         catch (...) {
00273           writelog("get_CTML_Tree: caught something \n");; 
00274         }
00275       string ffull = inname.substr(0,idot) + ".xml";
00276       ff = "./" + getBaseName(ffull) + ".xml"; 
00277 #ifdef DEBUG_PATHS
00278       writelogf("ffull name = %s\n", ffull.c_str());
00279       writelogf("ff name = %s\n", ff.c_str());
00280 #endif
00281     }
00282     else {
00283       ff = inname;
00284     }
00285 #ifdef DEBUG_PATHS
00286     writelog("Attempting to parse xml file " + ff + "\n");
00287 #else
00288     if (debug > 0)
00289       writelog("Attempting to parse xml file " + ff + "\n");
00290 #endif
00291     ifstream fin(ff.c_str());
00292     if (!fin) {
00293       throw 
00294         CanteraError("get_CTML_Tree",
00295                      "XML file " + ff + " not found");
00296     }
00297     rootPtr->build(fin);
00298     fin.close();
00299   }
00300 }
Generated by  doxygen 1.6.3