Code Monkey home page Code Monkey logo

diffeqpy's Introduction

diffeqpy

Join the chat at https://gitter.im/JuliaDiffEq/Lobby CI

diffeqpy is a package for solving differential equations in Python. It utilizes DifferentialEquations.jl for its core routines to give high performance solving of many different types of differential equations, including:

  • Discrete equations (function maps, discrete stochastic (Gillespie/Markov) simulations)
  • Ordinary differential equations (ODEs)
  • Split and Partitioned ODEs (Symplectic integrators, IMEX Methods)
  • Stochastic ordinary differential equations (SODEs or SDEs)
  • Random differential equations (RODEs or RDEs)
  • Differential algebraic equations (DAEs)
  • Delay differential equations (DDEs)
  • Mixed discrete and continuous equations (Hybrid Equations, Jump Diffusions)

directly in Python.

If you have any questions, or just want to chat about solvers/using the package, please feel free to chat in the Gitter channel. For bug reports, feature requests, etc., please submit an issue.

Installation

To install diffeqpy, use pip:

pip install diffeqpy

and you're good!

Collab Notebook Examples

General Flow

Import and setup the solvers available in DifferentialEquations.jl via the command:

from diffeqpy import de

In case only the solvers available in OrdinaryDiffEq.jl are required then use the command:

from diffeqpy import ode

The general flow for using the package is to follow exactly as would be done in Julia, except add de. or ode. in front. Note that ode. has lesser loading time and a smaller memory footprint compared to de.. Most of the commands will work without any modification. Thus the DifferentialEquations.jl documentation and the DiffEqTutorials are the main in-depth documentation for this package. Below we will show how to translate these docs to Python code.

Note about !

Python does not allow ! in function names, so this is also a limitation of pyjulia To use functions which on the Julia side have a !, like step!, replace ! by _b, for example:

from diffeqpy import de

def f(u,p,t):
    return -u

u0 = 0.5
tspan = (0., 1.)
prob = de.ODEProblem(f, u0, tspan)
integrator = de.init(prob, de.Tsit5())
de.step_b(integrator)

is valid Python code for using the integrator interface.

Ordinary Differential Equation (ODE) Examples

One-dimensional ODEs

from diffeqpy import de

def f(u,p,t):
    return -u

u0 = 0.5
tspan = (0., 1.)
prob = de.ODEProblem(f, u0, tspan)
sol = de.solve(prob)

The solution object is the same as the one described in the DiffEq tutorials and in the solution handling documentation (note: the array interface is missing). Thus for example the solution time points are saved in sol.t and the solution values are saved in sol.u. Additionally, the interpolation sol(t) gives a continuous solution.

We can plot the solution values using matplotlib:

import matplotlib.pyplot as plt
plt.plot(sol.t,sol.u)
plt.show()

f1

We can utilize the interpolation to get a finer solution:

import numpy
t = numpy.linspace(0,1,100)
u = sol(t)
plt.plot(t,u)
plt.show()

f2

Solve commands

The common interface arguments can be used to control the solve command. For example, let's use saveat to save the solution at every t=0.1, and let's utilize the Vern9() 9th order Runge-Kutta method along with low tolerances abstol=reltol=1e-10:

sol = de.solve(prob,de.Vern9(),saveat=0.1,abstol=1e-10,reltol=1e-10)

The set of algorithms for ODEs is described at the ODE solvers page.

Compilation with de.jit and Julia

When solving a differential equation, it's pertinent that your derivative function f is fast since it occurs in the inner loop of the solver. We can convert the entire ode problem to symbolic form, optimize that symbolic form, and emit efficient native code to simulate it using de.jit to improve the efficiency of the solver at the expense of added setup time:

fast_prob = de.jit(prob)
sol = de.solve(fast_prob)

Additionally, you can directly define the functions in Julia. This will also allow for specialization and could be helpful to increase the efficiency for repeat or long calls. This is done via seval:

jul_f = de.seval("(u,p,t)->-u") # Define the anonymous function in Julia
prob = de.ODEProblem(jul_f, u0, tspan)
sol = de.solve(prob)

Limitations

de.jit, uses ModelingToolkit.jl's modelingtoolkitize internally and some restrictions apply. Not all models can be jitted. See the modelingtoolkitize documentation for more info.

Systems of ODEs: Lorenz Equations

To solve systems of ODEs, simply use an array as your initial condition and define f as an array function:

def f(u,p,t):
    x, y, z = u
    sigma, rho, beta = p
    return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]

u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,8/3]
prob = de.ODEProblem(f, u0, tspan, p)
sol = de.solve(prob,saveat=0.01)

plt.plot(sol.t,de.transpose(de.stack(sol.u)))
plt.show()

f3

or we can draw the phase plot:

us = de.stack(sol.u)
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(us[0,:],us[1,:],us[2,:])
plt.show()

f4

In-Place Mutating Form

When dealing with systems of equations, in many cases it's helpful to reduce memory allocations by using mutating functions. In diffeqpy, the mutating form adds the mutating vector to the front. Let's make a fast version of the Lorenz derivative, i.e. mutating and JIT compiled:

def f(du,u,p,t):
    x, y, z = u
    sigma, rho, beta = p
    du[0] = sigma * (y - x)
    du[1] = x * (rho - z) - y
    du[2] = x * y - beta * z

u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(f, u0, tspan, p)
jit_prob = de.jit(prob)
sol = de.solve(jit_prob)

or using a Julia function:

jul_f = de.seval("""
function f(du,u,p,t)
  x, y, z = u
  sigma, rho, beta = p
  du[1] = sigma * (y - x)
  du[2] = x * (rho - z) - y
  du[3] = x * y - beta * z
end""")
u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(jul_f, u0, tspan, p)
sol = de.solve(prob)

Stochastic Differential Equation (SDE) Examples

One-dimensional SDEs

Solving one-dimensonal SDEs du = f(u,t)dt + g(u,t)dW_t is like an ODE except with an extra function for the diffusion (randomness or noise) term. The steps follow the SDE tutorial.

def f(u,p,t):
  return 1.01*u

def g(u,p,t):
  return 0.87*u

u0 = 0.5
tspan = (0.0,1.0)
prob = de.SDEProblem(f,g,u0,tspan)
sol = de.solve(prob,reltol=1e-3,abstol=1e-3)

plt.plot(sol.t,de.stack(sol.u))
plt.show()

f5

Systems of SDEs with Diagonal Noise

An SDE with diagonal noise is where a different Wiener process is applied to every part of the system. This is common for models with phenomenological noise. Let's add multiplicative noise to the Lorenz equation:

def f(du,u,p,t):
    x, y, z = u
    sigma, rho, beta = p
    du[0] = sigma * (y - x)
    du[1] = x * (rho - z) - y
    du[2] = x * y - beta * z

def g(du,u,p,t):
    du[0] = 0.3*u[0]
    du[1] = 0.3*u[1]
    du[2] = 0.3*u[2]

u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.jit(de.SDEProblem(f, g, u0, tspan, p))
sol = de.solve(prob)

# Now let's draw a phase plot

us = de.stack(sol.u)
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(us[0,:],us[1,:],us[2,:])
plt.show()

f6

Systems of SDEs with Non-Diagonal Noise

In many cases you may want to share noise terms across the system. This is known as non-diagonal noise. The DifferentialEquations.jl SDE Tutorial explains how the matrix form of the diffusion term corresponds to the summation style of multiple Wiener processes. Essentially, the row corresponds to which system the term is applied to, and the column is which noise term. So du[i,j] is the amount of noise due to the jth Wiener process that's applied to u[i]. We solve the Lorenz system with correlated noise as follows:

def f(du,u,p,t):
  x, y, z = u
  sigma, rho, beta = p
  du[0] = sigma * (y - x)
  du[1] = x * (rho - z) - y
  du[2] = x * y - beta * z

def g(du,u,p,t):
  du[0,0] = 0.3*u[0]
  du[1,0] = 0.6*u[0]
  du[2,0] = 0.2*u[0]
  du[0,1] = 1.2*u[1]
  du[1,1] = 0.2*u[1]
  du[2,1] = 0.3*u[1]


u0 = [1.0,0.0,0.0]
tspan = (0.0,100.0)
p = [10.0,28.0,2.66]
nrp = numpy.zeros((3,2))
prob = de.SDEProblem(f,g,u0,tspan,p,noise_rate_prototype=nrp)
jit_prob = de.jit(prob)
sol = de.solve(jit_prob,saveat=0.005)

# Now let's draw a phase plot

us = de.stack(sol.u)
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(us[0,:],us[1,:],us[2,:])
plt.show()

f7

Here you can see that the warping effect of the noise correlations is quite visible!

Differential-Algebraic Equation (DAE) Examples

A differential-algebraic equation is defined by an implicit function f(du,u,p,t)=0. All of the controls are the same as the other examples, except here you define a function which returns the residuals for each part of the equation to define the DAE. The initial value u0 and the initial derivative du0 are required, though they do not necessarily have to satisfy f (known as inconsistent initial conditions). The methods will automatically find consistent initial conditions. In order for this to occur, differential_vars must be set. This vector states which of the variables are differential (have a derivative term), with false meaning that the variable is purely algebraic.

This example shows how to solve the Robertson equation:

def f(du,u,p,t):
  resid1 = - 0.04*u[0]               + 1e4*u[1]*u[2] - du[0]
  resid2 = + 0.04*u[0] - 3e7*u[1]**2 - 1e4*u[1]*u[2] - du[1]
  resid3 = u[0] + u[1] + u[2] - 1.0
  return [resid1,resid2,resid3]

u0 = [1.0, 0.0, 0.0]
du0 = [-0.04, 0.04, 0.0]
tspan = (0.0,100000.0)
differential_vars = [True,True,False]
prob = de.DAEProblem(f,du0,u0,tspan,differential_vars=differential_vars)
sol = de.solve(prob)

f8

and the in-place JIT compiled form:

def f(resid,du,u,p,t):
  resid[0] = - 0.04*u[0]               + 1e4*u[1]*u[2] - du[0]
  resid[1] = + 0.04*u[0] - 3e7*u[1]**2 - 1e4*u[1]*u[2] - du[1]
  resid[2] = u[0] + u[1] + u[2] - 1.0

prob = de.DAEProblem(f,du0,u0,tspan,differential_vars=differential_vars)
jit_prob = de.jit(prob) # Error: no method matching matching modelingtoolkitize(::SciMLBase.DAEProblem{...})
sol = de.solve(jit_prob)

Mass Matrices, Sparse Arrays, and More

Mass matrix DAEs, along with many other forms, can be handled by doing an explicit conversion to the Julia types. See the PythonCall module's documentation for more details.

As an example, let's convert the mass matrix ODE tutorial in diffeqpy. To do this, the one aspect we need to handle is the conversion of the mass matrix in to a Julia array object. This is done as follows:

from diffeqpy import de
from juliacall import Main as jl
import numpy as np

def rober(du, u, p, t):
    y1, y2, y3 = u
    k1, k2, k3 = p
    du[0] = -k1 * y1 + k3 * y2 * y3
    du[1] = k1 * y1 - k3 * y2 * y3 - k2 * y2**2
    du[2] = y1 + y2 + y3 - 1
    return

M = np.array([[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,0.0]])
f = de.ODEFunction(rober, mass_matrix = jl.convert(jl.Array,M))
prob_mm = de.ODEProblem(f, [1.0, 0.0, 0.0], (0.0, 1e5), (0.04, 3e7, 1e4))
sol = de.solve(prob_mm, de.Rodas5P(), reltol = 1e-8, abstol = 1e-8)

Notice the only addition is to create the np.array object and to perform the manual conversion via jl.convert(jl.Array,M) to receive the Julia Array object. This can be done in any case where diffeqpy is not adequately auto-converting to the right Julia type. In some cases this can be used to improve performance, though here we do it simply for compatability.

Similarly, sparse matrices can be passed in much the same way. For example:

import scipy
spM = scipy.sparse.csr_array(M)
jl.seval("using SparseArrays")

f = de.ODEFunction(rober, mass_matrix = jl.convert(jl.SparseMatrixCSC,M))
prob_mm = de.ODEProblem(f, [1.0, 0.0, 0.0], (0.0, 1e5), (0.04, 3e7, 1e4))
sol = de.solve(prob_mm, de.Rodas5P(), reltol = 1e-8, abstol = 1e-8)

Delay Differential Equations

A delay differential equation is an ODE which allows the use of previous values. In this case, the function needs to be a JIT compiled Julia function. It looks just like the ODE, except in this case there is a function h(p,t) which allows you to interpolate and grab previous values.

We must provide a history function h(p,t) that gives values for u before t0. Here we assume that the solution was constant before the initial time point. Additionally, we pass constant_lags = [20.0] to tell the solver that only constant-time lags were used and what the lag length was. This helps improve the solver accuracy by accurately stepping at the points of discontinuity. Together this is:

f = de.seval("""
function f(du, u, h, p, t)
  du[1] = 1.1/(1 + sqrt(10)*(h(p, t-20)[1])^(5/4)) - 10*u[1]/(1 + 40*u[2])
  du[2] = 100*u[1]/(1 + 40*u[2]) - 2.43*u[2]
end""")
u0 = [1.05767027/3, 1.030713491/3]

