使用不连续输入/强制数据求解 ODE

2023-12-23

我正在尝试用 Python 求解耦合一阶 ODE 系统。我对此很陌生,但是僵尸启示录示例 http://wiki.scipy.org/Cookbook/Zombie_Apocalypse_ODEINT到目前为止,SciPy.org 提供了很大的帮助。

在我的例子中,一个重要的区别是用于“驱动”我的 ODE 系统的输入数据发生了变化abruptly在不同的时间点,我不知道如何最好地处理这个问题。下面的代码是我能想到的用来说明我的问题的最简单的示例。我很欣赏这个例子有一个简单的解析解,但我的实际 ODE 系统更复杂,这就是为什么我试图理解数值方法的基础知识。

简化示例

Consider a bucket with a hole in the bottom (this kind of "linear reservoir" is the basic building block of many hydrological models). The input flow rate to the bucket is R and the output from the hole is Q. Q is assumed to be proportional to the volume of water in the bucket, V. The constant of proportionality is usually written as formula1, where T is the "residence time" of the store. This gives a simple ODE of the form

事实上,R是观测到的每日降雨量时间序列。Within假设每天的降雨量是恒定的,但是between汇率突然变化的天数(即R is a 不连续的时间的函数)。我试图理解这对于解决我的常微分方程的影响。

策略1

最明显的策略(至少对我来说)是应用 SciPyodeint在每个降雨时间步长内分别起作用。这意味着我可以治疗R作为常数。像这样的东西:

import numpy as np, pandas as pd, matplotlib.pyplot as plt, seaborn as sn
from scipy.integrate import odeint

np.random.seed(seed=17)

def f(y, t, R_t):
    """ Function to integrate.
    """
    # Unpack parameters
    Q_t = y[0]

    # ODE to solve
    dQ_dt = (R_t - Q_t)/T

    return dQ_dt

# #############################################################################
# User input   
T = 10      # Time constant (days)
Q0 = 0.     # Initial condition for outflow rate (mm/day)
days = 300  # Number of days to simulate
# #############################################################################

# Create a fake daily time series for R
# Generale random values from uniform dist
df = pd.DataFrame({'R':np.random.uniform(low=0, high=5, size=days+20)},
                  index=range(days+20))

# Smooth with a moving window to make more sensible                  
df['R'] = pd.rolling_mean(df['R'], window=20)

# Chop off the NoData at the start due to moving window
df = df[20:].reset_index(drop=True)

# List to store results
Q_vals = []

# Vector of initial conditions
y0 = [Q0, ]

# Loop over each day in the R dataset
for step in range(days):
    # We want to find the value of Q at the end of this time step
    t = [0, 1]

    # Get R for this step
    R_t = float(df.ix[step])   

    # Solve the ODEs
    soln = odeint(f, y0, t, args=(R_t,))

    # Extract flow at end of step from soln
    Q = float(soln[1])

    # Append result
    Q_vals.append(Q)

    # Update initial condition for next step
    y0 = [Q, ]

# Add results to df
df['Q'] = Q_vals

策略2

第二种方法是将所有内容简单地提供给odeint并让它处理不连续性。使用相同的参数和R值如上:

def f(y, t):
    """ Function used integrate.
    """
    # Unpack incremental values for S and D
    Q_t = y[0]

    # Get the value for R at this t
    idx = df.index.get_loc(t, method='ffill') 
    R_t = float(df.ix[idx])       

    # ODE to solve
    dQ_dt = (R_t - Q_t)/T

    return dQ_dt

# Vector of initial parameter values
y0 = [Q0, ]

# Time grid
t = np.arange(0, days, 1)

# solve the ODEs
soln = odeint(f, y0, t)

# Add result to df
df['Q'] = soln[:, 0]

这两种方法给出了相同的答案,如下所示:

然而,第二种策略虽然代码更紧凑,但它much比第一个慢。我想这与不连续性有关R造成问题odeint?

我的问题

  1. Is 策略1这里最好的方法,或者有一个更好的方法?
  2. Is 策略2这是一个坏主意,为什么这么慢?

谢谢你!


1.) Yes

2.) Yes

两者的原因:Runge-Kutta 求解器期望 ODE 函数的可微性阶数至少与求解器的阶数一样高。这是必要的,以便给出预期误差项的泰勒展开式存在。这意味着即使是 1 阶欧拉方法也需要可微的 ODE 函数。因此不允许跳跃,在 1 阶中可以容忍扭结,但在更高阶的求解器中则不允许。

对于具有自动步长调整的实现尤其如此。每当接近微分阶数不满足的点时,求解器就会看到一个刚性系统,并将步长驱动到 0,这会导致求解器速度减慢。

