Search code examples
pythonarraystypeerrorodeint

Pass an array in python odeint


I am quite new to Python, so do excuse me if the following question has a 'duh' answer.

So, I'm trying to solve an ODE using odeint and wish to pass an array. But, the TypeError: can't multiply sequence by non-int of type 'float' keeps cropping up, in the line:

CA0 = (-kd-kn*Cv)*CAi/(1+(CAi/ks))

So, the code is:

from scipy.integrate import odeint
import numpy as np

Ap_data = [2, 7, 91, 1.6, 0.4, 5]
tdata= [0, 1, 4, 5, 4, 20]
Cv_data = [43, 580, 250, 34, 30, 3]

#Define parameters
kn = 1E-5 #change 
ks = 1E+5 #change
kd = 0.058  

def deriv (CAi,t, Cv):
    CA0 = (-kd-kn*Cv)*CAi/(1+(CAi/ks))
    return CA0

#Initial conditions
CA_init = 21.6

#Solve the ODE
(CAb_soln) = odeint (derivCAb, CA_init, tdata, (Cv_data,))

print CAb_soln

Some help, please?


Solution

  • Your immediate problem is that your deriv function is trying to multiply the ordinary Python list, Cv_data (passed in as Cv) by float values. If you want to vectorize this operation, use NumPy arrays:

    Ap_data = np.array([2, 7, 91, 1.6, 0.4, 5])
    tdata= np.array([0, 1, 4, 5, 4, 20])
    Cv_data = np.array([43, 580, 250, 34, 30, 3])
    

    to solve this. You now have the problem that odeint fails for the input you give it...

     intdy--  t (=r1) illegal      
          in above message,  r1 =  0.4000000000000D+01
          t not in interval tcur - hu (= r1) to tcur (=r2)       
          in above,  r1 =  0.4287484688360D+01   r2 =  0.5551311182627D+01
     lsoda--  trouble from intdy. itask = i1, tout = r1ls
          in above message,  i1 =         1
          in above message,  r1 =  0.4000000000000D+01
    Illegal input detected (internal error).
    Run with full_output = 1 to get quantitative information.
    [[ 21.6       ]
     [ 20.37432613]
     [ 17.09897165]
     [ 16.12866355]
     [ 16.12866355]
     [ -0.90614016]]
    

    Perhaps you can give more information about what your equation is and how it relates to Cv_data. In particular, your derivative doesn't depend on t, but you have a range of values for this parameter, Cv.

    UPDATE: It fails because of your funny time series. odeint works properly if it is monotonic, for example:

    from scipy.integrate import odeint
    import numpy as np
    
    Ap_data = [2, 7, 91, 1.6, 0.4, 5]
    tdata= np.array([0, 1, 4, 5, 10, 20])
    Cv_data = np.array([43, 580, 250, 34, 30, 3])
    
    #Define parameters
    kn = 1E-5 #change 
    ks = 1E+5 #change
    kd = 0.058  
    
    def deriv (CAi,t, Cv):
        CA0 = (-kd-kn*Cv)*CAi/(1+(CAi/ks))
        return CA0
    
    #Initial conditions
    CA_init = 21.6
    
    #Solve the ODE
    (CAb_soln) = odeint (deriv, CA_init, tdata, (Cv_data,))
    print CAb_soln
    

    The result:

    [[ 21.6       ]
     [ 20.37432613]
     [ 17.09897165]
     [ 16.12866355]
     [ 12.04306424]
     [  6.71431758]]