h = de.seval("""
function h(p,t)
  [1.05767027/3, 1.030713491/3]
end
""")

tspan = (0.0, 100.0)
constant_lags = [20.0]
prob = de.DDEProblem(f,u0,h,tspan,constant_lags=constant_lags)
sol = de.solve(prob,saveat=0.1)

u1 = [sol.u[i][0] for i in range(0,len(sol.u))]
u2 = [sol.u[i][1] for i in range(0,len(sol.u))]

import matplotlib.pyplot as plt
plt.plot(sol.t,u1)
plt.plot(sol.t,u2)
plt.show()

dde

Notice that the solver accurately is able to simulate the kink (discontinuity) at t=20 due to the discontinuity of the derivative at the initial time point! This is why declaring discontinuities can enhance the solver accuracy.

GPU-Accelerated ODE Solving of Ensembles

In many cases one is interested in solving the same ODE many times over many different initial conditions and parameters. In diffeqpy parlance this is called an ensemble solve. diffeqpy inherits the parallelism tools of the SciML ecosystem that are used for things like automated equation discovery and acceleration. Here we will demonstrate using these parallel tools to accelerate the solving of an ensemble.

First, let's define the JIT-accelerated Lorenz equation like before:

from diffeqpy import de

def f(u,p,t):
    x, y, z = u
    sigma, rho, beta = p
    return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]

u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,8/3]
prob = de.ODEProblem(f, u0, tspan, p)
fast_prob = de.jit32(prob)
sol = de.solve(fast_prob,saveat=0.01)

Note that here we used de.jit32 to JIT-compile the problem into a Float32 form in order to make it more efficient on most GPUs.

Now we use the EnsembleProblem as defined on the ensemble parallelism page of the documentation: Let's build an ensemble by utilizing uniform random numbers to randomize the initial conditions and parameters:

import random
def prob_func(prob,i,rep):
  return de.remake(prob,u0=[random.uniform(0, 1)*u0[i] for i in range(0,3)],
            p=[random.uniform(0, 1)*p[i] for i in range(0,3)])

ensembleprob = de.EnsembleProblem(fast_prob, prob_func=prob_func, safetycopy=False)

Now we solve the ensemble in serial:

sol = de.solve(ensembleprob,de.Tsit5(),de.EnsembleSerial(),trajectories=10000,saveat=0.01)

To add GPUs to the mix, we need to bring in DiffEqGPU. The command from diffeqpy import cuda will install CUDA for you and bring all of the bindings into the returned object:

Note: from diffeqpy import cuda can take awhile to run the first time as it installs the drivers!

Now we simply use EnsembleGPUKernel(cuda.CUDABackend()) with a GPU-specialized ODE solver cuda.GPUTsit5() to solve 10,000 ODEs on the GPU in parallel:

sol = de.solve(ensembleprob,cuda.GPUTsit5(),cuda.EnsembleGPUKernel(cuda.CUDABackend()),trajectories=10000,saveat=0.01)

For the full list of choices for specialized GPU solvers, see the DiffEqGPU.jl documentation.

Note that EnsembleGPUArray can be used as well, like:

sol = de.solve(ensembleprob,de.Tsit5(),cuda.EnsembleGPUArray(cuda.CUDABackend()),trajectories=10000,saveat=0.01)

though we highly recommend the EnsembleGPUKernel methods for more speed. Given the way the JIT compilation performed will also ensure that the faster kernel generation methods work, EnsembleGPUKernel is almost certainly the better choice in most applications.

Benchmark

To see how much of an effect the parallelism has, let's test this against R's deSolve package. This is exactly the same problem as the documentation example for deSolve, so let's copy that verbatim and then add a function to do the ensemble generation:

import numpy as np
from scipy.integrate import odeint

def lorenz(state, t, sigma, beta, rho):
    x, y, z = state

    dx = sigma * (y - x)
    dy = x * (rho - z) - y
    dz = x * y - beta * z

    return [dx, dy, dz]

sigma = 10.0
beta = 8.0 / 3.0
rho = 28.0
p = (sigma, beta, rho)
y0 = [1.0, 1.0, 1.0]

t = np.arange(0.0, 100.0, 0.01)
result = odeint(lorenz, y0, t, p)

Using lapply to generate the ensemble we get:

import timeit
def time_func():
    for itr in range(1, 1001):
        result = odeint(lorenz, y0, t, p)

timeit.Timer(time_func).timeit(number=1)

# 38.08861699999761 seconds

Now let's see how the JIT-accelerated serial Julia version stacks up against that:

def time_func():
    sol = de.solve(ensembleprob,de.Tsit5(),de.EnsembleSerial(),trajectories=1000,saveat=0.01)

timeit.Timer(time_func).timeit(number=1)

# 3.1903300999983912

Julia is already about 12x faster than the pure Python solvers here! Now let's add GPU-acceleration to the mix:

def time_func():
    sol = de.solve(ensembleprob,cuda.GPUTsit5(),cuda.EnsembleGPUKernel(cuda.CUDABackend()),trajectories=1000,saveat=0.01)

timeit.Timer(time_func).timeit(number=1)

# 0.013322799997695256

Already 2900x faster than SciPy! But the GPU acceleration is made for massively parallel problems, so let's up the trajectories a bit. We will not use more trajectories from R because that would take too much computing power, so let's see what happens to the Julia serial and GPU at 10,000 trajectories:

def time_func():
    sol = de.solve(ensembleprob,de.Tsit5(),de.EnsembleSerial(),trajectories=10000,saveat=0.01)

timeit.Timer(time_func).timeit(number=1)

# 68.80795999999827
def time_func():
    sol = de.solve(ensembleprob,cuda.GPUTsit5(),cuda.EnsembleGPUKernel(cuda.CUDABackend()),trajectories=10000,saveat=0.01)

timeit.Timer(time_func).timeit(number=1)

# 0.10774460000175168

To compare this to the pure Julia code:

using OrdinaryDiffEq, DiffEqGPU, CUDA, StaticArrays
function lorenz(u, p, t)
    σ = p[1]
    ρ = p[2]
    β = p[3]
    du1 = σ * (u[2] - u[1])
    du2 = u[1] *- u[3]) - u[2]
    du3 = u[1] * u[2] - β * u[3]
    return SVector{3}(du1, du2, du3)
end

u0 = SA[1.0f0; 0.0f0; 0.0f0]
tspan = (0.0f0, 10.0f0)
p = SA[10.0f0, 28.0f0, 8 / 3.0f0]
prob = ODEProblem{false}(lorenz, u0, tspan, p)
prob_func = (prob, i, repeat) -> remake(prob, p = (@SVector rand(Float32, 3)) .* p)
monteprob = EnsembleProblem(prob, prob_func = prob_func, safetycopy = false)
@time sol = solve(monteprob, GPUTsit5(), EnsembleGPUKernel(CUDA.CUDABackend()),
    trajectories = 10_000,
    saveat = 0.01);

# 0.014481 seconds (257.64 k allocations: 13.130 MiB)

which is about an order of magnitude faster for computing 10,000 trajectories, note that the major factors are that we cannot define 32-bit floating point values from Python and the prob_func for generating the initial conditions and parameters is a major bottleneck since this function is written in Python.

To see how this scales in Julia, let's take it to insane heights. First, let's reduce the amount we're saving:

@time sol = solve(monteprob,GPUTsit5(),EnsembleGPUKernel(CUDA.CUDABackend()),trajectories=10_000,saveat=1.0f0)
0.015040 seconds (257.64 k allocations: 13.130 MiB)

This highlights that controlling memory pressure is key with GPU usage: you will get much better performance when requiring less saved points on the GPU.

@time sol = solve(monteprob,GPUTsit5(),EnsembleGPUKernel(CUDA.CUDABackend()),trajectories=100_000,saveat=1.0f0)
# 0.150901 seconds (2.60 M allocations: 131.576 MiB)

compared to serial:

@time sol = solve(monteprob,Tsit5(),EnsembleSerial(),trajectories=100_000,saveat=1.0f0)
# 22.136743 seconds (16.40 M allocations: 1.628 GiB, 42.98% gc time)

And now we start to see that scaling power! Let's solve 1 million trajectories:

@time sol = solve(monteprob,GPUTsit5(),EnsembleGPUKernel(CUDA.CUDABackend()),trajectories=1_000_000,saveat=1.0f0)
# 1.031295 seconds (3.40 M allocations: 241.075 MiB)

For reference, let's look at deSolve with the change to only save that much:

t = np.arange(0.0, 100.0, 1.0)
def time_func():
    for itr in range(1, 1001):
        result = odeint(lorenz, y0, t, p)

timeit.Timer(time_func).timeit(number=1)

# 37.42609280000033

The GPU version is solving 1000x as many trajectories, 37x as fast! So conclusion, if you need the most speed, you may want to move to the Julia version to get the most out of your GPU due to Float32's, and when using GPUs make sure it's a problem with a relatively average or low memory pressure, and these methods will give orders of magnitude acceleration compared to what you might be used to.

GPU Backend Choices

Just like DiffEqGPU.jl, diffeqpy supports many different GPU venders. from diffeqpy import cuda is just for cuda, but the following others are supported:

  • from diffeqpy import cuda with cuda.CUDABackend for NVIDIA GPUs via CUDA
  • from diffeqpy import amdgpu with amdgpu.AMDGPUBackend for AMD GPUs
  • from diffeqpy import oneapi with oneapi.oneAPIBackend for Intel's oneAPI GPUs
  • from diffeqpy import metal with metal.MetalBackend for Apple's Metal GPUs (on M-series processors)

For more information, see the DiffEqGPU.jl documentation.

Known Limitations

  • Autodiff does not work on Python functions. When applicable, either define the derivative function as a Julia function or set the algorithm to use finite differencing, i.e. Rodas5(autodiff=false). All default methods use autodiff.
  • Delay differential equations have to use Julia-defined functions otherwise the history function is not appropriately typed with the overloads.

Testing

Unit tests can be run by tox.

tox

Troubleshooting

In case you encounter silent failure from tox, try running it with -- -s (e.g., tox -e py36 -- -s) where -s option (--capture=no, i.e., don't capture stdio) is passed to py.test. It may show an error message "error initializing LibGit2 module". In this case, setting environment variable SSL_CERT_FILE may help; e.g., try:

SSL_CERT_FILE=PATH/TO/cert.pem tox -e py36

See also: julia#18693.

diffeqpy's People

Contributors

asinghvi17 avatar bjodah avatar chrisrackauckas avatar jonniedie avatar karajan9 avatar lilithhafner avatar pallharaldsson avatar sibyjackgrove avatar tkf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

diffeqpy's Issues

FileNotFoundError when trying to import diffeqpy from Jupyter

I have just installed Julia-1.2 on macOS (version 10.14.6 (18G3020)), and then installed diffeqpy. I tried to import it in a Jupyter notebook with the command from diffeqpy import de, but got this error message:

FileNotFoundError                         Traceback (most recent call last)
<ipython-input-5-65b37eb28595> in <module>
----> 1 from diffeqpy import de
      2 
      3 def f(u,p,t):
      4     return -u
      5 

/opt/anaconda3/lib/python3.7/site-packages/diffeqpy/de.py in <module>
      2 import sys
      3 
----> 4 from julia import Main
      5 
      6 script_dir = os.path.dirname(os.path.realpath(__file__))

/opt/anaconda3/lib/python3.7/importlib/_bootstrap.py in _find_and_load(name, import_)

/opt/anaconda3/lib/python3.7/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

/opt/anaconda3/lib/python3.7/importlib/_bootstrap.py in _load_unlocked(spec)

/opt/anaconda3/lib/python3.7/importlib/_bootstrap.py in _load_backward_compatible(spec)

/opt/anaconda3/lib/python3.7/site-packages/julia/core.py in load_module(self, fullname)
    244         if juliapath == 'Main':
    245             return sys.modules.setdefault(fullname,
--> 246                                           JuliaMainModule(self, fullname))
    247         elif self.julia.isafunction(juliapath):
    248             return self.julia.eval(juliapath)

/opt/anaconda3/lib/python3.7/site-packages/julia/core.py in __init__(self, loader, *args, **kwargs)
    146     def __init__(self, loader, *args, **kwargs):
    147         super(JuliaModule, self).__init__(*args, **kwargs)
--> 148         self._julia = loader.julia
    149         self.__loader__ = loader
    150 

/opt/anaconda3/lib/python3.7/site-packages/julia/core.py in julia(self)
    236     @property
    237     def julia(self):
--> 238         self.__class__.julia = julia = Julia()
    239         return julia
    240 

/opt/anaconda3/lib/python3.7/site-packages/julia/core.py in __init__(self, init_julia, jl_init_path, runtime, jl_runtime_path, debug, **julia_options)
    465             self.api = get_libjulia()
    466         elif init_julia:
--> 467             jlinfo = JuliaInfo.load(runtime)
    468             if jlinfo.version_info < (0, 7):
    469                 raise RuntimeError("PyJulia does not support Julia < 0.7 anymore")

/opt/anaconda3/lib/python3.7/site-packages/julia/juliainfo.py in load(cls, julia, **popen_kwargs)
     71             stderr=subprocess.PIPE,
     72             universal_newlines=True,
---> 73             **popen_kwargs
     74         )
     75 

