OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
cpp_python_funct.cpp File Reference
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <regex>
#include <iomanip>
#include <limits>
#include <dlfcn.h>
#include <dirent.h>
#include "cpp_python_funct.h"
#include "cpp_python_sampling.h"
#include "python_signal.h"

Go to the source code of this file.

Typedefs

typedef float my_real

Functions

template<std::size_t N>
std::string element_parenthesis_to_underscore (const std::string &input, const std::array< const char *, N > &keywords)
std::string node_parenthesis_to_underscore (const std::string &input)
std::string parenthesis_to_underscore (const std::string &input)
void extract_node_uid (const std::string &input)
void extract_element_keywords (const std::string &input)
template<typename T>
void load_functions (T h, bool &python_initialized)
void exit_with_message (const char *message)
void check_error (int line_number)
void python_signal_handler (int signum)
PyObjectcall_python_function_with_state (const char *func_name)
PyObjectcall_python_function (const char *func_name, double *args, int num_args)
void call_python_function1D_vectors (const char *func_name, std::vector< double > &X, std::vector< double > &Y)
void python_execute_code (const std::string &code)
std::string extract_function_name (const std::string &signature)
bool try_load_library (const std::string &path)
void python_load_library ()
void cpp_python_initialize (int *ierror)
void cpp_python_load_environment ()
void cpp_python_sync (void *pcontext)
void cpp_python_finalize ()
void cpp_python_execute_code (const char *code)
void cpp_python_initialize_global_variables ()
void cpp_python_register_function (char *name, char code[], int num_lines)
void cpp_python_call_function (char *name, int num_args, double *args, int num_return, double *return_values)
void cpp_python_call_function_with_state (char *name, double *return_values)
void cpp_python_check_function (char *name, int *error)
void cpp_python_update_reals (char *basename, int *uid, my_real *reals, int num_reals)
void cpp_python_update_time (my_real TIME, my_real DT)
void cpp_python_get_number_of_nodes (int *num_nodes)
void cpp_python_get_nodes (int *nodes_uid_array)
void cpp_python_create_node_mapping (int *itab, int *num_nodes)
void cpp_python_update_sensors (int *types, int *uids, int *statuses, double *results, int *num_sensors)
void cpp_python_update_active_node (int name_len, char *name, double *values)
void cpp_python_update_active_node_ids (int id, int uid)
void cpp_python_update_nodal_entity (int numnod, int name_len, char *name, my_real *values)
void cpp_python_update_elemental_entity (char *name, double value, int uid)
void cpp_python_get_number_elemental_entities (int *nb)
void cpp_python_get_elemental_entity (int nb, char *name, int *uid)
void cpp_python_sample_function (char *name, double *x, double *y, int n)
void cpp_python_add_ints_to_dict (void *context_ptr, const char *name, int len_name, int *values, int nvalues)
void cpp_python_add_doubles_to_dict (void *context_ptr, const char *name, int len_name, double *values, int nvalues)
void * cpp_python_create_context ()
void cpp_python_free_context (void *context)
PyThreadStatepy_begin_allow_threads ()
void py_end_allow_threads (PyThreadState *saved_state)

Variables

void * handle = nullptr
PyObjectpDict = nullptr
bool python_initialized = false
bool sync_enabled = false
std::set< int > nodes_uid
std::map< int, int > nodes_uid_to_local_id
KeywordPairs element_variables
static PyObjectpersistent_dict = nullptr
static PyObjectpersistent_arg = nullptr

Typedef Documentation

◆ my_real

typedef float my_real

Definition at line 49 of file cpp_python_funct.cpp.

Function Documentation

◆ call_python_function()

PyObject * call_python_function ( const char * func_name,
double * args,
int num_args )

Definition at line 322 of file cpp_python_funct.cpp.

323{
324 check_error(__LINE__);
325 PyObject *pFunc, *pArgs, *pValue;
326 pFunc = static_cast<PyObject *>(MyDict_GetItemString(pDict, func_name));
327 if (MyCallable_Check(pFunc))
328 {
329 check_error(__LINE__);
330 pArgs = static_cast<PyObject *>(MyTuple_New(num_args));
331 for (size_t i = 0; i < num_args; i++)
332 {
333 MyTuple_SetItem(pArgs, i, static_cast<PyObject *>(MyFloat_FromDouble(args[i])));
334 }
335 check_error(__LINE__);
336 pValue = static_cast<PyObject *>(MyObject_CallObject(pFunc, pArgs));
337 check_error(__LINE__);
338 My_DecRef(pArgs);
339 if (pValue != nullptr)
340 {
341 // Function executed successfully
342 }
343 else
344 {
345 // convert func_name to a string
346 std::string func_name_str(func_name);
347 std::cout << "ERROR in Python function " << func_name_str << ": function execution failed" << std::endl;
348 if (MyErr_Occurred())
349 {
350 // Fetch the error
351 PyObject *pType = nullptr, *pValue = nullptr, *pTraceback = nullptr;
352 MyErr_Fetch(&pType, &pValue, &pTraceback);
353 if (pType)
354 std::cout<<"[PYTHON]"<< MyUnicode_AsUTF8(MyObject_Str(pType)) << std::endl;
355 if (pValue)
356 std::cout<<"[PYTHON]"<< MyUnicode_AsUTF8(MyObject_Str(pValue)) << std::endl;
357 if (pTraceback)
358 std::cout<<"[PYTHON]"<< MyUnicode_AsUTF8(MyObject_Str(pTraceback)) << std::endl;
359
360 // Print the error
361 //MyErr_Display(pType, pValue, pTraceback);
362 // Decrement reference counts for the error objects
363 My_DecRef(pType);
364 My_DecRef(pValue);
365 My_DecRef(pTraceback);
366 exit_with_message("ERROR: Python function failed");
367 }
368 }
369
370 return pValue;
371 }
372 std::cout << "ERROR in Python function: cannot call function: " << func_name << std::endl;
373 return nullptr;
374}
void exit_with_message(const char *message)
void check_error(int line_number)
PyObject * pDict
T_Py_DecRef My_DecRef
T_PyTuple_SetItem MyTuple_SetItem
T_PyCallable_Check MyCallable_Check
void * PyObject
T_PyUnicode_AsUTF8 MyUnicode_AsUTF8
T_PyDict_GetItemString MyDict_GetItemString
T_PyErr_Occurred MyErr_Occurred
T_PyErr_Fetch MyErr_Fetch
T_PyTuple_New MyTuple_New
T_PyObject_CallObject MyObject_CallObject
T_PyObject_Str MyObject_Str
T_PyFloat_FromDouble MyFloat_FromDouble

◆ call_python_function1D_vectors()

void call_python_function1D_vectors ( const char * func_name,
std::vector< double > & X,
std::vector< double > & Y )

Definition at line 376 of file cpp_python_funct.cpp.

377{
378 PyObject *pFunc, *pArgs, *pValue;
379 const int num_args = X.size();
380 pFunc = static_cast<PyObject *>(MyDict_GetItemString(pDict, func_name));
381 if (MyCallable_Check(pFunc))
382 {
383 for (size_t i = 0; i < num_args; i++)
384 {
385 pArgs = static_cast<PyObject *>(MyTuple_New(1));
386 MyTuple_SetItem(pArgs, 0, static_cast<PyObject *>(MyFloat_FromDouble(X[i])));
387 pValue = static_cast<PyObject *>(MyObject_CallObject(pFunc, pArgs));
388 My_DecRef(pArgs);
389
390 if (pValue != nullptr)
391 {
392 // Function executed successfully
393 Y[i]= (MyFloat_AsDouble(pValue));
394 My_DecRef(pValue);
395 }
396 else
397 {
398 MyErr_Clear();
399 Y[i] = static_cast<double>(std::numeric_limits<float>::max());
400 }
401// std::cout<<"X["<<i<<"] = "<<X[i]<<" Y["<<i<<"] = "<<Y[i]<<std::endl;
402 }
403 }
404}
T_PyErr_Clear MyErr_Clear
T_PyFloat_AsDouble MyFloat_AsDouble

