def __call__(self, x): if x < self.x[0] or x > self.x[-1]: raise ValueError('x is outside of valid domain') from scitools.std import wrap2callable y = self.values q = wrap2callable((self.x,y)) return q(x)
def find_dt(problem, method=ODESolver.ForwardEuler, tol=0.01, dt_min=1E-6): """ Return a "solved" class Solver instance where the difference in the solution and one with a double time step is less than tol. problem: class Problem instance. method: class in ODESolver hierarchy. tol: tolerance (chosen relative to problem.R). dt_min: minimum allowed time step. """ dt = problem.T/10 # start with 10 intervals solver = Solver(problem, dt, method) solver.solve() from scitools.std import wrap2callable good_approximation = False while not good_approximation: dt = dt/2.0 if dt < dt_min: raise ValueError('dt=%g < %g - abort' % (dt, dt_min)) solver2 = Solver(problem, dt, method) solver2.solve() # Make continuous functions u(t) and u2(t) u = wrap2callable((solver. t, solver. u)) u2 = wrap2callable((solver2.t, solver2.u)) # Sample the difference in n points in [0, t_end] n = 13 t_end = min(solver2.t[-1], solver.t[-1]) t = np.linspace(0, t_end, n) u_diff = np.abs(u(t) - u2(t)).max() print u_diff, dt, tol if u_diff < tol: good_approximation = True else: solver = solver2 return solver2
def __call__(self, x): q = wrap2callable((self.x, self.values)) return q(x)