/opt/anaconda3/lib/python3.7/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors, text)
    798                                 c2pread, c2pwrite,
    799                                 errread, errwrite,
--> 800                                 restore_signals, start_new_session)
    801         except:
    802             # Cleanup if the child failed starting.

/opt/anaconda3/lib/python3.7/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)
   1549                         if errno_num == errno.ENOENT:
   1550                             err_msg += ': ' + repr(err_filename)
-> 1551                     raise child_exception_type(errno_num, err_msg, err_filename)
   1552                 raise child_exception_type(err_msg)
   1553 

FileNotFoundError: [Errno 2] No such file or directory: 'julia': 'julia'

I tried to install and build IJulia but it doesn't seem to make a difference... any help?

Transpile sympy expressions to Julia?

Using Python function to define the problem is sadly inefficient. I think using sympy would be a nice solution for low-dimensional especially if you combine it with StaticArrays. (Though exposing ModelingToolkit.jl to Python would be much better.)

Here is a quick hack to do it for ODEProblem:

import sympy.printing


def as_ode_f_code(expr, u_syms, p_syms, name=""):
    ubase = sympy.IndexedBase("u")
    pbase = sympy.IndexedBase("p")
    u = [ubase[i + 1] for i in range(len(u_syms))]
    p = [pbase[i + 1] for i in range(len(p_syms))]
    expr = [e.subs(zip(u_syms, u)) for e in expr]
    expr = [e.subs(zip(p_syms, p)) for e in expr]

    du = sympy.Array(expr)
    body = sympy.printing.julia_code(du, contract=False)
    return f"""
    function {name}(u, p, t)
        StaticArrays.@SVector {body}
    end
    """


def jl_lambdify(expr, u_syms, p_syms, t_sym=sympy.symbols('t')):
    from julia import Main
    # eval(Module(), ...) can't be used:
    # https://github.com/JuliaLang/julia/issues/28917
    func = as_ode_f_code(expr, u_syms, p_syms)
    code = f"""
    import StaticArrays
    {func}
    """
    return Main.eval(code)


if __name__ == "__main__":
    def f(u, p, t):
        x, y, z = u
        sigma, rho, beta = p
        return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]

    u_syms = sympy.symbols("x, y, z")
    p_syms = sympy.symbols("sigma, rho, beta")
    expr = f(u_syms, p_syms, None)
    print(as_ode_f_code(expr, u_syms, p_syms))

    f = jl_lambdify(expr, u_syms, p_syms)

It generates (and print):

function (u, p, t)
    StaticArrays.@SVector [(-u[1] + u[2])*p[1], (p[2] - u[3])*u[1] - u[2], -p[3]*u[3] + u[1]*u[2]]
end

The only pitfall I had was that contract=False had to be passed to sympy.printing.julia_code.

the following import in python "from diffeqpy import de" takes 1-2 minutes to complete

Im running Julia 1.5.3 and Python 3.7 through the PyCharm IDE.

I set up as per the isntructions on the repository main page, the module eventually imports and the functions work as described, just the time to import it is something I've not seen before; is this a standard wait time everyone else experiences with this module or do I have a problem with my setup somewhere?

Thanks :)

Bundle Julia scripts (DiffEqPy.jl) in diffeqpy Python package?

Since current DiffEqPy.jl is very small, why not bundle it in the Python package? I've done it in #19 and it's not difficult.

This way, change in Julia code directly trigger the tests here. Also, we don't need to worry about DiffEqPy.jl-vs-diffeqpy API compatibility this way (although currently there is no complex API).

Crash at "from diffeqpy import de".

Hello,

Background:

I am using Julia v 0.6.2 and Python 3.6.3 (installed using Continuum's Anaconda) on Ubuntu 16.04 LTS.

I can successfully run DifferentialEquations from within Julia; for example http://docs.juliadiffeq.org/latest/tutorials/dde_example.html.

I need to run julia with the following command:

LD_PRELOAD=/home/phn/bin/anaconda3/envs/py36/lib/libz.so ~/bin/julia-d386e40c17/bin/julia

This command is needed to use pyplot; see JuliaPy/PyPlot.jl#151 .

When installing DifferentialEquations, with Pkg.add("DifferentialEquations"), I had started Julia using the above command and while the particular conda environment I want was activated(i.e., python points to python in this conda environment). I also had to create a symlink "gcc" that points to gcc inside this environment so that I can get Rmath to install. The system gcc I have is old and couldn't compile Rmath.

Issue:

When I run the Python statement "from diffeqpy import de" inside an IPython session, IPython crashes with
the following error:

In [1]: from diffeqpy import de
PyError (ccall(@pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, arg, C_NULL)) PyError (ccall(@pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, arg, C_NULL)) PyError (ccall(@pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, arg, C_NULL)) PyError (ccall(@pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, arg, C_NULL)) fatal: error thrown and no exception handler available.
PyCall.PyError(msg="ccall(@pysym(PyString_AsStringAndSize), Cint, (PyPtr, Ptr{Ptr{UInt8}}, Ptr{Int}), po, _ps_ptr, _ps_len)", T=PyCall.PyObject(o=0x0000555f8e49ff40), val=PyCall.PyObject(o=0x00007f4a131ea6d0), traceback=PyCall.PyObject(o=0x0000000000000000))
rec_backtrace at /buildworker/worker/package_linux64/build/src/stackwalk.c:84
record_backtrace at /buildworker/worker/package_linux64/build/src/task.c:245
jl_throw at /buildworker/worker/package_linux64/build/src/task.c:564
pyerr_check at /home/phn/.julia/v0.6/PyCall/src/exception.jl:58 [inlined]
pyerr_check at /home/phn/.julia/v0.6/PyCall/src/exception.jl:62 [inlined]
macro expansion at /home/phn/.julia/v0.6/PyCall/src/exception.jl:82 [inlined]
convert at /home/phn/.julia/v0.6/PyCall/src/conversions.jl:111
pystring at /home/phn/.julia/v0.6/PyCall/src/PyCall.jl:224
show at /home/phn/.julia/v0.6/PyCall/src/PyCall.jl:229
show_delim_array at ./show.jl:381
show at ./show.jl:397
unknown function (ip: 0x7f49f839a186)
jl_call_fptr_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:358 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:1926
show_default at ./show.jl:140
unknown function (ip: 0x7f49f8399c46)
jl_call_fptr_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:358 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:1926
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1424 [inlined]
jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:51
print at ./strings/io.jl:29
unknown function (ip: 0x7f49f83993c6)
jl_call_fptr_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:358 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:1926
#print_to_string#229 at ./strings/io.jl:102
pyraise at /home/phn/.julia/v0.6/PyCall/src/exception.jl:127
unknown function (ip: 0x7f49f8398f72)
jl_call_fptr_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:358 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:1926
_pyjlwrap_call at /home/phn/.julia/v0.6/PyCall/src/callback.jl:56
unknown function (ip: 0x7f49f838d735)
jl_call_fptr_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:339 [inlined]
jl_call_method_internal at /buildworker/worker/package_linux64/build/src/julia_internal.h:358 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:1926
pyjlwrap_call at /home/phn/.julia/v0.6/PyCall/src/callback.jl:63
unknown function (ip: 0x7f49f8363a9f)
_PyObject_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e11f00d)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e118b8a)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e118b8a)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyEval_EvalCodeEx at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyEval_EvalCode at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e13df2d)
PyCFunction_Call at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e118b8a)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e118b8a)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e118b8a)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyFunction_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyObject_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyObject_CallMethodIdObjArgs at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyImport_ImportModuleLevelObject at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e12a1d9)
PyCFunction_Call at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyFunction_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyObject_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyObject_CallMethodIdObjArgs at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyImport_ImportModuleLevelObject at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyEval_EvalCodeEx at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyEval_EvalCode at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e13df2d)
_PyCFunction_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e11eebb)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e11828d)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e118b8a)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
_PyFunction_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyObject_FastCallDict at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyObject_Call_Prepend at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyObject_Call at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e117f23)
unknown function (ip: 0x555f8e118dc0)
unknown function (ip: 0x555f8e11ef94)
_PyEval_EvalFrameDefault at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyEval_EvalCodeEx at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyEval_EvalCode at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
unknown function (ip: 0x555f8e194ce3)
PyRun_FileExFlags at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
PyRun_SimpleFileExFlags at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
Py_Main at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
main at /home/phn/bin/anaconda3/envs/py36/bin/python (unknown line)
__libc_start_main at /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
unknown function (ip: 0x555f8e1470d9)


Hope this helps you identify the problem(either on my side or with diffeqpy). Let me know if you need more information.

Thanks.

Regards,
Prasanth

Can't get diffeqpy to run

I have Anaconda3 and Julia 1.1 installed on OS X.
I tried installing diffeqpy and running the small example given on the website, but got the following error (attached). Any idea what the issue might be?

`In [1]: from diffeqpy import de
   ...: 
   ...: def f(u,p,t):
   ...:     return -u
   ...: 
   ...: u0 = 0.5
   ...: tspan = (0., 1.)
   ...: prob = de.ODEProblem(f, u0, tspan)
   ...: sol = de.solve(prob)
   ...: 
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-1-65b37eb28595> in <module>()
----> 1 from diffeqpy import de
      2 
      3 def f(u,p,t):
      4     return -u
      5 

/anaconda3/lib/python3.6/site-packages/diffeqpy/de.py in <module>()
      2 import sys
      3 
----> 4 from julia import Main
      5 
      6 script_dir = os.path.dirname(os.path.realpath(__file__))

/anaconda3/lib/python3.6/importlib/_bootstrap.py in _find_and_load(name, import_)

/anaconda3/lib/python3.6/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

/anaconda3/lib/python3.6/importlib/_bootstrap.py in _load_unlocked(spec)

/anaconda3/lib/python3.6/importlib/_bootstrap.py in _load_backward_compatible(spec)

/anaconda3/lib/python3.6/site-packages/julia/core.py in load_module(self, fullname)
    178         if juliapath == 'Main':
    179             return sys.modules.setdefault(fullname,
--> 180                                           JuliaMainModule(self, fullname))
    181         elif isafunction(self.julia, juliapath):
    182             return self.julia.eval(juliapath)

/anaconda3/lib/python3.6/site-packages/julia/core.py in __init__(self, loader, *args, **kwargs)
     83     def __init__(self, loader, *args, **kwargs):
     84         super(JuliaModule, self).__init__(*args, **kwargs)
---> 85         self._julia = loader.julia
     86         self.__loader__ = loader
     87 

/anaconda3/lib/python3.6/site-packages/julia/core.py in julia(self)
    170     @property
    171     def julia(self):
--> 172         self.__class__.julia = julia = Julia()
    173         return julia
    174 

/anaconda3/lib/python3.6/site-packages/julia/core.py in __init__(self, init_julia, jl_init_path, runtime, jl_runtime_path, debug)
    612                         "PyJulia does not support Julia < 0.6 anymore")
    613                 elif version_range == 1:
--> 614                     raise_separate_cache_error(runtime, jlinfo)
    615                 # Intercept precompilation
    616                 os.environ["PYCALL_PYTHON_EXE"] = sys.executable

/anaconda3/lib/python3.6/site-packages/julia/core.py in raise_separate_cache_error(runtime, jlinfo, _determine_if_statically_linked)
    426         jl_libpython=normalize_path(jlinfo.libpython),
    427         sys=sys)
--> 428     raise RuntimeError(message)
    429 
    430 

RuntimeError: It seems your Julia and PyJulia setup are not supported.

Julia interpreter:
    julia
Python interpreter and libpython used by PyCall.jl:
    /Users/kamesh/.julia/conda/3/bin/python
    /Users/kamesh/.julia/conda/3/lib/libpython3.7m.dylib
Python interpreter used to import PyJulia and its libpython.
    /anaconda3/bin/python
    /anaconda3/lib/libpython3.6m.dylib

Your Python interpreter "/anaconda3/bin/python"
is statically linked to libpython.  Currently, PyJulia does not support
such Python interpreter.  One easy workaround is to run your Python
script with `python-jl` command bundled in PyJulia.  You can simply do:

    python-jl PATH/TO/YOUR/SCRIPT.py

See `python-jl --help` for more information.

For other available workarounds, see:
    https://github.com/JuliaPy/pyjulia#troubleshooting

For more information, see:
    https://github.com/JuliaPy/pyjulia
    https://github.com/JuliaPy/PyCall.jl`

Using class bound methods as the RHS for solving ODEs

I have a function bound to a class that I want to use for solving my ODEs, for example

class potclass:
    def __init__(self):
        self.f_eval = 0
    def get_negative_grad(self, u, p, t):
        self.f_eval += 1
        return -2*u

where I'm interested in using pot.get_negative_grad as f(u, p, t)

I'm now initializing my problem with

