12 #include <fmt/format.h>
14 #include <pybind11/embed.h>
15 #include <pybind11/stl.h>
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>();
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>();
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>();
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>();
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);
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>();
235 pybind11::initialize_interpreter(
true);
239 pybind11::finalize_interpreter();
double var(InputIterator begin, InputIterator end)
void move(Item *q1, Item *q2, Item *q3)
static constexpr char CNEXP_METHOD[]
cnexp method in nmodl
static constexpr char EULER_METHOD[]
euler method in nmodl
std::tuple< std::vector< std::string >, std::string > call_solve_nonlinear_system(const std::vector< std::string > &eq_system, const std::vector< std::string > &state_vars, const std::set< std::string > &vars, const std::set< std::string > &function_calls)
std::tuple< std::string, std::string > call_diff2c(const std::string &expression, const std::pair< std::string, std::optional< int >> &variable, const std::unordered_set< std::string > &indexed_vars)
Differentiates an expression with respect to a variable.
void initialize_interpreter_func()
void finalize_interpreter_func()
std::tuple< std::string, std::string > call_analytic_diff(const std::vector< std::string > &expressions, const std::set< std::string > &used_names_in_block)
std::tuple< std::string, std::string > call_diffeq_solver(const std::string &node_as_nmodl, const std::string &dt_var, const std::set< std::string > &vars, bool use_pade_approx, const std::set< std::string > &function_calls, const std::string &method)
NMODL_EXPORT pybind_wrap_api nmodl_init_pybind_wrapper_api() noexcept
std::tuple< std::vector< std::string >, std::vector< std::string >, std::string > call_solve_linear_system(const std::vector< std::string > &eq_system, const std::vector< std::string > &state_vars, const std::set< std::string > &vars, bool small_system, bool elimination, const std::string &tmp_unique_prefix, const std::set< std::string > &function_calls)
encapsulates code generation backend implementations