◆ call_python_function_with_state()

PyObject * call_python_function_with_state ( const char * func_name)

Definition at line 248 of file cpp_python_funct.cpp.

249{
250 PyObject *pFunc, *pValue;
252 // Retrieve the Python function from the module dictionary
253 pFunc = static_cast<PyObject *>(MyDict_GetItemString(pDict, func_name));
254 if (MyCallable_Check(pFunc))
255 {
256 // Initialize persistent dictionary on the first call
257 if (!persistent_dict)
258 {
260 if (!persistent_dict)
261 {
262 std::cout << "ERROR: Failed to create persistent dictionary." << std::endl;
263 return nullptr;
264 }
265 // Create a tuple to hold the single dictionary argument
266 persistent_arg = static_cast<PyObject *>(MyTuple_New(1)); // Only 1 argument: the dictionary
267 if (!persistent_arg)
268 {
269 std::cout << "ERROR: Failed to create argument tuple." << std::endl;
270 return nullptr;
271 }
272
273 MyTuple_SetItem(persistent_arg, 0, persistent_dict); // Borrowed reference to persistent_dict Is this the problem????
274 }
275
276 // Set the dictionary in the tuple
277
278 // Call the Python function
279 pValue = static_cast<PyObject *>(MyObject_CallObject(pFunc, persistent_arg)); // segmentation fault here
280
281 if (pValue != nullptr)
282 {
283 // Function executed successfully
284 // Optionally handle the result (if required)
285 }
286 else
287 {
288 // Handle Python exception
289 std::string func_name_str(func_name);
290 std::cout << "ERROR in Python function " << func_name_str << ": function execution failed" << std::endl;
291 if (MyErr_Occurred())
292 {
293 // Fetch the error details
294 PyObject *pType, *pValue, *pTraceback;
295 MyErr_Fetch(&pType, &pValue, &pTraceback);
296 if (pType)
297 std::cout << "[PYTHON] " << MyUnicode_AsUTF8(MyObject_Str(pType)) << std::endl;
298 if (pValue)
299 std::cout << "[PYTHON] " << MyUnicode_AsUTF8(MyObject_Str(pValue)) << std::endl;
300 if (pTraceback)
301 std::cout << "[PYTHON]: " << MyUnicode_AsUTF8(MyObject_Str(pTraceback)) << std::endl;
302
303 // Print the error
304 //MyErr_Display(pType, pValue, pTraceback);
305
306 // Decrement reference counts for error objects
307 My_DecRef(pType);
308 My_DecRef(pValue);
309 My_DecRef(pTraceback);
310 exit_with_message("ERROR: Python function failed");
311 }
312 }
314 return pValue;
315 }
316
317 std::cout << "ERROR in Python function: cannot call function: " << func_name << std::endl;
318 return nullptr;
319}
void python_signal_handler(int signum)
static PyObject * persistent_arg
static PyObject * persistent_dict
T_PyDict_New MyDict_New
void activate_signal_handling(SignalHandler handler, int signal=SIGINT)
void restore_default_signal_handling(int signal=SIGINT)

◆ check_error()

void check_error ( int line_number)

Definition at line 209 of file cpp_python_funct.cpp.

210{
211 if (MyErr_Occurred())
212 {
213 //std::cout<<"Error at line: "<<line_number<<std::endl;
214 // Fetch the error
215 PyObject *pType = nullptr, *pValue = nullptr, *pTraceback = nullptr;
216 MyErr_Fetch(&pType, &pValue, &pTraceback);
217 if (pType)
218 std::cout<<"[PYTHON]"<< MyUnicode_AsUTF8(MyObject_Str(pType)) << std::endl;
219 if (pValue)
220 std::cout<<"[PYTHON]"<< MyUnicode_AsUTF8(MyObject_Str(pValue)) << std::endl;
221 if (pTraceback)
222 std::cout<<"[PYTHON]"<< MyUnicode_AsUTF8(MyObject_Str(pTraceback)) << std::endl;
223
224 // Print the error
225 //MyErr_Display(pType, pValue, pTraceback);
226 // Decrement reference counts for the error objects
227 My_DecRef(pType);
228 My_DecRef(pValue);
229 My_DecRef(pTraceback);
230 exit_with_message("ERROR: Python function failed");
231 }
232}

◆ cpp_python_add_doubles_to_dict()

void cpp_python_add_doubles_to_dict ( void * context_ptr,
const char * name,
int len_name,
double * values,
int nvalues )

Definition at line 1438 of file cpp_python_funct.cpp.

1439{ // expose the array without copying
1440 if (!python_initialized)
1441 {
1442 return;
1443 }
1444 check_error(__LINE__);
1445 PyObject * context = static_cast<PyObject*>(context_ptr);
1446 char ptr_key[100],size_key[100],type_key[100];
1447 snprintf(ptr_key, sizeof(ptr_key), "%s_ptr", name);
1448 snprintf(size_key, sizeof(size_key), "%s_size", name);
1449 snprintf(type_key, sizeof(type_key), "%s_type", name);
1450 PyObject* ptr_value = MyLong_FromVoidPtr(values);
1451 PyObject* size_value = MyLong_FromLong(static_cast<long>(nvalues));
1452 PyObject* type_value = MyUnicode_FromString("double");
1453 // set the values in the context dictionary
1454 MyDict_SetItemString(context, ptr_key, ptr_value);
1455 MyDict_SetItemString(context, size_key, size_value);
1456 MyDict_SetItemString(context, type_key, type_value);
1457 // release the references
1458 My_DecRef(ptr_value);
1459 My_DecRef(size_value);
1460 My_DecRef(type_value);
1461 check_error(__LINE__);
1462}
bool python_initialized
T_PyLong_FromLong MyLong_FromLong
T_PyLong_FromVoidPtr MyLong_FromVoidPtr
T_PyUnicode_FromString MyUnicode_FromString
T_PyDict_SetItemString MyDict_SetItemString

◆ cpp_python_add_ints_to_dict()

void cpp_python_add_ints_to_dict ( void * context_ptr,
const char * name,
int len_name,
int * values,
int nvalues )

Definition at line 1409 of file cpp_python_funct.cpp.

1410{ // expose the array without copying
1411 if (!python_initialized)
1412 {
1413 return;
1414 }
1415 check_error(__LINE__);
1416 PyObject * context = static_cast<PyObject*>(context_ptr);
1417 char ptr_key[100],size_key[100],type_key[100];
1418 snprintf(ptr_key, sizeof(ptr_key), "%s_ptr", name);
1419 snprintf(size_key, sizeof(size_key), "%s_size", name);
1420 snprintf(type_key, sizeof(type_key), "%s_type", name);
1421 PyObject* ptr_value = MyLong_FromVoidPtr(values);
1422 PyObject* size_value = MyLong_FromLong(static_cast<long>(nvalues));
1423 PyObject* type_value = MyUnicode_FromString("int");
1424
1425 // set the values in the context dictionary
1426 MyDict_SetItemString(context, ptr_key, ptr_value);
1427 MyDict_SetItemString(context, size_key, size_value);
1428 MyDict_SetItemString(context, type_key, type_value);
1429
1430 // release the references
1431 My_DecRef(ptr_value);
1432 My_DecRef(size_value);
1433 My_DecRef(type_value);
1434 check_error(__LINE__);
1435
1436}

◆ cpp_python_call_function()

void cpp_python_call_function ( char * name,
int num_args,
double * args,
int num_return,
double * return_values )

Definition at line 916 of file cpp_python_funct.cpp.