u0 = 0.5
pot = potclass()
tspan = (0, 1.0)
print(pot.get_negative_grad(1, 1, 1))
prob = de.ODEProblem(pot.get_negative_grad,u0, tspan)
de.init(prob, de.Tsit5())

however, running the code with python-jl with Julia 1.5 and python 3.8.1 causes an error, maybe since python implicitly uses the first argument as self(?).

is there any way I can pass class-bound methods as the functions for the ode solver since all my functions of interest are bound to classes?

I have attached the python file along with the output I got in the zipped folder
code_and_output.zip

EXCEPTION_ACCESS_VIOLATION from Sundials

I see this error in Python 3 test on AppVeyor in #39 / 81bf0fd

Exception: EXCEPTION_ACCESS_VIOLATION at 0x653414d3 -- N_VGetArrayPointer_Serial at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\deps\usr\bin\libsundials_nvecserial.dll (unknown line)
in expression starting at no file:0
N_VGetArrayPointer_Serial at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\deps\usr\bin\libsundials_nvecserial.dll (unknown line)
Type at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\src\wrapped_api\nvector.jl:116 [inlined]
convert at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\src\nvector_wrapper.jl:54 [inlined]
IDAInit at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\src\wrapped_api\idas.jl:116
unknown function (ip: 00000092F233105C)
jl_fptr_trampoline at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:1831
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:2184
#__init#58 at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\src\common_interface\solve.jl:720
#__init at .\none:0
#init#428 at C:\Users\appveyor\.julia\packages\DiffEqBase\ZQVwI\src\solve.jl:20 [inlined]
#init at .\none:0 [inlined]
#__solve#19 at C:\Users\appveyor\.julia\packages\Sundials\eAJ5O\src\common_interface\solve.jl:10
unknown function (ip: 00000092F2326960)
jl_fptr_trampoline at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:1831
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:2184 [inlined]
jl_apply at /home/Administrator/buildbot/worker/package_win64/build/src\julia.h:1537 [inlined]
jl_invoke at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:56
#__solve at .\none:0 [inlined]
#__solve at .\none:0 [inlined]
#__solve at .\none:0 [inlined]
#__solve at .\none:0 [inlined]
#__solve at .\none:0
unknown function (ip: 00000092F23264D7)
jl_fptr_trampoline at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:1831
jl_apply_generic at /home/Administrator/buildbot/worker/package_win64/build/src\gf.c:2184
#__solve#2 at C:\Users\appveyor\.julia\packages\DifferentialEquations\UZIcy\src\default_solve.jl:15

See full trace here https://ci.appveyor.com/project/ChrisRackauckas/diffeqpy/builds/23656293/job/syfa8el2iuyt7sgv#L303

Error importing diffeqpy

I get an exception when I import diffeqpy:

$ python -c"from diffeqpy import de"
Failed to import the site module
Traceback (most recent call last):
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/site.py, line 541, in <module>
    main()
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/site.py, line 522, in main
    known_paths = addusersitepackages(known_paths)
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/site.py, line 282, in addusersitepackages
    user_site = getusersitepackages()
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/site.py, line 258, in getusersitepackages
    user_base = getuserbase() # this will also set USER_BASE
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/site.py, line 248, in getuserbase
    USER_BASE = get_config_var('userbase')
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/sysconfig.py, line 608, in get_config_var
    return get_config_vars().get(name)
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/sysconfig.py, line 587, in get_config_vars
    import _osx_support
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/_osx_support.py, line 4, in <module>
    import re
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/re.py, line 122, in <module>
    import enum
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/enum.py, line 2, in <module>
    from types import MappingProxyType, DynamicClassAttribute
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/types.py, line 171, in <module>
    import functools as _functools
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/functools.py, line 21, in <module>
    from collections import namedtuple
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/collections/__init__.py, line 29, in <module>
    import heapq as _heapq
  File /Users/adrianseyboldt/.julia/v0.6/Conda/deps/usr/lib/python3.6/heapq.py, line 587, in <module>
    from _heapq import *
SystemError: initialization of _heapq did not return an extension module

This is using python3.6 from anaconda, and julia from brew on OsX.
I installed diffeqpy 0.4 with pip install diffeqpy, and executed diffeqpy.install()

Delay differential equations need a wrapper on the history function

def f(u, h, p, t):
  du1 = 1.1/(1 + 3.16227*(h(p, t-20)[0])**(1.25)) - 10*u[0]/(1 + 40*u[1])
  du2 = 100*u[0]/(1 + 40*u[1]) - 2.43*u[1]
  return[du1,du2]

u0 = [1.05767027/3, 1.030713491/3]
def h(p,t):
  [1.05767027/3, 1.030713491/3]

tspan = (0.0, 100.0)
constant_lags = [20.0]
prob = de.DDEProblem(f,u0,h,tspan,constant_lags=constant_lags)
sol = de.pysolve(prob)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
TypeError: 'NoneType' object is not subscriptable

AppVeyor test issues

Let's track AppVeyor CI issues here. I don't have Windows machine at the moment so I don't think I can debug further, but I leave some possibly relevant information.

Currently, I think we have working Python 3 setup. However, Python 2 tests never succeeds.

Python 2

In #18, I tried to debug AppVeyor setup by running the CI with Julia(debug=True) and pytest ... -sv. It spits out:

exception occured? NonLLVM ERROR: Program used external function 'rint' which could not be resolved!

--- https://ci.appveyor.com/project/ChrisRackauckas/diffeqpy/build/1.0.52/job/d7xhrhde2wgdaf09#L4263

Note that the log has some lines of "exception occured? None" before the clash.

Googling the message, I find: JuliaInterop/Cxx.jl#223 Is it some kind of gcc-clang ABI incompatibility?

Python 3: how it got fixed (maybe)

