35#ifndef PYTHON_DISABLED
65HMODULE python_exec = NULL;
85template <std::
size_t N>
88 std::string output = input;
89 for (
const auto &keyword : keywords)
91 std::regex pattern(std::string(keyword) + R
"(\(\s*(\d+)\s*\))");
92 output = std::regex_replace(output, pattern, std::string(keyword) + "_$1");
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");
122 std::regex pattern(R
"((?:[^a-zA-Z0-9]|^)[ACDV][R]*[XYZ]_[0-9]+)");
124 auto begin = std::sregex_iterator(input.begin(), input.end(), pattern);
125 auto end = std::sregex_iterator();
127 for (
auto i = begin; i !=
end; ++i)
131 std::string match_str = match.str();
132 size_t underscore_pos = match_str.find(
'_');
133 if (underscore_pos != std::string::npos)
135 int number = std::stoi(match_str.substr(underscore_pos + 1));
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)
152 std::smatch match = *i;
153 int id = std::stoi(match.str(1));
199 std::cout << message << std::endl;
200 std::cerr << message << std::endl;
211 PyObject *pType =
nullptr, *pValue =
nullptr, *pTraceback =
nullptr;
231 std::cout <<
"[PYTHON] Caught signal " << signum << std::endl;
232 std::cerr <<
"[PYTHON] Caught signal " << signum << std::endl;
234 std::cout << std::flush;
235 std::cerr << std::flush;
258 std::cout <<
"ERROR: Failed to create persistent dictionary." << std::endl;
265 std::cout <<
"ERROR: Failed to create argument tuple." << std::endl;
277 if (pValue !=
nullptr)
285 std::string func_name_str(func_name);
286 std::cout <<
"ERROR in Python function " << func_name_str <<
": function execution failed" << std::endl;
290 PyObject *pType, *pValue, *pTraceback;
313 std::cout <<
"ERROR in Python function: cannot call function: " << func_name << std::endl;
327 for (
size_t i = 0; i < num_args; i++)
335 if (pValue !=
nullptr)
342 std::string func_name_str(func_name);
343 std::cout <<
"ERROR in Python function " << func_name_str <<
": function execution failed" << std::endl;
347 PyObject *pType =
nullptr, *pValue =
nullptr, *pTraceback =
nullptr;
368 std::cout <<
"ERROR in Python function: cannot call function: " << func_name << std::endl;
375 const int num_args = X.size();
379 for (
size_t i = 0; i < num_args; i++)
386 if (pValue !=
nullptr)
395 Y[i] =
static_cast<double>(std::numeric_limits<float>::max());
412 if (signature.substr(0, 3) !=
"def")
414 std::cout <<
"ERROR in Python function: signature does not start with 'def'" << std::endl;
417 std::size_t startPos = signature.find_first_not_of(
" ", 3);
418 if (startPos == std::string::npos)
420 std::cout <<
"ERROR in Python function: function name not found" << std::endl;
424 std::size_t endPos = signature.find(
"(", startPos);
425 if (endPos == std::string::npos)
427 std::cout <<
"ERROR in Python function: opening parenthesis not found" << std::endl;
431 return signature.substr(startPos, endPos - startPos);
443 char python_path[20000];
444 int path_size = GetEnvironmentVariable(
"RAD_PYTHON_PATH", python_path, 20000);
452 handle = LoadLibrary(python_path);
466 python_exec = LoadLibrary(
"python.exe");
468 if (python_exec == NULL)
470 std::cout <<
"ERROR: No python installation found." << std::endl;
471 std::cout <<
" Set PATH to Python Installation or set RAD_PYTHON_PATH to the Python library" << std::endl;
476 char python_filename[2048];
477 DWORD filelen = GetModuleFileName(python_exec, python_filename, 2048);
479 while (i > 0 && python_filename[i - 1] !=
'\\')
481 python_filename[i] =
'\0';
483 strcpy_s(python_path, 20000, python_filename);
484 FreeLibrary(python_exec);
486 std::string dir_path = std::string(python_path);
488 WIN32_FIND_DATA find_file_data;
489 HANDLE hFind = FindFirstFile((dir_path +
"python*.dll").c_str(), &find_file_data);
491 if (hFind == INVALID_HANDLE_VALUE)
493 std::cout <<
"ERROR: Could not find any python*.dll files in " << dir_path << std::endl;
500 std::string full_dll_path = dir_path + find_file_data.cFileName;
501 handle = LoadLibrary(full_dll_path.c_str());
517 }
while (FindNextFile(hFind, &find_file_data) != 0);
532 handle = dlopen(path.c_str(), RTLD_LAZY |RTLD_GLOBAL);
535 std::cout <<
"Trying python library: " << path << std::endl;
539 std::cout <<
"INFO: Python library found at " << path << std::endl;
543 std::cout <<
"ERROR: My_Initialize failed" << std::endl;
558 const char *python_path = getenv(
"RAD_PYTHON_PATH");
559 if (python_path ==
nullptr)
571 python_path = getenv(
"PYTHONHOME");
574 std::cout <<
"INFO: searching for python library in PYTHONHOME" << std::endl;
575 std::vector<std::string> possible_dirs = {
"/lib64/",
"/lib/",
"/usr/lib64/",
"/usr/lib/",
"/usr/lib/x86_64-linux-gnu/"};
576 for (
const auto &dir : possible_dirs)
578 std::string dir_path = std::string(python_path) + dir;
579 DIR *d = opendir(dir_path.c_str());
582 struct dirent *entry;
583 while ((entry = readdir(d)) !=
nullptr)
585 std::string filename(entry->d_name);
586 if (filename.find(
"libpython") == 0 && filename.find(
".so") != std::string::npos)
603 std::cout <<
" INFO: searching for python library in default locations LD_LIBRARY_PATH" << std::endl;
604 std::vector<std::string> possible_names = {
620 for (
const auto &name : possible_names)
622 std::string libname = name;
653 std::cout <<
"ERROR in Python: fetching main module dictionary" << std::endl;
659 std::cerr <<
"ERROR: Failed to import math module in Python." << std::endl;
664 PyObject *pType, *pValue, *pTraceback;
697 "if 'initialize_environment' in globals():\n"
698 " initialize_environment()\n";
727 std::cout <<
"ERROR: Failed to create Python tuple." << std::endl;
734 std::cout <<
"ERROR: Python function not found: " << func_name << std::endl;
739 std::cerr <<
"[PYTHON] Error: '" << func_name <<
"' is not callable" << std::endl;
747 PyObject *pType, *pValue, *pTraceback;
798 std::string entity_names[] = {
"C",
"D",
"V",
"A",
"VR",
"AR",
"DR"};
799 for (
auto name : entity_names)
801 const double x_values =
static_cast<double>(1);
802 const double y_values =
static_cast<double>(1);
803 const double z_values =
static_cast<double>(1);
807 if (!py_x_values || !py_y_values || !py_z_values)
809 std::cout <<
"ERROR: Failed to create Python objects from C++ doubles." << std::endl;
812 std::string x_name = name +
"X_" + std::to_string(node_uid);
813 std::string y_name = name +
"Y_" + std::to_string(node_uid);
814 std::string z_name = name +
"Z_" + std::to_string(node_uid);
820 if (py_x_values !=
nullptr)
822 if (py_y_values !=
nullptr)
824 if (py_z_values !=
nullptr)
831 double v =
static_cast<double>(1);
835 std::cout <<
"ERROR: Failed to create Python objects from C++ doubles." << std::endl;
838 std::string keyword(p.second);
839 std::string sname = keyword +
"_" + std::to_string(p.first);
841 if (py_value !=
nullptr)
851 std::string tmp_string;
852 int current_line = 0;
853 std::stringstream function_code;
857 std::cout <<
"ERROR: Python not initialized" << std::endl;
858 std::cout <<
"Make sure that the following python code is safe" << std::endl;
859 std::cout <<
"and rerun the starter with the -python option." << std::endl;
862 for (
int i = 0; current_line < num_lines;)
866 while (code[i] !=
'\0')
868 tmp_string += code[i];
871 if (current_line == 0)
875 if (function_name.empty())
877 std::cout <<
"ERROR: function name not found in function signature" << std::endl;
884 strcpy(name, function_name.c_str());
887 name[function_name.size()] =
'\0';
894 function_code << s << std::endl;
907 std::cout << function_code.str() << std::endl;
920 if (strcmp(name,
"initialize_environment") == 0)
return;
984 for (
int i = 0; i < num_reals; i++)
986 double value =
static_cast<double>(reals[i]);
990 std::cerr <<
"ERROR: Failed to create Python object from C++ double." << std::endl;
994 std::string key = std::string(basename) +
"_" + std::to_string(uid[i]);
1015 std::cerr <<
"ERROR: Python main module dictionary not initialized." << std::endl;
1019 double TIME2 =
static_cast<double>(TIME);
1020 double DT2 =
static_cast<double>(DT);
1025 if (!py_TIME || !py_DT)
1027 std::cerr <<
"ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1036 if (py_TIME !=
nullptr)
1038 if (py_DT !=
nullptr)
1066 nodes_uid_array[i] = node_uid;
1083 for (
int i = 0; i < *num_nodes; i++)
1085 if (itab[i] == node_uid)
1095 std::cout <<
"Node uid: " << node_uid <<
" not found in itab" << std::endl;
1105 constexpr int sensor_python = 40;
1108 constexpr int sensor_accel = 1;
1113 constexpr int sensor_inter = 6;
1119 constexpr int sensor_sect = 12;
1125 const std::map<int, std::string> sensor_type_to_name = {
1126 {sensor_python,
"PYTHON"},
1129 {sensor_accel,
"ACCE"},
1134 {sensor_inter,
"INTER"},
1140 {sensor_sect,
"SECT"},
1151 std::ostringstream oss;
1152 oss << std::setprecision(std::numeric_limits<double>::max_digits10) << std::hexfloat;
1153 oss <<
"sensors = { \n";
1154 for (
int i = 0; i < *num_sensors; i++)
1156 int type = types[i];
1158 int status = statuses[i];
1159 oss <<
" " << uid <<
" : { 'type' : '" << sensor_type_to_name.at(type) <<
"', 'status' : " << status;
1163 oss <<
", 'Eint' : float.fromhex('" << results[2 * i] <<
"'), 'Ekin' : float.fromhex('" << results[2 * i + 1] <<
"') ";
1167 oss <<
", 'Force' : float.fromhex('" << results[2 * i] <<
"') ";
1171 oss <<
", 'Distance' : float.fromhex('" << results[2 * i] <<
"') ";
1175 oss <<
", 'Pressure' : float.fromhex('" << results[2 * i] <<
"') ";
1177 if (i < *num_sensors - 1)
1188 std::string code = oss.str();
1206 double x_values, y_values, z_values;
1209 x_values =
static_cast<double>(values[0]);
1210 y_values =
static_cast<double>(values[1]);
1211 z_values =
static_cast<double>(values[2]);
1215 if (!py_x_values || !py_y_values || !py_z_values)
1217 std::cout <<
"ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1221 std::string x_name = std::string(name) +
"X_ACTIVE_NODE";
1222 std::string y_name = std::string(name) +
"Y_ACTIVE_NODE";
1223 std::string z_name = std::string(name) +
"Z_ACTIVE_NODE";
1229 if (py_x_values !=
nullptr)
1231 if (py_y_values !=
nullptr)
1233 if (py_z_values !=
nullptr)
1247 std::string id_name =
"ACTIVE_NODE";
1248 std::string uid_name =
"ACTIVE_NODE_UID";
1265 double x_values, y_values, z_values;
1269 int node_uid = it->first;
1270 int local_id = it->second;
1271 if(local_id > numnod-1)
1273 std::cout <<
"ERROR: local_id " << local_id <<
" is greater than numnod " << numnod << std::endl;
1276 x_values =
static_cast<double>(values[3 * local_id]);
1277 y_values =
static_cast<double>(values[3 * local_id + 1]);
1278 z_values =
static_cast<double>(values[3 * local_id + 2]);
1282 if (!py_x_values || !py_y_values || !py_z_values)
1284 std::cout <<
"ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1288 std::string x_name = std::string(name) +
"X_" + std::to_string(node_uid);
1289 std::string y_name = std::string(name) +
"Y_" + std::to_string(node_uid);
1290 std::string z_name = std::string(name) +
"Z_" + std::to_string(node_uid);
1296 if (py_x_values !=
nullptr)
1298 if (py_y_values !=
nullptr)
1300 if (py_z_values !=
nullptr)
1310 double v =
static_cast<double>(value);
1315 std::cout <<
"ERROR: Failed to create Python objects from C++ doubles." << std::endl;
1317 std::string sname = std::string(name) +
"_" + std::to_string(uid);
1320 if (py_value !=
nullptr)
1333 size_t n =
static_cast<size_t>(nb - 1);
1345 strcpy(name, p.second);
1352 constexpr size_t N = 10000;
1353 double x_max = 1e+6;
1355 std::vector<double> X(2*
N, 0.0);
1356 double scale = x_max /
N;
1359 for (
size_t i = 0; i <
N; i++)
1361 X[i] = -scale * Xtmp[
N - i - 1];
1363 for (
size_t i = 0; i <
N; i++)
1365 X[i +
N] = scale * Xtmp[i];
1369 std::vector<double> Y(X.size(), 0.0);
1374 std::vector<double> new_y(
n, 0.0);
1378 for (
int i = 0; i <
n; i++)
1380 x[i] =
static_cast<my_real>(new_x[i]);
1381 y[i] =
static_cast<my_real>(new_y[i]);
1404 char ptr_key[100],size_key[100],type_key[100];
1405 snprintf(ptr_key,
sizeof(ptr_key),
"%s_ptr", name);
1406 snprintf(size_key,
sizeof(size_key),
"%s_size", name);
1407 snprintf(type_key,
sizeof(type_key),
"%s_type", name);
1433 char ptr_key[100],size_key[100],type_key[100];
1434 snprintf(ptr_key,
sizeof(ptr_key),
"%s_ptr", name);
1435 snprintf(size_key,
sizeof(size_key),
"%s_size", name);
1436 snprintf(type_key,
sizeof(type_key),
"%s_type", name);
1495 std::cout <<
"ERROR: python not enabled" << std::endl;
1499 std::cout <<
"ERROR: python not enabled" << std::endl;
1503 std::cout <<
"ERROR: python not enabled" << std::endl;
std::string element_parenthesis_to_underscore(const std::string &input, const std::array< const char *, N > &keywords)
void cpp_python_update_sensors(int *types, int *uids, int *statuses, double *results, int *num_sensors)
void python_signal_handler(int signum)
std::string parenthesis_to_underscore(const std::string &input)
void exit_with_message(const char *message)
void cpp_python_update_time(my_real TIME, my_real DT)
void * cpp_python_create_context()
void cpp_python_create_node_mapping(int *itab, int *num_nodes)
void check_error(int line_number)
void python_load_library()
void cpp_python_finalize()
std::map< int, int > nodes_uid_to_local_id
void cpp_python_sample_function(char *name, my_real *x, my_real *y, int n)
KeywordPairs element_variables
void cpp_python_get_nodes(int *nodes_uid_array)
bool try_load_library(const std::string &path)
void cpp_python_update_nodal_entity(int numnod, int name_len, char *name, my_real *values)
void cpp_python_register_function(char *name, char code[], int num_lines)
void cpp_python_update_reals(char *basename, int *uid, my_real *reals, int num_reals)
void cpp_python_check_function(char *name, int *error)
void cpp_python_call_function(char *name, int num_args, double *args, int num_return, double *return_values)
void cpp_python_add_ints_to_dict(void *context_ptr, const char *name, int len_name, int *values, int nvalues)
void cpp_python_update_active_node(int name_len, char *name, double *values)
void cpp_python_initialize_global_variables()
void cpp_python_add_doubles_to_dict(void *context_ptr, const char *name, int len_name, double *values, int nvalues)
void cpp_python_load_environment()
void cpp_python_update_active_node_ids(int id, int uid)
void extract_element_keywords(const std::string &input)
PyObject * call_python_function(const char *func_name, double *args, int num_args)
void cpp_python_get_number_of_nodes(int *num_nodes)
void cpp_python_initialize(int *ierror)
static PyObject * persistent_arg
std::string node_parenthesis_to_underscore(const std::string &input)
void load_functions(T h, bool &python_initialized)
void python_execute_code(const std::string &code)
void cpp_python_call_function_with_state(char *name, double *return_values)
void cpp_python_get_number_elemental_entities(int *nb)
void cpp_python_update_elemental_entity(char *name, double value, int uid)
void cpp_python_execute_code(const char *code)
void cpp_python_free_context(void *context)
void call_python_function1D_vectors(const char *func_name, std::vector< double > &X, std::vector< double > &Y)
PyObject * call_python_function_with_state(const char *func_name)
void cpp_python_sync(void *pcontext)
static PyObject * persistent_dict
std::string extract_function_name(const std::string &signature)
void cpp_python_get_elemental_entity(int nb, char *name, int *uid)
void extract_node_uid(const std::string &input)
std::set< int > nodes_uid
T_PyModule_GetDict MyModule_GetDict
T_PyErr_Display MyErr_Display
T_PyTuple_SetItem MyTuple_SetItem
T_PyCallable_Check MyCallable_Check
T_PyLong_FromLong MyLong_FromLong
T_PyLong_FromVoidPtr MyLong_FromVoidPtr
constexpr std::array< const char *, 89 > ELEMENT_KEYWORDS
T_PyUnicode_FromString MyUnicode_FromString
T_PyUnicode_AsUTF8 MyUnicode_AsUTF8
T_PyDict_GetItemString MyDict_GetItemString
KeywordPair get_keyword_pair(const KeywordPairs &keywordPairs, size_t n)
#define max_variable_length
T_PyErr_Clear MyErr_Clear
std::pair< int, const char * > KeywordPair
T_PyErr_Occurred MyErr_Occurred
T_Py_IsInitialized My_IsInitialized
T_Py_Initialize My_Initialize
T_PyErr_Fetch MyErr_Fetch
T_Py_Finalize My_Finalize
T_PyFloat_AsDouble MyFloat_AsDouble
T_PyImport_AddModule MyImport_AddModule
std::set< std::pair< int, const char * >, ComparePairs > KeywordPairs
void load_function(void *h, const std::string &func_name, T &func_ptr, bool &python_initialized)
T_PyDict_SetItemString MyDict_SetItemString
T_PyTuple_New MyTuple_New
T_PyRun_SimpleString MyRun_SimpleString
T_PyList_SetItem MyList_SetItem
T_PyObject_CallObject MyObject_CallObject
T_PyObject_Str MyObject_Str
T_PyFloat_FromDouble MyFloat_FromDouble
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)
end[inform, rinform, sol, inst, schur, redrhs, pivnul_list, sym_perm, uns_perm, icntl, cntl, colsca_out, rowsca_out, keep_out, dkeep_out]
void activate_signal_handling(SignalHandler handler, int signal=SIGINT)
void restore_default_signal_handling(int signal=SIGINT)
subroutine sensor_and(nsensor, sensor_tab, sens)
subroutine sensor_dist(sensor, x, xsens)
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)
subroutine sensor_not(nsensor, sensor_tab, sens)
subroutine sensor_or(nsensor, sensor_tab, sens)
subroutine sensor_rbody(sensor, dimfb, stabs, tabs, fbsav6)
subroutine sensor_rwall(sensor, nprw, dimfb, stabs, tabs, fbsav6)
subroutine sensor_sens(nsensor, sensor_tab, sens)
subroutine sensor_temp(sensor, isens, igrnod)
subroutine sensor_time(sensor, time, timestep)
subroutine sensor_vel(sensor, v)
subroutine sensor_work(sensor, x, xsens, dimfb, stabs, tabs, fbsav6)