917 {
919 {
920 return;
921 }
922 //GIL
924 check_error(__LINE__);
925 if (strcmp(name, "initialize_environment") == 0) return;
926 PyObject *result = call_python_function(name, args, num_args);
927 if (result)
928 {
929 return_values[0] = MyFloat_AsDouble(result);
930 My_DecRef(result);
931 } else
932 {
933 exit_with_message("ERROR: Python function failed");
934 }
935 check_error(__LINE__);
936 MyGILState_Release(gstate);
937 }
PyObject * call_python_function(const char *func_name, double *args, int num_args)
T_PyGILState_Release MyGILState_Release
int PyGILState_STATE
T_PyGILState_Ensure MyGILState_Ensure

◆ cpp_python_call_function_with_state()

void cpp_python_call_function_with_state ( char * name,
double * return_values )

Definition at line 939 of file cpp_python_funct.cpp.

940 {
942 {
943 return;
944 }
946 check_error(__LINE__);
948 if (result)
949 {
950 *return_values = MyFloat_AsDouble(result);
951 My_DecRef(result);
952 } else {
953 exit_with_message("ERROR: Python function failed");
954 }
955 check_error(__LINE__);
956 MyGILState_Release(gstate);
957 }
PyObject * call_python_function_with_state(const char *func_name)

◆ cpp_python_check_function()

void cpp_python_check_function ( char * name,
int * error )

Definition at line 959 of file cpp_python_funct.cpp.

960 {
961 PyObject *pFunc;
962 // std::cout << "Checking if function exists: " << name << std::endl;
964 {
965 pFunc = static_cast<PyObject *>(MyDict_GetItemString(pDict, name));
966 if (MyCallable_Check(pFunc))
967 {
968 *error = 0;
969 }
970 else
971 {
972 *error = 1;
973 }
974 }
975 else
976 {
977 *error = 1;
978 }
979
980 // std::cout << "Function exists? " << *error << std::endl;
981 }

◆ cpp_python_create_context()

void * cpp_python_create_context ( )

Definition at line 1466 of file cpp_python_funct.cpp.

1466 {
1467 check_error(__LINE__);
1468 PyObject* context = MyDict_New();
1469 if (!context) {
1470 return NULL;
1471 }
1472 return context;
1473 check_error(__LINE__);
1474}

◆ cpp_python_create_node_mapping()

void cpp_python_create_node_mapping ( int * itab,
int * num_nodes )

Definition at line 1085 of file cpp_python_funct.cpp.

1086 {
1087 // print number of nodes and python_initialized
1088 // std::cout << "Number of nodes: " << *num_nodes << " python_initialized" << python_initialized << std::endl;
1090 {
1091 // loop over the set
1092 for (auto node_uid : nodes_uid)
1093 {
1094 // find i such that itab[i] = node_uid
1095 bool found = false;
1096 for (int i = 0; i < *num_nodes; i++)
1097 {
1098 if (itab[i] == node_uid)
1099 {
1100 nodes_uid_to_local_id[node_uid] = i;
1101 // std::cout << "Node uid: " << node_uid << " local id: " << i << std::endl;
1102 found = true;
1103 break;
1104 }
1105 }
1106 if (!found)
1107 {
1108 std::cout << "Node uid: " << node_uid << " not found in itab" << std::endl;
1109 }
1110 }
1111 check_error(__LINE__);
1112 }
1113 }
std::map< int, int > nodes_uid_to_local_id
std::set< int > nodes_uid

◆ cpp_python_execute_code()

void cpp_python_execute_code ( const char * code)

Definition at line 777 of file cpp_python_funct.cpp.

778 {
779 MyRun_SimpleString(code);
780 check_error(__LINE__);
781
782 }
T_PyRun_SimpleString MyRun_SimpleString

◆ cpp_python_finalize()

void cpp_python_finalize ( )

Definition at line 773 of file cpp_python_funct.cpp.

774 {
775 My_Finalize();
776 }
T_Py_Finalize My_Finalize

◆ cpp_python_free_context()

void cpp_python_free_context ( void * context)

Definition at line 1476 of file cpp_python_funct.cpp.

1476 {
1477 if (context) {
1478 My_DecRef(static_cast<PyObject*>(context));
1479 }
1480}

◆ cpp_python_get_elemental_entity()

void cpp_python_get_elemental_entity ( int nb,
char * name,
int * uid )

Definition at line 1344 of file cpp_python_funct.cpp.

1345 {
1346 size_t n = static_cast<size_t>(nb - 1);
1348 for (int i = 0; i < max_variable_length; i++)
1349 {
1350 name[i] = '\0';
1351 }
1352 // copy user id
1353 *uid = p.first;
1354 // copy variable name
1355#ifdef _WIN64
1356 strcpy_s(name, max_variable_length, p.second);
1357#else
1358 strcpy(name, p.second);
1359#endif
1360 }
KeywordPairs element_variables
KeywordPair get_keyword_pair(const KeywordPairs &keywordPairs, size_t n)
#define max_variable_length
std::pair< int, const char * > KeywordPair
n

◆ cpp_python_get_nodes()

void cpp_python_get_nodes ( int * nodes_uid_array)

Definition at line 1071 of file cpp_python_funct.cpp.

1072 {
1074 {
1075 int i = 0;
1076 for (auto node_uid : nodes_uid)
1077 {
1078 // std::cout << "Node uid: " << node_uid << std::endl;
1079 nodes_uid_array[i] = node_uid;
1080 i++;
1081 }
1082 }
1083 }

◆ cpp_python_get_number_elemental_entities()

void cpp_python_get_number_elemental_entities ( int * nb)

Definition at line 1339 of file cpp_python_funct.cpp.

1340 {
1341 *nb = element_variables.size();
1342 }

◆ cpp_python_get_number_of_nodes()

void cpp_python_get_number_of_nodes ( int * num_nodes)

Definition at line 1057 of file cpp_python_funct.cpp.

1058 {
1059 if (!python_initialized)
1060 {
1061 *num_nodes = 0;
1062 }
1063 else
1064 {
1065 *num_nodes = nodes_uid.size();
1066 }
1067
1068 }

◆ cpp_python_initialize()

void cpp_python_initialize ( int * ierror)

Definition at line 640 of file cpp_python_funct.cpp.

641 {
643 { // already initialized
644 return;
645 }
646 // if ierror = 1 on entry, then "-python" is missing from the starter command line, and we will not execute any python code
647 if (*ierror == 1)
648 return;
649 *ierror = 1;
650 // Load Python dynamic library
653 {
654 pDict = MyModule_GetDict(MyImport_AddModule("__main__")); // Get the main module dictionary
655 if (!pDict)
656 {
657 std::cout << "ERROR in Python: fetching main module dictionary" << std::endl;
658 return;
659 }
660 int result = MyRun_SimpleString("import math"); // Import the math module for sin and other functions
661 if (result != 0)
662 {
663 std::cerr << "ERROR: Failed to import math module in Python." << std::endl;
664 // Print Python error traceback
665 if (MyErr_Occurred())
666 {
667 // Fetch the error details
668 PyObject *pType, *pValue, *pTraceback;
669 MyErr_Fetch(&pType, &pValue, &pTraceback);
670 if (pType)
671 std::cout << "[PYTHON] " << MyUnicode_AsUTF8(MyObject_Str(pType)) << std::endl;
672 if (pValue)
673 std::cout << "[PYTHON] " << MyUnicode_AsUTF8(MyObject_Str(pValue)) << std::endl;
674 if (pTraceback)
675 std::cout << "[PYTHON]: " << MyUnicode_AsUTF8(MyObject_Str(pTraceback)) << std::endl;
676
677 // Print the error
678 //MyErr_Display(pType, pValue, pTraceback);
679
680 // Decrement reference counts for error objects
681 My_DecRef(pType);
682 My_DecRef(pValue);
683 My_DecRef(pTraceback);
684 exit_with_message("ERROR: Python function failed");
685 }
686 }else
687 {
688 *ierror = 0;
689 }
690 check_error(__LINE__);
691 }
692 }
void python_load_library()
T_PyModule_GetDict MyModule_GetDict
T_PyImport_AddModule MyImport_AddModule

