美文网首页
R包deSolve解微分方程

R包deSolve解微分方程

作者: 小潤澤 | 来源:发表于2022-05-11 21:22 被阅读0次

在求解一些诸如动力学方程的时候,可以利用R包 deSolve 来完成

这里举两个实用性的例子:

普通的微分方程组:

library(deSolve)
library(scatterplot3d)
## Chaos in the atmosphere
Lorenz <- function(t, state, parameters) {
  with(as.list(c(state, parameters)), {
    dX <-  a * X + Y * Z
    dY <-  b * (Y - Z)
    dZ <- -X * Y + c * Y - Z
    list(c(dX, dY, dZ))
  })
}

parameters <- c(a = -8/3, b = -10, c = 28)
state <- c(X = 1, Y = 1, Z = 1)
times <- seq(0, 100, by = 0.01)

out <- ode(y = state, times = times, func = Lorenz, parms = parameters)


利用函数 ode() 可以计算出三个函数 X,Y,Z 的轨迹函数图像


带有误差延时的微分方程组

首先是单个方程的情况:

其中 (t-1)代表延迟,也就是这一部分中,函数 y() 在 t 时刻 前移了1个单位

library(deSolve)

# 传入方程参数 y 和 t;函数y写在state里面
derivs <- function(t, state, parms) {
  with(as.list(c(state, parms)), {
    if (t < 1){
      dy <- 1
    }
    else{
      dy <- -1*lagvalue(t - 1) + t^2+1
    }
    list(c(dy))
  })
}

state <- c(y = 0)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = derivs, parms = NULL)
plot(yout)

### 或者这样写
library(deSolve)

# 传入方程参数 y 和 t
derivs <- function(t,  y, parms) {
    if (t < 1){
      dy <- 1
    }
    else{
      dy <- -1*lagvalue(t - 1) + t^2+1
    }
    list(c(dy))
}

state <- c(y = 0)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = derivs, parms = NULL)
plot(yout)

其中:

  1. dy <- -1*lagvalue(t - 1) + t^2+1代表方程形式为 dy / dx = -y( t - 1 ) + t2 + 1
  2. 该方程的其中一个解为:当 t < 1 时,y = t;当t ≥ 1时,y = t2

第二种是方程组的形式:

其中(t-1)代表延迟,也就是在这一部分中,函数y() 在 t 时刻前移了1个单位;
(t-0.5)也代表延迟,也就是在这一部分中,函数x() 在 t 时刻前移了0.5个单位

library(deSolve)

# 注意如果是方程组需要传入待求解函数(本例中为 x,y;因此传入 x,y并存入state)
derivs <- function(t,state, parms) {
  with(as.list(c(state, parms)), {
    if (t < 1){
      dx <- 1
      dy <- 1
    }
    else{
      dx <- -1*lagvalue(t - 0.5,1) + 2*lagvalue(t - 1,2) + y^2 + 1
      dy <- -1*lagvalue(t - 1,2) + lagvalue(t - 0.5,1) + x
    }
    list(c(dy,dx))
  })
}

state <- c(x = 10,y = 0)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = derivs, parms = NULL)
plot(yout)


### 或者这样写
library(deSolve)

# 注意如果是方程组需要传入待求解函数(本例中为 x,y;因此传入 x,y)
derivs <- function(t, x , y, parms) {
    if (t < 1){
      dx <- 1
      dy <- 1
    }
    else{
      dx <- -1*lagvalue(t - 0.5,1) + 2*lagvalue(t - 1,2) + y^2 + 1
      dy <- -1*lagvalue(t - 1,2) + lagvalue(t - 0.5,1) + x
    }
    list(c(dy,dx))
}

state <- c(x = 10,y = 0)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = derivs, parms = NULL)
plot(yout)

其中:

  1. lagvalue(t - 0.5,1) 代表函数 x( t - 0.5 )lagvalue(t - 1,2) 代表函数 y( t - 1 );1 代表 state里面的第一个函数 x(),2 代表 state里面的第二个函数 y()
  2. state 代表初始值函数,对应 x 和 y 的初始值
  3. derivs <- function(t, x,y, parms) {} 如果待求解函数 (dx,dy),则需要传入 x 和 y两个参数

以不同时间段设置不同的延时:

微分方程形式:


library(deSolve)

# lamb为可变的延时系数
func_dirct <- function(t, state, parms) {
  with(as.list(c(state, parms)), {
    if (t < 1){
      dy <- 1
    }
    else if (t < 2 & t > 1) {
      lamb = 1
      dy <- -1*lagvalue(t - lamb,1)
    }
    else {
      lamb = 0.1
      dy <- -1*lagvalue(t - lamb,1) + y
    }
    list(c(dy))
  })
}

state <- c(y = 10)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = func_dirct, parms = NULL)
plot(yout)

### 或者这样写
library(deSolve)

# lamb为可变的延时系数
func_dirct <- function(t,  y, parms) {
    if (t < 1){
      dy <- 1
    }
    else if (t < 2 & t > 1) {
      lamb = 1
      dy <- -1*lagvalue(t - lamb,1)
    }
    else {
      lamb = 0.1
      dy <- -1*lagvalue(t - lamb,1) + y
    }
    list(c(dy))
}

state <- c(y = 10)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = func_dirct, parms = NULL)
plot(yout)