It is probably fixed by avoiding @pyimport inspect (original fix: SciML/DiffEqPy.jl@050a088; it's bundled in diffeqpy now: #23) as advised in JuliaPy/PyCall.jl#498 (see also #20).

Success example:

MethodError: no method matching unwrap_cache(::DelayDiffEq.DDEIntegrator...

@ChrisRackauckas This seems to be an API usage error or something:

https://ci.appveyor.com/project/ChrisRackauckas/diffeqpy/builds/24966633/job/534340b3jalo748h#L219

Julia exception: MethodError: no method matching unwrap_cache(::DelayDiffEq.DDEIntegrator{OrdinaryDiffEq.CompositeAlgorithm{Tuple{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType}},OrdinaryDiffEq.AutoSwitch{OrdinaryDiffEq.Tsit5,OrdinaryDiffEq.Rosenbrock23{0,false,DiffEqBase.DefaultLinSolve,DataType},Rational{Int64},Float64}} (...and so on...)

then

Closest candidates are:
  unwrap_cache(!Matched::OrdinaryDiffEq.ODEIntegrator, ::Any) at C:\Users\appveyor\.julia\packages\OrdinaryDiffEq\Cc6K8\src\cache_utils.jl:6
  unwrap_cache(!Matched::StochasticDiffEq.SDEIntegrator, ::Any) at C:\Users\appveyor\.julia\packages\StochasticDiffEq\YRc41\src\cache_utils.jl:2

Cannot run Julia-defined function from example in README

I am running Julia 0.6.4 and Python 3.7.0. I tried running the following example from the README to use a Julia-defined function

jul_f = de.eval("""
function f(du,u,p,t)
  x, y, z = u
  sigma, rho, beta = p
  du[1] = sigma * (y - x)
  du[2] = x * (rho - z) - y
  du[3] = x * y - beta * z
end""")
u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(jul_f, u0, tspan, p)
sol = de.solve(prob)

But I get the error

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-2-c07076744217> in <module>
     10 tspan = (0., 100.)
     11 p = [10.0,28.0,2.66]
---> 12 prob = de.ODEProblem(jul_f, u0, tspan, p)
     13 sol = de.solve(prob)

ValueError: Julia exception: ArgumentError("reducing over an empty collection is not allowed")

Strangely, the example below that uses a Python-defined function works correctly for me

def f(du,u,p,t):
    x, y, z = u
    sigma, rho, beta = p
    du[0] = sigma * (y - x)
    du[1] = x * (rho - z) - y
    du[2] = x * y - beta * z

numba_f = numba.jit(f)
u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(numba_f, u0, tspan, p)
sol = de.solve(prob)

Thanks for the help!

Solving SDEs using a complex parameter p object

Hi @ChrisRackauckas,

I believe I have an interesting problem for you or anyone else who wants to join the conversation. We are building a program that solves a System of Stochastic Differential Equations as underlying problem. In that context, we are using DifferentialEquations.jl because it has state of the art algorithms for that purpose. However, for some reasons that do not matter, we are bounded to code in Python, not it Julia, so we use diffeqpy to connect to DifferentialEquations.jl.

That being said, I want to be really detailed so we can be in the same page. Please try to follow me, it's worth it. Let's begin.

The user describes the problem to solve by means of a high-level plain-text input file containing, among other things:

  • algebraic expressions,
  • data for function interpolation.

This means that the user cannot program in python, she provides the instructions in a simple input file, like if she was writing on a piece of paper.

Let's say that the user wants to simulate a process given by the following SDE:

dS(t) = f(S, t) * dt + g(S, t) * dW(t)

where the auxiliary functions f and g are given by algebraic expressions:

f(x, y) = kappa(y) * (theta(y) - x)
g(x, y) =  sigma(y) * sqrt(x)

and kappa, theta and sigma are functions given by 1D interpolated data (obtained somehow by calibration methods).
In this case, the input file might be given by:

Function kappa(x):
  xdata: [ provide pointwise data ]
  fdata: [ provide pointwise data ]
  method: cubic

Function theta(x):
  xdata: [ provide pointwise data ]
  fdata: [ provide pointwise data ]
  method: cubic

Function sigma(x):
  xdata: [ provide pointwise data ]
  fdata: [ provide pointwise data ]
  method: cubic

Function f(x,y) = kappa(y) * (theta(y) - x)
Function g(x,y) = sigma(y) * sqrt(x)

Process X:
  x0:         sqrt(pi)
  drift:     f(X_t, t)
  diffusion: g(X_t, t)

Just in case you are wondering what is X_t, it is an special variable that takes the value of the process X at each time t. Also, check out that the auxiliary functions f and g are defined using variables x and y but then they are evaluated at the special variable X_t and time t (this is also a special variable that takes the time value).

To parse this input, we use Sympy and other strategies (for handling interpolators). At the end of the parsing, the drift and diffusion of the process X are expressions that can be evaluated by means of Python functions:

def drift(X_t, t):
    return kappa(t) * (theta(t) - X_t)

def diffusion(X_t, t):
    return sigma(t) * sqrt(X_t)

and kappa, theta and sigma are SciPy interpolators for example. Now, the definition of the SDE problem is given by:

sde = de.SDEProblem(f_for_julia, g_for_julia, u0, tspan, p)

where f_for_julia and g_for_julia are simple to understand but they actually involve a lot of things, so writing them on Julia is not an straightforward task. For example, we have:

def f_for_julia(du, u, p, t):

        # set time variable value to solver time value
        p.get_variable('t').set_value(t)

        # set all processes variables to solver estimation
        for i, process in enumerate(p.processes):
            process.var.set_value(u[i])

        # once all variables are set, compute derivatives
        for i, process in enumerate(p.processes):
            du[i] = process.expr_drift.eval()

In this function, many things happen:

  1. parameter p is an instance of a class that haves a lot of information, not just a list of constant numbers.
  2. set the variable t value to the solver t value. This is because we will evaluate expressions depending on t variable.
  3. set all processes variables (for example, X_t) to the solver value. This is because we will evaluate expressions depending X_t variable.
  4. evaluate the drift expression provided in the input file for each process. In this case, this means the evaluation of f(X_t, t). Variable t has been set to the solver value in item 1. and variable X_t has been set to the solver value in item 2.

In this last item 3, the evaluation of the expression f(X_t, t) involves calling the python function drift described above with the correct values of X_t and t. In that function, there are calls to SciPy interpolators.

So, at this point I am able to describe my problem. Even though everything works as expected, it takes a lot of time. I believe every time the Python function f_for_julia is called from Julia for the computation of a Monte Carlo time step involves a lot of time. In this page, you describe a similar problem in section Performance: Ordinary Differential Equations (ODEs), where it takes 111.4923981380125 sec to solve an ODE system. If you instead use jul_f = de.eval(""" ... """), the involved time decreases drastically and you get to solve the same problem in 0.8532032310031354 sec.

The thing is that in that example, is really simple to migrate your python f function to Julia, while in my case, f_for_julia cannot be migrated to Julia so easily.

What would you do? Would you use the ModellingToolkit .jl package to migrate my expressions to Julia and provide them in a big Julia script for jul_f = de.eval(""" ... """), where ... contains the lines of the script? Of course, I would also have to migrate the interpolators, etc.

Thank you very much for everything, I will be waiting for your response.

Ramiro

Error trying to install diffeqpy

This package looks really interesting to me (since most of my work has been using Python so far), thank you for putting in the effort to provide Python bindings (for us who haven't yet gotten on the Julia bandwagon)!

I followed the installation instructions from the README (I'm on a Ubuntu 16.04 machine with Python 3.5 and Julia 0.6.2), and this is how far I got:

bjorn@yoga720:~$ python3 -m pip install --user diffeqpy
Collecting diffeqpy
  Downloading https://files.pythonhosted.org/packages/f7/38/07ec0d7703451d81bbf89d2602f306169b18b4a8b69b512d2da0d53a2239/diffeqpy-0.2.tar.gz
Collecting julia (from diffeqpy)
  Downloading https://files.pythonhosted.org/packages/2e/2a/04e16c1b1cde76c669328e09da9e833ee50a9aed4fad2b1fddf137d2d199/julia-0.1.5-py2.py3-none-any.whl (222kB)
    100% |████████████████████████████████| 225kB 7.8MB/s 
Building wheels for collected packages: diffeqpy
  Running setup.py bdist_wheel for diffeqpy ... done
  Stored in directory: /home/bjorn/.cache/pip/wheels/81/32/69/c19322b0bf49ace80a1ddb3d9cd462aead7d2c545ac709e9f7
Successfully built diffeqpy
Installing collected packages: julia, diffeqpy
Successfully installed diffeqpy-0.2 julia-0.1.5
You are using pip version 10.0.0, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
bjorn@yoga720:~$ julia
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: https://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.6.2 (2017-12-13 18:08 UTC)
 _/ |\__'_|_|_|\__'_|  |  Official http://julialang.org/ release
|__/                   |  x86_64-pc-linux-gnu

julia> Pkg.add("DiffEqPy")
ERROR: unknown package DiffEqPy
macro expansion at ./pkg/entry.jl:53 [inlined]
(::Base.Pkg.Entry.##1#3{String,Base.Pkg.Types.VersionSet})() at ./task.jl:335
Stacktrace:
 [1] sync_end() at ./task.jl:287
 [2] macro expansion at ./task.jl:303 [inlined]
 [3] add(::String, ::Base.Pkg.Types.VersionSet) at ./pkg/entry.jl:51
 [4] (::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#add,Tuple{String}})() at ./pkg/dir.jl:36
 [5] cd(::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#add,Tuple{String}}, ::String) at ./file.jl:70
 [6] #cd#1(::Array{Any,1}, ::Function, ::Function, ::String, ::Vararg{String,N} where N) at ./pkg/dir.jl:36
 [7] add(::String) at ./pkg/pkg.jl:117

julia> 

Since I'm new to Julia I'm not sure how to debug this, any ideas?

Using diffeqpy on Google Colab

I have problem importing this package in google Colab. is there any way you would suggest help me with that?
when I try out " from diffeqpy import de" I receive this error:

`---------------------------------------------------------------------------
UnsupportedPythonError Traceback (most recent call last)
in ()
----> 1 from diffeqpy import de

8 frames
/usr/local/lib/python3.6/dist-packages/julia/core.py in init(self, init_julia, jl_init_path, runtime, jl_runtime_path, debug, **julia_options)
481 logger.debug("compiled_modules = %r", options.compiled_modules)
482 if not (options.compiled_modules == "no" or is_compatible_python):
--> 483 raise UnsupportedPythonError(jlinfo)
484
485 self.api.init_julia(options)

UnsupportedPythonError: It seems your Julia and PyJulia setup are not supported.

Julia executable:
julia
Python interpreter and libpython used by PyCall.jl:
/usr/bin/python3
/usr/lib/x86_64-linux-gnu/libpython3.6m.so.1.0
Python interpreter used to import PyJulia and its libpython.
/usr/bin/python3
/usr/lib/x86_64-linux-gnu/libpython3.6m.so.1.0

Your Python interpreter "/usr/bin/python3"
is statically linked to libpython. Currently, PyJulia does not fully
support such Python interpreter.

The easiest workaround is to pass compiled_modules=False to Julia
constructor. To do so, first reboot your Python REPL (if this happened
inside an interactive session) and then evaluate:

>>> from julia.api import Julia
>>> jl = Julia(compiled_modules=False)

Another workaround is to run your Python script with python-jl
command bundled in PyJulia. You can simply do:

$ python-jl PATH/TO/YOUR/SCRIPT.py

See python-jl --help for more information.

For more information, see:

https://pyjulia.readthedocs.io/en/latest/troubleshooting.html`

Release Process

From a clean slate. Delete any hidden build folders or else the new version won't be built.

C:\Users\accou\.julia\external\diffeqpy>python setup.py sdist bdist_wheel
running sdist
running egg_info
creating diffeqpy.egg-info
writing diffeqpy.egg-info\PKG-INFO
writing dependency_links to diffeqpy.egg-info\dependency_links.txt
writing requirements to diffeqpy.egg-info\requires.txt
writing top-level names to diffeqpy.egg-info\top_level.txt
writing manifest file 'diffeqpy.egg-info\SOURCES.txt'
reading manifest file 'diffeqpy.egg-info\SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching 'docs\*.txt'
writing manifest file 'diffeqpy.egg-info\SOURCES.txt'
running check
creating diffeqpy-1.1.0
creating diffeqpy-1.1.0\diffeqpy
creating diffeqpy-1.1.0\diffeqpy.egg-info
creating diffeqpy-1.1.0\diffeqpy\tests
copying files to diffeqpy-1.1.0...
copying LICENSE.md -> diffeqpy-1.1.0
copying MANIFEST.in -> diffeqpy-1.1.0
copying README.md -> diffeqpy-1.1.0
copying setup.cfg -> diffeqpy-1.1.0
copying setup.py -> diffeqpy-1.1.0
copying diffeqpy\__init__.py -> diffeqpy-1.1.0\diffeqpy
copying diffeqpy\de.py -> diffeqpy-1.1.0\diffeqpy
copying diffeqpy\install.jl -> diffeqpy-1.1.0\diffeqpy
copying diffeqpy\setup.jl -> diffeqpy-1.1.0\diffeqpy
copying diffeqpy.egg-info\PKG-INFO -> diffeqpy-1.1.0\diffeqpy.egg-info
copying diffeqpy.egg-info\SOURCES.txt -> diffeqpy-1.1.0\diffeqpy.egg-info
copying diffeqpy.egg-info\dependency_links.txt -> diffeqpy-1.1.0\diffeqpy.egg-info
copying diffeqpy.egg-info\not-zip-safe -> diffeqpy-1.1.0\diffeqpy.egg-info
copying diffeqpy.egg-info\requires.txt -> diffeqpy-1.1.0\diffeqpy.egg-info
copying diffeqpy.egg-info\top_level.txt -> diffeqpy-1.1.0\diffeqpy.egg-info
copying diffeqpy\tests\__init__.py -> diffeqpy-1.1.0\diffeqpy\tests
copying diffeqpy\tests\test_dae.py -> diffeqpy-1.1.0\diffeqpy\tests
copying diffeqpy\tests\test_dde.py -> diffeqpy-1.1.0\diffeqpy\tests
copying diffeqpy\tests\test_ode.py -> diffeqpy-1.1.0\diffeqpy\tests
copying diffeqpy\tests\test_sde.py -> diffeqpy-1.1.0\diffeqpy\tests
Writing diffeqpy-1.1.0\setup.cfg
creating dist
Creating tar archive
removing 'diffeqpy-1.1.0' (and everything under it)
running bdist_wheel
running build
running build_py
creating build
creating build\lib
creating build\lib\diffeqpy
copying diffeqpy\de.py -> build\lib\diffeqpy
copying diffeqpy\__init__.py -> build\lib\diffeqpy
creating build\lib\diffeqpy\tests
copying diffeqpy\tests\test_dae.py -> build\lib\diffeqpy\tests
copying diffeqpy\tests\test_dde.py -> build\lib\diffeqpy\tests
copying diffeqpy\tests\test_ode.py -> build\lib\diffeqpy\tests
copying diffeqpy\tests\test_sde.py -> build\lib\diffeqpy\tests
copying diffeqpy\tests\__init__.py -> build\lib\diffeqpy\tests
copying diffeqpy\install.jl -> build\lib\diffeqpy
copying diffeqpy\setup.jl -> build\lib\diffeqpy
installing to build\bdist.win-amd64\wheel
running install
running install_lib
creating build\bdist.win-amd64
creating build\bdist.win-amd64\wheel
creating build\bdist.win-amd64\wheel\diffeqpy
copying build\lib\diffeqpy\de.py -> build\bdist.win-amd64\wheel\.\diffeqpy
copying build\lib\diffeqpy\install.jl -> build\bdist.win-amd64\wheel\.\diffeqpy
copying build\lib\diffeqpy\setup.jl -> build\bdist.win-amd64\wheel\.\diffeqpy
creating build\bdist.win-amd64\wheel\diffeqpy\tests
copying build\lib\diffeqpy\tests\test_dae.py -> build\bdist.win-amd64\wheel\.\diffeqpy\tests
copying build\lib\diffeqpy\tests\test_dde.py -> build\bdist.win-amd64\wheel\.\diffeqpy\tests
copying build\lib\diffeqpy\tests\test_ode.py -> build\bdist.win-amd64\wheel\.\diffeqpy\tests
copying build\lib\diffeqpy\tests\test_sde.py -> build\bdist.win-amd64\wheel\.\diffeqpy\tests
copying build\lib\diffeqpy\tests\__init__.py -> build\bdist.win-amd64\wheel\.\diffeqpy\tests
copying build\lib\diffeqpy\__init__.py -> build\bdist.win-amd64\wheel\.\diffeqpy
running install_egg_info
Copying diffeqpy.egg-info to build\bdist.win-amd64\wheel\.\diffeqpy-1.1.0-py3.7.egg-info
running install_scripts
adding license file "LICENSE.md" (matched pattern "LICEN[CS]E*")
creating build\bdist.win-amd64\wheel\diffeqpy-1.1.0.dist-info\WHEEL
creating 'dist\diffeqpy-1.1.0-py3-none-any.whl' and adding 'build\bdist.win-amd64\wheel' to it
adding 'diffeqpy/__init__.py'
adding 'diffeqpy/de.py'
adding 'diffeqpy/install.jl'
adding 'diffeqpy/setup.jl'
adding 'diffeqpy/tests/__init__.py'
adding 'diffeqpy/tests/test_dae.py'
adding 'diffeqpy/tests/test_dde.py'
adding 'diffeqpy/tests/test_ode.py'
adding 'diffeqpy/tests/test_sde.py'
adding 'diffeqpy-1.1.0.dist-info/LICENSE.md'
adding 'diffeqpy-1.1.0.dist-info/METADATA'
adding 'diffeqpy-1.1.0.dist-info/WHEEL'
adding 'diffeqpy-1.1.0.dist-info/top_level.txt'
adding 'diffeqpy-1.1.0.dist-info/RECORD'
removing build\bdist.win-amd64\wheel

C:\Users\accou\.julia\external\diffeqpy>python -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/* --verbose
Enter your username: ChrisRackauckas
Enter your password:
Uploading distributions to https://upload.pypi.org/legacy/
Uploading diffeqpy-1.1.0-py3-none-any.whl
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 28.6k/28.6k [00:01<00:00, 15.0kB/s]
Uploading diffeqpy-1.1.0.tar.gz
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 29.6k/29.6k [00:01<00:00, 16.8kB/s]

Numba / llvmlite error

This test

https://github.com/JuliaDiffEq/diffeqpy/blob/7186d2b1287cafe67ed13db5f416543eac75e348/diffeqpy/tests/test_ode.py#L6-L19

ran in #40 / d104896 failed with

.tox/py36/lib/python3.6/site-packages/diffeqpy/tests/test_dde.py::test PASSED
.tox/py36/lib/python3.6/site-packages/diffeqpy/tests/test_ode.py::test_ode_sol 
signal (11): Segmentation fault
in expression starting at no file:0
unknown function (ip: 0x7fa7a26ce335)
_ZN4llvm15SmallVectorImplINS_15LayoutAlignElemEEaSERKS2_ at /home/travis/julia/bin/../lib/julia/libLLVM-6.0.so (unknown line)
_ZN4llvm5MCJITC2ESt10unique_ptrINS_6ModuleESt14default_deleteIS2_EES1_INS_13TargetMachineES3_IS6_EESt10shared_ptrINS_18MCJITMemoryManagerEES9_INS_23LegacyJITSymbolResolverEE at /home/travis/build/JuliaDiffEq/diffeqpy/.tox/py36/lib/python3.6/site-packages/llvmlite/binding/libllvmlite.so (unknown line)
_ZN4llvm5MCJIT9createJITESt10unique_ptrINS_6ModuleESt14default_deleteIS2_EEPSsSt10shared_ptrINS_18MCJITMemoryManagerEES7_INS_23LegacyJITSymbolResolverEES1_INS_13TargetMachineES3_ISC_EE at /home/travis/build/JuliaDiffEq/diffeqpy/.tox/py36/lib/python3.6/site-packages/llvmlite/binding/libllvmlite.so (unknown line)
_ZN4llvm13EngineBuilder6createEPNS_13TargetMachineE at /home/travis/build/JuliaDiffEq/diffeqpy/.tox/py36/lib/python3.6/site-packages/llvmlite/binding/libllvmlite.so (unknown line)
create_execution_engine at /root/llvmlite/ffi/executionengine.cpp:90
ffi_call_unix64 at /usr/lib/x86_64-linux-gnu/libffi.so.6 (unknown line)
ffi_call at /usr/lib/x86_64-linux-gnu/libffi.so.6 (unknown line)
_call_function_pointer at /tmp/python-build.20171128184602.6036/Python-3.6.3/Modules/_ctypes/callproc.c:809 [inlined]
_ctypes_callproc at /tmp/python-build.20171128184602.6036/Python-3.6.3/Modules/_ctypes/callproc.c:1147
PyCFuncPtr_call at /tmp/python-build.20171128184602.6036/Python-3.6.3/Modules/_ctypes/_ctypes.c:3935
PyObject_Call at /tmp/python-build.20171128184602.6036/Python-3.6.3/Objects/abstract.c:2261

see full trace here https://travis-ci.org/JuliaDiffEq/diffeqpy/jobs/516791663#L665

How to specifiy algorithm

I'm trying to solve a relatively simple set of ode's that describe the temperature, pressure and composition of a reacting gas mixture down a tube.

I'm trying to replace scipy solvers with Julia. I am encouraged by the range of algorithms but am deterred by the lack of documentation.

The specific issue is that the composition of species within the mixture become negative, typically changing method will resolve this issue but I can not find how to do it with this package!

I've tried:
sol = de.solve(prob,alg='Rosenbrock23()')
and,
sol = de.solve(prob,alg='Rosenbrock23')

which gives:
RuntimeError: Julia exception: MethodError(DiffEqBase.isadaptive, ("Rosenbrock23()",), 0x000000000000623c)

I tried:
sol = de.solve(prob,'Rosenbrock23')
which gives:

RuntimeError: Julia exception: ErrorException("Inappropiate solve command. The arguments do not make sense. Likely, you gave an algorithm which does not actually exist (or does not <:DiffEqBase.DEAlgorithm)")

Can someone point me in the right direction?
I understand I'm a new user but the error messages given are not particularly helpful.

Integration works in standalone Julia; fails with diffeqpy

I'm using diffeqpy to solve an ODE system, but running into an error. However, if I copy/paste the equation system into a separate Julia program and run that directly, it works without error.

Here's a gist with the Python program and Julia equivalent.

This is the error that I'm seeing on the Python version:

  File "diffeqpy_test.py", line 116, in <module>
    result = de.solve(prob)
RuntimeError: Julia exception: MethodError: no method matching llvmtype(::Type{Float64})
The applicable method may be too new: running in world age 32048, while current world is 73638.
Closest candidates are:
  llvmtype(::Any) at /Users/alex/.julia/packages/VectorizationBase/kIoqa/src/vectorizable.jl:22 (method too new to be called from this world context.)
Stacktrace:
 [1] #s693#7 at /Users/alex/.julia/packages/VectorizationBase/kIoqa/src/VectorizationBase.jl:106 [inlined]
 [2] #s693#7(::Any, ::Any, ::Any, ::Any, ::Any) at ./none:0

I'm using Julia 1.5.1 with diffeqpy 1.1.0 and Python 3.6.10.

Thanks in advance for any insights you're able to provide.

libjulia.so: No such file or directory

I installed diffeqpy and am trying to solve a simple ODE. I am not sure if this is an error with diffeqpy or with julia so forgive me if this is in the wrong place.

I run from diffeqpy import de and get the following error:

Traceback (most recent call last): File "", line 1, in File "/home/sean/anaconda3/lib/python3.7/site-packages/diffeqpy/de.py", line 4, in from julia import Main File "", line 983, in _find_and_load File "", line 967, in _find_and_load_unlocked File "", line 668, in _load_unlocked File "", line 638, in _load_backward_compatible File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 247, in load_module JuliaMainModule(self, fullname)) File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 149, in __init__ self._julia = loader.julia File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 239, in julia self.__class__.julia = julia = Julia() File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 468, in __init__ jlinfo = JuliaInfo.load(runtime) File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/juliainfo.py", line 88, in load retcode, [julia, "-e", "..."], stdout, stderr subprocess.CalledProcessError: Command '['julia', '-e', '...']' returned non-zero exit status 1.

If I run from julia import Main I get the same error as far as I can tell:

Traceback (most recent call last): File "", line 1, in File "", line 983, in _find_and_load File "", line 967, in _find_and_load_unlocked File "", line 668, in _load_unlocked File "", line 638, in _load_backward_compatible File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 247, in load_module JuliaMainModule(self, fullname)) File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 149, in __init__ self._julia = loader.julia File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 239, in julia self.__class__.julia = julia = Julia() File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/core.py", line 468, in __init__ jlinfo = JuliaInfo.load(runtime) File "/home/sean/anaconda3/lib/python3.7/site-packages/julia/juliainfo.py", line 88, in load retcode, [julia, "-e", "..."], stdout, stderr subprocess.CalledProcessError: Command '['julia', '-e', '...']' returned non-zero exit status 1.

Digging around in the code it seems to be caused by this command: julia --startup-file=no /home/sean/anaconda3/lib/python3.7/site-packages/julia/juliainfo.jl which, if I run in a normal terminal instance, fails with this output:

1.4.1 1 4 1 /usr/bin ERROR: LoadError: could not load library "libjulia" libjulia.so: cannot open shared object file: No such file or directory Stacktrace: [1] dlopen(::String, ::UInt32; throw_error::Bool) at /build/julia-98cBbp/julia-1.4.1+dfsg/usr/share/julia/stdlib/v1.4/Libdl/src/Libdl.jl:109 [2] dlopen at /build/julia-98cBbp/julia-1.4.1+dfsg/usr/share/julia/stdlib/v1.4/Libdl/src/Libdl.jl:109 [inlined] (repeats 2 times) [3] dlpath(::String) at /build/julia-98cBbp/julia-1.4.1+dfsg/usr/share/julia/stdlib/v1.4/Libdl/src/Libdl.jl:232 [4] top-level scope at /home/sean/anaconda3/lib/python3.7/site-packages/julia/juliainfo.jl:14 [5] include(::Module, ::String) at ./Base.jl:377 [6] exec_options(::Base.JLOptions) at ./client.jl:288 [7] _start() at ./client.jl:484 in expression starting at /home/sean/anaconda3/lib/python3.7/site-packages/julia/juliainfo.jl:14

Critically it seems that the cause is libjulia.so: cannot open shared object file: No such file or directory. I can execute julia code normally through the julia command (e.g. julia MyJuliaFile.jl), just not with the examples provided in this README.

I installed julia 1.4.1 through apt (and have checked, libjulia1 is showing as installed in apt), and diffeqpy 1.1.0 though pip.

HamiltonianProblem gives inconsistent results

Hello,
I'm trying to integrate this Hamiltonian

H=(p1^2+p2^2)/(2mu)+V(exp(-aq1)-1)^2+V(exp(-aq2)-1)^2-p1p2/m2

but it looks like HamiltonianProblem is giving me inconsistent results

m1,m2,a,V=1.,1.,1.,1.
mu=m1*m2/(m1+m2)
param = [a,V,mu,m2]
tspan = (0., 1000.)
jul_H = Main.eval("""
function H(p,q,param)
    p1, p2 = p
    q1, q2 = q
    a, V, mu, m2 = param
    (p1^2+p2^2)/(2*mu)+V*(exp(-a*q1)-1)^2+V*(exp(-a*q2)-1)^2-p1*p2/m2
    end""")
q1,p1,q2,p2,=0.5,0.,0.,0.    
p0=[p1,p2]    
q0=[q1,q2]
prob=de.HamiltonianProblem(jul_H,p0,q0,tspan,param)
sol = de.solve(prob,de.VelocityVerlet(),dt=0.01)

For example in this case with the VelocityVerlet integrator p2 and q2 remain zero, but the other integrators don't seem to work either.

On the other hand, by applying the Hamilton equations and integrating with ODEProblem, I get good results

jul_f = Main.eval("""
function f(dX,X,p,t)
  q1, p1, q2, p2 = X
  a, V, mu, m2 = p
  dX[1] = p1/mu - p2/m2
  dX[2] = 2*V*(exp(-a*q1)-1)*a*exp(-a*q1)
  dX[3] = p2/mu - p1/m2
  dX[4] = 2*V*(exp(-a*q2)-1)*a*exp(-a*q2)
end""")

X0=[q1,p1,q2,p2]
prob = de.ODEProblem(jul_f, X0, tspan, param)
sol = de.solve(prob,de.ImplicitMidpoint(),dt=0.01)

I would like to make HamiltonianProblem work because it allows to use several symplectic integrators!

Thanks,
Valentin

Vender ModelingToolkit.jl with diffeqpy?

It seems like it would be a good front end for diffeqpy which would allow users to easily build Julia functions and get the full speed. I would need help finding out how to vender it so it just shows up, but from there it should be quite straightforward. The macros couldn't be used, but the constructor form would work, and we can just add constructors that allow strings and convert internally to symbols so that it works natively from Python.

DifferentialEquations.jl <diffeqpy?> PyTorch/torchdyn

We're the devs of the PyTorch-based younger brother of JuliaDiffEq, torchdyn. Since we don't have the bandwidth (nor it is our objective at the moment) to improve / reimplement the differential equation solvers available in our ecosystem, I was toying with the idea of somehow utilizing the fully-featured DifferentialEquations.jl and Julia as an additional backend option for torchdyn models. It is my understanding that diffeqpy wouldn't work out of the box for us, since it'd be interfacing with PyTorch.

It'd be nice to pick your brain around this direction @ChrisRackauckas . Do you think the overheads would be small enough such that a switch to a Julia diffeq solvers backend would benefit the PyTorch userbase?

I'll be glad to keep you up to date with our attempts if you're interested :)

Installing diffeqpy in local Julia environment

I am trying to write a script to automatically install julia and diffeqpy:

import julia
from julia import Pkg
import diffeqpy

Pkg.activate(".") # use local environment
julia.install()
diffeqpy.install()

However, when running the final line, I get

   Updating registry at `~/.julia/registries/General`
  Resolving package versions...
No Changes to `~/.julia/environments/v1.5/Project.toml`
No Changes to `~/.julia/environments/v1.5/Manifest.toml`
  Resolving package versions...
No Changes to `~/.julia/environments/v1.5/Project.toml`
No Changes to `~/.julia/environments/v1.5/Manifest.toml`
  Resolving package versions...
No Changes to `~/.julia/environments/v1.5/Project.toml`
No Changes to `~/.julia/environments/v1.5/Manifest.toml`
  Resolving package versions...
No Changes to `~/.julia/environments/v1.5/Project.toml`
No Changes to `~/.julia/environments/v1.5/Manifest.toml`

i.e. it installs to the default v1.5 instead of my local environment. Is there a way to tell diffeqpy where to install?

Example problems giving similar but not exact match solutions.

Im running python 3.8 on a x64 system.

I have numpy, numba, julia and matplotlib imported succesfully.

The results from running the copied and pasted "Lorenz equations" & "One dimensional SDE's" problems give me the following results.

Lorenz_3D
Lorenz_2D

The general shape of the graphs follows that of the example solutions but on closer inspection is not the same.

Has anyone came across this issue too ?

Calling the differential function for ODE solving from a class in python

This is generically my code:

from diffeqpy import de
class A():
def init(self):
self.run()

def run(self):     
    tspan = (0, 1, 2)
    y=[0, 0]

    prob = de.ODEProblem(self.ODE_function, y, tspan)
    sol = de.solve(prob, saveat=0.01)

def ODE_function(self, y, p, t):
    #Code that creates differentials from new y values.
    return [#list of differentials]

A()


I get this error:
sol = de.solve(prob, saveat=0.01)
TypeError: ODE_function() takes 4 positional arguments but 5 were given

I udnerstand the error code but havent strayed from the ODE example except in using a classed fucntion, is this something the module cant fathom ?

Error when defining an ODEProblem via ModelingToolkit

If a de.ODEProblem is setup via MTK's ODESystem interface, it produces a MethodError (MethodError: no method matching one(::Tuple{Operation,Float64}))

Setup

from julia import Main, ModelingToolkit
from diffeqpy import de

Main.eval("""
using ModelingToolkit, DifferentialEquations
""")
Main.eval(
    """
begin
# v -> x1
@variables t, x1(t)
@derivatives D'~t

eqs = [
D(x1) ~ -2 * x1,
]
sys = ODESystem(eqs, t)

u0 = [
x1 => 1.0,
]
end
"""
)

Approach 1: solve using Main.eval (works)

Main.eval(
"""
begin
prob = ODEProblem(sys, u0, (0.0,10.0))
sol = solve(prob)
end
"""
)

Approach 2: define ODEProblem using Main.eval then solve using diffeqpy (works)

Main.eval("prob = ODEProblem(sys, u0, (0.0,10.0))")
de.solve(Main.prob)

Approach 3: define ODEProblem using diffeqpy (fails)

prob = de.ODEProblem(Main.sys, Main.u0, (0.0, 10.0))
de.solve(prob)

or

Main.prob_de = de.ODEProblem(Main.sys, Main.u0, (0.0, 10.0))
Main.eval("solve(prob_de)")

Both fail with

RuntimeError: Julia exception: MethodError: no method matching one(::Tuple{Operation,Float64})
Closest candidates are:
  one(!Matched::Type{Missing}) at missing.jl:103
  one(!Matched::Type{ModelingToolkit.TermCombination}) at /Users/vsulzer/.julia/packages/ModelingToolkit/4JKjD/src/linearity.jl:57
  one(!Matched::Missing) at missing.jl:100
  ...
Stacktrace:
 [1] oneunit(::Tuple{Operation,Float64}) at ./number.jl:299
 [2] _broadcast_getindex_evalf at ./broadcast.jl:648 [inlined]
 [3] _broadcast_getindex at ./broadcast.jl:621 [inlined]
 [4] _getindex at ./broadcast.jl:644 [inlined]
 [5] _broadcast_getindex at ./broadcast.jl:620 [inlined]
 [6] _getindex at ./broadcast.jl:645 [inlined]
 [7] _broadcast_getindex at ./broadcast.jl:620 [inlined]
 [8] getindex at ./broadcast.jl:575 [inlined]
 [9] copy at ./broadcast.jl:876 [inlined]
 [10] materialize at ./broadcast.jl:837 [inlined]
 [11] __init(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}, ::CompositeAlgorithm{Tuple{Vern9,Rodas5{0,false,DefaultLinSolve,DataType}},AutoSwitch{Vern9,Rodas5{0,false,DefaultLinSolve,DataType},Rational{Int64},Int64}}, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Type{Val{true}}; saveat::Tuple{}, tstops::Tuple{}, d_discontinuities::Tuple{}, save_idxs::Nothing, save_everystep::Bool, save_on::Bool, save_start::Bool, save_end::Bool, callback::Nothing, dense::Bool, calck::Bool, dt::Float64, dtmin::Nothing, dtmax::Float64, force_dtmin::Bool, adaptive::Bool, gamma::Rational{Int64}, abstol::Nothing, reltol::Nothing, qmin::Rational{Int64}, qmax::Int64, qsteady_min::Int64, qsteady_max::Int64, qoldinit::Rational{Int64}, fullnormalize::Bool, failfactor::Int64, beta1::Nothing, beta2::Nothing, maxiters::Int64, internalnorm::typeof(DiffEqBase.ODE_DEFAULT_NORM), internalopnorm::typeof(LinearAlgebra.opnorm), isoutofdomain::typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), unstable_check::typeof(DiffEqBase.ODE_DEFAULT_UNSTABLE_CHECK), verbose::Bool, timeseries_errors::Bool, dense_errors::Bool, advance_to_tstop::Bool, stop_at_next_tstop::Bool, initialize_save::Bool, progress::Bool, progress_steps::Int64, progress_name::String, progress_message::typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), userdata::Nothing, allow_extrapolation::Bool, initialize_integrator::Bool, alias_u0::Bool, alias_du0::Bool, initializealg::OrdinaryDiffEq.DefaultInit, kwargs::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol,Symbol},NamedTuple{(:default_set, :second_time),Tuple{Bool,Bool}}}) at /Users/vsulzer/.julia/packages/OrdinaryDiffEq/VPJBD/src/solve.jl:144
 [12] __solve(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}, ::CompositeAlgorithm{Tuple{Vern9,Rodas5{0,false,DefaultLinSolve,DataType}},AutoSwitch{Vern9,Rodas5{0,false,DefaultLinSolve,DataType},Rational{Int64},Int64}}; kwargs::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol,Symbol},NamedTuple{(:default_set, :second_time),Tuple{Bool,Bool}}}) at /Users/vsulzer/.julia/packages/OrdinaryDiffEq/VPJBD/src/solve.jl:4
 [13] __solve(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}, ::Nothing; default_set::Bool, kwargs::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:second_time,),Tuple{Bool}}}) at /Users/vsulzer/.julia/packages/DifferentialEquations/fpohE/src/default_solve.jl:7
 [14] #__solve#471 at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:258 [inlined]
 [15] __solve(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:245
 [16] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [17] invokelatest at ./essentials.jl:709 [inlined]
 [18] solve_call(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}; merge_callbacks::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:90
 [19] solve_call at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:65 [inlined]
 [20] #solve_up#461 at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:117 [inlined]
 [21] solve_up at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:107 [inlined]
 [22] #solve#460 at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:102 [inlined]
 [23] solve at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/solve.jl:100 [inlined]
 [24] (::PyCall.var"#65#71"{PyCall.var"#65#66#72"{typeof(solve)}})(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}; kws::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:103
 [25] #65 at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:103 [inlined]
 [26] #_#60 at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:61 [inlined]
 [27] (::PyCall.FuncWrapper{Tuple{Vararg{PyAny,N} where N},PyCall.var"#65#71"{PyCall.var"#65#66#72"{typeof(solve)}}})(::ODEProblem{Array{Tuple{Operation,Float64},1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,DiffEqBase.EvalFunc{ModelingToolkit.var"#f#168"{ModelingToolkit.var"#474#475",ModelingToolkit.var"#476#477"}},LinearAlgebra.UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Array{Symbol,1},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}) at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:61
 [28] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [29] invokelatest(::Any, ::Any) at ./essentials.jl:709
 [30] _pyjlwrap_call(::PyCall.FuncWrapper{Tuple{Vararg{PyAny,N} where N},PyCall.var"#65#71"{PyCall.var"#65#66#72"{typeof(solve)}}}, ::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}) at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:28
 [31] pyjlwrap_call(::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}) at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:49

Defining an MTK model through Main.eval

In MTK >= 4 (but not in MTK<4), the following python code:

from julia import Main
Main.eval("using ModelingToolkit")
Main.eval("@parameters t")

raises an error

JuliaError: Exception 'MethodError: no method matching Float64(::Num)
Closest candidates are:
  Float64(::Real, !Matched::RoundingMode) where T<:AbstractFloat at rounding.jl:200
  Float64(::T) where T<:Number at boot.jl:716
  Float64(!Matched::Irrational{:γ}) at irrationals.jl:189
  ...' occurred while calling julia code:
convert(PyCall.PyObject, @variables t)

could not load library "libopenlibm"

    sol = de.solve(prob, solver)
RuntimeError: <PyCall.jlwrap (in a Julia function called from Python)
JULIA: could not load library "libopenlibm"
The specified module could not be found.
Stacktrace:
 [1] log10 at .\math.jl:566 [inlined]
 [2] ode_determine_initdt(::Array{Float64,2}, ::Float64, ::Float64, ::Float64, ::Float64, ::Float64, ::typeof(DiffEqBase.ODE_DEFAULT_NORM), ::ODEProblem{Array{Float64,2},Tuple{Float64,Float64},true,TendParams,ODEFunction{true,typeof(tend!),LinearAlgebra.UniformScaling{Bool},...
...

I couldn't find info about how to fix this. I don't have this issue when Python isn't involved (using DifferentialEquations.jl in Julia normally). Let me know if you want to me to provide more info.

Autodiff doesn't work on Python functions

>>> import diffeqpy
>>> de = diffeqpy.setup()
>>> def f(u,p,t):
...     return -u
... 
>>> u0 = 0.5
>>> tspan = (0., 1.)
>>> prob = de.ODEProblem(f, u0, tspan)
>>> sol = de.pysolve(prob)
>>> sol = de.pysolve(prob,de.Tsit5())
>>> sol = de.pysolve(prob,de.Rosenbrock23())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Julia exception: MethodError(convert, (Float64, Dual{ForwardDiff.Tag{DiffEqDiffTools.TimeDerivativeWrapper{PyCall.PyObject,Float64,Void},Float64}}(0.0,1.0)), 0x00000000000055a7)

CalledProcessError

I got this error when I tried to run the simple example from the README:

CalledProcessError                        Traceback (most recent call last)
<ipython-input-1-aec2df851171> in <module>
----> 1 from diffeqpy import de
      2 def f(u,p,t):
      3     return -u
      4 u0 = 0.5
      5 tspan = (0., 1.)

/usr/local/lib/python3.8/dist-packages/diffeqpy/de.py in <module>
      2 import sys
      3 
----> 4 from julia import Main
      5 
      6 script_dir = os.path.dirname(os.path.realpath(__file__))

/usr/lib/python3.8/importlib/_bootstrap.py in _find_and_load(name, import_)

/usr/lib/python3.8/importlib/_bootstrap.py in _find_and_load_unlocked(name, import_)

/usr/lib/python3.8/importlib/_bootstrap.py in _load_unlocked(spec)

/usr/lib/python3.8/importlib/_bootstrap.py in _load_backward_compatible(spec)

/usr/local/lib/python3.8/dist-packages/julia/core.py in load_module(self, fullname)
    245         if juliapath == 'Main':
    246             return sys.modules.setdefault(fullname,
--> 247                                           JuliaMainModule(self, fullname))
    248         elif self.julia.isafunction(juliapath):
    249             return self.julia.eval(juliapath)

/usr/local/lib/python3.8/dist-packages/julia/core.py in __init__(self, loader, *args, **kwargs)
    147     def __init__(self, loader, *args, **kwargs):
    148         super(JuliaModule, self).__init__(*args, **kwargs)
--> 149         self._julia = loader.julia
    150         self.__loader__ = loader
    151 

/usr/local/lib/python3.8/dist-packages/julia/core.py in julia(self)
    237     @property
    238     def julia(self):
--> 239         self.__class__.julia = julia = Julia()
    240         return julia
    241 

/usr/local/lib/python3.8/dist-packages/julia/core.py in __init__(self, init_julia, jl_init_path, runtime, jl_runtime_path, debug, **julia_options)
    466             self.api = get_libjulia()
    467         elif init_julia:
--> 468             jlinfo = JuliaInfo.load(runtime)
    469             if jlinfo.version_info < (0, 7):
    470                 raise RuntimeError("PyJulia does not support Julia < 0.7 anymore")

/usr/local/lib/python3.8/dist-packages/julia/juliainfo.py in load(cls, julia, **popen_kwargs)
     85                 )
     86             else:
---> 87                 raise subprocess.CalledProcessError(
     88                     retcode, [julia, "-e", "..."], stdout, stderr
     89                 )

CalledProcessError: Command '['julia', '-e', '...']' returned non-zero exit status 1.

I have Julia 1.4.1 on Ubuntu 20.10.

Getting Assertion failed error message

I was able to install successfully diffeqpy on my Mac Pro (2019) running Mac OS X ver. 10.15.4 (Catalina). I'm running Python version 3.7.6 from the Anaconda distribution. The problem I'm having is when I run the test program test_ode.py (see the attached file test_ode.py.txt), I get an "Assertion failed error message (see the attached file diffeqpy_run.txt).

Please advise.

Sam Dupree.

diffeqpy_run.txt
test_ode.py.txt

Deprecation warnings in setup.jl

Obviously, not a breaking issue at the moment, but may be worth fixing:

┌ Warning: `haskey(o::PyObject, s::Union{Symbol, AbstractString})` is deprecated, use `hasproperty(o, s)` instead.
│   caller = numargs(::PyObject) at setup.jl:9
└ @ Main /usr/lib/python3.7/site-packages/diffeqpy/setup.jl:9
┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.
│   caller = numargs(::PyObject) at setup.jl:13
└ @ Main /usr/lib/python3.7/site-packages/diffeqpy/setup.jl:13

https://github.com/JuliaDiffEq/diffeqpy/blob/e5acd6c9d1836d920eae802f1bed10dd6d86b424/diffeqpy/setup.jl#L9-L13

v1.0

Hi,

I'm trying to install diffeqpy for my python installation (Winpython w/ python 3.5.4)

Following the instructions:

  • used pip to install to python with "pip install diffeqpy"

  • downloaded the julia prgram from https://julialang.org/downloads/

  • Installed Julia to: "C:\WinPython\python-3.5.4.amd64\Julia-1.0.0"

  • Added "C:\WinPython\python-3.5.4.amd64\Julia-1.0.0" and "C:\WinPython\python-3.5.4.amd64\Julia-1.0.0\bin" to my path in windows' system variables and user variables

  • Tried to install "DifferentialEquations.jl" and "PyCall.jl" with
    "julia>using Pkg
    julia>Pkg.add("DifferentialEquations")
    julia>Pkg.add("PyCall")"

  • Using Python Interpreter I ran
    ">>> import diffeqpy

diffeqpy.install()"

but got:

">>> import diffeqpy

diffeqpy.install()
ERROR: LoadError: UndefVarError: Pkg not defined
Stacktrace:
[1] top-level scope at none:0
[2] include at .\boot.jl:317 [inlined]
[3] include_relative(::Module, ::String) at .\loading.jl:1038
[4] include(::Module, ::String) at .\sysimg.jl:29
[5] exec_options(::Base.JLOptions) at .\client.jl:229
[6] start() at .\client.jl:421
in expression starting at C:\WinPython\python-3.5.4.amd64\lib\site-packages\diff
eqpy\install.jl:1
Traceback (most recent call last):
File "", line 1, in
File "C:\WinPython\python-3.5.4.amd64\lib\site-packages\diffeqpy_init
.py",
line 33, in install
subprocess.check_call(['julia', os.path.join(script_dir, 'install.jl')])
File "C:\WinPython\python-3.5.4.amd64\lib\subprocess.py", line 271, in check_c
all
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['julia', 'C:\WinPython\python-3.5.4.a
md64\lib\site-packages\diffeqpy\install.jl']' returned non-zero exit status
1
Command '['julia', 'C:\WinPython\python-3.5.4.amd64\lib\site-packages\diffe
qpy\install.jl']' returned non-zero exit status 1

"

I'm not sure if this is an issue with my path or something else.

I've tried checking my installations of PyCall and DifferentialEquations within Julia by using:

"julia> using Pkg

julia> Pkg.installed("PyCall")
ERROR: MethodError: no method matching installed(::String)
Closest candidates are:
installed() at C:\cygwin\home\Administrator\buildbot\worker\package_win64\buil
d\usr\share\julia\stdlib\v1.0\Pkg\src\API.jl:261
Stacktrace:
[1] top-level scope at none:0

julia>"

I'm sorry if this is a very simple issue or does not belong in this forum but I couldn't find much help out there for this installation.

Apologies for poor formatting on github / understanding of Julia, i just want something better than scipy.

Thanks,

Isaac

Gett KeyError: 'scale' from GitHub example

I'm attempting to run the example posted on the GitHub page for diffeqpy. I've installed diffeqpy successfully on a Mac Pro (2019) running Mac OS X 10.15.4 (Catalina). I'm running the Anaconda distribution for Python ver. 3.7.6.

The code I'm running is the following:

#!/Users/user/opt/anaconda3/bin/python
from diffeqpy import de

def f(u,p,t):
    return -u

u0 = 0.5
tspan = (0., 1.)
prob = de.ODEProblem(f, u0, tspan)
sol = de.solve(prob)

print( "\n\n")
print( " sol   = ", sol   )
print( "\n\n")
print( " sol.t = ", sol.t )
print( " sol.u = ", sol.u )
print( "\n\n")

import matplotlib.pyplot as plt
plt.plot( sol.t, sol.u )
plt.show()

The problem I'm running into seems to be in Matplotlib:

(base) user@Samuels-Mac-Pro ~ % python-jl diffeqpy-ex-1.py
┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.
│   caller = top-level scope at none:4
└ @ Core none:4



 sol   =  <PyCall.jlwrap retcode: Success
Interpolation: Automatic order switching interpolation
t: [0.0, 0.10003996803834632, 0.3421523089031354, 0.6555323945666935, 1.0]
u: [0.5, 0.45240062712255974, 0.35512001851684183, 0.2595828347330421, 0.18393979662761353]>



 sol.t =  [0.         0.10003997 0.34215231 0.65553239 1.        ]
 sol.u =  [0.5        0.45240063 0.35512002 0.25958283 0.1839398 ]



Traceback (most recent call last):
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/julia/pseudo_python_cli.py", line 308, in main
    python(**vars(ns))
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/julia/pseudo_python_cli.py", line 59, in python
    scope = runpy.run_path(script, run_name="__main__")
  File "/Users/user/.julia/conda/3/lib/python3.7/runpy.py", line 263, in run_path
    pkg_name=pkg_name, script_name=fname)
  File "/Users/user/.julia/conda/3/lib/python3.7/runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "/Users/user/.julia/conda/3/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "diffeqpy-ex-1.py", line 19, in <module>
    import matplotlib.pyplot as plt
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/matplotlib/pyplot.py", line 40, in <module>
    from matplotlib.figure import Figure, figaspect
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/matplotlib/figure.py", line 20, in <module>
    from matplotlib import backends, docstring, projections
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/matplotlib/projections/__init__.py", line 4, in <module>
    from mpl_toolkits.mplot3d import Axes3D
  File "/Users/user/.julia/conda/3/lib/python3.7/site-packages/mpl_toolkits/mplot3d/__init__.py", line 1, in <module>
    from .axes3d import Axes3D
  File "/Users/user/.julia/conda/3/lib/python3.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 42, in <module>
    class Axes3D(Axes):
  File "/Users/user/.julia/conda/3/lib/python3.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 52, in Axes3D
    azim=-60, elev=30, zscale=None, sharez=None, proj_type='persp',
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/matplotlib/docstring.py", line 116, in dedent_interpd
    return interpd(func)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/matplotlib/docstring.py", line 40, in __call__
    func.__doc__ %= self.params
KeyError: 'scale'
(base) user@Samuels-Mac-Pro ~ %

The statement executing plt.plot seems to be okay, but I get KeyError: 'scale', which I do not understand.

Any suggestions?

Sam Dupree.

using numba: No matching definition for argument type(s) float64, pyobject, float64

Using numba as per the examples give, a warning;

"NumbaWarning: Function "numba_f" was compiled in object mode without forceobj=True.

File "plop.py", line 39:
@jit
def numba_f(u,p,t):
^

state.func_ir.loc))
c:\flmapps\python37\lib\site-packages\numba\object_mode_passes.py:188: NumbaDeprecationWarning:
Fall-back from the nopython compilation path to the object mode compilation path has been detected, this is deprecated behaviour.

For more information visit http://numba.pydata.org/numba-doc/latest/reference/deprecation.html#deprecation-of-object-mode-fall-back-behaviour-when-using-jit
this warning can be avoided using the forceobj=true flag in jit, but the numba guide indicates that this results in significantly lower performance:

"If true, nopython forces the function to be compiled in nopython mode. If not possible, compilation will raise an error.

If true, forceobj forces the function to be compiled in object mode. Since object mode is slower than nopython mode, this is mostly useful for testing purposes."

When trying to inform Jit of the types eg:

@jit('float64(float64,float64,float64)')
def numba_f(u,p,t):
return -u+t**2

we get an error from the numba dispach system:

Traceback (most recent call last):

File "C:\flmapps\Python37\FLM\test\plop.py", line 43, in
sol = de.solve(prob)

File "c:\flmapps\python37\lib\site-packages\numba\dispatcher.py", line 574, in _explain_matching_error
raise TypeError(msg)

TypeError: No matching definition for argument type(s) float64, pyobject, float64

It appeas that the function defined is being accessed with the middle parameter a pyobject, rather then the requested float64. No matter how I define the variuable U0

prob = de.ODEProblem(numba_f,np.float64(u0), tspan)
sol = de.solve(prob)

the solver persists in using a pyobject...

I am using a freshly installed python37, and JuliaPro. the juliainit file records the actions taken to get julia pro to work python and diffeq (note I had to reinstall the Pkg from the pyton command prompt, even though I allready had installed them in JP, as using julia.py reverts to the .julia userfolder, not the .juliapro userfolder...) the juliainit.zip gives the actions I had to complete to link to julia and diffeqsolver.jl))

plop.zip
JuliaInit.zip

performance

Is there any way we can improve the performance when using a Python function for an ODEProblem?

I know that I can use something like:

jul_f = de.eval("""
function f(du,u,p,t)
  x, y, z = u
  sigma, rho, beta = p
  du[1] = sigma * (y - x)
  du[2] = x * (rho - z) - y
  du[3] = x * y - beta * z
end""")

u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(jul_f, u0, tspan, p)
sol = de.solve(prob,saveat=t,abstol=1e-8,reltol=1e-8)

instead of

def f(du,u,p,t):
    x, y, z = u
    sigma, rho, beta = p
    du[0] = sigma * (y - x)
    du[1] = x * (rho - z) - y
    du[2] = x * y - beta * z

u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(f, u0, tspan, p)
sol = de.solve(prob,saveat=t,abstol=1e-8,reltol=1e-8)

but I cannot translate my function to Julia code (it is way more complicated than this example and it relies in many Python objects and auxiliary functions).
Maybe what is making the code run slow is that PyCall.jl needs to convert python objects to julia objects and vice versa. So... is there any way I can let Julia or Python know the types of du, u and t.

Thanks! If there is no easy way to hack this it is fine, but I just wanted to know if I could make my code run faster.

"using DiffEqPy" stalls sometimes

The main problem is that:

It looks like the test itself choke sometimes randomly. It happens both locally and in Travis. It's probably that using DiffEqPy hangs. When it occurs, sudo strace -p <pid> shows something like

futex(0x7f507c45caa0, FUTEX_WAIT_PRIVATE, 2, NULL

I'm not sure it helps. Does it mean there is a deadlock somewhere in Julia-Python bridge?

--- #3 (comment)

Not sure if it's related (Edit: no it's not #20 (comment)), but:

Locally playing with setup Julia function, it looks like pollings are not triggered during using DiffEqPy. Is it probably due to some non-Julia blocking calls?

--- #19 (comment)

Using `de.eval` leads to "ArgumentError: reducing over an empty collection is not allowed"

Working through the examples in the Jupyter post, one of the examples fails
TLDR: de.eval doesn't work but using Main.eval instead does

Doesn't work

from diffeqpy import de
jul_f = de.eval("""
function f(du,u,p,t)
  x, y, z = u
  sigma, rho, beta = p
  du[1] = sigma * (y - x)
  du[2] = x * (rho - z) - y
  du[3] = x * y - beta * z
end""")
u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(jul_f, u0, tspan, p)
sol = de.solve(prob,abstol=1e-8,reltol=1e-8)

error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-c01f82d1aa9d> in <module>
     11 tspan = (0., 100.)
     12 p = [10.0,28.0,2.66]
---> 13 prob = de.ODEProblem(jul_f, u0, tspan, p)
     14 sol = de.solve(prob,abstol=1e-8,reltol=1e-8)
     15 sol.u

ValueError: Julia exception: ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
 [1] _empty_reduce_error() at ./reduce.jl:299
 [2] reduce_empty(::Function, ::Type{Any}) at ./reduce.jl:309
 [3] mapreduce_empty(::typeof(identity), ::Function, ::Type{T} where T) at ./reduce.jl:343
 [4] reduce_empty(::Base.MappingRF{typeof(identity),typeof(max)}, ::Type{Any}) at ./reduce.jl:329
 [5] reduce_empty_iter at ./reduce.jl:355 [inlined]
 [6] mapreduce_empty_iter(::Function, ::Function, ::Array{Any,1}, ::Base.HasEltype) at ./reduce.jl:351
 [7] _mapreduce(::typeof(identity), ::typeof(max), ::IndexLinear, ::Array{Any,1}) at ./reduce.jl:400
 [8] _mapreduce_dim at ./reducedim.jl:318 [inlined]
 [9] #mapreduce#620 at ./reducedim.jl:310 [inlined]
 [10] mapreduce at ./reducedim.jl:310 [inlined]
 [11] _maximum at ./reducedim.jl:724 [inlined]
 [12] _maximum(::Array{Any,1}, ::Colon) at ./reducedim.jl:723
 [13] #maximum#631 at ./reducedim.jl:719 [inlined]
 [14] maximum at ./reducedim.jl:719 [inlined]
 [15] numargs(::String) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/utils.jl:13
 [16] isinplace(::String, ::Int64) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/utils.jl:42
 [17] DiffEqBase.ODEFunction(::String; kwargs::Base.Iterators.Pairs{Symbol,Nothing,NTuple{10,Symbol},NamedTuple{(:analytic, :tgrad, :jac, :jvp, :vjp, :Wfact, :Wfact_t, :paramjac, :syms, :colorvec),NTuple{10,Nothing}}}) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/diffeqfunction.jl:391
 [18] convert at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/diffeqfunction.jl:1083 [inlined]
 [19] DiffEqBase.ODEProblem(::String, ::Array{Float64,1}, ::Tuple{Float64,Float64}, ::Array{Float64,1}; kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/problems/ode_problems.jl:76
 [20] DiffEqBase.ODEProblem(::String, ::Array{Float64,1}, ::Tuple{Float64,Float64}, ::Array{Float64,1}) at /Users/vsulzer/.julia/packages/DiffEqBase/T5smF/src/problems/ode_problems.jl:76
 [21] invokelatest(::Any, ::Any, ::Vararg{Any,N} where N; kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at ./essentials.jl:710
 [22] invokelatest(::Any, ::Any, ::Vararg{Any,N} where N) at ./essentials.jl:709
 [23] _pyjlwrap_call(::Type{T} where T, ::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}) at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:28
 [24] pyjlwrap_call(::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}) at /Users/vsulzer/.julia/packages/PyCall/zqDXB/src/callback.jl:49

Does work

from diffeqpy import de
from julia import Main
jul_f = Main.eval("""
function f(du,u,p,t)
  x, y, z = u
  sigma, rho, beta = p
  du[1] = sigma * (y - x)
  du[2] = x * (rho - z) - y
  du[3] = x * y - beta * z
end""")
u0 = [1.0,0.0,0.0]
tspan = (0., 100.)
p = [10.0,28.0,2.66]
prob = de.ODEProblem(jul_f, u0, tspan, p)
sol = de.solve(prob,abstol=1e-8,reltol=1e-8)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.