cantera/src/base/ct2ctml.cpp
2012-03-09 23:00:16 +00:00

192 lines
6 KiB
C++

/**
* @file ct2ctml.cpp
* Driver for the system call to the python executable that converts
* cti files to ctml files (see \ref inputfiles).
*/
// Copyright 2001-2005 California Institute of Technology
#include "cantera/base/ct_defs.h"
#include "cantera/base/ctexceptions.h"
#include "cantera/base/ctml.h"
#include "cantera/base/global.h"
#include "cantera/base/stringUtils.h"
#include "../../ext/libexecstream/exec-stream.h"
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace Cantera;
using namespace std;
namespace ctml
{
//! return the full path to the Python interpreter.
/*!
* Use the environment variable PYTHON_CMD if it is set. If not, return
* the string 'python'.
*
* Note, there are hidden problems here that really direct us to use
* a full pathname for the location of python. Basically the system
* call will use the shell /bin/sh, in order to launch python.
* This default shell may not be the shell that the user is employing.
* Therefore, the default path to python may be different during
* a system call than during the default user shell environment.
* This is quite a headache. The answer is to always set the
* PYTHON_CMD environmental variable in the user environment to
* an absolute path to locate the python executable. Then this
* issue goes away.
*/
static string pypath()
{
string s = "python";
const char* py = getenv("PYTHON_CMD");
if (py) {
string sp = stripws(string(py));
if (sp.size() > 0) {
s = sp;
}
}
return s;
}
// Convert a cti file into a ctml file
/*
*
* @param file Pointer to the file
* @param debug Turn on debug printing
*
* @ingroup inputfiles
*/
void ct2ctml(const char* file, const int debug)
{
#ifdef HAS_NO_PYTHON
/*
* Section to bomb out if python is not
* present in the computation environment.
*/
string ppath = file;
throw CanteraError("ct2ctml",
"python cti to ctml conversion requested for file, " + ppath +
", but not available in this computational environment");
#endif
string python_output;
int python_exit_code;
try {
exec_stream_t python;
python.set_wait_timeout(exec_stream_t::s_child, 10000);
python.start(pypath(), "-i");
stringstream output_stream;
python.in() <<
"if True:\n" << // Use this so that the rest is a single block
" import sys\n" <<
" sys.stderr = sys.stdout\n" <<
" import ctml_writer\n" <<
" ctml_writer.convert(r'" << file << "')\n";
python.close_in();
std::string line;
while (std::getline(python.out(), line).good()) {
output_stream << line << std::endl;;
}
python.close();
python_exit_code = python.exit_code();
python_output = stripws(output_stream.str());
} catch (std::exception& err) {
// Report failure to execute the python
stringstream message;
message << "Error executing python while converting input file:\n";
message << "Python command was: '" << pypath() << "'\n";
message << err.what() << std::endl;
throw CanteraError("ct2ctml", message.str());
}
if (python_exit_code != 0) {
// Report a failure in the conversion process
stringstream message;
message << "Error converting input file \"" << file << "\" to CTML.\n";
message << "Python command was: '" << pypath() << "'\n";
if (python_output.size() > 0) {
message << "-------------- start of converter log --------------\n";
message << python_output << std::endl;
message << "--------------- end of converter log ---------------";
}
throw CanteraError("ct2ctml", message.str());
}
if (python_output.size() > 0) {
// Warn if there was any output from the conversion process
stringstream message;
message << "Warning: Unexpected output from CTI converter\n";
message << "-------------- start of converter log --------------\n";
message << python_output << std::endl;
message << "--------------- end of converter log ---------------\n";
writelog(message.str());
}
}
// Read an ctml file from a file and fill up an XML tree
/*
* This is the main routine that reads a ctml file and puts it into
* an XML_Node tree
*
* @param node Root of the tree
* @param file Name of the file
* @param debug Turn on debugging printing
*/
void get_CTML_Tree(Cantera::XML_Node* rootPtr, const std::string file, const int debug)
{
std::string ff, ext = "";
// find the input file on the Cantera search path
std::string inname = findInputFile(file);
if (debug > 0) {
writelog("Found file: "+inname+"\n");
}
if (inname == "") {
throw CanteraError("get_CTML_Tree", "file "+file+" not found");
}
/*
* Check whether or not the file is XML. If not, it will be first
* processed with the preprocessor.
*/
std::string::size_type idot = inname.rfind('.');
if (idot != string::npos) {
ext = inname.substr(idot, inname.size());
}
if (ext != ".xml" && ext != ".ctml") {
try {
ctml::ct2ctml(inname.c_str(), debug);
} catch (std::exception& err) {
writelog("get_CTML_Tree: caught an exception:\n");
writelog(err.what());
}
string ffull = inname.substr(0,idot) + ".xml";
ff = "./" + getBaseName(ffull) + ".xml";
if (debug > 0) {
writelogf("ffull name = %s\n", ffull.c_str());
writelogf("ff name = %s\n", ff.c_str());
}
} else {
ff = inname;
}
if (debug > 0) {
writelog("Attempting to parse xml file " + ff + "\n");
}
ifstream fin(ff.c_str());
if (!fin) {
throw
CanteraError("get_CTML_Tree",
"XML file " + ff + " not found");
}
rootPtr->build(fin);
fin.close();
}
}