当前位置: 首页 > news >正文

MATLAB 常微分方程数值求解算法探索:以两自由度无阻尼振动系统为例

MATLAB常微分方程数值求解算法程序(龙格库塔法、威尔逊法、纽马克法、中心差分法),以两自由度无阻尼振动系统为例,在MATLAB中建模并编制数值计算输出四种算法下物块的位移、速度和加速度曲线,后续可在此基础上继续开展算法求解误差对比。

在动力学分析领域,常微分方程(ODE)的数值求解是一项关键任务。今天咱们就来聊聊 MATLAB 中针对常微分方程的几种常见数值求解算法,包括龙格 - 库塔法、威尔逊法、纽马克法以及中心差分法。咱们以两自由度无阻尼振动系统为实例,看看如何在 MATLAB 里建模,并用这几种算法算出物块的位移、速度和加速度曲线,后续还能对这些算法的求解误差做个对比。

两自由度无阻尼振动系统的数学模型

两自由度无阻尼振动系统可以用下面的二阶常微分方程组来描述:

\[

m1\ddot{x}1 + k1 x1 - k2 (x2 - x_1) = 0

\]

\[

m2\ddot{x}2 + k2 (x2 - x_1) = 0

\]

为了能在 MATLAB 里求解,我们把它转化为一阶常微分方程组。设 \( y1 = x1 \),\( y2 = \dot{x}1 \),\( y3 = x2 \),\( y4 = \dot{x}2 \),则方程组变为:

\[

\dot{y}1 = y2

MATLAB常微分方程数值求解算法程序(龙格库塔法、威尔逊法、纽马克法、中心差分法),以两自由度无阻尼振动系统为例,在MATLAB中建模并编制数值计算输出四种算法下物块的位移、速度和加速度曲线,后续可在此基础上继续开展算法求解误差对比。

\]

\[

\dot{y}2 = \frac{- (k1 + k2)y1 + k2 y3}{m_1}

\]

\[

\dot{y}3 = y4

\]

\[

\dot{y}4 = \frac{k2 y1 - k2 y3}{m2}

\]

龙格 - 库塔法

龙格 - 库塔法是一种常用且高精度的数值求解方法。在 MATLAB 里,我们可以利用ode45函数来实现,它就是基于龙格 - 库塔法的。

% 参数设置 m1 = 1; m2 = 1; k1 = 100; k2 = 100; tspan = 0:0.01:10; % 时间范围 y0 = [0; 0; 0; 0]; % 初始条件 % 定义微分方程 odefun = @(t,y) [y(2); (- (k1 + k2)*y(1) + k2*y(3))/m1; y(4); (k2*y(1) - k2*y(3))/m2]; % 使用ode45求解 [t,y] = ode45(odefun,tspan,y0); % 提取位移、速度和加速度 x1 = y(:,1); v1 = y(:,2); a1 = (- (k1 + k2)*y(:,1) + k2*y(:,3))./m1; x2 = y(:,3); v2 = y(:,4); a2 = (k2*y(:,1) - k2*y(:,3))./m2; % 绘制曲线 figure; subplot(3,1,1); plot(t,x1,t,x2); title('位移曲线'); xlabel('时间 t (s)'); ylabel('位移 x (m)'); legend('物块1位移','物块2位移'); subplot(3,1,2); plot(t,v1,t,v2); title('速度曲线'); xlabel('时间 t (s)'); ylabel('速度 v (m/s)'); legend('物块1速度','物块2速度'); subplot(3,1,3); plot(t,a1,t,a2); title('加速度曲线'); xlabel('时间 t (s)'); ylabel('加速度 a (m/s^2)'); legend('物块1加速度','物块2加速度');

代码分析:

  1. 首先设定了系统参数 \( m1 \)、\( m2 \)、\( k1 \)、\( k2 \),时间范围tspan和初始条件y0
  2. 然后定义了微分方程odefun,这就是前面转化后的一阶常微分方程组。
  3. 接着使用ode45函数求解微分方程,得到时间t和状态变量y
  4. y中提取出物块 1 和物块 2 的位移、速度和加速度。
  5. 最后用subplot函数绘制出位移、速度和加速度曲线。