◆ cpp_python_initialize_global_variables()

void cpp_python_initialize_global_variables ( )

Definition at line 784 of file cpp_python_funct.cpp.

785 {
787 {
788 return;
789 }
790 // initialize TIME and DT to 0
791 check_error(__LINE__);
792
793
794 PyObject *py_TIME = static_cast<PyObject *>(MyFloat_FromDouble(0.0));
795 PyObject *py_DT = static_cast<PyObject *>(MyFloat_FromDouble(0.0));
796 MyDict_SetItemString(pDict, "TIME", py_TIME);
797 MyDict_SetItemString(pDict, "DT", py_DT);
798
799 // loop over the set of nodes
800 for (auto node_uid : nodes_uid)
801 {
802 std::string entity_names[] = {"C", "D", "V", "A", "VR", "AR", "DR"};
803 for (auto name : entity_names)
804 {
805 const double x_values = static_cast<double>(1);
806 const double y_values = static_cast<double>(1);
807 const double z_values = static_cast<double>(1);
808 PyObject *py_x_values = static_cast<PyObject *>(MyFloat_FromDouble(x_values));
809 PyObject *py_y_values = static_cast<PyObject *>(MyFloat_FromDouble(y_values));
810 PyObject *py_z_values = static_cast<PyObject *>(MyFloat_FromDouble(z_values));
811 if (!py_x_values || !py_y_values || !py_z_values)
812 {
813 std::cout << "ERROR: Failed to create Python objects from C++ doubles." << std::endl;
814 return;
815 }
816 std::string x_name = name + "X_" + std::to_string(node_uid);
817 std::string y_name = name + "Y_" + std::to_string(node_uid);
818 std::string z_name = name + "Z_" + std::to_string(node_uid);
819 // std::cout<<" write to python: "<<x_name<<" "<<y_name<<" "<<z_name<<std::endl;
820 MyDict_SetItemString(pDict, x_name.c_str(), py_x_values);
821 MyDict_SetItemString(pDict, y_name.c_str(), py_y_values);
822 MyDict_SetItemString(pDict, z_name.c_str(), py_z_values);
823 // Release the Python objects
824 if (py_x_values != nullptr)
825 My_DecRef(py_x_values);
826 if (py_y_values != nullptr)
827 My_DecRef(py_y_values);
828 if (py_z_values != nullptr)
829 My_DecRef(py_z_values);
830 }
831 }
832 // Initialize all elements keywords to 1
833 for (auto p : element_variables)
834 {
835 double v = static_cast<double>(1);
836 PyObject *py_value = static_cast<PyObject *>(MyFloat_FromDouble(v));
837 if (!py_value)
838 {
839 std::cout << "ERROR: Failed to create Python objects from C++ doubles." << std::endl;
840 }
841 // convert p.second (const char *) to std::string
842 std::string keyword(p.second);
843 std::string sname = keyword + "_" + std::to_string(p.first);
844 MyDict_SetItemString(pDict, sname.c_str(), py_value);
845 if (py_value != nullptr)
846 My_DecRef(py_value);
847 }
848 check_error(__LINE__);
849
850 }

◆ cpp_python_load_environment()

void cpp_python_load_environment ( )

Definition at line 693 of file cpp_python_funct.cpp.

694 {
696 {
697 return;
698 }
699 check_error(__LINE__);
700 const char *code =
701 "if 'initialize_environment' in globals():\n"
702 " initialize_environment()\n";
703 int result = MyRun_SimpleString(code);
704 check_error(__LINE__);
705 }

◆ cpp_python_register_function()

void cpp_python_register_function ( char * name,
char code[],
int num_lines )

Definition at line 853 of file cpp_python_funct.cpp.

854 {
855 std::string tmp_string;
856 int current_line = 0;
857 std::stringstream function_code;
858
860 {
861 std::cout << "ERROR: Python not initialized" << std::endl;
862 std::cout << "Make sure that the following python code is safe" << std::endl;
863 std::cout << "and rerun the starter with the -python option." << std::endl;
864 }
865
866 for (int i = 0; current_line < num_lines;)
867 {
868 tmp_string.clear();
869 // Extract characters into the temporary string until a null character is found
870 while (code[i] != '\0')
871 {
872 tmp_string += code[i];
873 i++;
874 }
875 if (current_line == 0)
876 {
877 std::string function_name = extract_function_name(tmp_string);
878 if(function_name == "sync") sync_enabled = true;
879 if (function_name.empty())
880 {
881 std::cout << "ERROR: function name not found in function signature" << std::endl;
882 return;
883 }
884// copy function_name into argument name
885#ifdef _WIN64
886 strcpy_s(name, max_line_length, function_name.c_str());
887#else
888 strcpy(name, function_name.c_str());
889#endif
890 // add the null char at the end of the string
891 name[function_name.size()] = '\0';
892 }
893
894 const std::string s = parenthesis_to_underscore(tmp_string);
896
898 function_code << s << std::endl; // Add the line to the function code
899 i++; // Move past the null character
900 current_line++;
901 }
903 {
904 // initialize the global variables found in the python function
906 python_execute_code(function_code.str());
907 }
908 else
909 {
910 // print the python function to stdout and stderr
911 std::cout << function_code.str() << std::endl;
912 }
913 }
std::string parenthesis_to_underscore(const std::string &input)
void cpp_python_initialize_global_variables()
void extract_element_keywords(const std::string &input)
void python_execute_code(const std::string &code)
std::string extract_function_name(const std::string &signature)
bool sync_enabled
void extract_node_uid(const std::string &input)
#define max_line_length

◆ cpp_python_sample_function()

void cpp_python_sample_function ( char * name,
double * x,
double * y,
int n )

Definition at line 1362 of file cpp_python_funct.cpp.

1363 {
1364 //write the name
1365 constexpr size_t N = 10000; // Number of points
1366 double x_max = 1e+6;
1367 std::vector<double> Xtmp = initial_sampling(x_max,N);
1368 std::vector<double> X(2*N, 0.0);
1369 double scale = x_max / N;
1370
1371 // X = -Xtmp(N) .. -Xtmp(1) Xtmp(1) .. Xtmp(N)
1372 for (size_t i = 0; i < N; i++)
1373 {
1374 X[i] = -scale * Xtmp[N - i - 1];
1375 }
1376 for (size_t i = 0; i < N; i++)
1377 {
1378 X[i + N] = scale * Xtmp[i];
1379 }
1380 // I would like to symmetrically sample the function around 0, so I will sample the function at -X and X
1381 //Y of size N, filled with 0
1382 std::vector<double> Y(X.size(), 0.0);
1383 // evaluate the function at all X values using cpp_
1385 //Sample the function to get n points:
1386 std::vector<double> new_x = select_points(X,Y,size_t(n));
1387 std::vector<double> new_y(n, 0.0);
1388 call_python_function1D_vectors(name, new_x, new_y);
1389 //sizes:
1390 // copy the values to the output arrays
1391 for (int i = 0; i < n; i++)
1392 {
1393 x[i] = static_cast<my_real>(new_x[i]);
1394 y[i] = static_cast<my_real>(new_y[i]);
1395 }
1396 }
void call_python_function1D_vectors(const char *func_name, std::vector< double > &X, std::vector< double > &Y)
std::vector< double > initial_sampling(double x_max, size_t n)
std::vector< double > select_points(const std::vector< double > &x, const std::vector< double > &F_values, size_t n_points)
#define my_real
Definition cppsort.cpp:32
#define N

◆ cpp_python_sync()

