代码之家  ›  专栏  ›  技术社区  ›  Alex__S12

scipy ode更新集合_f_参数内部函数集合为集合_solout

  •  2
  • Alex__S12  · 技术社区  · 9 年前

    将ode与scipy集成时,ode接受的函数的参数多于t和y。例如:

    def fun(t, y, param1, param2):

    这些参数的值可以使用 set_f_params

    然而,当使用 set_solout 方法并尝试使用更新参数 在该函数中,积分保持不变,就好像没有修改参数一样。

    我想从dopri5密集输出中受益

    下面显示了一个最小示例。

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.integrate import ode
    
    def fun(t, x, param):
        return x - param
    
    def f_param(t):
        return t
    
    ode1 = ode(fun).set_integrator('dopri5').set_initial_value([10.0])
    ode1.set_f_params(f_param(0))
    results1 = ([], [])
    
    ode2 = ode(fun).set_integrator('dopri5').set_initial_value([10.0])
    ode2.set_f_params(f_param(0))
    results2 = ([], [])
    
    def callback1(t, x):
        results1[0].append(t)
        results1[1].append(x.copy())
    
    def callback2(t, x):
        results2[0].append(t)
        results2[1].append(x.copy())
        ode2.set_f_params(f_param(t))
    
    ode1.set_solout(callback1)
    ode2.set_solout(callback2)
    
    ode1.integrate(3)
    ode2.integrate(3)
    
    plt.plot(results1[0], results1[1], 'o-', alpha=0.7, label='ode1')
    plt.plot(results2[0], results2[1], '.--', label='ode2')
    plt.legend()
    

    结果如下所示:

    image

    2 回复  |  直到 9 年前
        1
  •  4
  •   astrojuanlu    9 年前

    这就是一个人要做的 the new ODE solvers

    from functools import partial
    
    import numpy as np
    from scipy.integrate import solve_ivp
    
    import matplotlib.pyplot as plt
    
    
    def fun_fixed(t, x, param):
        return x - param
    
    sol_fixed = solve_ivp(
        partial(fun_fixed, param=0), (0, 3), [10.0], dense_output=True)
    
    def fun_param(t, x, fun):
        return -x + fun(t)
    
    def f_param(t):
        return t
    
    sol_param = solve_ivp(
        partial(fun_param, fun=f_param), (0, 3), [10.0], dense_output=True)
    
    t = np.linspace(0, 3, num=16)
    
    plt.figure(figsize=(8, 5))
    plt.plot(t, sol_fixed.sol(t)[0], 'o-', alpha=0.7, label='ode1')
    plt.plot(t, sol_param.sol(t)[0], 's-.', label='ode3')
    plt.legend()
    

    Two solutions

        2
  •  1
  •   Alex__S12    9 年前

    受@Wrzlprmft注释的启发,如果参数不是常数,则不使用参数更安全,并在要更新的函数中直接调用更新参数的函数。正如他所说,这意味着:

    def fun(t, x):
        return x - f_param(t)
    

    f_param 在这种情况下),可能无法在要集成的函数的命名空间中访问( fun 在上述示例中)。因此,将函数设置为要集成和使用的函数的参数更方便 set_f_params

    作为问题代码的延续:

    def fun3(t, x, fun):
    return -x + fun(t)
    
    def fun4(t, x):
        return -x + t 
    
    ode3 = ode(fun3).set_integrator('dopri5').set_initial_value([10.0])
    ode3.set_f_params(f_param)
    results3 = ([], [])
    
    ode4 = ode(fun4).set_integrator('dopri5').set_initial_value([10.0])
    results4 = ([], [])
    
    def callback3(t, x):
        results3[0].append(t)
        results3[1].append(x.copy())
    
    def callback4(t, x):
        results4[0].append(t)
        results4[1].append(x.copy())
    
    ode3.set_solout(callback3)
    ode4.set_solout(callback4)
    
    ode3.integrate(3)
    ode4.integrate(3)
    
    plt.figure(figsize=(8, 5))
    plt.plot(results1[0], results1[1], 'o-', alpha=0.7, label='ode1')
    plt.plot(results2[0], results2[1], '.--', label='ode2')
    plt.plot(results3[0], results3[1], 's-.', label='ode3')
    plt.plot(results4[0], results4[1], '^-.', label='ode3')
    plt.legend()
    

    solutions