Cantera  2.0
ct2ctml.cpp
Go to the documentation of this file.
1 /**
2  * @file ct2ctml.cpp
3  * Driver for the system call to the python executable that converts
4  * cti files to ctml files (see \ref inputfiles).
5  */
6 // Copyright 2001-2005 California Institute of Technology
7 
8 #include "cantera/base/ct_defs.h"
10 #include "cantera/base/ctml.h"
11 #include "cantera/base/global.h"
13 #include "../../ext/libexecstream/exec-stream.h"
14 
15 #include <fstream>
16 #include <sstream>
17 #include <string>
18 #include <cstdlib>
19 #include <ctime>
20 
21 using namespace Cantera;
22 using namespace std;
23 
24 namespace ctml
25 {
26 
27 //! return the full path to the Python interpreter.
28 /*!
29  * Use the environment variable PYTHON_CMD if it is set. If not, return
30  * the string 'python'.
31  *
32  * Note, there are hidden problems here that really direct us to use
33  * a full pathname for the location of python. Basically the system
34  * call will use the shell /bin/sh, in order to launch python.
35  * This default shell may not be the shell that the user is employing.
36  * Therefore, the default path to python may be different during
37  * a system call than during the default user shell environment.
38  * This is quite a headache. The answer is to always set the
39  * PYTHON_CMD environmental variable in the user environment to
40  * an absolute path to locate the python executable. Then this
41  * issue goes away.
42  */
43 static string pypath()
44 {
45  string s = "python";
46  const char* py = getenv("PYTHON_CMD");
47 
48  if (py) {
49  string sp = stripws(string(py));
50  if (sp.size() > 0) {
51  s = sp;
52  }
53  }
54  return s;
55 }
56 
57 // Convert a cti file into a ctml file
58 /*
59  *
60  * @param file Pointer to the file
61  * @param debug Turn on debug printing
62  *
63  * @ingroup inputfiles
64  */
65 void ct2ctml(const char* file, const int debug)
66 {
67 #ifdef HAS_NO_PYTHON
68  /*
69  * Section to bomb out if python is not
70  * present in the computation environment.
71  */
72  string ppath = file;
73  throw CanteraError("ct2ctml",
74  "python cti to ctml conversion requested for file, " + ppath +
75  ", but not available in this computational environment");
76 #endif
77 
78  string python_output;
79  int python_exit_code;
80  try {
81  exec_stream_t python;
82  python.set_wait_timeout(exec_stream_t::s_all, 1800000); // 30 minutes
83  python.start(pypath(), "-i");
84  stringstream output_stream;
85  python.in() <<
86  "if True:\n" << // Use this so that the rest is a single block
87  " import sys\n" <<
88  " sys.stderr = sys.stdout\n" <<
89  " import ctml_writer\n" <<
90  " ctml_writer.convert(r'" << file << "')\n" <<
91  " sys.exit(0)\n\n"
92  "sys.exit(7)\n";
93  python.close_in();
94  std::string line;
95  while (python.out().good()) {
96  std::getline(python.out(), line);
97  output_stream << line << std::endl;;
98  }
99  python.close();
100  python_exit_code = python.exit_code();
101  python_output = stripws(output_stream.str());
102  } catch (std::exception& err) {
103  // Report failure to execute Python
104  stringstream message;
105  message << "Error executing python while converting input file:\n";
106  message << "Python command was: '" << pypath() << "'\n";
107  message << err.what() << std::endl;
108  throw CanteraError("ct2ctml", message.str());
109  }
110 
111  if (python_exit_code != 0) {
112  // Report a failure in the conversion process
113  stringstream message;
114  message << "Error converting input file \"" << file << "\" to CTML.\n";
115  message << "Python command was: '" << pypath() << "'\n";
116  message << "The exit code was: " << python_exit_code << "\n";
117  if (python_output.size() > 0) {
118  message << "-------------- start of converter log --------------\n";
119  message << python_output << std::endl;
120  message << "--------------- end of converter log ---------------";
121  } else {
122  message << "The command did not produce any output." << endl;
123  }
124  throw CanteraError("ct2ctml", message.str());
125  }
126 
127  if (python_output.size() > 0) {
128  // Warn if there was any output from the conversion process
129  stringstream message;
130  message << "Warning: Unexpected output from CTI converter\n";
131  message << "-------------- start of converter log --------------\n";
132  message << python_output << std::endl;
133  message << "--------------- end of converter log ---------------\n";
134  writelog(message.str());
135  }
136 }
137 
138 
139 // Read an ctml file from a file and fill up an XML tree
140 /*
141  * This is the main routine that reads a ctml file and puts it into
142  * an XML_Node tree
143  *
144  * @param node Root of the tree
145  * @param file Name of the file
146  * @param debug Turn on debugging printing
147  */
148 void get_CTML_Tree(Cantera::XML_Node* rootPtr, const std::string file, const int debug)
149 {
150  std::string ff, ext = "";
151 
152  // find the input file on the Cantera search path
153  std::string inname = findInputFile(file);
154  if (debug > 0) {
155  writelog("Found file: "+inname+"\n");
156  }
157 
158  if (inname == "") {
159  throw CanteraError("get_CTML_Tree", "file "+file+" not found");
160  }
161 
162  /*
163  * Check whether or not the file is XML. If not, it will be first
164  * processed with the preprocessor.
165  */
166  std::string::size_type idot = inname.rfind('.');
167  if (idot != string::npos) {
168  ext = inname.substr(idot, inname.size());
169  }
170  if (ext != ".xml" && ext != ".ctml") {
171  try {
172  ctml::ct2ctml(inname.c_str(), debug);
173  } catch (std::exception& err) {
174  writelog("get_CTML_Tree: caught an exception:\n");
175  writelog(err.what());
176  }
177  string ffull = inname.substr(0,idot) + ".xml";
178  ff = "./" + getBaseName(ffull) + ".xml";
179  if (debug > 0) {
180  writelogf("ffull name = %s\n", ffull.c_str());
181  writelogf("ff name = %s\n", ff.c_str());
182  }
183  } else {
184  ff = inname;
185  }
186  if (debug > 0) {
187  writelog("Attempting to parse xml file " + ff + "\n");
188  }
189  ifstream fin(ff.c_str());
190  if (!fin) {
191  throw
192  CanteraError("get_CTML_Tree",
193  "XML file " + ff + " not found");
194  }
195  rootPtr->build(fin);
196  fin.close();
197 }
198 }