void cpp_python_sync ( void * pcontext)

Definition at line 707 of file cpp_python_funct.cpp.

708 {
709
710 //std::cout<<"[PYTHON] cpp_python_sync called"<<std::endl;
712 {
713 return;
714 }
715 check_error(__LINE__);
716
717 // cast the context to a double pointer as a PyObject
718 char func_name[100];
719 // func_name = "sync"
720 func_name[0] = 's';
721 func_name[1] = 'y';
722 func_name[2] = 'n';
723 func_name[3] = 'c';
724 func_name[4] = '\0';
725 //std::cout<<"[PYTHON] cpp_python_sync called with function name: "<<func_name<<std::endl;
726
727 PyObject *context = static_cast<PyObject *>(pcontext);
729 if(!args)
730 {
731 std::cout << "ERROR: Failed to create Python tuple." << std::endl;
732 }
733 My_IncRef(context);
734 MyTuple_SetItem(args, 0, context); // This steals the reference
735 PyObject *pFunc = static_cast<PyObject *>(MyDict_GetItemString(pDict, func_name));
736 if (!pFunc)
737 {
738 std::cout << "ERROR: Python function not found: " << func_name << std::endl;
739 My_DecRef(args);
740 }
741
742 if (!MyCallable_Check(pFunc)) {
743 std::cerr << "[PYTHON] Error: '" << func_name << "' is not callable" << std::endl;
744 My_DecRef(args);
745 }
746
747 PyObject* result = MyObject_CallObject(pFunc, args);
748 if (MyErr_Occurred())
749 {
750 // Fetch the error details
751 PyObject *pType, *pValue, *pTraceback;
752 MyErr_Fetch(&pType, &pValue, &pTraceback);
753 if (pType)
754 std::cout << "[PYTHON] " << MyUnicode_AsUTF8(MyObject_Str(pType)) << std::endl;
755 if (pValue)
756 std::cout << "[PYTHON] " << MyUnicode_AsUTF8(MyObject_Str(pValue)) << std::endl;
757 if (pTraceback)
758 std::cout << "[PYTHON]: " << MyUnicode_AsUTF8(MyObject_Str(pTraceback)) << std::endl;
759
760 // Decrement reference counts for error objects
761 My_DecRef(pType);
762 My_DecRef(pValue);
763 My_DecRef(pTraceback);
764 exit_with_message("ERROR: Python function failed");
765 }
766
767 My_DecRef(args);
768 check_error(__LINE__);
769
770 }
T_Py_IncRef My_IncRef

◆ cpp_python_update_active_node()

void cpp_python_update_active_node ( int name_len,
char * name,
double * values )

Definition at line 1212 of file cpp_python_funct.cpp.

1213 {
1214 if (!python_initialized)
1215 {
1216 return;
1217 }
1218 check_error(__LINE__);
1219 double x_values, y_values, z_values;
1220 // loop over the map nodes_uid_to_local_id
1221 {
1222 x_values = static_cast<double>(values[0]);
1223 y_values = static_cast<double>(values[1]);
1224 z_values = static_cast<double>(values[2]);
1225 PyObject *py_x_values = static_cast<PyObject *>(MyFloat_FromDouble(x_values));
1226 PyObject *py_y_values = static_cast<PyObject *>(MyFloat_FromDouble(y_values));
1227 PyObject *py_z_values = static_cast<PyObject *>(MyFloat_FromDouble(z_values));
1228 if (!py_x_values || !py_y_values || !py_z_values)
1229 {
1230 std::cout << "ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1231 return;
1232 }
1233 // Set the Python global variables in the main module's dictionary
1234 std::string x_name = std::string(name) + "X_ACTIVE_NODE";
1235 std::string y_name = std::string(name) + "Y_ACTIVE_NODE";
1236 std::string z_name = std::string(name) + "Z_ACTIVE_NODE";
1237 // std::cout<<" write to python: "<<x_name<<" "<<y_name<<" "<<z_name<<std::endl;
1238 MyDict_SetItemString(pDict, x_name.c_str(), py_x_values);
1239 MyDict_SetItemString(pDict, y_name.c_str(), py_y_values);
1240 MyDict_SetItemString(pDict, z_name.c_str(), py_z_values);
1241 // Release the Python objects
1242 if (py_x_values != nullptr)
1243 My_DecRef(py_x_values);
1244 if (py_y_values != nullptr)
1245 My_DecRef(py_y_values);
1246 if (py_z_values != nullptr)
1247 My_DecRef(py_z_values);
1248 check_error(__LINE__);
1249
1250 }
1251 }

◆ cpp_python_update_active_node_ids()

void cpp_python_update_active_node_ids ( int id,
int uid )

Definition at line 1252 of file cpp_python_funct.cpp.

1253 { // set ACTIVE_NODE as id, and ACTIVE_NODE_UID as uid
1254 if (!python_initialized)
1255 {
1256 return;
1257 }
1258 check_error(__LINE__);
1259 // Set the Python global variables in the main module's dictionary
1260 std::string id_name = "ACTIVE_NODE";
1261 std::string uid_name = "ACTIVE_NODE_UID";
1262 MyDict_SetItemString(pDict, id_name.c_str(), static_cast<PyObject *>(MyLong_FromLong(static_cast<long>(id))));
1263 MyDict_SetItemString(pDict, uid_name.c_str(), static_cast<PyObject *>(MyLong_FromLong(static_cast<long>(uid))));
1264 check_error(__LINE__);
1265
1266 }

◆ cpp_python_update_elemental_entity()

void cpp_python_update_elemental_entity ( char * name,
double value,
int uid )

Definition at line 1321 of file cpp_python_funct.cpp.

