12 #include <fmt/format.h>
14 #include <pybind11/embed.h>
15 #include <pybind11/stl.h>
22 namespace py = pybind11;
23 using namespace py::literals;
26 namespace pybind_wrappers {
28 std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
30 const std::vector<std::string>& state_vars,
31 const std::set<std::string>& vars,
34 const std::string& tmp_unique_prefix,
35 const std::set<std::string>& function_calls) {
36 const auto locals = py::dict(
"eq_strings"_a = eq_system,
37 "state_vars"_a = state_vars,
39 "small_system"_a = small_system,
40 "do_cse"_a = elimination,
41 "function_calls"_a = function_calls,
42 "tmp_unique_prefix"_a = tmp_unique_prefix);
43 std::string script = R
"(
44 exception_message = ""
46 solutions, new_local_vars = solve_lin_system(eq_strings,
53 except Exception as e:
54 # if we fail, fail silently and return empty string
58 exception_message = traceback.format_exc()
61 py::exec(nmodl::pybind_wrappers::ode_py + script, locals);
63 auto solutions = locals[
"solutions"].cast<std::vector<std::string>>();
65 auto new_local_vars = locals[
"new_local_vars"].cast<std::vector<std::string>>();
67 auto exception_message = locals[
"exception_message"].cast<std::string>();
69 return {std::move(solutions), std::move(new_local_vars), std::move(exception_message)};
74 const std::vector<std::string>& eq_system,
75 const std::vector<std::string>& state_vars,
76 const std::set<std::string>& vars,
77 const std::set<std::string>& function_calls) {
78 const auto locals = py::dict(
"equation_strings"_a = eq_system,
79 "state_vars"_a = state_vars,
81 "function_calls"_a = function_calls);
82 std::string script = R
"(
83 exception_message = ""
85 solutions = solve_non_lin_system(equation_strings,
89 except Exception as e:
90 # if we fail, fail silently and return empty string
93 exception_message = traceback.format_exc()
96 py::exec(nmodl::pybind_wrappers::ode_py + script, locals);
98 auto solutions = locals[
"solutions"].cast<std::vector<std::string>>();
100 auto exception_message = locals[
"exception_message"].cast<std::string>();
102 return {std::move(solutions), std::move(exception_message)};
107 const std::string& dt_var,
108 const std::set<std::string>& vars,
109 bool use_pade_approx,
110 const std::set<std::string>& function_calls,
111 const std::string& method) {
112 const auto locals = py::dict(
"equation_string"_a = node_as_nmodl,
115 "use_pade_approx"_a = use_pade_approx,
116 "function_calls"_a = function_calls);
122 std::string script = R
"(
123 exception_message = ""
125 solution = forwards_euler2c(equation_string, dt_var, vars, function_calls)
126 except Exception as e:
127 # if we fail, fail silently and return empty string
130 exception_message = traceback.format_exc()
133 py::exec(nmodl::pybind_wrappers::ode_py + script, locals);
138 std::string script = R
"(
139 exception_message = ""
141 solution = integrate2c(equation_string, dt_var, vars,
143 except Exception as e:
144 # if we fail, fail silently and return empty string
147 exception_message = traceback.format_exc()
150 py::exec(nmodl::pybind_wrappers::ode_py + script, locals);
155 auto solution = locals[
"solution"].cast<std::string>();
156 auto exception_message = locals[
"exception_message"].cast<std::string>();
158 return {std::move(solution), std::move(exception_message)};
163 const std::vector<std::string>& expressions,
164 const std::set<std::string>& used_names_in_block) {
165 auto locals = py::dict(
"expressions"_a = expressions,
"vars"_a = used_names_in_block);
166 std::string script = R
"(
167 exception_message = ""
169 rhs = expressions[-1].split("=", 1)[1]
170 solution = differentiate2c(rhs,
175 except Exception as e:
176 # if we fail, fail silently and return empty string
179 exception_message = traceback.format_exc()
182 py::exec(nmodl::pybind_wrappers::ode_py + script, locals);
184 auto solution = locals[
"solution"].cast<std::string>();
185 auto exception_message = locals[
"exception_message"].cast<std::string>();
187 return {std::move(solution), std::move(exception_message)};
191 const std::string& expression,
192 const std::pair<std::string, std::optional<int>>& variable,
193 const std::unordered_set<std::string>& indexed_vars) {
194 std::string statements;
196 for (
const auto& var: indexed_vars) {
197 statements += fmt::format(
"_allvars.append(sp.IndexedBase('{}', shape=[1]))\n", var);
199 auto [name, property] = variable;
200 if (property.has_value()) {
201 name = fmt::format(
"sp.IndexedBase('{}', shape=[1])", name);
202 statements += fmt::format(
"_allvars.append({})", name);
204 name = fmt::format(
"'{}'", name);
206 auto locals = py::dict(
"expression"_a = expression);
212 exception_message = ""
214 solution = differentiate2c(expression,
218 except Exception as e:
219 # if we fail, fail silently and return empty string
221 exception_message = str(e)
224 property.has_value() ? fmt::format("{}[{}]", name, property.value()) : name);
226 py::exec(nmodl::pybind_wrappers::ode_py + script, locals);
228 auto solution = locals[
"solution"].cast<std::string>();
229 auto exception_message = locals[
"exception_message"].cast<std::string>();
231 return {std::move(solution), std::move(exception_message)};
235 pybind11::initialize_interpreter(
true);
239 pybind11::finalize_interpreter();