如果您使用具有固定步长且步长为 1 天的一小部分的求解器,则可以组合策略 1 和 2。然后,日间循环的采样点将用作具有新常数的(隐式)重启点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用不连续输入/强制数据求解 ODE 的相关文章

  • 熊猫按 n 最大总和分组

    我正在尝试使用groupby nlargest and sum在 Pandas 中一起运行 但在运行时遇到困难 State County Population Alabama a 100 Alabama b 50 Alabama c 40
  • 如何把父母和孩子联系起来?

    有两个简单的类 一个只有parent属性 并且两者兼而有之parent and children属性 这意味着同时具备两者的人parent and children继承自唯一的parent 这是只有parent属性 我们就这样称呼它吧Chi
  • Vimeo API:获取下载所有视频文件的链接列表

    再会 我正在尝试从 Vimeo 帐户获取所有视频文件的列表 直接下载的链接 有没有办法在 1 GET 请求中做到这一点 好的 如果是API限制的话 就100倍 我有硬编码脚本 我在其中发出 12 个 GET 请求 1100 多个视频 根据文
  • 为什么 Mypy 在 __init__ 中分配已在类主体中进行类型提示的属性时不给出键入错误?

    这是我的示例 python 文件 class Person name str age int def init self name age self name name self age age p Person 5 5 但当我跑步时myp
  • 从内存地址创建python对象(使用gi.repository)

    有时我需要调用仅存在于 C 中的 gtk gobject 函数 但返回一个具有 python 包装器的对象 之前我使用过基于 ctypes 的解决方案 效果很好 现在我从 PyGtk import gtk 切换到 GObject intro
  • 如何通过 python 中的函数运行列表?

    我试图通过我创建的函数运行我的列表 但不断收到错误 我不知道出了什么问题 温度 F temp f 19 21 21 21 23 功能 def fahrToCelsius tempFahrenheit return tempFahrenhei
  • Python 不考虑 distutils.cfg

    我已经尝试了给出的所有内容 并且所有教程都指向相同的方向 即使用 mingw 作为 python 而不是 Visual C 中的编译器 我确实有 Visual C 和 mingw 当我想使用 pip 安装时 问题开始出现 它总是给Unabl
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • pandas groupby 操作缺少数据

    在 pandas 数据框中 我有一列如下所示 0 M 1 E 2 L 3 M 1 4 M 2 5 M 3 6 E 1 7 E 2 8 E 3 9 E 4 10 L 1 11 L 2 12 M 1 a 13 M 1 b 14 M 1 c 15
  • Eclipse/PyDev 中未使用导入警告,尽管已使用

    我正在我的文件中导入一个绘图包 如下所示 import matplotlib pyplot as plt 稍后我会在我的代码中成功使用此导入 fig plt figure figsize 16 10 然而 Eclipse 告诉我 未使用的导
  • Python:导入模块一次然后与多个文件共享

    我有如下文件 file1 py file2 py file3 py 假设这三个都使用 lib7 py lib8 py lib9 py 目前 这三个文件中的每一个都有以下行 import lib7 import lib8 import lib
  • 根据标点符号列表替换数据框中的标点符号[重复]

    这个问题在这里已经有答案了 使用 Canopy 和 Pandas 我有数据框 a 其定义如下 a pd read csv text txt df pd DataFrame a df columns test test txt 是一个单列文件
  • 将 Django 中的所有视图限制为经过身份验证的用户

    我是 Django 新手 我正在开发一个项目 该项目有一个登录页面作为其索引和一个注册页面 其余页面都必须仅限于登录用户 如果未经身份验证的用户尝试访问这些页面 则必须将他 她重定向到登录页面 我看到 login required装饰器会将
  • 如何检测一个二维数组是否在另一个二维数组内?

    因此 在堆栈溢出成员的帮助下 我得到了以下代码 data needle s which is a png image base64 code goes here decoded data decode base64 f cStringIO
  • 类返回语句不打印任何输出

    我正在学习课程 但遇到了问题return语句 它是语句吗 我希望如此 程序什么也没有打印出来 它只是结束而不做任何事情 class className def createName self name self name name def
  • 从给定的项目列表创建子列表

    我首先要说的是以下问题不是为了家庭作业目的即使因为我几个月前就完成了软件工程师的工作 无论如何 今天我正在工作 一位朋友向我询问了这个奇怪的排序问题 我有一个包含 1000 行的列表 每行代表一个数字 我想创建 10 个子列表 每个子列表都
  • ProcessPoolExecutor 传递多个参数

    ESPN播放器免费 class ESPNPlayerFree def init self player id match id match id team 团队名单1 277906 cA2i150s81HI3qbq1fzi za1Oq5CG
  • Chrome 驱动程序和 Chromium 二进制文件无法在 aws lambda 上运行

    我陷入了一个问题 我需要在 AWS lambda 上做一些抓取工作 所以我按照下面提到的博客及其代码库作为起点 这非常有帮助 并且在运行时环境 Python 3 6 的 AWS lambda 上对我来说工作得很好 https manivan
  • 超过两个点的Python相对导入

    是否可以使用路径中包含两个以上点的模块引用 就像这个例子一样 Project structure sound init py codecs init py echo init py nix init py way1 py way2 py w
  • Tkinter 将鼠标点击绑定到框架

    我一定错过了一些明显的东西 我的 Tkinter 程序中有两个框架 每个框架在网格布局中都有一堆标签 我想将鼠标点击绑定到其中一个而不是另一个 我目前使用 root bind

随机推荐