威尔逊法

威尔逊法是一种逐步积分法,常用于结构动力学分析。以下是威尔逊法求解两自由度无阻尼振动系统的代码示例:

% 参数设置 m1 = 1; m2 = 1; k1 = 100; k2 = 100; tspan = 0:0.01:10; % 时间范围 dt = tspan(2)-tspan(1); % 时间步长 y0 = [0; 0; 0; 0]; % 初始条件 % 初始化变量 n = length(tspan); x1 = zeros(n,1); v1 = zeros(n,1); a1 = zeros(n,1); x2 = zeros(n,1); v2 = zeros(n,1); a2 = zeros(n,1); x1(1) = y0(1); v1(1) = y0(2); a1(1) = (- (k1 + k2)*y0(1) + k2*y0(3))/m1; x2(1) = y0(3); v2(1) = y0(4); a2(1) = (k2*y0(1) - k2*y0(3))/m2; % 威尔逊法迭代 for i = 1:n-1 % 预测 a1_pred = a1(i); a2_pred = a2(i); v1_pred = v1(i) + dt*a1(i); v2_pred = v2(i) + dt*a2(i); x1_pred = x1(i) + dt*v1(i) + 0.5*dt^2*a1(i); x2_pred = x2(i) + dt*v2(i) + 0.5*dt^2*a2(i); % 校正 M = [m1 0 0 0; 0 m1 0 0; 0 0 m2 0; 0 0 0 m2]; K = [k1 + k2 -k2 0 0; -k2 k1 + k2 0 0; 0 0 k2 -k2; 0 0 -k2 k2]; F = [0; 0; 0; 0]; a = M \ (F - K * [x1_pred; x2_pred]); a1(i+1) = a(1); a2(i+1) = a(3); v1(i+1) = v1_pred + 0.5*dt*(a1(i+1) - a1_pred); v2(i+1) = v2_pred + 0.5*dt*(a2(i+1) - a2_pred); x1(i+1) = x1_pred + dt*v1_pred + 0.1666667*dt^2*(a1(i+1) + 2*a1_pred); x2(i+1) = x2_pred + dt*v2_pred + 0.1666667*dt^2*(a2(i+1) + 2*a2_pred); end % 绘制曲线 figure; subplot(3,1,1); plot(tspan,x1,tspan,x2); title('位移曲线'); xlabel('时间 t (s)'); ylabel('位移 x (m)'); legend('物块1位移','物块2位移'); subplot(3,1,2); plot(tspan,v1,tspan,v2); title('速度曲线'); xlabel('时间 t (s)'); ylabel('速度 v (m/s)'); legend('物块1速度','物块2速度'); subplot(3,1,3); plot(tspan,a1,tspan,a2); title('加速度曲线'); xlabel('时间 t (s)'); ylabel('加速度 a (m/s^2)'); legend('物块1加速度','物块2加速度');

代码分析:

  1. 同样先设定参数、时间范围和初始条件。
  2. 初始化位移、速度和加速度变量,并根据初始条件算出初始值。
  3. 在迭代循环中,先进行预测步骤,根据上一步的加速度、速度和位移预测下一步的值。
  4. 然后通过系统的质量矩阵M、刚度矩阵K和外力向量F进行校正,得到更准确的加速度、速度和位移。
  5. 最后绘制曲线展示结果。

纽马克法

纽马克法也是一种逐步积分方法,下面是它的实现代码:

% 参数设置 m1 = 1; m2 = 1; k1 = 100; k2 = 100; tspan = 0:0.01:10; % 时间范围 dt = tspan(2)-tspan(1); % 时间步长 y0 = [0; 0; 0; 0]; % 初始条件 % 初始化变量 n = length(tspan); x1 = zeros(n,1); v1 = zeros(n,1); a1 = zeros(n,1); x2 = zeros(n,1); v2 = zeros(n,1); a2 = zeros(n,1); x1(1) = y0(1); v1(1) = y0(2); a1(1) = (- (k1 + k2)*y0(1) + k2*y0(3))/m1; x2(1) = y0(3); v2(1) = y0(4); a2(1) = (k2*y0(1) - k2*y0(3))/m2; % 纽马克法参数 beta = 0.25; gamma = 0.5; % 纽马克法迭代 for i = 1:n-1 % 计算中间变量 A = M + gamma*dt*C + beta*dt^2*K; b = F + M*(v1(i) + (1 - gamma)*dt*a1(i)) + C*(x1(i) + dt*v1(i) + (0.5 - beta)*dt^2*a1(i)); % 求解位移 x = A \ b; x1(i+1) = x(1); x2(i+1) = x(3); % 计算速度和加速度 a1(i+1) = (x1(i+1) - x1(i) - dt*v1(i)) / (beta*dt^2); a2(i+1) = (x2(i+1) - x2(i) - dt*v2(i)) / (beta*dt^2); v1(i+1) = v1(i) + (1 - gamma)*dt*a1(i) + gamma*dt*a1(i+1); v2(i+1) = v2(i) + (1 - gamma)*dt*a2(i) + gamma*dt*a2(i+1); end % 绘制曲线 figure; subplot(3,1,1); plot(tspan,x1,tspan,x2); title('位移曲线'); xlabel('时间 t (s)'); ylabel('位移 x (m)'); legend('物块1位移','物块2位移'); subplot(3,1,2); plot(tspan,v1,tspan,v2); title('速度曲线'); xlabel('时间 t (s)'); ylabel('速度 v (m/s)'); legend('物块1速度','物块2速度'); subplot(3,1,3); plot(tspan,a1,tspan,a2); title('加速度曲线'); xlabel('时间 t (s)'); ylabel('加速度 a (m/s^2)'); legend('物块1加速度','物块2加速度');

代码分析:

  1. 设定参数、时间范围和初始条件与前面类似。
  2. 初始化变量,并根据初始条件算出初始值。
  3. 定义纽马克法的参数betagamma
  4. 在迭代循环中,先计算中间矩阵A和向量b,然后求解位移。
  5. 根据位移计算速度和加速度,最后绘制曲线。

中心差分法

中心差分法是一种简单直观的数值求解方法。代码如下:

% 参数设置 m1 = 1; m2 = 1; k1 = 100; k2 = 100; tspan = 0:0.01:10; % 时间范围 dt = tspan(2)-tspan(1); % 时间步长 y0 = [0; 0; 0; 0]; % 初始条件 % 初始化变量 n = length(tspan); x1 = zeros(n,1); v1 = zeros(n,1); a1 = zeros(n,1); x2 = zeros(n,1); v2 = zeros(n,1); a2 = zeros(n,1); x1(1) = y0(1); v1(1) = y0(2); a1(1) = (- (k1 + k2)*y0(1) + k2*y0(3))/m1; x2(1) = y0(3); v2(1) = y0(4); a2(1) = (k2*y0(1) - k2*y0(3))/m2; % 中心差分法迭代 for i = 2:n-1 % 计算加速度 a1(i) = (- (k1 + k2)*x1(i) + k2*x2(i))/m1; a2(i) = (k2*x1(i) - k2*x2(i))/m2; % 计算位移 x1(i+1) = 2*x1(i) - x1(i-1) + dt^2*a1(i); x2(i+1) = 2*x2(i) - x2(i-1) + dt^2*a2(i); % 计算速度 v1(i) = (x1(i+1) - x1(i-1)) / (2*dt); v2(i) = (x2(i+1) - x2(i-1)) / (2*dt); end % 绘制曲线 figure; subplot(3,1,1); plot(tspan,x1,tspan,x2); title('位移曲线'); xlabel('时间 t (s)'); ylabel('位移 x (m)'); legend('物块1位移','物块2位移'); subplot(3,1,2); plot(tspan,v1,tspan,v2); title('速度曲线'); xlabel('时间 t (s)'); ylabel('速度 v (m/s)'); legend('物块1速度','物块2速度'); subplot(3,1,3); plot(tspan,a1,tspan,a2); title('加速度曲线'); xlabel('时间 t (s)'); ylabel('加速度 a (m/s^2)'); legend('物块1加速度','物块2加速度');

