OOFEM 3.0
Loading...
Searching...
No Matches
pythonexpression.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35#include <Python.h>
36
37#include "pythonexpression.h"
38#include "dynamicinputrecord.h"
39#include "classfactory.h"
40#include "error.h"
41
42#include <sstream>
43#include <iostream>
44#include <fstream>
45
46// Defines the name for the return variable;
47#define RETURN_VARIABLE "ret"
48
49namespace oofem {
51
52PythonExpression :: PythonExpression(int n, Domain *d) : Function(n, d) { }
53
54PythonExpression :: ~PythonExpression()
55{
57 //Py_DECREF(this->main_dict);
58}
59
60void
61PythonExpression :: initializeFrom(InputRecord &ir)
62{
63 Function :: initializeFrom(ir);
64
65 // Check if the f expression is given
68 } else {
69 std::string path;
71 this->readFile2String(path, this->fExpression);
72 }
73 this->f = Py_CompileString(fExpression.c_str(), "<internal_f>", Py_file_input);
74 if ( this->f == nullptr) {
75 PyErr_Print();
76 }
77
78 // Check if the dfdt expression is given
82 std::string path;
84 this->readFile2String(path, this->dfdtExpression);
85 }
86 this->dfdt = Py_CompileString(dfdtExpression.c_str(), "<internal_dfdt>", Py_file_input);
87 if ( this->dfdt == nullptr) {
88 PyErr_Print();
89 }
90
91 // Check if the d2fdt2 expression is given
95 std::string path;
97 this->readFile2String(path, this->d2fdt2Expression);
98 }
99 this->d2fdt2 = Py_CompileString(d2fdt2Expression.c_str(), "<internal_d2fdt2>", Py_file_input);
100 if ( this->d2fdt2 == nullptr) {
101 PyErr_Print();
102 }
103
105 if ( !main_dict ) {
106 PyObject *main_module = PyImport_ImportModule("__main__");
107 if (main_module != NULL) {
108 this->main_dict = PyModule_GetDict(main_module);
109 Py_DECREF(main_module); // Decrease reference count
110 } else {
111 // Handle error: could not import __main__ module
112 OOFEM_WARNING("Could not import __main__ module");
113 this->main_dict = PyDict_New();
114 }
115 }
116}
117
118
119void
120PythonExpression :: giveInputRecord(DynamicInputRecord &input)
121{
122 Function :: giveInputRecord(input);
126}
127
128
129PyObject *
130PythonExpression :: getDict(const std :: map< std :: string, FunctionArgument > &valDict)
131{
132 PyObject *local_dict = PyDict_New();
133 for ( const auto &named_arg: valDict ) {
134 const FunctionArgument &arg = named_arg.second;
135 PyObject *tmp;
136 if ( arg.type == FunctionArgument :: FAT_double ) {
137 tmp = PyFloat_FromDouble(arg.val0);
138 } else if ( arg.type == FunctionArgument :: FAT_FloatArray ) {
139 tmp = PyList_New( arg.val1.giveSize() );
140 for ( int i = 0; i < arg.val1.giveSize(); ++i ) {
141 PyList_SET_ITEM( tmp, i, PyFloat_FromDouble( arg.val1[i] ) );
142 }
143 } else if ( arg.type == FunctionArgument :: FAT_int ) {
144 tmp = PyLong_FromLong(arg.val2);
145 } else if ( arg.type == FunctionArgument :: FAT_IntArray ) {
146 tmp = PyList_New( arg.val3.giveSize() );
147 for ( int i = 0; i < arg.val3.giveSize(); ++i ) {
148 PyList_SET_ITEM( tmp, i, PyLong_FromLong( arg.val3[i] ) );
149 }
150 } else {
151 tmp = NULL;
152 OOFEM_ERROR("Unsupported FunctionArgumentType");
153 }
154 PyDict_SetItemString(local_dict, named_arg.first.c_str(), tmp);
155 }
156 return local_dict;
157}
158
159
160void
161PythonExpression :: getArray(FloatArray &answer, PyObject **func, const std :: map< std :: string, FunctionArgument > &valDict)
162{
163#ifdef _OPENMP
164#pragma omp critical
165#endif
166{
167 PyObject *local_dict = getDict(valDict);
168 PyObject *dummy = PyEval_EvalCode( *func, main_dict, local_dict );
169
170 if ( dummy == nullptr ) {
171 PyErr_Print();
172 }
173 PyObject *ret = PyDict_GetItemString(local_dict, RETURN_VARIABLE);
174 if ( PyList_Check(ret) ) {
175 int size = PyList_GET_SIZE(ret);
176 answer.resize(size);
177 for ( int i = 0; i < size; ++i ) {
178 answer(i) = this->pyObj2double( PyList_GET_ITEM(ret, i) );
179 }
180 } else {
181 answer = {this->pyObj2double(ret) };
182 }
183
184 Py_DECREF(local_dict);
185 Py_DECREF(dummy);
186 Py_DECREF(ret);
187}
188}
189
190
191void
192PythonExpression :: evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp, double param)
193{
194 this->getArray(answer, &this->f, valDict);
195}
196
197
198void
199PythonExpression :: evaluateVelocity(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict)
200{
201 this->getArray(answer, &this->dfdt, valDict);
202}
203
204
205void
206PythonExpression :: evaluateAcceleration(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict)
207{
208 this->getArray(answer, &this->d2fdt2, valDict);
209}
210
211
212double
213PythonExpression :: getScalar(PyObject *func, double time)
214{
215 PyObject *local_dict = PyDict_New();
216 PyDict_SetItemString( local_dict, "t", PyFloat_FromDouble(time) );
217 PyObject *dummy = PyEval_EvalCode( func, main_dict, local_dict );
218 double val = 0.;
219 PyObject *ret = PyDict_GetItemString(local_dict, RETURN_VARIABLE);
220 if ( PyNumber_Check(ret) ) {
221 val = pyObj2double(ret);
222 } else if ( PyList_Check(ret) ) {
223 if ( PyList_GET_SIZE(ret) != 1 ) {
224 OOFEM_ERROR("Result from python is not a real float!");
225 } else {
226 val = pyObj2double( PyList_GET_ITEM(ret, 0) );
227 }
228 } else {
229 OOFEM_ERROR("Result from python is not a real float!");
230 }
231
232 Py_DECREF(local_dict);
233 Py_DECREF(dummy);
234 Py_DECREF(ret);
235 return val;
236}
237
238
239double PythonExpression :: evaluateAtTime(double time)
240{
241 return this->getScalar(this->f, time);
242}
243
244double PythonExpression :: evaluateVelocityAtTime(double time)
245{
246 return this->getScalar(this->dfdt, time);
247}
248
249
250double PythonExpression :: evaluateAccelerationAtTime(double time)
251{
252 return this->getScalar(this->d2fdt2, time);
253}
254
255
257 if (PyNumber_Check(obj)) {
258 PyObject *float_obj = PyNumber_Float(obj);
259 if (float_obj != NULL) {
260 double result = PyFloat_AsDouble(float_obj);
261 Py_DECREF(float_obj); // Decrease reference count
262 return result;
263 }
264 }
265 // Handle error: object is not a number or conversion failed
266 return -1.0; // Or some other error indicator
267}
268
269
270void PythonExpression::readFile2String(const std::string &path, std::string &content) {
271 std::ifstream file(path);
272 if (file.is_open()) {
273 std::stringstream buffer;
274 buffer << file.rdbuf();
275 content = buffer.str();
276 file.close();
277 } else {
278 OOFEM_ERROR("Could not open file %s", path.c_str());
279 }
280}
281
282} // end namespace oofem
#define REGISTER_Function(class)
void setField(int item, InputFieldType id)
void resize(Index s)
Definition floatarray.C:94
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
FunctionArgumentType type
Determines which of the types the instance points towards.
Definition function.h:72
Function(int n, Domain *d)
Definition function.C:44
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
int giveSize() const
Definition intarray.h:211
double getScalar(PyObject *func, double time)
Helper function to run given function for given time.
void readFile2String(const std ::string &path, std ::string &content)
std::string d2fdt2Expression
Expression for second time derivative or path to python script.
double pyObj2double(PyObject *obj)
std::string dfdtExpression
Expression for first time derivative or path to python script.
PyObject * getDict(const std ::map< std ::string, FunctionArgument > &valDict)
Helper function to convert the std::map to a Python dictionary.
void getArray(FloatArray &answer, PyObject **func, const std ::map< std ::string, FunctionArgument > &valDict)
Helper function to run given function for given value dictionary.
std::string fExpression
Expression for the function value or path to python script.
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define RETURN_VARIABLE
#define _IFT_PythonExpression_d2fdt2file
Acceleration with return variable named "ret".
#define _IFT_PythonExpression_d2fdt2
Acceleration with return variable named "ret".
#define _IFT_PythonExpression_dfdtfile
Velocity with return variable named "ret".
#define _IFT_PythonExpression_f
Expression with return variable named "ret".
#define _IFT_PythonExpression_dfdt
Velocity with return variable named "ret".
#define _IFT_PythonExpression_ffile
Expression with return variable named "ret".
_object PyObject

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011