其中:
lamb 为可变的延时变量,用if语句进行控制

如果是想让延时系数与时间 t 有关,则需要进行如下改下:

library(deSolve)

# 连续变量型的延时系数书写方式,传入参数 parms <- c(lamb = 1)
func_dirct <- function(t, state,parms) {
  with(as.list(c(state, parms)), {
    # 对延时系数lamb进行条件筛选
    if (t < 1){
      lamb <- 1
    }
    else if (t < 2 & t > 1) {
      lamb <- t/100000
    }
    else {
      lamb <- 3*t/100000
    }
    
    print(lamb)
    if (t < 1){
      dy <- 1
    }
    else if (t < 2 & t > 1) {
      dy <- -1*lagvalue(t - lamb,1)
    }
    else {
      dy <- -1*lagvalue(t - lamb,1) + y
    }
    list(c(dy))
  })
}

parms <- c(lamb = 1)
state <- c(y = 10)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = func_dirct, parms = parms)
plot(yout)

### 或者这样写
library(deSolve)

# 连续变量型的延时系数书写方式, 把参数 lamb 写在 function() 里面
func_dirct <- function(t, y, lamb,parms) {
  # 对延时系数lamb进行条件筛选
  if (t < 1){
    lamb <- 1
  }
  else if (t < 2 & t > 1) {
    lamb <- t/100000
  }
  else {
    lamb <- 3*t/100000
  }
  
  print(lamb)
  if (t < 1){
    dy <- 1
  }
  else if (t < 2 & t > 1) {
    dy <- -1*lagvalue(t - lamb,1)
  }
  else {
    dy <- -1*lagvalue(t - lamb,1) + y
  }
  list(c(dy))
}

parms <- c(lamb = 1)
state <- c(y = 10)
times <- seq(0, 2, 0.1)

yout <- dede(y = state, times = times, func = func_dirct, parms = parms)
plot(yout)


对延时系数 lamb 进行条件判断以及设置 lamb 和 t 的函数关系式,可以进行可变延时系数的计算

对函数值进行判断,对应不同的微分方程:

library(deSolve)

# 利用函数值做判断,原理是迭代计算每一个time对应的函数值
derivs <- function(t,x, y, parms) {
  print(x)
  if (x[1] == 10 & x[2] == 0){
    dx <- 1
    dy <- 3
  }
  else if (x[1] < 7 & x[2] < 1.2) {
    dx <- -1*x + y^2
    dy <- -5*y + x*y^2 + x^2*y
  }
  else if (x[1] < x[2]) {
    dx <- -1*x + y^2
    dy <- -5*y + x*y^2 + x^2*y
  }
  else {
    dx <- 2*x
    dy <- 5*y
  }
  list(c(dy,dx))
}

state <- c(x = 9,y = 0)
times <- seq(0, 0.5, 0.05)

yout <- dede(y = state, times = times, func = derivs, parms = NULL)
plot(yout)

## 这种情况就不能用 with(as.list(c(state, parms)), {}) 语句了

其中

  1. 在函数derivs中print(x)打印出来的是

    分别对应 xy 的值,因此 x[1] 代表的是 x(t)函数随时间 t 变化的值x[2] 代表的是 y(t)函数随时间 t 变化的值;因此可以依据 x[1] 和 x[2] 进行判断
  2. 这种情况就不能用 with(as.list(c(state, parms)), {}) 语句了

相关文章

  • R包deSolve解微分方程

    在求解一些诸如动力学方程的时候,可以利用R包 deSolve[http://desolve.r-forge.r-p...

  • 性格真的能够决定命运吗?微分方程数值解的启示:能!

    学过微分方程的人可能都还记得,自刘维尔的工作后,人们的注意力从求微分方程的解析解转移到微分方程的数值解上来。而接触...

  • 高等数学(七)常微分方程

    (一)常微分方程的基本概念 微分方程 微分方程的阶/解 微分方程的通解/特解 初始条件 积分曲线 (二)一阶微分方...

  • 特殊函数不特殊

    学习量子力学,就要解微分方程,解微分方程,就离不开特殊函数,先前,被这些函数的气势所吓,碰见就绕着走,结果,问题是...

  • Python机器学习及分析工具:Scipy篇

      Scipy是一个用于数学、科学、工程领域的常用软件包,可以处理插值、积分、优化、图像处理、常微分方程数值解的求...

  • Scipy数据操作归纳总结

    Scipy是一个用于数学、科学、工程领域的常用软件包,可以处理插值、积分、优化、图像处理、常微分方程数值解的求解、...

  • 第二讲:动力学方程的数值积分

    计算机动画的本质上是解微分方程,因此本文主要介绍微分方程常用的一些解法。 particle system 首先从最...

  • 专升本手札51

    二阶常系数齐次线性微分方程 标准形式:y"+py'+qy=0 求通解: r²+pr+q=0 求出r1,r2

  • 数学模型——微分方程

    通过微分方程,探索与拟合自变量与因变量之间的关系。 大致方法 建立微分方程:将 趋近于零时,由导数的定义得然后解...

  • 微分方程数值解中的Euler格式

    本文是本科生课程,微分方程数值解的作业之一。 Abstract This report focuses on in...

网友评论

      本文标题:R包deSolve解微分方程

      本文链接:https://www.haomeiwen.com/subject/cbodurtx.html