代码分析:

  1. 同样设定参数、时间范围和初始条件并初始化变量。
  2. 在迭代循环中,先根据当前位移计算加速度。
  3. 然后利用中心差分公式计算下一个时刻的位移。
  4. 最后根据位移计算速度,完成后绘制曲线。

后续的算法求解误差对比

通过上面的代码,我们已经得到了四种算法下物块的位移、速度和加速度曲线。接下来就可以对比它们的求解误差了。一种常见的方法是与精确解对比(如果精确解已知的话),或者将一种高精度算法的结果作为参考解,对比其他算法与参考解的误差。例如,我们可以把龙格 - 库塔法(ode45)的结果作为参考解,计算其他三种算法在每个时间点的误差,然后绘制误差曲线,这样就能直观地看出哪种算法在这个系统中的精度更高。具体实现这里就不再展开啦,感兴趣的小伙伴可以自己动手试试。

希望这篇博文能让大家对 MATLAB 中这几种常微分方程数值求解算法在两自由度无阻尼振动系统中的应用有更清晰的认识。大家要是有啥问题或者想法,欢迎在评论区留言交流。

http://www.cnnetsun.cn/news/1423415.html

相关文章:

  • AgentScope 可观测体系:OpenTelemetry 全链路追踪与 AgentScope Studio 诊断
  • SpringBoot+Vue开源MES系统二次开发指南:从接口对接到看板定制
  • TI高精度实验室-运算放大器-噪声分析与降噪实战指南
  • Camunda流程实例修改全指南:从单实例回退到批量跳转的Java代码实战
  • OpenHarmony 5.0实战:用WS63开发板玩转LiteOS-M内核线程调度(附完整代码)
  • 导师又让重写?10个AI论文平台全场景通用测评,开题报告/毕业论文/科研写作全搞定
  • RMBG-2.0在医疗影像处理中的创新应用
  • 永磁同步电机SVPWM模糊PI控制仿真Simulink模型探索
  • vue+python校园综合服务系统的设计与实现
  • 编写程序让智能宠物喂食器定时触发,每天固定时间,提示“投放粮食”,省心养宠。
  • 保姆级教程:用Android Studio CPU Profiler分析视频播放卡顿问题(含火焰图解读技巧)
  • Python实战:5分钟搞定核密度估计可视化(附完整代码)
  • 语义分割实战:Hausdorff损失函数在医学图像分割中的调参技巧
  • ESP32+ENC28J60以太网Web服务器兼容库
  • uniApp XR-Frame小程序实战 | 模型资源池与按需加载策略
  • Cal.com:开源日程预约管理平台,Calendly的最佳替代方案
  • 好写作AI | 导师视角下AI辅助毕业论文写作的指导策略与评判困境
  • CTF线下赛救星:94GB的ctftools-all-in-one_proV2离线工具包,手把手教你部署与实战避坑
  • SmolVLA模拟技术面试官:动态追问与深度评估展示
  • 计算机毕业设计springboot智慧城市物业管理系统 基于Spring Boot的智慧社区综合服务平台设计与实现 基于Java Web的数字化小区物业运营管理系统开发
  • Modelsim仿真避坑指南:从Verilog代码到波形分析的完整流程(附随机激励生成技巧)
  • HTML + CSS + JavaScript 快速入门(三):JS 与 jQuery 实战
  • Ubuntu双系统安装失败?天选5Pro的Intel RST问题全解析
  • SecGPT-14B一文详解:SecGPT-14B在ATTCK战术层(TA0002/TA0003)的映射能力
  • 微信小游戏开发者必看:如何防止你的游戏被CE修改和反编译?
  • Vivado工程芯片型号更换全流程:从IP更新到生成新bit文件(避坑指南)
  • 为什么90%的MCP跨语言调用会偶发“UnknownError: code=12”?——基于Wireshark+eBPF的协议栈级深度溯源
  • Java Web开发基础与Servlet核心技术
  • 告别卡顿!用FPGA+SDRAM实现OV7670视频流平滑显示的关键时序设计
  • 深耕B端拓客:号码核验的行业困局与技术破局路径氪迹科技法人股东号码筛选核验系统