Fix ct2ctml when string passed as 'source' argument
Make ct2ctml create a temp cti file for a large source argument Fixes #416
This commit is contained in:
parent
e515afd9e1
commit
3593fad14a
2 changed files with 83 additions and 0 deletions
|
|
@ -459,3 +459,33 @@ class CtmlConverterTest(utilities.CanteraTest):
|
|||
self.assertNear(R.orders.get('OH'), 0.15)
|
||||
self.assertTrue(R.allow_negative_orders)
|
||||
self.assertNear(R.orders.get('H2'), -0.25)
|
||||
|
||||
def test_long_source_input(self):
|
||||
"""
|
||||
Here we are testing if passing a very long string will result in a
|
||||
Solution object. This should result in a temp file creation in most OS's
|
||||
"""
|
||||
|
||||
gas = ct.Solution(pjoin(self.test_data_dir, 'pdep-test.cti'))
|
||||
|
||||
with open(pjoin(self.test_data_dir, 'pdep-test.cti'), 'r') as f:
|
||||
data = f.read()
|
||||
data_size_2048kB = data + ' '*2048*1024
|
||||
gas2 = ct.Solution(source=data_size_2048kB)
|
||||
|
||||
self.assertEqual(gas.n_reactions, gas2.n_reactions)
|
||||
|
||||
def test_short_source_input(self):
|
||||
"""
|
||||
Here we are testing if passing a short string will result in a Solution
|
||||
object. This should not result in a temp file creation in most OS's
|
||||
"""
|
||||
|
||||
gas = ct.Solution(pjoin(self.test_data_dir, 'pdep-test.cti'))
|
||||
|
||||
with open(pjoin(self.test_data_dir, 'pdep-test.cti'), 'r') as f:
|
||||
data = f.read()
|
||||
data_size_32kB = data + ' '*18000
|
||||
gas2 = ct.Solution(source=data_size_32kB)
|
||||
|
||||
self.assertEqual(gas.n_reactions, gas2.n_reactions)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,15 @@
|
|||
#include "cantera/base/stringUtils.h"
|
||||
#include "../../ext/libexecstream/exec-stream.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -79,6 +82,9 @@ void ct2ctml(const char* file, const int debug)
|
|||
static std::string call_ctml_writer(const std::string& text, bool isfile)
|
||||
{
|
||||
std::string file, arg;
|
||||
bool temp_file_created = false;
|
||||
std::string temp_cti_file_name = std::tmpnam(nullptr);
|
||||
|
||||
if (isfile) {
|
||||
file = text;
|
||||
arg = "r'" + text + "'";
|
||||
|
|
@ -87,6 +93,44 @@ static std::string call_ctml_writer(const std::string& text, bool isfile)
|
|||
arg = "text=r'''" + text + "'''";
|
||||
}
|
||||
|
||||
// If the user wants to convert a mechanism using a text passed via the
|
||||
// source="""..."""
|
||||
// argument in python, then we have to make sure that it is short enough
|
||||
// to fit in the command line when routed to python as:
|
||||
// python -c ...
|
||||
// statement downstream in the code
|
||||
|
||||
// So, check the max size of a string that can be passed on the command line
|
||||
// This is OS Specific. *nix systems have the sysconf() function that tells
|
||||
// us the largest argument we can pass. Since such a function does not exist
|
||||
// for Windows, we set a safe limit of 32 kB
|
||||
|
||||
#ifdef _WIN32
|
||||
long int max_argv_size = 32768;
|
||||
#else
|
||||
long int max_argv_size = sysconf(_SC_ARG_MAX);
|
||||
#endif
|
||||
|
||||
if (text.size() > static_cast<size_t>(max_argv_size) - 500) {
|
||||
// If the file is too big to be passed as a command line argument later
|
||||
// in the file, then create a temporary file and execute this function
|
||||
// as though an input file was specified as the source.
|
||||
// We assume the text passed + 500 chars = total size of argv
|
||||
|
||||
ofstream temp_cti_file(temp_cti_file_name);
|
||||
|
||||
if (temp_cti_file) {
|
||||
temp_cti_file << text;
|
||||
file = temp_cti_file_name;
|
||||
arg = "r'" + file + "'";
|
||||
temp_file_created = true;
|
||||
} else {
|
||||
// If we are here, then a temp file could not be created
|
||||
throw CanteraError("call_ctml_writer", "Very long source argument. "
|
||||
"Error creating temporary file");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_NO_PYTHON
|
||||
//! Section to bomb out if python is not present in the computation
|
||||
//! environment.
|
||||
|
|
@ -170,6 +214,15 @@ static std::string call_ctml_writer(const std::string& text, bool isfile)
|
|||
message << "--------------- end of converter log ---------------\n";
|
||||
writelog(message.str());
|
||||
}
|
||||
|
||||
if (temp_file_created) {
|
||||
// A temp file was created and has to be removed
|
||||
bool status = std::remove(temp_cti_file_name.c_str());
|
||||
if (status) {
|
||||
writelog("WARNING: Error removing tmp file {}\n", temp_cti_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
return python_output;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue