Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if time == sympy_t:
return sympy_current_y(index)
else:
return sympy_past_y(time, index, sympy_anchors(time))
sympy_current_y = sympy.Function("current_y",real=True)
sympy_past_y = sympy.Function("past_y",real=True)
sympy_anchors = sympy.Function("anchors",real=True)
symengine_t = symengine.Symbol("t",real=True)
def symengine_y(index,time=symengine_t):
if time == symengine_t:
return symengine_current_y(index)
else:
return symengine_past_y(time, index, symengine_anchors(time))
symengine_current_y = symengine.Function("current_y",real=True)
symengine_past_y = symengine.Function("past_y",real=True)
symengine_anchors = symengine.Function("anchors",real=True)
symengine_manually = [
symengine_t,
symengine_y,
symengine.cos,
]
sympy_manually = [
sympy_t,
sympy_y,
sympy.cos,
]
jitcdde_provisions = [
self.substitutions = {
control_par: symengine.Symbol("self->parameter_"+control_par.name)
for control_par in self.control_pars
}
def finalise(expression):
expression = expression.subs(self.substitutions)
self.past_calls += count_calls(expression,anchors)
return expression
if helpers_wc:
get_helper = symengine.Function("get_f_helper")
set_helper = symengine.Function("set_f_helper")
get_anchor = symengine.Function("get_f_anchor_helper")
set_anchor = symengine.Function("set_f_anchor_helper")
for helper in helpers_wc:
if (
type(helper[1]) == type(anchors(0)) and
helper[1].get_name() == anchors.name
):
converted_helpers.append(set_anchor(anchor_i, finalise(helper[1])))
self.substitutions[helper[0]] = get_anchor(anchor_i)
anchor_i += 1
else:
converted_helpers.append(set_helper(helper_i, finalise(helper[1])))
self.substitutions[helper[0]] = get_helper(helper_i)
helper_i += 1
if helper_i:
arguments.append(("f_helper","double", helper_i))
"""
self._generate_helpers_C()
# working copy
jac_sym_wc = ( (entry.subs(self.general_subs) for entry in line) for line in self.jac_sym )
self.sparse_jac = sparse
arguments = self._default_arguments()
if self.helpers:
arguments.append(("general_helper","double const *__restrict const"))
if do_cse:
import sympy
get_helper = sympy.Function("get_jac_helper")
set_helper = symengine.Function("set_jac_helper")
jac_sym_wc = sympy.Matrix([
[ sympy.sympify(entry) for entry in line ]
for line in jac_sym_wc
])
_cse = sympy.cse(
sympy.sympify(jac_sym_wc),
symbols = (get_helper(i) for i in count())
)
more_helpers = symengine.sympify(_cse[0])
jac_sym_wc = symengine.sympify(_cse[1][0].tolist())
if more_helpers:
arguments.append(("jac_helper","double *__restrict const"))
self.render_and_write_code(
(set_helper(i, helper[1]) for i,helper in enumerate(more_helpers)),
def generate_helpers_C(self, chunk_size=100):
"""
translates the helpers to C code using SymEngine’s `C-code printer `_.
Parameters
----------
chunk_size : integer
If the number of instructions in the final C code exceeds this number, it will be split into chunks of this size. See `large_systems` on why this is useful.
If there is an obvious grouping of your helpers, the group size suggests itself for `chunk_size`.
If smaller than 1, no chunking will happen.
"""
if self.helpers:
get_helper = symengine.Function("get_general_helper")
set_helper = symengine.Function("set_general_helper")
for i,helper in enumerate(self.helpers):
self.general_subs[helper[0]] = get_helper(i)
self.render_and_write_code(
(set_helper(i, helper[1].subs(self.general_subs)) for i,helper in enumerate(self.helpers)),
name = "general_helpers",
chunk_size = chunk_size,
arguments = self._default_arguments() + [("general_helper","double *__restrict const")],
omp = False,
)
self._helper_C_source = True
)
more_helpers = symengine.sympify(_cse[0])
jac_sym_wc = symengine.sympify(_cse[1][0].tolist())
if more_helpers:
arguments.append(("jac_helper","double *__restrict const"))
self.render_and_write_code(
(set_helper(i, helper[1]) for i,helper in enumerate(more_helpers)),
name = "jac_helpers",
chunk_size = chunk_size,
arguments = arguments,
omp = False
)
self._number_of_jac_helpers = len(more_helpers)
set_dfdy = symengine.Function("set_dfdy")
self.render_and_write_code(
(
set_dfdy(i,j,entry)
for i,line in enumerate(jac_sym_wc)
for j,entry in enumerate(line)
if ( (entry != 0) or not self.sparse_jac )
),
name = "jac",
chunk_size = chunk_size,
arguments = arguments+[("dfdY", "PyArrayObject *__restrict const")]
)
self._jac_C_source = True
def dy(index,time):
"""
This is the function representing the DDE’s past derivative used for defining the differential equation. The first integer argument denotes the component. The second, argument denotes the time. If you use this, you get a neutral DDE which may make addressing initial discontinuities more difficult. Do not use this to get the current derivative. Instead compute it using your dynamical equations. This will not work with tangential Lyapunov exponents.
**This feature is experimental.**
This automatically expands to using `current_y`, `past_y`, and `anchors`; so do not be surprised when you look at the output and it is different than what you entered or expected. You can import a SymPy variant from the submodule `sympy_symbols` instead (see `SymPy vs. SymEngine`_ for details).
"""
if time == t:
raise ValueError("Do not use `dy` to compute the current derivative. Use your dynamical equations instead.")
else:
return past_dy(time, index, anchors(time))
#: the symbol for the current state for defining the differential equation. It is a function and the integer argument denotes the component. This is only needed for specific optimisations of large DDEs; in all other cases use `y` instead. You can import a SymPy variant from the submodule `sympy_symbols` instead (see `SymPy vs. SymEngine`_ for details).
current_y = symengine.Function("current_y")
#: the symbol for DDE’s past state for defining differential equation. It is a function with the first integer argument denoting the component and the second argument being a pair of past points (as being returned by `anchors`) from which the past state is interpolated (or, in rare cases, extrapolated). This is only needed for specific optimisations of large DDEs; in all other cases use `y` instead. You can import a SymPy variant from the submodule `sympy_symbols` instead (see `SymPy vs. SymEngine`_ for details).
past_y = symengine.Function("past_y")
#: the symbol for DDE’s past derivative for defining differential equation. It is a function with the first integer argument denoting the component and the second argument being a pair of past points (as being returned by `anchors`) from which the past state is interpolated (or, in rare cases, extrapolated). This is only needed for specific optimisations of large DDEs; in all other cases use `dy` instead. You can import a SymPy variant from the submodule `sympy_symbols` instead (see `SymPy vs. SymEngine`_ for details).
past_dy = symengine.Function("past_dy")
#: the symbol representing two anchors for defining the differential equation. It is a function and the float argument denotes the time point to which the anchors pertain. This is only needed for specific optimisations of large DDEs; in all other cases use `y` instead. You can import a SymPy variant from the submodule `sympy_symbols` instead (see `SymPy vs. SymEngine`_ for details).
anchors = symengine.Function("anchors")
def _get_delays(f, helpers=()):
delay_terms = set().union(*(collect_arguments(entry, anchors) for entry in f()))
delay_terms.update(*(collect_arguments(helper[1], anchors) for helper in helpers))
delays = [
(t-delay_term[0]).simplify()
for delay_term in delay_terms
)
more_helpers = symengine.sympify(_cse[0])
f_sym_wc = symengine.sympify(_cse[1][0])
if more_helpers:
arguments.append(("f_helper","double *__restrict const"))
self.render_and_write_code(
(set_helper(i,helper[1]) for i,helper in enumerate(more_helpers)),
name = "f_helpers",
chunk_size = chunk_size,
arguments = arguments,
omp = False,
)
self._number_of_f_helpers = len(more_helpers)
set_dy = symengine.Function("set_dy")
self.render_and_write_code(
(set_dy(i,entry) for i,entry in enumerate(f_sym_wc)),
name = "f",
chunk_size = chunk_size,
arguments = arguments+[("dY", "PyArrayObject *__restrict const")]
)
self._f_C_source = True