3

I've defined a python class in order to compute the solution of system of differential eq. Do ding so I define a classes named Rhs (right and side) that should represent the right and side of the dy/dt(i-th) this class contains a single float value (initial time , initial value , final time ) and a function (array of function) in order to define this array I simply defined 3 lambda function that rapresent equation(i) and create a np.array of this function

func1 = lambda t,u : 10   * (u[1] - u[0])
func2 = lambda t,u : 28   * u[0] - u[1] - u[0] * u[2]  
func3 = lambda t,u : -8/3 * u[2] + u[0]*u[1]

and then passed to the rhs class in this way:

func = np.array([func1,func2,func3])
y0 = np.array([1.,0.,0.])
problem3 = rhs.Rhs(func,0.0,100.0,y0,1000) 

the Rhs class is this :

    class Rhs:
    def __init__(self, fnum : np.ndarray , t0: np.float, tf: np.float, y0 : np.array, n: int , fanal = None ):
          self.func = fnum
          Rhs.solution  = fanal
          self.t0   = t0
          self.tf   = tf
          self.n    = n
          self.u0   = y0
   def createArray(self):
      '''   
         Create the Array time and f(time) 
         - the time array can be create now 
         - the solution array can be just initialize with the IV
      ''' 
      self.t = np.linspace(self.t0, self.tf, self.n )
      self.u = np.array([self.u0  for i in range(self.n) ])


      return self.t,self.u   

   def f(self,ti,ui):
      return self.func(ti,ui)     

   def Df(self,ti,ui):
      eps = 10e-6
      return ((self.func(ti,ui)+eps) - self.f(ti,ui))/eps

The problem here is when the euler class call the function f

class Explicit:
     def __init__(self, dydt: rhs.Rhs, save : bool=True, _print: bool=False,  filename : str=None):
          self.dydt   = dydt
          self.dt     = (dydt.tf-dydt.t0)/dydt.n
          self._print = _print 

   def solve(self):
      self.time, self.u = self.dydt.createArray() 
      for i in range(len(self.time)-1): 
         self.u[i+1] = self.u[i] + self.dt*self.dydt.f(self.time[i],self.u[i])


      Explicit.solved = True 

      print('here')

      if self._print:
          with open(filename) as f:
              print('here')
              for i in range(len(self.u)):      
                f.write('%.4f %4f %4f %4f' %(self.time ,self.u[0,i], self.u[1], self.u[2]))


      if self.save:
         return self.time,self.u

the question here is : which is the correct method to pass the vector u that is shape = 1000,3 to the function (in order to work using the 3 function applied to the 3 vector indexing in the lambda function system ..) what I don't understand is why in C++ i didn't got this problem have a look here : all the class hierarchy I don't know in which way compute this thing

this is the error :

Traceback (most recent call last):
  File "drive.py", line 94, in <module>
    main()
  File "drive.py", line 63, in main
    fet,feu = fwdeuler_p1.solve()
  File "/home/marco/Programming/Python/Numeric/OdeSystem/euler.py", line 77, in solve
    self.u[i+1] = self.u[i] + self.dt*self.dydt.f(self.time[i],self.u[i])
  File "/home/marco/Programming/Python/Numeric/OdeSystem/rhs.py", line 44, in f
    return self.func(ti,ui)     
TypeError: 'numpy.ndarray' object is not callable

EDIT thank for reply .. but unfortunately no :( this is the error message :

drive.py:31: RuntimeWarning: overflow encountered in double_scalars
  func2 = lambda t,u : 28   * u[0] - u[1] - u[0] * u[2]
drive.py:32: RuntimeWarning: overflow encountered in double_scalars
  func3 = lambda t,u : -8/3 * u[2] + u[0]*u[1]
drive.py:31: RuntimeWarning: invalid value encountered in double_scalars
  func2 = lambda t,u : 28   * u[0] - u[1] - u[0] * u[2]
/home/marco/Programming/Python/Numeric/OdeSystem/euler.py:77: RuntimeWarning: invalid value encountered in add
  self.u[i+1] = self.u[i] + self.dt*self.dydt.f(self.time[i],self.u[i])

thanks a lot for your help ! do you have in mind other solution ?

@LutzL I don't need to doing a copy of u0 , self.u0 is shape=3, self.u should be 1000,3 (1000 row) the 3 columns represent respectively the u[0],u[1],u[2] in the equation (array of function) , by the way if I increase the number of step (decreasing the delta)

2
  • The answer got you past the initial error - that of trying use an array as a function. It doesn't matter that the elements are functions. The new error is a new question. Commented Jul 9, 2018 at 4:24
  • Ok I really sorry sorry !! I'm going to open one other post ! thanks Commented Jul 9, 2018 at 7:20

2 Answers 2

1

this should work

def f(self,ti,ui):
    return  np.array([function(ti,ui) for function in self.func])
Sign up to request clarification or add additional context in comments.

Comments

0
  self.u = np.array([self.u0  for i in range(self.n) ])

should also give you problems, as that produces a matrix or 2d array with u0 as rows, instead of the intended copy. You probably want

  self.u = np.array([self.u0[i]  for i in range(self.n) ])

or easier

  self.u = self.u0.copy()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.