8 #ifndef FIELD_PYTHON_IMPL_HH_
9 #define FIELD_PYTHON_IMPL_HH_
12 #include <boost/type_traits.hpp>
17 namespace it = Input::Type;
19 template <
int spacedim,
class Value>
24 template <
int spacedim,
class Value>
33 "Python script given as in place string")
35 "Python script given as external file")
37 "Function in the given script that returns tuple containing components of the return type.\n"
38 "For NxM tensor values: tensor(row,col) = tuple( M*row + col ).");
45 template <
int spacedim,
class Value>
55 xprintf(
UsrErr,
"Flow123d compiled without support for Python, FieldPython can not be used.\n");
61 template <
int spacedim,
class Value>
65 p_module_ = PythonLoader::load_module_from_string(
"python_field_"+func_name, python_source);
74 template <
int spacedim,
class Value>
78 set_python_field_from_string( *it, rec.
val<
string>(
"function") );
81 if (! it)
xprintf(
UsrErr,
"Either 'script_string' or 'script_file' has to be specified in PythonField initialization.");
82 set_python_field_from_file( *it, rec.
val<
string>(
"function") );
88 template <
int spacedim,
class Value>
92 p_module_ = PythonLoader::load_module_from_file(
string(file_name) );
100 template <
int spacedim,
class Value>
104 char func_char[func_name.size()+2];
105 std::strcpy(func_char, func_name.c_str());
106 p_func_ = PyObject_GetAttrString(p_module_, func_char );
108 if (PyErr_Occurred()) PyErr_Print();
109 xprintf(
UsrErr,
"Field '%s' not found in the python module: %s\n", func_name.c_str(), PyModule_GetName(p_module_) );
111 Py_XDECREF(p_module_);
114 if (! PyCallable_Check(p_func_)) {
115 xprintf(
UsrErr,
"Field '%s' from the python module: %s is not callable.\n", func_name.c_str(), PyModule_GetName(p_module_) );
117 Py_XDECREF(p_module_);
121 p_args_ = PyTuple_New( spacedim );
124 for(
unsigned int i = 0; i < spacedim; i++) {
125 p_value_ = PyFloat_FromDouble(
double(i) );
126 PyTuple_SetItem(p_args_, i, p_value_);
128 p_value_ = PyObject_CallObject(p_func_, p_args_);
130 if (p_value_ == NULL) {
133 xprintf(
Err,
"Failed to call field '%s' from the python module: %s\n", func_name.c_str(), PyModule_GetName(p_module_) );
136 if ( ! PyTuple_Check( p_value_)) {
137 xprintf(
UsrErr,
"Field '%s' from the python module: %s doesn't return Tuple.\n", func_name.c_str(), PyModule_GetName(p_module_) );
140 unsigned int size = PyTuple_Size( p_value_);
142 unsigned int value_size=this->value_.n_rows() * this->value_.n_cols();
143 if ( size != value_size) {
144 xprintf(
UsrErr,
"Field '%s' from the python module: %s returns %d components but should return %d components.\n"
145 ,func_name.c_str(), PyModule_GetName(p_module_), size, value_size);
148 #endif // HAVE_PYTHON
155 template <
int spacedim,
class Value>
158 set_value(p,elm, this->value_);
159 return this->r_value_;
166 template <
int spacedim,
class Value>
171 for(
unsigned int i=0; i< point_list.size(); i++) {
172 Value envelope(value_list[i]);
173 ASSERT( envelope.n_rows()==this->value_.n_rows(),
174 "value_list[%d] has wrong number of rows: %d; should match number of components: %d\n",
175 i, envelope.n_rows(),this->value_.n_rows());
176 set_value(point_list[i], elm, envelope );
183 template <
int spacedim,
class Value>
187 for(
unsigned int i = 0; i < spacedim; i++) {
188 p_value_ = PyFloat_FromDouble( p[i] );
189 PyTuple_SetItem(p_args_, i, p_value_);
191 p_value_ = PyObject_CallObject(p_func_, p_args_);
193 if (p_value_ == NULL) {
199 for(
unsigned int row=0; row < value.n_rows(); row++)
200 for(
unsigned int col=0; col < value.n_cols(); col++, pos++)
201 if ( boost::is_integral< typename Value::element_type >::value ) value(row,col) = PyLong_AsLong( PyTuple_GetItem( p_value_, pos ) );
202 else value(row,col) = PyFloat_AsDouble( PyTuple_GetItem( p_value_, pos ) );
204 #endif // HAVE_PYTHON
210 template <
int spacedim,
class Value>
217 #endif // HAVE_PYTHON
void set_python_field_from_file(const FilePath &file_name, const string &func_name)
void set_func(const string &func_name)
void set_python_field_from_string(const string &python_source, const string &func_name)
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list)
void set_value(const Point &p, const ElementAccessor< spacedim > &elm, Value &value)
#define ASSERT_EQUAL(a, b)
FieldPython(unsigned int n_comp=0)
static Input::Type::Record get_input_type(Input::Type::AbstractRecord &a_type, const typename Value::ElementInputType *eit)
Space< spacedim >::Point Point
Dedicated class for storing path to input and output files.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm)
virtual void init_from_input(const Input::Record &rec)