1322 {
1323 double v = static_cast<double>(value);
1324 check_error(__LINE__);
1325 PyObject *py_value = static_cast<PyObject *>(MyFloat_FromDouble(v));
1326 if (!py_value)
1327 {
1328 std::cout << "ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1329 }
1330 std::string sname = std::string(name) + "_" + std::to_string(uid);
1331 // std::cout<<"[PYTHON] update elemental entity: "<<sname<<" value: "<<v<<std::endl;
1332 MyDict_SetItemString(pDict, sname.c_str(), py_value);
1333 if (py_value != nullptr)
1334 My_DecRef(py_value);
1335 check_error(__LINE__);
1336 }

◆ cpp_python_update_nodal_entity()

void cpp_python_update_nodal_entity ( int numnod,
int name_len,
char * name,
my_real * values )

Definition at line 1270 of file cpp_python_funct.cpp.

1271 {
1272 if (!python_initialized)
1273 {
1274 return;
1275 }
1276
1277 check_error(__LINE__);
1278 double x_values, y_values, z_values;
1279 // loop over the map nodes_uid_to_local_id
1280 for (auto it = nodes_uid_to_local_id.begin(); it != nodes_uid_to_local_id.end(); ++it)
1281 {
1282 int node_uid = it->first;
1283 int local_id = it->second;
1284 if(local_id > numnod-1)
1285 {
1286 std::cout << "ERROR: local_id " << local_id << " is greater than numnod " << numnod << std::endl;
1287 return;
1288 }
1289 x_values = static_cast<double>(values[3 * local_id]);
1290 y_values = static_cast<double>(values[3 * local_id + 1]);
1291 z_values = static_cast<double>(values[3 * local_id + 2]);
1292 PyObject *py_x_values = static_cast<PyObject *>(MyFloat_FromDouble(x_values));
1293 PyObject *py_y_values = static_cast<PyObject *>(MyFloat_FromDouble(y_values));
1294 PyObject *py_z_values = static_cast<PyObject *>(MyFloat_FromDouble(z_values));
1295 if (!py_x_values || !py_y_values || !py_z_values)
1296 {
1297 std::cout << "ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1298 return;
1299 }
1300 // Set the Python global variables in the main module's dictionary
1301 std::string x_name = std::string(name) + "X_" + std::to_string(node_uid);
1302 std::string y_name = std::string(name) + "Y_" + std::to_string(node_uid);
1303 std::string z_name = std::string(name) + "Z_" + std::to_string(node_uid);
1304 // std::cout<<" write to python: "<<x_name<<" "<<y_name<<" "<<z_name<<std::endl;
1305 MyDict_SetItemString(pDict, x_name.c_str(), py_x_values);
1306 MyDict_SetItemString(pDict, y_name.c_str(), py_y_values);
1307 MyDict_SetItemString(pDict, z_name.c_str(), py_z_values);
1308 // Release the Python objects
1309 if (py_x_values != nullptr)
1310 My_DecRef(py_x_values);
1311 if (py_y_values != nullptr)
1312 My_DecRef(py_y_values);
1313 if (py_z_values != nullptr)
1314 My_DecRef(py_z_values);
1315
1316 check_error(__LINE__);
1317 }
1318 }

◆ cpp_python_update_reals()

void cpp_python_update_reals ( char * basename,
int * uid,
my_real * reals,
int num_reals )

Definition at line 983 of file cpp_python_funct.cpp.

984 {
985 // add BASENAME_$UID = reals[i] to the python dictionary
987 {
988 return;
989 }
990
992 check_error(__LINE__);
993 // Convert C++ doubles to Python objects
994 for (int i = 0; i < num_reals; i++)
995 {
996 double value = static_cast<double>(reals[i]);
997 PyObject *py_value = static_cast<PyObject *>(MyFloat_FromDouble(value));
998 if (!py_value)
999 {
1000 std::cerr << "ERROR: Failed to create Python object from C++ double." << std::endl;
1001 return;
1002 }
1003 // Create the key in the format BASENAME_$UID
1004 std::string key = std::string(basename) + "_" + std::to_string(uid[i]);
1005 // Set the item in the Python dictionary
1006 MyDict_SetItemString(pDict, key.c_str(), py_value);
1007 // Release the Python object
1008 My_DecRef(py_value);
1009 }
1010 // Release the Python object
1011 check_error(__LINE__);
1012 MyGILState_Release(gstate);
1013 }

◆ cpp_python_update_sensors()

void cpp_python_update_sensors ( int * types,
int * uids,
int * statuses,
double * results,
int * num_sensors )

Definition at line 1115 of file cpp_python_funct.cpp.

1116 {
1117 //std::cout << "[PYTHON] update sensors" << std::endl;
1118 constexpr int sensor_python = 40; // PYTHON
1119 constexpr int sensor_energy = 14; // ENERGY
1120 constexpr int sensor_time = 0; // TIME
1121 constexpr int sensor_accel = 1; // ACCE
1122 constexpr int sensor_dist = 2; // DISP
1123 constexpr int sensor_sens = 3; // SENS
1124 constexpr int sensor_and = 4; // AND
1125 constexpr int sensor_or = 5; // OR
1126 constexpr int sensor_inter = 6; // INTER
1127 constexpr int sensor_rwall = 7; // RWALL
1128 constexpr int sensor_not = 8; // NOT
1129 constexpr int sensor_vel = 9; // VEL
1130 constexpr int sensor_gauge = 10; // GAUGE
1131 constexpr int sensor_rbody = 11; // RBODY
1132 constexpr int sensor_sect = 12; // SECT
1133 constexpr int sensor_work = 13; // WORK
1134 constexpr int sensor_dist_surf = 15; // DIST_SURF
1135 constexpr int sensor_hic = 16; // HIC
1136 constexpr int sensor_temp = 17; // TEMP
1137 // create a python dictionary with associating type to name
1138 const std::map<int, std::string> sensor_type_to_name = {
1139 {sensor_python, "PYTHON"},
1140 {sensor_energy, "ENERGY"},
1141 {sensor_time, "TIME"},
1142 {sensor_accel, "ACCE"},
1143 {sensor_dist, "DIST"},
1144 {sensor_sens, "SENS"},
1145 {sensor_and, "AND"},
1146 {sensor_or, "OR"},
1147 {sensor_inter, "INTER"},
1148 {sensor_rwall, "RWALL"},
1149 {sensor_not, "NOT"},
1150 {sensor_vel, "VEL"},
1151 {sensor_gauge, "GAUGE"},
1152 {sensor_rbody, "RBODY"},
1153 {sensor_sect, "SECT"},
1154 {sensor_work, "WORK"},
1155 {sensor_dist_surf, "DIST_SURF"},
1156 {sensor_hic, "HIC"},
1157 {sensor_temp, "TEMP"}};
1158
1159 if (!python_initialized)
1160 {
1161 return;
1162 }
1163 check_error(__LINE__);
1164 std::ostringstream oss;
1165 oss << std::setprecision(std::numeric_limits<double>::max_digits10) << std::hexfloat;
1166 oss << "sensors = { \n";
1167 for (int i = 0; i < *num_sensors; i++)
1168 {
1169 int type = types[i];
1170 int uid = uids[i];
1171 int status = statuses[i];
1172 oss << " " << uid << " : { 'type' : '" << sensor_type_to_name.at(type) << "', 'status' : " << status;
1173 // depending on the type, the results are different
1174 if (type == sensor_energy)
1175 { // Eint = results[2*(i-1)], Ekin = results[2*(i-1)+1]
1176 oss << ", 'Eint' : float.fromhex('" << results[2 * i] << "'), 'Ekin' : float.fromhex('" << results[2 * i + 1] << "') ";
1177 }
1178 else if (type == sensor_inter || type == sensor_rwall)
1179 { // Force = results[2*(i-1)]
1180 oss << ", 'Force' : float.fromhex('" << results[2 * i] << "') ";
1181 }
1182 else if (type == sensor_dist || type == sensor_dist_surf)
1183 {
1184 oss << ", 'Distance' : float.fromhex('" << results[2 * i] << "') ";
1185 }
1186 else if (type == sensor_gauge)
1187 {
1188 oss << ", 'Pressure' : float.fromhex('" << results[2 * i] << "') ";
1189 }
1190 if (i < *num_sensors - 1)
1191 {
1192 oss << "},\n";
1193 }
1194 else
1195 {
1196 oss << "}\n";
1197 }
1198 }
1199 oss << "\n}";
1200
1201 std::string code = oss.str();
1202 // std::cout<< "Generated code: "<<code<<std::endl;
1203 python_execute_code(code);
1204 // check for errors
1205 check_error(__LINE__);
1206
1207 }
subroutine sensor_and(nsensor, sensor_tab, sens)
Definition sensor_and.F:31
subroutine sensor_dist(sensor, x, xsens)
Definition sensor_dist.F:32
subroutine sensor_dist_surf(sensor, x, igrsurf)
subroutine sensor_energy(sensor, isens, subset, partsav2, nsensor, sensor_struct)
subroutine sensor_gauge(sensor, gauge)
subroutine sensor_hic(sensor, accn, accel)
Definition sensor_hic.F:33
subroutine sensor_not(nsensor, sensor_tab, sens)
Definition sensor_not.F:31
subroutine sensor_or(nsensor, sensor_tab, sens)
Definition sensor_or.F:31
subroutine sensor_rbody(sensor, dimfb, stabs, tabs, fbsav6)
subroutine sensor_rwall(sensor, nprw, dimfb, stabs, tabs, fbsav6)
subroutine sensor_sens(nsensor, sensor_tab, sens)
Definition sensor_sens.F:31
subroutine sensor_temp(sensor, isens, igrnod)
Definition sensor_temp.F:32
subroutine sensor_time(sensor, time, timestep)
Definition sensor_time.F:33
subroutine sensor_vel(sensor, v)
Definition sensor_vel.F:34
subroutine sensor_work(sensor, x, xsens, dimfb, stabs, tabs, fbsav6)
Definition sensor_work.F:33

◆ cpp_python_update_time()

void cpp_python_update_time ( my_real TIME,
my_real DT )

Definition at line 1015 of file cpp_python_funct.cpp.

1016 {
1017 if (!python_initialized)
1018 {
1019 // std::cerr << "ERROR: Python is not initialized." << std::endl;
1020 return;
1021 }
1023 check_error(__LINE__);
1024 if (!pDict)
1025 {
1026 std::cerr << "ERROR: Python main module dictionary not initialized." << std::endl;
1027 MyGILState_Release(gstate);
1028 return;
1029 }
1030 // donvert TIME and DT to double precision in TIME2 and DT2
1031 double TIME2 = static_cast<double>(TIME);
1032 double DT2 = static_cast<double>(DT);
1033 // Convert C++ doubles to Python objects
1034 PyObject *py_TIME = static_cast<PyObject *>(MyFloat_FromDouble(TIME2));
1035 PyObject *py_DT = static_cast<PyObject *>(MyFloat_FromDouble(DT2));
1036
1037 if (!py_TIME || !py_DT)
1038 {
1039 std::cerr << "ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1040 MyGILState_Release(gstate);
1041 return;
1042 }
1043
1044 // Set the Python global variables in the main module's dictionary
1045 MyDict_SetItemString(pDict, "TIME", py_TIME);
1046 MyDict_SetItemString(pDict, "DT", py_DT);
1047
1048 // Release the Python objects
1049 if (py_TIME != nullptr)
1050 My_DecRef(py_TIME);
1051 if (py_DT != nullptr)
1052 My_DecRef(py_DT);
1053 check_error(__LINE__);
1054 MyGILState_Release(gstate);
1055 }

◆ element_parenthesis_to_underscore()

template<std::size_t N>
std::string element_parenthesis_to_underscore ( const std::string & input,
const std::array< const char *, N > & keywords )

Definition at line 86 of file cpp_python_funct.cpp.

87{
88 std::string output = input;
89 for (const auto &keyword : keywords)
90 {
91 std::regex pattern(std::string(keyword) + R"(\‍(\s*(\d+)\s*\))");
92 output = std::regex_replace(output, pattern, std::string(keyword) + "_$1");
93 }
94 return output;
95}

◆ exit_with_message()

void exit_with_message ( const char * message)

Definition at line 201 of file cpp_python_funct.cpp.

202{
203 std::cout << message << std::endl;
204 std::cerr << message << std::endl;
205 My_Finalize();
206 exit(1);
207}

◆ extract_element_keywords()

void extract_element_keywords ( const std::string & input)

Definition at line 142 of file cpp_python_funct.cpp.

143{
144 for (const auto &keyword : ELEMENT_KEYWORDS)
145 {
146 // std::regex pattern(std::string(keyword) + R"(_(\d+))");
147 std::regex pattern(std::string(R"((?:[^a-zA-Z0-9]|^))") + std::string(keyword) + R"(_(\d+))");
148 auto words_begin = std::sregex_iterator(input.begin(), input.end(), pattern);
149 auto words_end = std::sregex_iterator();
150 for (std::sregex_iterator i = words_begin; i != words_end; ++i)
151 {
152 std::smatch match = *i;
153 int id = std::stoi(match.str(1));
154 element_variables.emplace(id, keyword);
155 // std::cout<<"[PYTHON] keyword found: "<<keyword<<" id: "<<id<<std::endl;
156 }
157 }
158}
constexpr std::array< const char *, 89 > ELEMENT_KEYWORDS

◆ extract_function_name()

std::string extract_function_name ( const std::string & signature)

Definition at line 414 of file cpp_python_funct.cpp.

415{
416 if (signature.substr(0, 3) != "def")
417 {
418 std::cout << "ERROR in Python function: signature does not start with 'def'" << std::endl;
419 return "";
420 }
421 std::size_t startPos = signature.find_first_not_of(" ", 3);
422 if (startPos == std::string::npos)
423 {
424 std::cout << "ERROR in Python function: function name not found" << std::endl;
425 return "";
426 }
427 // Find the index of the opening parenthesis
428 std::size_t endPos = signature.find("(", startPos);
429 if (endPos == std::string::npos)
430 {
431 std::cout << "ERROR in Python function: opening parenthesis not found" << std::endl;
432 return "";
433 }
434 // Extract the function name
435 return signature.substr(startPos, endPos - startPos);
436}

◆ extract_node_uid()

void extract_node_uid ( const std::string & input)

Definition at line 111 of file cpp_python_funct.cpp.

112{
113 // Coordinates CX_n, CY_n, CZ_n
114 // Displacement DX_n, DY_n, DZ_n
115 // Acceleration AX_n, AY_n, AZ_n
116 // DisplacementR DRX_n, DRY_n, DRZ_n
117 // Velocity VX_n, VY_n , VZ_n
118 // VelocityR VRX_n, VRY_n, VRZ_n
119 // AccelerationR ARX_n, ARY_n, ARZ_n
120 // Regex pattern: non-alphanumeric or start of line, followed by A[XYZ] and underscore and numbers
121 // std::cout<<"input: "<<input<<std::endl;
122 std::regex pattern(R"((?:[^a-zA-Z0-9]|^)[ACDV][R]*[XYZ]_[0-9]+)");
123
124 auto begin = std::sregex_iterator(input.begin(), input.end(), pattern);
125 auto end = std::sregex_iterator();
126
127 for (auto i = begin; i != end; ++i)
128 {
129
130 auto match = *i;
131 std::string match_str = match.str();
132 size_t underscore_pos = match_str.find('_');
133 if (underscore_pos != std::string::npos)
134 {
135 int number = std::stoi(match_str.substr(underscore_pos + 1));
136 nodes_uid.insert(number);
137 }
138 }
139}
end[inform, rinform, sol, inst, schur, redrhs, pivnul_list, sym_perm, uns_perm, icntl, cntl, colsca_out, rowsca_out, keep_out, dkeep_out]
Definition dmumps.m:40

◆ load_functions()

template<typename T>
void load_functions ( T h,
bool & python_initialized )

Definition at line 163 of file cpp_python_funct.cpp.

164{
165 python_initialized = true;
166 load_function(h, "Py_Initialize", My_Initialize, python_initialized);
167 load_function(h, "Py_IsInitialized", My_IsInitialized, python_initialized);
168 load_function(h, "Py_Finalize", My_Finalize, python_initialized);
169 load_function(h, "PyDict_GetItemString", MyDict_GetItemString, python_initialized);
170 load_function(h, "PyCallable_Check", MyCallable_Check, python_initialized);
171 load_function(h, "PyTuple_New", MyTuple_New, python_initialized);
172 load_function(h, "PyFloat_FromDouble", MyFloat_FromDouble, python_initialized);
173 load_function(h, "PyObject_CallObject", MyObject_CallObject, python_initialized);
174 load_function(h, "PyImport_AddModule", MyImport_AddModule, python_initialized);
175 load_function(h, "PyModule_GetDict", MyModule_GetDict, python_initialized);
176 load_function(h, "PyRun_SimpleString", MyRun_SimpleString, python_initialized);
177 load_function(h, "PyTuple_SetItem", MyTuple_SetItem, python_initialized);
178 load_function(h, "PyList_SetItem", MyList_SetItem, python_initialized);
181 load_function(h, "PyFloat_AsDouble", MyFloat_AsDouble, python_initialized);
182 load_function(h, "PyDict_SetItemString", MyDict_SetItemString, python_initialized);
183 load_function(h, "PyErr_Fetch", MyErr_Fetch, python_initialized);
184 load_function(h, "PyErr_Display", MyErr_Display, python_initialized);
185 load_function(h, "PyErr_Occurred", MyErr_Occurred, python_initialized);
186 load_function(h, "PyObject_Str", MyObject_Str, python_initialized);
187 load_function(h, "PyUnicode_AsUTF8", MyUnicode_AsUTF8, python_initialized);
190 load_function(h, "PyErr_Clear", MyErr_Clear, python_initialized);
191 load_function(h, "PyLong_FromLong", MyLong_FromLong, python_initialized);
192 load_function(h, "PyLong_FromVoidPtr", MyLong_FromVoidPtr, python_initialized);
193 load_function(h, "PyUnicode_FromString", MyUnicode_FromString, python_initialized);
194 load_function(h, "PyEval_SaveThread", MyEval_SaveThread, python_initialized);
195 load_function(h, "PyEval_RestoreThread", MyEval_RestoreThread, python_initialized);
196 load_function(h, "PyGILState_Ensure", MyGILState_Ensure, python_initialized);
197 load_function(h, "PyGILState_Release", MyGILState_Release, python_initialized);
198}
T_PyEval_RestoreThread MyEval_RestoreThread
T_PyList_New MyList_New
T_PyErr_Display MyErr_Display
T_Py_IsInitialized My_IsInitialized
T_Py_Initialize My_Initialize
void load_function(void *h, const std::string &func_name, T &func_ptr, bool &python_initialized)
T_PyList_SetItem MyList_SetItem
T_PyEval_SaveThread MyEval_SaveThread

◆ node_parenthesis_to_underscore()

std::string node_parenthesis_to_underscore ( const std::string & input)

Definition at line 97 of file cpp_python_funct.cpp.

98{
99 std::regex pattern(R"(\b(DX|DY|DZ|AX|AY|AZ|CX|CY|CZ|VX|VY|VZ|ARX|ARY|ARZ|VRX|VRY|VRZ|DRX|DRY|DRZ|MONVOL_VOL|MONVOL_T|MONVOL_A|MONVOL_P)\b\s*\‍(\s*(\d+|ACTIVE_NODE)\s*\))");
100 std::string result = std::regex_replace(input, pattern, "$1_$2");
101 return result;
102}

◆ parenthesis_to_underscore()

std::string parenthesis_to_underscore ( const std::string & input)

Definition at line 104 of file cpp_python_funct.cpp.

105{
106 std::string result = node_parenthesis_to_underscore(input);
108}
std::string element_parenthesis_to_underscore(const std::string &input, const std::array< const char *, N > &keywords)
std::string node_parenthesis_to_underscore(const std::string &input)

◆ py_begin_allow_threads()

PyThreadState * py_begin_allow_threads ( )

Definition at line 1481 of file cpp_python_funct.cpp.

1481 {
1482 return MyEval_SaveThread();
1483}

◆ py_end_allow_threads()

void py_end_allow_threads ( PyThreadState * saved_state)

Definition at line 1485 of file cpp_python_funct.cpp.

1485 {
1486 MyEval_RestoreThread(saved_state);
1487}

◆ python_execute_code()

void python_execute_code ( const std::string & code)

Definition at line 407 of file cpp_python_funct.cpp.

408{
409 MyRun_SimpleString(code.c_str());
410 check_error(__LINE__);
411}

◆ python_load_library()

void python_load_library ( )

Definition at line 555 of file cpp_python_funct.cpp.

556{
557 python_initialized = false;
558 handle = nullptr;
559 // clear the previous errors in dlerror:
560 dlerror();
561 // Get the string from the environment variable RAD_PYTHON_PATH
562 const char *python_path = getenv("RAD_PYTHON_PATH");
563 if (python_path == nullptr)
564 {
565 python_initialized = false;
566 }
567 else
568 {
570 }
571
572 // if RAD_PYTHON_PATH was not found, or if the library was not loaded, try find PYTHONHOME
574 {
575 python_path = getenv("PYTHONHOME");
576 if (python_path)
577 {
578 std::cout << "INFO: searching for python library in PYTHONHOME" << std::endl;
579 std::vector<std::string> possible_dirs = {"/lib64/", "/lib/", "/usr/lib64/", "/usr/lib/", "/usr/lib/x86_64-linux-gnu/"};
580 for (const auto &dir : possible_dirs)
581 {
582 std::string dir_path = std::string(python_path) + dir;
583 DIR *d = opendir(dir_path.c_str());
584 if (d)
585 {
586 struct dirent *entry;
587 while ((entry = readdir(d)) != nullptr)
588 {
589 std::string filename(entry->d_name);
590 if (filename.find("libpython") == 0 && filename.find(".so") != std::string::npos)
591 {
592 python_initialized = try_load_library(dir_path + filename);
594 {
595 closedir(d);
596 return;
597 }
598 }
599 }
600 closedir(d);
601 }
602 }
603 }
604 }
605 // if we reach this point, we did not find any python library
606 // we look into some default locations
607 std::cout << " INFO: searching for python library in default locations LD_LIBRARY_PATH" << std::endl;
608 std::vector<std::string> possible_names = {
609 "libpython3.12.so",
610 "libpython3.11.so",
611 "libpython3.10.so",
612 "libpython3.9.so",
613 "libpython3.8.so",
614 "libpython3.7.so",
615 "libpython3.6.so",
616 "libpython3.5.so",
617 "libpython3.4.so",
618 "libpython3.3.so",
619 "libpython3.2.so",
620 "libpython3.1.so",
621 "libpython3.so",
622 "libpython3.0.so",
623 "libpython2.7.so"};
624 for (const auto &name : possible_names)
625 {
626 std::string libname = name;
629 {
630 return;
631 }
632 }
633}
bool try_load_library(const std::string &path)
void * handle

◆ python_signal_handler()

void python_signal_handler ( int signum)

Definition at line 234 of file cpp_python_funct.cpp.

234 {
235 std::cout << "[PYTHON] Caught signal " << signum << std::endl;
236 std::cerr << "[PYTHON] Caught signal " << signum << std::endl;
237 //How to flush the output buffers before exiting
238 std::cout << std::flush;
239 std::cerr << std::flush;
240 std::cerr.flush();
241 std::cout.flush();
242 //My_Finalize();
243 std::exit(signum);
244}

◆ try_load_library()

bool try_load_library ( const std::string & path)

Definition at line 533 of file cpp_python_funct.cpp.

534{
535 bool python_initialized = false;
536 handle = dlopen(path.c_str(), RTLD_LAZY |RTLD_GLOBAL);
537 if (handle)
538 {
539 std::cout << "Trying python library: " << path << std::endl;
542 {
543 std::cout << "INFO: Python library found at " << path << std::endl;
545 if (!My_IsInitialized())
546 {
547 std::cout << "ERROR: My_Initialize failed" << std::endl;
548 python_initialized = false;
549 }
550 }
551 }
552 return python_initialized;
553}
void load_functions(T h, bool &python_initialized)

Variable Documentation

◆ element_variables

KeywordPairs element_variables

Definition at line 80 of file cpp_python_funct.cpp.

◆ handle

void* handle = nullptr

Definition at line 67 of file cpp_python_funct.cpp.

◆ nodes_uid

std::set<int> nodes_uid

Definition at line 77 of file cpp_python_funct.cpp.

◆ nodes_uid_to_local_id

std::map<int, int> nodes_uid_to_local_id

Definition at line 79 of file cpp_python_funct.cpp.

◆ pDict

PyObject* pDict = nullptr

Definition at line 71 of file cpp_python_funct.cpp.

◆ persistent_arg

PyObject* persistent_arg = nullptr
static

Definition at line 82 of file cpp_python_funct.cpp.

◆ persistent_dict

PyObject* persistent_dict = nullptr
static

Definition at line 81 of file cpp_python_funct.cpp.

◆ python_initialized

bool python_initialized = false

Definition at line 72 of file cpp_python_funct.cpp.

◆ sync_enabled

bool sync_enabled = false

Definition at line 73 of file cpp_python_funct.cpp.