iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >用C++的odeint库求解微分方程
  • 411
分享到

用C++的odeint库求解微分方程

2024-04-02 19:04:59 411人浏览 独家记忆
摘要

目录1、集成方程2、求解单摆模型2.1 微分方程标准化2.2 代码实现微分方程的标准形式为: 即:\dot{\boldsymbol{x}} = \boldsymbol{f}(\b

微分方程的标准形式为:


即:\dot{\boldsymbol{x}} = \boldsymbol{f}(\boldsymbol{x}, t),\, \boldsymbol{x}(0) = \boldsymbol{x_0}

这是一阶微分方程组, \boldsymbol{x} \boldsymbol{f}(\boldsymbol{x}, t) 均为向量。如果要求解高阶微分方程,需要先转换成一阶微分方程组后再用odeint求解。

1、集成方程

api中最重要的是集成函数(integrate functions),一共有5种,它们的调用接口很类似。 integrate_const 的函数调用方式为:


integrate_const(stepper, system, x0, t0, t1, dt, observer)


其中:

  • stepper 是求解器,也就是所使用的数值算法(例如Runge-Kutta或Euler法)
  • system 是待求解的微分方程
  • x0 是初始条件
  • t0 和 t1 分别是初始时间和结束时间
  • dt 是时间间隔,它重要与否取决于求解器的类型
  • observer 是每N个时间间隔调用一次的函数,可用来打印实时的解,该参数是可选的,如果没有此参数,集成函数会从 t0 计算到 t1 ,不产生任何输出就返回

给定初始状态 x0 ,集成函数从初始时间 t0 到结束时间 t1 不断地调用给定的 stepper ,计算微分方程在不同时刻的解,用户还可以提供 observer 以分析某个时刻的状态值。具体选择哪个集成函数取决于你想要什么类型的结果,也就是调用 observer 的频次。

integrate_const 每过相等的时间间隔 dt 会调用一次 observer 语法为:


integrate_const(stepper, system, x0, t0, t1, dt, observer)

integrate_n_steps 和前面的类似,但它不需要知道结束时间,它只需要知道要计算的步数,语法为:


integrate_n_steps(stepper, system, x0, t0, dt, n, observer)


integrate_times 计算在用户给定时间点的值,语法为:


integrate_times(stepper, system, x0, times_start, times_end, dt, observer)
integrate_times(stepper, system, x0, time_range, dt, observer)


integrate_adaptive 用于需要在每个时间间隔调用 observer 的场合,语法为:


integrate_adaptive(stepper, system, x0, t0, t1, dt, observer)


integrate 是最方便的集成函数, 不需要指定 stepper ,简单快捷,语法为:


integrate(system, x0, t0, t1, dt, observer)


求解器stepper的选择(比如自适应方式会根据误差修改时间间隔)会改变计算的具体实现方式, 但是observer的调用(也就是你的输出结果)依然遵循上述规则。

2、求解单摆模型

2.1 微分方程标准化

现在求单摆系统微分方程的解,以得出单摆角度随时间变化的规律。其微分方程

即:\ddot{\theta}(t) = -\mu \dot{\theta}(t) - \frac{g}{L} \sin \theta(t)

即:\begin{cases} \dot{\theta}(t) & = \omega(t) \\ \dot{\omega}(t) & = -\mu \omega(t) - g/L \sin \theta(t) \end{cases}

令状态变量

即:\boldsymbol{x} = \begin{bmatrix} x_1(t)\\ x_2(t) \end{bmatrix} = \begin{bmatrix} \theta(t)\\ \omega(t) \end{bmatrix}

微分方程组变为

即:\frac{\mathrm{d}\boldsymbol{x}}{\mathrm{d}t}= \frac{\mathrm{d}}{\mathrm{d}t} \begin{bmatrix} x_1(t)\\ x_2(t) \end{bmatrix} = \begin{bmatrix} x_2(t)\\ -\mu x_2(t) - g/L \sin x_1(t) \end{bmatrix}

2.2 代码实现

代码中有如下几个关键点:

  1. 要定义状态变量的类型state_type,定义为 std::vector<double> 即可
  2. 要用方程表示微分方程模型,和MATLAB中模型方程的写法非常类似
  3. 要写一个Observer以打印出计算结果,Observer函数也可以直接将数据写入文件中
  4. 要选择合适的求解器stepper,各种stepper的特点总结可以看 这里
  5. 要根据需要选择合适的集成函数,一般选择 integrate_const 即可满足要求

下面的代码可作为标准模板使用:


#include <iOStream>
#include <cmath>
#include <boost/numeric/odeint.hpp>

using namespace std;
using namespace boost::numeric::odeint;

const double g  = 9.81; // 重力加速度
const double L  = 1.00; // 摆线长度
const double mu = 0.80; // 阻力系数

// 定义状态变量的类型
typedef std::vector<double> state_type;

// 要求解的微分方程
void pendulum(const state_type &x, state_type &dxdt, double t)
{
    dxdt[0] = x[1];
    dxdt[1] = -mu*x[1] - g/L*sin(x[0]);    
}

// Observer打印状态值
void write_pendulum(const state_type &x, const double t)
{
    cout << t << '\t' << x[0] << '\t' << x[1] << endl;
}

int main(int arGC, char **argv)
{
    // 初始条件,二维向量
    state_type x = {0.10 , 0.00};
    // 求解方法为runge_kutta4
    integrate_const(runge_kutta4<state_type>(), pendulum, x , 0.0 , 5.0 , 0.01 , write_pendulum);
}

编译该程序依赖boost库,要在 CMakeLists.txt 中添加相应的内容。编译成功后运行,会得到如下的结果:


0       0.1     0
0.01    0.0999512       -0.009753
0.02    0.0998052       -0.0194188
0.03    0.0995631       -0.0289887
0.04    0.0992258       -0.0384542
0.05    0.0987944       -0.0478069
0.06    0.0982701       -0.0570385
0.07    0.0976541       -0.0661412
0.08    0.0969477       -0.075107
0.09    0.0961524       -0.0839283
0.1     0.0952696       -0.0925977
0.11    0.094301        -0.101108
----    many lines ommitted    ----

可以将输出数据重定向到文本文件 data.txt 中,然后使用python等脚本语言提取数据并画图显示。下面是实现该功能的参考代码:


import numpy as np
import matplotlib.pyplot as plt

lines = tuple(open("data.txt", 'r')) # 读取文件行到tuple中

rows = len(lines)
time  = np.zeros(rows)
theta = np.zeros(rows)
omega = np.zeros(rows)

for r in range(rows):
    [str1, str2, str3] = lines[r].split()
    time[r]  = float(str1)
    theta[r] = float(str2)
    omega[r] = float(str3)

plt.plot(time, theta, time, omega) # 角度和角速度变化
# plt.plot(theta, omega) # 相图
plt.show()

到此这篇关于用c++的odeint库求解微分方程的文章就介绍到这了,更多相关C++的odeint库求解微分方程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 用C++的odeint库求解微分方程

本文链接: https://www.lsjlt.com/news/136109.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 用C++的odeint库求解微分方程
    目录1、集成方程2、求解单摆模型2.1 微分方程标准化2.2 代码实现微分方程的标准形式为: 即:\dot{\boldsymbol{x}} = \boldsymbol{f}(\b...
    99+
    2022-11-12
  • 数学——Euler方法求解微分方程详解(
    算法的数学描述图解 实例 用Euler算法求解初值问题 \[ \frac{dy}{dx}=y+\frac{2x}{y^2}\] 初始条件\(y(0)=1\),自变量的取值范围\(x \in [0, 2]\) 算法Python3代码求解...
    99+
    2023-01-30
    微分方程 详解 数学
  • C++实现二分法求方程近似解
    二分法是一种求解方程近似根的方法。对于一个函数 f(x)f(x),使用二分法求 f(x)f(x) 近似解的时候,我们先设定一个迭代区间(在这个题目上,我...
    99+
    2022-11-12
  • Python数值求解微分方程方法(欧拉法,隐式欧拉)
    不说什么,先上代码 这里先求解形如的微分方程 1.欧拉法 def eluer(rangee,h,fun,x0,y0): step = int(rangee/h) x ...
    99+
    2022-11-11
  • 微信小程序请求前置的方法详解
    问题 因为我们有的页面是在onload中去请求数据回来再渲染视图,如果我们可以将请求数据这一步提前到小程序页面跳转前做,就可以早一点把数据请求回来,优化的效果取决于页面跳转所需的时...
    99+
    2022-11-11
  • 用Python解微分方程用什么函数
    Python中使用sympy模块的dsolve函数求解微分方程,具体方法如下:import sympy as sy #导入sympy模块def differential_equation(x...
    99+
    2022-10-07
  • python 解决微分方程的操作(数值解法)
    Python求解微分方程(数值解法) 对于一些微分方程来说,数值解法对于求解具有很好的帮助,因为难以求得其原方程。 比如方程: 但是我们知道了它的初始条件,这对于我们叠代求解很有帮助,也是必须的。 那么现在我们也...
    99+
    2022-06-02
    python 微分方程 数值解法
  • 用C语言求解一元二次方程的简单实现
    目录C语言 求解一元二次方程求一元二次方程的解,考虑所有情况1、a = 02、a != 0C语言 求解一元二次方程 在用C语言求解一元二次方程的时候,首先,最重要的肯定是要引入&qu...
    99+
    2022-11-13
    C语言一元二次方程 求解一元二次方程 一元二次方程
  • PHP请求微信域名检测接口官方API的详解与示例分享
    微信域名检测接口API是腾讯官方对外公布的域名查询接口,请求接口可实时查询域名在微信种的状态信息。如果状态异常则返回结果提示“域名被封”,如果未有异常则返回结果提示“域名正常”。微信域名检测接口https://wx.horocn.com/应...
    99+
    2023-06-04
  • c# 理解csredis库实现分布式锁的详细流程
    声明: 这里首先使用的是csredis,地址是https://github.com/2881099/csredis 该库本身已经足够完善,这里我画蛇添足一下,为了方便自己的使用。 本...
    99+
    2022-11-13
  • Python调用C++程序的方法详解
    前言 大家都知道Python的优点是开发效率高,使用方便,C++则是运行效率高,这两者可以相辅相成,不管是在Python项目中嵌入C++代码,或是在C++项目中用Python实现外围功能,都可能遇到Pyth...
    99+
    2022-06-04
    详解 程序 方法
  • Qt之调用C#的动态库的解决方法
    环境:VS2019+Qt5.12 1. CLR库安装         首先,如果你VS2019没有安装...
    99+
    2022-11-12
  • 数据库在C++程序中的使用方法
    本篇内容主要讲解“数据库在C++程序中的使用方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“数据库在C++程序中的使用方法”吧!栈在编写代码时,堆栈是最常用的数据结构。它的概念简单,编写也比较...
    99+
    2023-06-17
  • 详解C++ functional库中的仿函数使用方法
    目录一、仿函数简介二、仿函数简要写法示例三、使用C++自带的仿函数(1)算术仿函数(2)关系仿函数(3)逻辑仿函数一、仿函数简介 仿函数(functor)又称之为函数对象(funct...
    99+
    2022-11-13
  • 微信小程序使用扩展组件库WeUI的方法
    本篇内容介绍了“微信小程序使用扩展组件库WeUI的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 学习参考2.NodeJs初始化这里...
    99+
    2023-06-30
  • 微信域名检测官方api接口的使用说明与请求示例分析
    今天就跟大家聊聊有关微信域名检测官方api接口的使用说明与请求示例分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。微信域名检测接口和QQ域名检测接口API皆是由腾讯官方对外公布的域...
    99+
    2023-06-04
  • python使用requests库提交multipart/form-data请求的方法详解
    目录前言multipart/form-dataPython 发送 multipart/form-data补充知识:multipart/form-data 参数转码总结前言 今天渗透测...
    99+
    2023-01-17
    python multipart/form-data python formdata请求 python multipart/form-data请求
  • 微信小程序获取用户openid的方法详解
    目录获取openid的思路需要修改的地方完整代码总结小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系然而因为小程序中的openid不可...
    99+
    2022-11-13
  • 微信小程序包大小超过2M的解决方法—分包加载
    小程序的包被限制在2M以下, 超出的时候点击预览, 发现报错: Error: 代码包大小为 3701 kb,上限为 2048 kb,请删除文件后重试 解决方法: 优化代码, 删除掉不用的代码 图片...
    99+
    2023-09-07
    微信小程序 小程序 微信
  • C#命令行参数解析库System.CommandLine的使用方法
    这篇文章主要介绍了C#命令行参数解析库System.CommandLine的使用方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。命令行参数平常在日常的开发过程中,会经常用到...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作